diff --git a/drivers/staging/speakup/sysfs-driver-speakup b/Documentation/ABI/stable/sysfs-driver-speakup similarity index 100% rename from drivers/staging/speakup/sysfs-driver-speakup rename to Documentation/ABI/stable/sysfs-driver-speakup diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index d3e53a6d8331bb3894456a15b23a9f505b97cea3..5c62bfb0f3f576017b83059b8840f128073f1f27 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1569,7 +1569,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_voc_raw KernelVersion: 4.3 Contact: linux-iio@vger.kernel.org Description: - Raw (unscaled no offset etc.) percentage reading of a substance. + Raw (unscaled no offset etc.) reading of a substance. Units + after application of scale and offset are percents. What: /sys/bus/iio/devices/iio:deviceX/in_resistance_raw What: /sys/bus/iio/devices/iio:deviceX/in_resistanceX_raw diff --git a/Documentation/ABI/testing/sysfs-bus-iio-icm42600 b/Documentation/ABI/testing/sysfs-bus-iio-icm42600 new file mode 100644 index 0000000000000000000000000000000000000000..0bf1fd4f5bf1498846ba830f8461b192c461d8a4 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-icm42600 @@ -0,0 +1,20 @@ +What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias +KernelVersion: 5.8 +Contact: linux-iio@vger.kernel.org +Description: + Hardware applied calibration offset (assumed to fix production + inaccuracies). Values represent a real physical offset expressed + in SI units (m/s^2 for accelerometer and rad/s for gyroscope). + +What: /sys/bus/iio/devices/iio:deviceX/in_accel_calibbias_available +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_calibbias_available +KernelVersion: 5.8 +Contact: linux-iio@vger.kernel.org +Description: + Range of available values for hardware offset. Values in SI + units (m/s^2 for accelerometer and rad/s for gyroscope). diff --git a/Documentation/ABI/testing/sysfs-bus-iio-scd30 b/Documentation/ABI/testing/sysfs-bus-iio-scd30 new file mode 100644 index 0000000000000000000000000000000000000000..b9712f390bec4770c64cafe0d23670f214287fdc --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-scd30 @@ -0,0 +1,34 @@ +What: /sys/bus/iio/devices/iio:deviceX/calibration_auto_enable +Date: June 2020 +KernelVersion: 5.8 +Contact: linux-iio@vger.kernel.org +Description: + Contaminants build-up in the measurement chamber or optical + elements deterioration leads to sensor drift. + + One can compensate for sensor drift by using automatic self + calibration procedure (asc). + + Writing 1 or 0 to this attribute will respectively activate or + deactivate asc. + + Upon reading current asc status is returned. + +What: /sys/bus/iio/devices/iio:deviceX/calibration_forced_value +Date: June 2020 +KernelVersion: 5.8 +Contact: linux-iio@vger.kernel.org +Description: + Contaminants build-up in the measurement chamber or optical + elements deterioration leads to sensor drift. + + One can compensate for sensor drift by using forced + recalibration (frc). This is useful in case there's known + co2 reference available nearby the sensor. + + Picking value from the range [400 1 2000] and writing it to the + sensor will set frc. + + Upon reading current frc value is returned. Note that after + power cycling default value (i.e 400) is returned even though + internally sensor had recalibrated itself. diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index 016724ec26d5a08c971eb981e2e9ded35af378f1..d1a352194d2eaf65d2d8ca435885bbded5424e6a 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -883,3 +883,139 @@ Contact: Subhash Jadavani Description: This entry shows the target state of an UFS UIC link for the chosen system power management level. The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_presv_us_en +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows if preserve user-space was configured + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_shared_alloc_units +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows the shared allocated units of WB buffer + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_type +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows the configured WB type. + 0x1 for shared buffer mode. 0x0 for dedicated buffer mode. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_buff_cap_adj +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows the total user-space decrease in shared + buffer mode. + The value of this parameter is 3 for TLC NAND when SLC mode + is used as WriteBooster Buffer. 2 for MLC NAND. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_max_alloc_units +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows the Maximum total WriteBooster Buffer size + which is supported by the entire device. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_max_wb_luns +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows the maximum number of luns that can support + WriteBooster. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_sup_red_type +Date: June 2020 +Contact: Asutosh Das +Description: The supportability of user space reduction mode + and preserve user space mode. + 00h: WriteBooster Buffer can be configured only in + user space reduction type. + 01h: WriteBooster Buffer can be configured only in + preserve user space type. + 02h: Device can be configured in either user space + reduction type or preserve user space type. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_sup_wb_type +Date: June 2020 +Contact: Asutosh Das +Description: The supportability of WriteBooster Buffer type. + 00h: LU based WriteBooster Buffer configuration + 01h: Single shared WriteBooster Buffer + configuration + 02h: Supporting both LU based WriteBooster + Buffer and Single shared WriteBooster Buffer + configuration + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/flags/wb_enable +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows the status of WriteBooster. + 0: WriteBooster is not enabled. + 1: WriteBooster is enabled + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/flags/wb_flush_en +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows if flush is enabled. + 0: Flush operation is not performed. + 1: Flush operation is performed. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/flags/wb_flush_during_h8 +Date: June 2020 +Contact: Asutosh Das +Description: Flush WriteBooster Buffer during hibernate state. + 0: Device is not allowed to flush the + WriteBooster Buffer during link hibernate + state. + 1: Device is allowed to flush the + WriteBooster Buffer during link hibernate + state + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_avail_buf +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows the amount of unused WriteBooster buffer + available. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_cur_buf +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows the amount of unused current buffer. + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_flush_status +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows the flush operation status. + 00h: idle + 01h: Flush operation in progress + 02h: Flush operation stopped prematurely. + 03h: Flush operation completed successfully + 04h: Flush operation general failure + The file is read only. + +What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_life_time_est +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows an indication of the WriteBooster Buffer + lifetime based on the amount of performed program/erase cycles + 01h: 0% - 10% WriteBooster Buffer life time used + ... + 0Ah: 90% - 100% WriteBooster Buffer life time used + The file is read only. + +What: /sys/class/scsi_device/*/device/unit_descriptor/wb_buf_alloc_units +Date: June 2020 +Contact: Asutosh Das +Description: This entry shows the configured size of WriteBooster buffer. + 0400h corresponds to 4GB. + The file is read only. diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 254bfafdcbcdb26031e0d876239ef58b097dac1f..ef66b3c45ba221041b0bcf0b58afa337392945a4 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -5804,8 +5804,9 @@ panic() code such as dumping handler. xen_nopvspin [X86,XEN] - Disables the ticketlock slowpath using Xen PV - optimizations. + Disables the qspinlock slowpath using Xen PV optimizations. + This parameter is obsoleted by "nopvspin" parameter, which + has equivalent effect for XEN platform. xen_nopv [X86] Disables the PV optimizations forcing the HVM guest to @@ -5831,6 +5832,11 @@ as generic guest with no PV drivers. Currently support XEN HVM, KVM, HYPER_V and VMWARE guest. + nopvspin [X86,XEN,KVM] + Disables the qspinlock slow path using PV optimizations + which allow the hypervisor to 'idle' the guest on lock + contention. + xirc2ps_cs= [NET,PCMCIA] Format: ,,,,,[,[,[,]]] diff --git a/drivers/staging/speakup/spkguide.txt b/Documentation/admin-guide/spkguide.txt similarity index 99% rename from drivers/staging/speakup/spkguide.txt rename to Documentation/admin-guide/spkguide.txt index 1e622cd34363395b043bb19959cd4f1725df6e6c..3782f6a09e97a6a6d5d84f59c9d29ff677761177 100644 --- a/drivers/staging/speakup/spkguide.txt +++ b/Documentation/admin-guide/spkguide.txt @@ -1531,7 +1531,7 @@ The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See -http://www.gnu.org/copyleft/. +https://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this diff --git a/Documentation/devicetree/bindings/arm/arm,scmi.txt b/Documentation/devicetree/bindings/arm/arm,scmi.txt index 1f293ea24cd85793402cf0b2f72b21db4a460594..55deb68230ebb2af17fe5185b1d93cc9af16bfb5 100644 --- a/Documentation/devicetree/bindings/arm/arm,scmi.txt +++ b/Documentation/devicetree/bindings/arm/arm,scmi.txt @@ -102,7 +102,7 @@ Required sub-node properties: [0] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html [1] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Documentation/devicetree/bindings/power/power-domain.yaml -[3] Documentation/devicetree/bindings/thermal/thermal.txt +[3] Documentation/devicetree/bindings/thermal/thermal*.yaml [4] Documentation/devicetree/bindings/sram/sram.yaml [5] Documentation/devicetree/bindings/reset/reset.txt diff --git a/Documentation/devicetree/bindings/arm/arm,scpi.txt b/Documentation/devicetree/bindings/arm/arm,scpi.txt index dd04d9d9a1b8e0b06e43d16683feb440ebbff4d5..bcd6c3ec471e68b3892ebc4703d04ff2a870fc26 100644 --- a/Documentation/devicetree/bindings/arm/arm,scpi.txt +++ b/Documentation/devicetree/bindings/arm/arm,scpi.txt @@ -108,7 +108,7 @@ Required properties: [0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html [1] Documentation/devicetree/bindings/clock/clock-bindings.txt -[2] Documentation/devicetree/bindings/thermal/thermal.txt +[2] Documentation/devicetree/bindings/thermal/thermal*.yaml [3] Documentation/devicetree/bindings/sram/sram.yaml [4] Documentation/devicetree/bindings/power/power-domain.yaml diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt index 10b8459e49f8c22a4ff12c2485b00030dc72df64..6064d98b103144e07e8a4d02853bc3fba5d9b02d 100644 --- a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt @@ -176,7 +176,7 @@ Required properties: "fsl,imx8qxp-sc-thermal" followed by "fsl,imx-sc-thermal"; -- #thermal-sensor-cells: See Documentation/devicetree/bindings/thermal/thermal.txt +- #thermal-sensor-cells: See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. Example (imx8qxp): diff --git a/Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt index 098d932fc9630a49a5c83b16231def0fb521c87e..e31511255d8e3b6aeb3215f996a42c07445d7b02 100644 --- a/Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt +++ b/Documentation/devicetree/bindings/arm/marvell/ap80x-system-controller.txt @@ -111,7 +111,7 @@ Thermal: -------- For common binding part and usage, refer to -Documentation/devicetree/bindings/thermal/thermal.txt +Documentation/devicetree/bindings/thermal/thermal*.yaml The thermal IP can probe the temperature all around the processor. It may feature several channels, each of them wired to one sensor. diff --git a/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt index f982a8ed93968f18957b88d37d1cb287327532e2..a21f7709596c08cc0c40c3ddeb4525073b618dae 100644 --- a/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +++ b/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt @@ -203,7 +203,7 @@ It is possible to setup an overheat interrupt by giving at least one critical point to any subnode of the thermal-zone node. For common binding part and usage, refer to -Documentation/devicetree/bindings/thermal/thermal.txt +Documentation/devicetree/bindings/thermal/thermal*.yaml Required properties: - compatible: must be one of: diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt index 332aed8f4597a86240e498f03933497028a66029..56f4423743838fcba50511a12cedd7e301bb3194 100644 --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt @@ -18,7 +18,8 @@ Optional properties: in unit of nanoseconds. - voltage-tolerance: Specify the CPU voltage tolerance in percentage. - #cooling-cells: - Please refer to Documentation/devicetree/bindings/thermal/thermal.txt. + Please refer to + Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml. Examples: diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt index 0551c78619de807b99908d76eaf76cd6831ee3a5..ea4994b35207d9757997d80de6a05bd73a300828 100644 --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt @@ -21,8 +21,8 @@ Optional properties: flow is handled by hardware, hence no software "voltage tracking" is needed. - #cooling-cells: - Please refer to Documentation/devicetree/bindings/thermal/thermal.txt - for detail. + For details, please refer to + Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml Example 1 (MT7623 SoC): diff --git a/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt index daeca6ae6b769b1084058ce0922d92f6bbc40076..52a24b82fd8643fd8eb72cd37d6d2a9fca2aa8ce 100644 --- a/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt +++ b/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt @@ -5,7 +5,7 @@ Required properties: - clocks: Must contain an entry for the CPU clock. See ../clocks/clock-bindings.txt for details. - operating-points-v2: See ../bindings/opp/opp.txt for details. -- #cooling-cells: Should be 2. See ../thermal/thermal.txt for details. +- #cooling-cells: Should be 2. See ../thermal/thermal-cooling-devices.yaml for details. For each opp entry in 'operating-points-v2' table: - opp-supported-hw: Two bitfields indicating: diff --git a/Documentation/devicetree/bindings/hwmon/gpio-fan.txt b/Documentation/devicetree/bindings/hwmon/gpio-fan.txt index 2becdcfdc840c60e6d02ffe0f3893c00eb80321d..f4cfa350f6a1448f88805158b0e03512cf45a95e 100644 --- a/Documentation/devicetree/bindings/hwmon/gpio-fan.txt +++ b/Documentation/devicetree/bindings/hwmon/gpio-fan.txt @@ -12,7 +12,8 @@ Optional properties: - alarm-gpios: This pin going active indicates something is wrong with the fan, and a udev event will be fired. - #cooling-cells: If used as a cooling device, must be <2> - Also see: Documentation/devicetree/bindings/thermal/thermal.txt + Also see: + Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml min and max states are derived from the speed-map of the fan. Note: At least one the "gpios" or "alarm-gpios" properties must be set. diff --git a/Documentation/devicetree/bindings/hwmon/lm90.txt b/Documentation/devicetree/bindings/hwmon/lm90.txt index c76a7ac47c3426361d02ced15f3458c709bc4a3e..398dcb9657514e5729006e6bed45656ac7daaeac 100644 --- a/Documentation/devicetree/bindings/hwmon/lm90.txt +++ b/Documentation/devicetree/bindings/hwmon/lm90.txt @@ -34,8 +34,8 @@ Optional properties: LM90 "-ALERT" pin output. See interrupt-controller/interrupts.txt for the format. -- #thermal-sensor-cells: should be set to 1. See thermal/thermal.txt for - details. See for the +- #thermal-sensor-cells: should be set to 1. See thermal/thermal-sensor.yaml + for details. See for the definition of the local, remote and 2nd remote sensor index constants. diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml index d124eba1ce54fb3025547024c8266637d5ed035c..fd4eaa3d0ab4127a7396e6f955a287d3b9ab6ae1 100644 --- a/Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml +++ b/Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml @@ -12,8 +12,8 @@ maintainers: description: | Analog Devices ADXL345/ADXL375 3-Axis Digital Accelerometers that supports both I2C & SPI interfaces. - http://www.analog.com/en/products/mems/accelerometers/adxl345.html - http://www.analog.com/en/products/sensors-mems/accelerometers/adxl375.html + https://www.analog.com/en/products/mems/accelerometers/adxl345.html + https://www.analog.com/en/products/sensors-mems/accelerometers/adxl375.html properties: compatible: diff --git a/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.txt b/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.txt deleted file mode 100644 index b25bf3a77e0fd3b08b5a810d504d2fe762df0b8c..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.txt +++ /dev/null @@ -1,22 +0,0 @@ -Kionix KXSD9 Accelerometer device tree bindings - -Required properties: - - compatible: should be set to "kionix,kxsd9" - - reg: i2c slave address - -Optional properties: - - vdd-supply: The input supply for VDD - - iovdd-supply: The input supply for IOVDD - - interrupts: The movement detection interrupt - - mount-matrix: See mount-matrix.txt - -Example: - -kxsd9@18 { - compatible = "kionix,kxsd9"; - reg = <0x18>; - interrupt-parent = <&foo>; - interrupts = <57 IRQ_TYPE_EDGE_FALLING>; - iovdd-supply = <&bar>; - vdd-supply = <&baz>; -}; diff --git a/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.yaml b/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d61ab4fa3d71e5a9af5744ac70379175ae367358 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/accel/kionix,kxsd9.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Kionix KXSD9 Accelerometer + +maintainers: + - Jonathan Cameron + +description: | + 3 axis 12 bit accelerometer with +-8G range on all axes. Also has a + 12 bit auxiliary ADC channel. Interface is either SPI or I2C. + +properties: + compatible: + const: kionix,kxsd9 + + reg: + maxItems: 1 + + vdd-supply: true + iovdd-supply: true + + interrupts: + maxItems: 1 + + mount-matrix: + description: an optional 3x3 mounting rotation matrix. + +required: + - compatible + - reg + +examples: + - | + # include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + accel@18 { + compatible = "kionix,kxsd9"; + reg = <0x18>; + iovdd-supply = <&iovdd>; + vdd-supply = <&vdd>; + interrupts = <57 IRQ_TYPE_EDGE_FALLING>; + mount-matrix = "-0.984807753012208", "0", "-0.173648177666930", + "0", "-1", "0", + "-0.173648177666930", "0", "0.984807753012208"; + }; + }; + - | + # include + spi { + #address-cells = <1>; + #size-cells = <0>; + accel@0 { + compatible = "kionix,kxsd9"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt deleted file mode 100644 index cd9048cf9dcf9276d0f0d756a10467e27e16cdca..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt +++ /dev/null @@ -1,49 +0,0 @@ -* Ingenic JZ47xx ADC controller IIO bindings - -Required properties: - -- compatible: Should be one of: - * ingenic,jz4725b-adc - * ingenic,jz4740-adc - * ingenic,jz4770-adc -- reg: ADC controller registers location and length. -- clocks: phandle to the SoC's ADC clock. -- clock-names: Must be set to "adc". -- #io-channel-cells: Must be set to <1> to indicate channels are selected - by index. - -ADC clients must use the format described in iio-bindings.txt, giving -a phandle and IIO specifier pair ("io-channels") to the ADC controller. - -Example: - -#include - -adc: adc@10070000 { - compatible = "ingenic,jz4740-adc"; - #io-channel-cells = <1>; - - reg = <0x10070000 0x30>; - - clocks = <&cgu JZ4740_CLK_ADC>; - clock-names = "adc"; - - interrupt-parent = <&intc>; - interrupts = <18>; -}; - -adc-keys { - ... - compatible = "adc-keys"; - io-channels = <&adc INGENIC_ADC_AUX>; - io-channel-names = "buttons"; - ... -}; - -battery { - ... - compatible = "ingenic,jz4740-battery"; - io-channels = <&adc INGENIC_ADC_BATTERY>; - io-channel-names = "battery"; - ... -}; diff --git a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9f414dbdae863454d02361fb642ab8d70b141618 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2019-2020 Artur Rojek +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/iio/adc/ingenic,adc.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Ingenic JZ47xx ADC controller IIO bindings + +maintainers: + - Artur Rojek + +description: > + Industrial I/O subsystem bindings for ADC controller found in + Ingenic JZ47xx SoCs. + + ADC clients must use the format described in iio-bindings.txt, giving + a phandle and IIO specifier pair ("io-channels") to the ADC controller. + +properties: + compatible: + enum: + - ingenic,jz4725b-adc + - ingenic,jz4740-adc + - ingenic,jz4770-adc + + '#io-channel-cells': + const: 1 + description: + Must be set to <1> to indicate channels are selected by index. + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: adc + + interrupts: + maxItems: 1 + +required: + - compatible + - '#io-channel-cells' + - reg + - clocks + - clock-names + - interrupts + +additionalProperties: false + +examples: + - | + #include + #include + + adc@10070000 { + compatible = "ingenic,jz4740-adc"; + #io-channel-cells = <1>; + + reg = <0x10070000 0x30>; + + clocks = <&cgu JZ4740_CLK_ADC>; + clock-names = "adc"; + + interrupt-parent = <&intc>; + interrupts = <18>; + }; diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.txt b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.txt deleted file mode 100644 index c8787688122af921211a48d997c4935c2faabe5d..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.txt +++ /dev/null @@ -1,173 +0,0 @@ -Qualcomm's SPMI PMIC ADC - -- SPMI PMIC voltage ADC (VADC) provides interface to clients to read - voltage. The VADC is a 15-bit sigma-delta ADC. -- SPMI PMIC5 voltage ADC (ADC) provides interface to clients to read - voltage. The VADC is a 16-bit sigma-delta ADC. - -VADC node: - -- compatible: - Usage: required - Value type: - Definition: Should contain "qcom,spmi-vadc". - Should contain "qcom,spmi-adc5" for PMIC5 ADC driver. - Should contain "qcom,spmi-adc-rev2" for PMIC rev2 ADC driver. - Should contain "qcom,pms405-adc" for PMS405 PMIC - -- reg: - Usage: required - Value type: - Definition: VADC base address in the SPMI PMIC register map. - -- #address-cells: - Usage: required - Value type: - Definition: Must be one. Child node 'reg' property should define ADC - channel number. - -- #size-cells: - Usage: required - Value type: - Definition: Must be zero. - -- #io-channel-cells: - Usage: required - Value type: - Definition: Must be one. For details about IIO bindings see: - Documentation/devicetree/bindings/iio/iio-bindings.txt - -- interrupts: - Usage: optional - Value type: - Definition: End of conversion interrupt. - -Channel node properties: - -- reg: - Usage: required - Value type: - Definition: ADC channel number. - See include/dt-bindings/iio/qcom,spmi-vadc.h - -- label: - Usage: required for "qcom,spmi-adc5" and "qcom,spmi-adc-rev2" - Value type: - Definition: ADC input of the platform as seen in the schematics. - For thermistor inputs connected to generic AMUX or GPIO inputs - these can vary across platform for the same pins. Hence select - the platform schematics name for this channel. - -- qcom,decimation: - Usage: optional - Value type: - Definition: This parameter is used to decrease ADC sampling rate. - Quicker measurements can be made by reducing decimation ratio. - - For compatible property "qcom,spmi-vadc", valid values are - 512, 1024, 2048, 4096. If property is not found, default value - of 512 will be used. - - For compatible property "qcom,spmi-adc5", valid values are 250, 420 - and 840. If property is not found, default value of 840 is used. - - For compatible property "qcom,spmi-adc-rev2", valid values are 256, - 512 and 1024. If property is not present, default value is 1024. - -- qcom,pre-scaling: - Usage: optional - Value type: - Definition: Used for scaling the channel input signal before the signal is - fed to VADC. The configuration for this node is to know the - pre-determined ratio and use it for post scaling. Select one from - the following options. - <1 1>, <1 3>, <1 4>, <1 6>, <1 20>, <1 8>, <10 81>, <1 10> - If property is not found default value depending on chip will be used. - -- qcom,ratiometric: - Usage: optional - Value type: - Definition: Channel calibration type. - - For compatible property "qcom,spmi-vadc", if this property is - specified VADC will use the VDD reference (1.8V) and GND for - channel calibration. If property is not found, channel will be - calibrated with 0.625V and 1.25V reference channels, also - known as absolute calibration. - - For compatible property "qcom,spmi-adc5" and "qcom,spmi-adc-rev2", - if this property is specified VADC will use the VDD reference - (1.875V) and GND for channel calibration. If property is not found, - channel will be calibrated with 0V and 1.25V reference channels, - also known as absolute calibration. - -- qcom,hw-settle-time: - Usage: optional - Value type: - Definition: Time between AMUX getting configured and the ADC starting - conversion. The 'hw_settle_time' is an index used from valid values - and programmed in hardware to achieve the hardware settling delay. - - For compatible property "qcom,spmi-vadc" and "qcom,spmi-adc-rev2", - Delay = 100us * (hw_settle_time) for hw_settle_time < 11, - and 2ms * (hw_settle_time - 10) otherwise. - Valid values are: 0, 100, 200, 300, 400, 500, 600, 700, 800, - 900 us and 1, 2, 4, 6, 8, 10 ms. - If property is not found, channel will use 0us. - - For compatible property "qcom,spmi-adc5", delay = 15us for - value 0, 100us * (value) for values < 11, - and 2ms * (value - 10) otherwise. - Valid values are: 15, 100, 200, 300, 400, 500, 600, 700, 800, - 900 us and 1, 2, 4, 6, 8, 10 ms - Certain controller digital versions have valid values of - 15, 100, 200, 300, 400, 500, 600, 700, 1, 2, 4, 8, 16, 32, 64, 128 ms - If property is not found, channel will use 15us. - -- qcom,avg-samples: - Usage: optional - Value type: - Definition: Number of samples to be used for measurement. - Averaging provides the option to obtain a single measurement - from the ADC that is an average of multiple samples. The value - selected is 2^(value). - - For compatible property "qcom,spmi-vadc", valid values - are: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 - If property is not found, 1 sample will be used. - - For compatible property "qcom,spmi-adc5" and "qcom,spmi-adc-rev2", - valid values are: 1, 2, 4, 8, 16 - If property is not found, 1 sample will be used. - -NOTE: - -For compatible property "qcom,spmi-vadc" following channels, also known as -reference point channels, are used for result calibration and their channel -configuration nodes should be defined: -VADC_REF_625MV and/or VADC_SPARE1(based on PMIC version) VADC_REF_1250MV, -VADC_GND_REF and VADC_VDD_VADC. - -Example: - -#include -#include -/* ... */ - - /* VADC node */ - pmic_vadc: vadc@3100 { - compatible = "qcom,spmi-vadc"; - reg = <0x3100>; - interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>; - #address-cells = <1>; - #size-cells = <0>; - #io-channel-cells = <1>; - io-channel-ranges; - - /* Channel node */ - adc-chan@VADC_LR_MUX10_USB_ID { - reg = ; - qcom,decimation = <512>; - qcom,ratiometric; - qcom,hw-settle-time = <200>; - qcom,avg-samples = <1>; - qcom,pre-scaling = <1 3>; - }; - }; - - /* IIO client node */ - usb { - io-channels = <&pmic_vadc VADC_LR_MUX10_USB_ID>; - io-channel-names = "vadc"; - }; diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e6263b61794172b569034325b89e2dc2ad0e1389 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml @@ -0,0 +1,278 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/qcom,spmi-vadc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm's SPMI PMIC ADC + +maintainers: + - Andy Gross + - Bjorn Andersson + +description: | + SPMI PMIC voltage ADC (VADC) provides interface to clients to read + voltage. The VADC is a 15-bit sigma-delta ADC. + SPMI PMIC5/PMIC7 voltage ADC (ADC) provides interface to clients to read + voltage. The VADC is a 16-bit sigma-delta ADC. + +properties: + compatible: + oneOf: + - items: + - const: qcom,pms405-adc + - const: qcom,spmi-adc-rev2 + + - items: + - enum: + - qcom,spmi-vadc + - qcom,spmi-adc5 + - qcom,spmi-adc-rev2 + - qcom,spmi-adc7 + + reg: + description: VADC base address in the SPMI PMIC register map + maxItems: 1 + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + '#io-channel-cells': + const: 1 + + interrupts: + maxItems: 1 + description: + End of conversion interrupt. + +required: + - compatible + - reg + - '#address-cells' + - '#size-cells' + - '#io-channel-cells' + +patternProperties: + "^.*@[0-9a-f]+$": + type: object + description: | + Represents the external channels which are connected to the ADC. + For compatible property "qcom,spmi-vadc" following channels, also known as + reference point channels, are used for result calibration and their channel + configuration nodes should be defined: + VADC_REF_625MV and/or VADC_SPARE1(based on PMIC version) VADC_REF_1250MV, + VADC_GND_REF and VADC_VDD_VADC. + + properties: + reg: + description: | + ADC channel number. + See include/dt-bindings/iio/qcom,spmi-vadc.h + For PMIC7 ADC, the channel numbers are specified separately per PMIC + in the PMIC-specific files in include/dt-bindings/iio/. + + label: + $ref: /schemas/types.yaml#/definitions/string + description: | + ADC input of the platform as seen in the schematics. + For thermistor inputs connected to generic AMUX or GPIO inputs + these can vary across platform for the same pins. Hence select + the platform schematics name for this channel. + + qcom,decimation: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + This parameter is used to decrease ADC sampling rate. + Quicker measurements can be made by reducing decimation ratio. + + qcom,pre-scaling: + description: | + Used for scaling the channel input signal before the signal is + fed to VADC. The configuration for this node is to know the + pre-determined ratio and use it for post scaling. It is a pair of + integers, denoting the numerator and denominator of the fraction by which + input signal is multiplied. For example, <1 3> indicates the signal is scaled + down to 1/3 of its value before ADC measurement. + If property is not found default value depending on chip will be used. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-array + oneOf: + - items: + - const: 1 + - enum: [ 1, 3, 4, 6, 20, 8, 10 ] + + - items: + - const: 10 + - const: 81 + + qcom,ratiometric: + description: | + Channel calibration type. + - For compatible property "qcom,spmi-vadc", if this property is + specified VADC will use the VDD reference (1.8V) and GND for + channel calibration. If property is not found, channel will be + calibrated with 0.625V and 1.25V reference channels, also + known as absolute calibration. + - For compatible property "qcom,spmi-adc5", "qcom,spmi-adc7" and + "qcom,spmi-adc-rev2", if this property is specified VADC will use + the VDD reference (1.875V) and GND for channel calibration. If + property is not found, channel will be calibrated with 0V and 1.25V + reference channels, also known as absolute calibration. + type: boolean + + qcom,hw-settle-time: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Time between AMUX getting configured and the ADC starting + conversion. The 'hw_settle_time' is an index used from valid values + and programmed in hardware to achieve the hardware settling delay. + + qcom,avg-samples: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Number of samples to be used for measurement. + Averaging provides the option to obtain a single measurement + from the ADC that is an average of multiple samples. The value + selected is 2^(value). + + required: + - reg + +allOf: + - if: + properties: + compatible: + contains: + const: qcom,spmi-vadc + + then: + patternProperties: + "^.*@[0-9a-f]+$": + properties: + qcom,decimation: + enum: [ 512, 1024, 2048, 4096 ] + default: 512 + + qcom,hw-settle-time: + enum: [ 0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1, 2, + 4, 6, 8, 10 ] + default: 0 + + qcom,avg-samples: + enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 ] + default: 1 + + - if: + properties: + compatible: + contains: + const: qcom,spmi-adc-rev2 + + then: + patternProperties: + "^.*@[0-9a-f]+$": + properties: + qcom,decimation: + enum: [ 256, 512, 1024 ] + default: 1024 + + qcom,hw-settle-time: + enum: [ 0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1, 2, + 4, 6, 8, 10 ] + default: 0 + + qcom,avg-samples: + enum: [ 1, 2, 4, 8, 16 ] + default: 1 + + - if: + properties: + compatible: + contains: + const: qcom,spmi-adc5 + + then: + patternProperties: + "^.*@[0-9a-f]+$": + properties: + qcom,decimation: + enum: [ 250, 420, 840 ] + default: 840 + + qcom,hw-settle-time: + enum: [ 15, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1, 2, + 4, 6, 8, 10, 16, 32, 64, 128 ] + default: 15 + + qcom,avg-samples: + enum: [ 1, 2, 4, 8, 16 ] + default: 1 + + - if: + properties: + compatible: + contains: + const: qcom,spmi-adc7 + + then: + patternProperties: + "^.*@[0-9a-f]+$": + properties: + qcom,decimation: + enum: [ 85, 340, 1360 ] + default: 1360 + + qcom,hw-settle-time: + enum: [ 15, 100, 200, 300, 400, 500, 600, 700, 1000, 2000, 4000, + 8000, 16000, 32000, 64000, 128000 ] + default: 15 + + qcom,avg-samples: + enum: [ 1, 2, 4, 8, 16 ] + default: 1 + +examples: + - | + spmi_bus { + #address-cells = <1>; + #size-cells = <0>; + /* VADC node */ + pmic_vadc: adc@3100 { + compatible = "qcom,spmi-vadc"; + reg = <0x3100>; + interrupts = <0x0 0x31 0x0 0x1>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + io-channel-ranges; + + /* Channel node */ + adc-chan@39 { + reg = <0x39>; + qcom,decimation = <512>; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,avg-samples = <1>; + qcom,pre-scaling = <1 3>; + }; + + adc-chan@9 { + reg = <0x9>; + }; + + adc-chan@a { + reg = <0xa>; + }; + + adc-chan@e { + reg = <0xe>; + }; + + adc-chan@f { + reg = <0xf>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/adc/ti,ads8688.yaml b/Documentation/devicetree/bindings/iio/adc/ti,ads8688.yaml new file mode 100644 index 0000000000000000000000000000000000000000..97fe6cbb2efab66b5b0180820207ca8624774a4e --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti,ads8688.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/ti,ads8688.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments' ADS8684 and ADS8688 ADC chip + +maintainers: + - Sean Nyekjaer + +description: | + SPI 16bit ADCs with 4/8 channels. + +properties: + compatible: + enum: + - ti,ads8684 + - ti,ads8688 + + reg: + maxItems: 1 + + vref-supply: + description: Optional external reference. If not supplied, assume + REFSEL input tied low to enable the internal reference. + +required: + - compatible + - reg + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "ti,ads8688"; + reg = <0>; + vref-supply = <&vdd_supply>; + spi-max-frequency = <1000000>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/adc/ti-ads8688.txt b/Documentation/devicetree/bindings/iio/adc/ti-ads8688.txt deleted file mode 100644 index a02337d7efa447f46265dbd4a460e8c760ea45f5..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/iio/adc/ti-ads8688.txt +++ /dev/null @@ -1,20 +0,0 @@ -* Texas Instruments' ADS8684 and ADS8688 ADC chip - -Required properties: - - compatible: Should be "ti,ads8684" or "ti,ads8688" - - reg: spi chip select number for the device - -Recommended properties: - - spi-max-frequency: Definition as per - Documentation/devicetree/bindings/spi/spi-bus.txt - -Optional properties: - - vref-supply: The regulator supply for ADC reference voltage - -Example: -adc@0 { - compatible = "ti,ads8688"; - reg = <0>; - vref-supply = <&vdd_supply>; - spi-max-frequency = <1000000>; -}; diff --git a/Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml b/Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml new file mode 100644 index 0000000000000000000000000000000000000000..40d87346ff4cffab5b51b24b4d2d4c8e344acafa --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/chemical/sensirion,scd30.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sensirion SCD30 carbon dioxide sensor + +maintainers: + - Tomasz Duszynski + +description: | + Air quality sensor capable of measuring co2 concentration, temperature + and relative humidity. + +properties: + compatible: + enum: + - sensirion,scd30 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + vdd-supply: true + + sensirion,sel-gpios: + description: GPIO connected to the SEL line + maxItems: 1 + + sensirion,pwm-gpios: + description: GPIO connected to the PWM line + maxItems: 1 + +required: + - compatible + +additionalProperties: false + +examples: + - | + # include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + co2-sensor@61 { + compatible = "sensirion,scd30"; + reg = <0x61>; + vdd-supply = <&vdd>; + interrupt-parent = <&gpio0>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + - | + # include + serial { + co2-sensor { + compatible = "sensirion,scd30"; + vdd-supply = <&vdd>; + interrupt-parent = <&gpio0>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/iio/dac/ti,dac7612.txt b/Documentation/devicetree/bindings/iio/dac/ti,dac7612.txt index 639c94ed83e994460935b533057cedd13a810b65..17af395b99d9fef436c793690fca382c48febce5 100644 --- a/Documentation/devicetree/bindings/iio/dac/ti,dac7612.txt +++ b/Documentation/devicetree/bindings/iio/dac/ti,dac7612.txt @@ -6,7 +6,7 @@ Is is programmable through an SPI interface. The internal DACs are loaded when the LOADDACS pin is pulled down. -http://www.ti.com/lit/ds/sbas106/sbas106.pdf +https://www.ti.com/lit/ds/sbas106/sbas106.pdf Required Properties: - compatible: Should be one of: diff --git a/Documentation/devicetree/bindings/iio/iio-bindings.txt b/Documentation/devicetree/bindings/iio/iio-bindings.txt index af33267727f4e121839c94e244b9ef26f19310a2..aa63cac7323ecca359bc3b5e5dafa5f15fc79334 100644 --- a/Documentation/devicetree/bindings/iio/iio-bindings.txt +++ b/Documentation/devicetree/bindings/iio/iio-bindings.txt @@ -9,7 +9,7 @@ specifier is an array of one or more cells identifying the IIO output on a device. The length of an IIO specifier is defined by the value of a #io-channel-cells property in the IIO provider node. -[1] http://marc.info/?l=linux-iio&m=135902119507483&w=2 +[1] https://marc.info/?l=linux-iio&m=135902119507483&w=2 ==IIO providers== diff --git a/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml b/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml index 0d0ef84e22b997ba46f2bfb450919088c4389bb1..33d8e9fd14b7553c30a53cd853978125638fd985 100644 --- a/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml +++ b/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml @@ -37,6 +37,15 @@ properties: set if the specified interrupt pin should be configured as open drain. If not set, defaults to push-pull. + vdd-supply: + description: provide VDD power to the sensor. + + vddio-supply: + description: provide VDD IO power to the sensor. + + mount-matrix: + description: an optional 3x3 mounting rotation matrix + required: - compatible - reg @@ -52,9 +61,14 @@ examples: bmi160@68 { compatible = "bosch,bmi160"; reg = <0x68>; + vdd-supply = <&pm8916_l17>; + vddio-supply = <&pm8916_l6>; interrupt-parent = <&gpio4>; interrupts = <12 IRQ_TYPE_EDGE_RISING>; interrupt-names = "INT1"; + mount-matrix = "0", "1", "0", + "-1", "0", "0", + "0", "0", "1"; }; }; - | diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml new file mode 100644 index 0000000000000000000000000000000000000000..abd8d25e1136a44d35beefbadeca29b823651062 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml @@ -0,0 +1,90 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/imu/invensense,icm42600.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: InvenSense ICM-426xx Inertial Measurement Unit + +maintainers: + - Jean-Baptiste Maneyrol + +description: | + 6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis + accelerometer. + + It has a configurable host interface that supports I3C, I2C and SPI serial + communication, features a 2kB FIFO and 2 programmable interrupts with + ultra-low-power wake-on-motion support to minimize system power consumption. + + Other industry-leading features include InvenSense on-chip APEX Motion + Processing engine for gesture recognition, activity classification, and + pedometer, along with programmable digital filters, and an embedded + temperature sensor. + + https://invensense.tdk.com/wp-content/uploads/2020/03/DS-000292-ICM-42605-v1.4.pdf + +properties: + compatible: + enum: + - invensense,icm42600 + - invensense,icm42602 + - invensense,icm42605 + - invensense,icm42622 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + drive-open-drain: + type: boolean + + vdd-supply: + description: Regulator that provides power to the sensor + + vddio-supply: + description: Regulator that provides power to the bus + +required: + - compatible + - reg + - interrupts + +examples: + - | + #include + #include + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + + icm42605@68 { + compatible = "invensense,icm42605"; + reg = <0x68>; + interrupt-parent = <&gpio2>; + interrupts = <7 IRQ_TYPE_EDGE_FALLING>; + vdd-supply = <&vdd>; + vddio-supply = <&vddio>; + }; + }; + - | + #include + #include + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + icm42602@0 { + compatible = "invensense,icm42602"; + reg = <0>; + spi-max-frequency = <24000000>; + spi-cpha; + spi-cpol; + interrupt-parent = <&gpio1>; + interrupts = <2 IRQ_TYPE_EDGE_FALLING>; + vdd-supply = <&vdd>; + vddio-supply = <&vddio>; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/light/apds9300.txt b/Documentation/devicetree/bindings/iio/light/apds9300.txt index aa199e09a493f179ecee2cf55a45054203c5a9a7..3aa6db3ee99d272d536a73d5279bbbd5ef3468e2 100644 --- a/Documentation/devicetree/bindings/iio/light/apds9300.txt +++ b/Documentation/devicetree/bindings/iio/light/apds9300.txt @@ -1,6 +1,6 @@ * Avago APDS9300 ambient light sensor -http://www.avagotech.com/docs/AV02-1077EN +https://www.avagotech.com/docs/AV02-1077EN Required properties: diff --git a/Documentation/devicetree/bindings/iio/light/apds9960.txt b/Documentation/devicetree/bindings/iio/light/apds9960.txt index 3af325ad194b9137da740ace14d9fc9188ddc4fa..c53ddb81c4aa64b9eb392ae819ac341fb6f34bea 100644 --- a/Documentation/devicetree/bindings/iio/light/apds9960.txt +++ b/Documentation/devicetree/bindings/iio/light/apds9960.txt @@ -1,6 +1,6 @@ * Avago APDS9960 gesture/RGB/ALS/proximity sensor -http://www.avagotech.com/docs/AV02-4191EN +https://www.avagotech.com/docs/AV02-4191EN Required properties: diff --git a/Documentation/devicetree/bindings/iio/light/opt3001.txt b/Documentation/devicetree/bindings/iio/light/opt3001.txt index 47b13eb8f4ecb02835295522860ed0643f707a51..9e6f2998e75154a58020840a4ae34a56e660f99a 100644 --- a/Documentation/devicetree/bindings/iio/light/opt3001.txt +++ b/Documentation/devicetree/bindings/iio/light/opt3001.txt @@ -6,7 +6,7 @@ the optional generation of IIO events on rising/falling light threshold changes requires the use of interrupts. Without interrupts, only the simple reading of the current light value is supported through the IIO API. -http://www.ti.com/product/opt3001 +https://www.ti.com/product/opt3001 Required properties: - compatible: should be "ti,opt3001" diff --git a/Documentation/devicetree/bindings/iio/light/vl6180.txt b/Documentation/devicetree/bindings/iio/light/vl6180.txt index 2c52952715a0e279596067b14554c0462e3a2e9b..fb9137d85df972a67eecf1ac98fbe867b924a74b 100644 --- a/Documentation/devicetree/bindings/iio/light/vl6180.txt +++ b/Documentation/devicetree/bindings/iio/light/vl6180.txt @@ -1,6 +1,6 @@ STMicro VL6180 - ALS, range and proximity sensor -Link to datasheet: http://www.st.com/resource/en/datasheet/vl6180x.pdf +Link to datasheet: https://www.st.com/resource/en/datasheet/vl6180x.pdf Required properties: diff --git a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt b/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt deleted file mode 100644 index aa67ceb0d4e046cc0f228baa10f12de33f2f6484..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt +++ /dev/null @@ -1,30 +0,0 @@ -* AsahiKASEI AK8975 magnetometer sensor - -Required properties: - - - compatible : should be "asahi-kasei,ak8975" - - reg : the I2C address of the magnetometer - -Optional properties: - - - gpios : should be device tree identifier of the magnetometer DRDY pin - - vdd-supply: an optional regulator that needs to be on to provide VDD - - mount-matrix: an optional 3x3 mounting rotation matrix - -Example: - -ak8975@c { - compatible = "asahi-kasei,ak8975"; - reg = <0x0c>; - gpios = <&gpj0 7 0>; - vdd-supply = <&ldo_3v3_gnss>; - mount-matrix = "-0.984807753012208", /* x0 */ - "0", /* y0 */ - "-0.173648177666930", /* z0 */ - "0", /* x1 */ - "-1", /* y1 */ - "0", /* z1 */ - "-0.173648177666930", /* x2 */ - "0", /* y2 */ - "0.984807753012208"; /* z2 */ -}; diff --git a/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml b/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f4393bfbf355360534e828f91e7d1b8a51d93399 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/magnetometer/asahi-kasei,ak8975.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AsahiKASEI AK8975 magnetometer sensor + +maintainers: + - Jonathan Albrieux + +properties: + compatible: + oneOf: + - enum: + - asahi-kasei,ak8975 + - asahi-kasei,ak8963 + - asahi-kasei,ak09911 + - asahi-kasei,ak09912 + - enum: + - ak8975 + - ak8963 + - ak09911 + - ak09912 + deprecated: true + + reg: + maxItems: 1 + + gpios: + maxItems: 1 + description: | + AK8975 has a "Data ready" pin (DRDY) which informs that data + is ready to be read and is possible to listen on it. If used, + this should be active high. Prefer interrupt over this. + + interrupts: + maxItems: 1 + description: interrupt for DRDY pin. Triggered on rising edge. + + vdd-supply: + description: | + an optional regulator that needs to be on to provide VDD power to + the sensor. + + mount-matrix: + description: an optional 3x3 mounting rotation matrix. + + reset-gpios: + description: | + an optional pin needed for AK09911 to set the reset state. This should + be usually active low + +required: + - compatible + - reg + +examples: + - | + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + magnetometer@c { + compatible = "asahi-kasei,ak8975"; + reg = <0x0c>; + interrupt-parent = <&gpio6>; + interrupts = <15 IRQ_TYPE_EDGE_RISING>; + vdd-supply = <&ldo_3v3_gnss>; + reset-gpios = <&msmgpio 111 GPIO_ACTIVE_LOW>; + mount-matrix = "-0.984807753012208", /* x0 */ + "0", /* y0 */ + "-0.173648177666930", /* z0 */ + "0", /* x1 */ + "-1", /* y1 */ + "0", /* z1 */ + "-0.173648177666930", /* x2 */ + "0", /* y2 */ + "0.984807753012208"; /* z2 */ + }; + }; diff --git a/Documentation/devicetree/bindings/iio/magnetometer/bmc150_magn.txt b/Documentation/devicetree/bindings/iio/magnetometer/bmc150_magn.txt index fd5fca90fb39614c97861e61f99429b8935cda31..22912e43b60c0f6a26b88a00c7eca37a9d8993a8 100644 --- a/Documentation/devicetree/bindings/iio/magnetometer/bmc150_magn.txt +++ b/Documentation/devicetree/bindings/iio/magnetometer/bmc150_magn.txt @@ -4,7 +4,11 @@ http://ae-bst.resource.bosch.com/media/products/dokumente/bmc150/BST-BMC150-DS00 Required properties: - - compatible : should be "bosch,bmc150_magn" + - compatible : should be one of: + "bosch,bmc150_magn" + "bosch,bmc156_magn" + "bosch,bmm150" + "bosch,bmm150_magn" (DEPRECATED, use bosch,bmm150) - reg : the I2C address of the magnetometer Optional properties: diff --git a/Documentation/devicetree/bindings/iio/potentiometer/mcp41010.txt b/Documentation/devicetree/bindings/iio/potentiometer/mcp41010.txt index 566711b9950cf8c0d55d74569ed719c8a673e0f4..4f245e8469fdb00f21accbde3ea7142c76b9354e 100644 --- a/Documentation/devicetree/bindings/iio/potentiometer/mcp41010.txt +++ b/Documentation/devicetree/bindings/iio/potentiometer/mcp41010.txt @@ -1,7 +1,7 @@ * Microchip MCP41010/41050/41100/42010/42050/42100 Digital Potentiometer Datasheet publicly available at: -http://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf +https://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf The node for this driver must be a child node of a SPI controller, hence all mandatory properties described in diff --git a/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt b/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt index e6d0c2eb345c4cbf4fca7022549325ffa0a727d5..f3ab02b0dd415f1ec8e472bfdca6eb1770e1717a 100644 --- a/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt +++ b/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt @@ -1,7 +1,7 @@ * Texas Instruments LMP91000 series of potentiostats -LMP91000: http://www.ti.com/lit/ds/symlink/lmp91000.pdf -LMP91002: http://www.ti.com/lit/ds/symlink/lmp91002.pdf +LMP91000: https://www.ti.com/lit/ds/symlink/lmp91000.pdf +LMP91002: https://www.ti.com/lit/ds/symlink/lmp91002.pdf Required properties: diff --git a/Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml b/Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml index 64c18f1693f008ce21e374501e431efc5846c358..be2be4b556dbbd3b520d95374b0875edc57160e7 100644 --- a/Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml +++ b/Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml @@ -13,7 +13,7 @@ description: | Bindings for the All Sensors DLH series pressure sensors. Specifications about the sensors can be found at: - http://www.allsensors.com/cad/DS-0355_Rev_B.PDF + https://www.allsensors.com/cad/DS-0355_Rev_B.PDF properties: compatible: diff --git a/Documentation/devicetree/bindings/iio/proximity/devantech-srf04.yaml b/Documentation/devicetree/bindings/iio/proximity/devantech-srf04.yaml index f86f8b23ef18fd3d9daaeef35096f2c09074cfe0..ce795279839ef951ae70dc69a3ae7a5ef3f6031e 100644 --- a/Documentation/devicetree/bindings/iio/proximity/devantech-srf04.yaml +++ b/Documentation/devicetree/bindings/iio/proximity/devantech-srf04.yaml @@ -17,9 +17,9 @@ description: | until it is received once again Specifications about the devices can be found at: - http://www.robot-electronics.co.uk/htm/srf04tech.htm + https://www.robot-electronics.co.uk/htm/srf04tech.htm - http://www.maxbotix.com/documents/LV-MaxSonar-EZ_Datasheet.pdf + https://www.maxbotix.com/documents/LV-MaxSonar-EZ_Datasheet.pdf properties: compatible: diff --git a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml index 75b8521eb7cb5e2580ad585c52aec9274ad6d373..06d5f251ec8805b0198226ed200ee37d5df0eb02 100644 --- a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml +++ b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml @@ -35,9 +35,11 @@ properties: description: label associated with this uart st,hw-flow-ctrl: - description: enable hardware flow control + description: enable hardware flow control (deprecated) $ref: /schemas/types.yaml#/definitions/flag + uart-has-rtscts: true + dmas: minItems: 1 maxItems: 2 diff --git a/Documentation/devicetree/bindings/soc/microchip/atmel,at91rm9200-tcb.yaml b/Documentation/devicetree/bindings/soc/microchip/atmel,at91rm9200-tcb.yaml index d226fd7d52588e8d68e6133c49b1bdbde1c225e5..3cd0b70cd6cff87f5d2e6f1d9afe655b81ef8eb6 100644 --- a/Documentation/devicetree/bindings/soc/microchip/atmel,at91rm9200-tcb.yaml +++ b/Documentation/devicetree/bindings/soc/microchip/atmel,at91rm9200-tcb.yaml @@ -52,14 +52,20 @@ properties: patternProperties: "^timer@[0-2]$": - description: The timer block channels that are used as timers. + description: The timer block channels that are used as timers or counters. type: object properties: compatible: - const: atmel,tcb-timer + items: + - enum: + - atmel,tcb-timer + - microchip,tcb-capture reg: description: - List of channels to use for this particular timer. + List of channels to use for this particular timer. In Microchip TCB capture + mode channels are registered as a counter devices, for the qdec mode TCB0's + channel <0> and <1> are required. + minItems: 1 maxItems: 3 @@ -153,3 +159,23 @@ examples: reg = <1>; }; }; + /* TCB0 Capture with QDEC: */ + timer@f800c000 { + compatible = "atmel,at91rm9200-tcb", "simple-mfd", "syscon"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xfff7c000 0x100>; + interrupts = <18 4>; + clocks = <&tcb0_clk>, <&clk32k>; + clock-names = "t0_clk", "slow_clk"; + + timer@0 { + compatible = "microchip,tcb-capture"; + reg = <0>, <1>; + }; + + timer@2 { + compatible = "atmel,tcb-timer"; + reg = <2>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/adi,adau1977.txt b/Documentation/devicetree/bindings/sound/adi,adau1977.txt index 9225472c80b4c4f2c0b049c896b7f34d240cbfa4..37f8aad012037db098738115697f613afe940c99 100644 --- a/Documentation/devicetree/bindings/sound/adi,adau1977.txt +++ b/Documentation/devicetree/bindings/sound/adi,adau1977.txt @@ -1,9 +1,9 @@ Analog Devices ADAU1977/ADAU1978/ADAU1979 Datasheets: -http://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1977.pdf -http://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1978.pdf -http://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1979.pdf +https://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1977.pdf +https://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1978.pdf +https://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1979.pdf This driver supports both the I2C and SPI bus. diff --git a/Documentation/devicetree/bindings/sound/ak4613.txt b/Documentation/devicetree/bindings/sound/ak4613.txt deleted file mode 100644 index 49a2e74fd9cb1489b145b1132f2f892209c8b448..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/ak4613.txt +++ /dev/null @@ -1,27 +0,0 @@ -AK4613 I2C transmitter - -This device supports I2C mode only. - -Required properties: - -- compatible : "asahi-kasei,ak4613" -- reg : The chip select number on the I2C bus - -Optional properties: -- asahi-kasei,in1-single-end : Boolean. Indicate input / output pins are single-ended. -- asahi-kasei,in2-single-end rather than differential. -- asahi-kasei,out1-single-end -- asahi-kasei,out2-single-end -- asahi-kasei,out3-single-end -- asahi-kasei,out4-single-end -- asahi-kasei,out5-single-end -- asahi-kasei,out6-single-end - -Example: - -&i2c { - ak4613: ak4613@10 { - compatible = "asahi-kasei,ak4613"; - reg = <0x10>; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/ak4613.yaml b/Documentation/devicetree/bindings/sound/ak4613.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ef4055ef0ccdc6e1dc29407fe560d1626e738c37 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ak4613.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ak4613.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AK4613 I2C transmitter Device Tree Bindings + +maintainers: + - Kuninori Morimoto + +properties: + compatible: + const: asahi-kasei,ak4613 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +patternProperties: + "^asahi-kasei,in[1-2]-single-end$": + description: Input Pin 1 - 2. + $ref: /schemas/types.yaml#/definitions/flag + + "^asahi-kasei,out[1-6]-single-end$": + description: Output Pin 1 - 6. + $ref: /schemas/types.yaml#/definitions/flag + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + ak4613: codec@10 { + compatible = "asahi-kasei,ak4613"; + reg = <0x10>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/ak4642.txt b/Documentation/devicetree/bindings/sound/ak4642.txt deleted file mode 100644 index 58e48ee9717547f2766a2c0a89fec19536431634..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/ak4642.txt +++ /dev/null @@ -1,37 +0,0 @@ -AK4642 I2C transmitter - -This device supports I2C mode only. - -Required properties: - - - compatible : "asahi-kasei,ak4642" or "asahi-kasei,ak4643" or "asahi-kasei,ak4648" - - reg : The chip select number on the I2C bus - -Optional properties: - - - #clock-cells : common clock binding; shall be set to 0 - - clocks : common clock binding; MCKI clock - - clock-frequency : common clock binding; frequency of MCKO - - clock-output-names : common clock binding; MCKO clock name - -Example 1: - -&i2c { - ak4648: ak4648@12 { - compatible = "asahi-kasei,ak4642"; - reg = <0x12>; - }; -}; - -Example 2: - -&i2c { - ak4643: codec@12 { - compatible = "asahi-kasei,ak4643"; - reg = <0x12>; - #clock-cells = <0>; - clocks = <&audio_clock>; - clock-frequency = <12288000>; - clock-output-names = "ak4643_mcko"; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/ak4642.yaml b/Documentation/devicetree/bindings/sound/ak4642.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6cd213be2266f98ce724d15c24eaa7f24dc85ae0 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ak4642.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ak4642.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AK4642 I2C transmitter Device Tree Bindings + +maintainers: + - Kuninori Morimoto + +properties: + compatible: + enum: + - asahi-kasei,ak4642 + - asahi-kasei,ak4643 + - asahi-kasei,ak4648 + + reg: + maxItems: 1 + + "#clock-cells": + const: 0 + "#sound-dai-cells": + const: 0 + + clocks: + maxItems: 1 + + clock-frequency: + description: common clock binding; frequency of MCKO + $ref: /schemas/types.yaml#/definitions/uint32 + + clock-output-names: + description: common clock name + $ref: /schemas/types.yaml#/definitions/string + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + ak4643: codec@12 { + compatible = "asahi-kasei,ak4643"; + #sound-dai-cells = <0>; + reg = <0x12>; + #clock-cells = <0>; + clocks = <&audio_clock>; + clock-frequency = <12288000>; + clock-output-names = "ak4643_mcko"; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/everest,es8316.txt b/Documentation/devicetree/bindings/sound/everest,es8316.txt deleted file mode 100644 index 1bf03c5f2af4d06ea8a202db3416a55300669c90..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/everest,es8316.txt +++ /dev/null @@ -1,23 +0,0 @@ -Everest ES8316 audio CODEC - -This device supports both I2C and SPI. - -Required properties: - - - compatible : should be "everest,es8316" - - reg : the I2C address of the device for I2C - -Optional properties: - - - clocks : a list of phandle, should contain entries for clock-names - - clock-names : should include as follows: - "mclk" : master clock (MCLK) of the device - -Example: - -es8316: codec@11 { - compatible = "everest,es8316"; - reg = <0x11>; - clocks = <&clks 10>; - clock-names = "mclk"; -}; diff --git a/Documentation/devicetree/bindings/sound/everest,es8316.yaml b/Documentation/devicetree/bindings/sound/everest,es8316.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3b752bba748b57f4fda8db8e72ab21d501dd4997 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/everest,es8316.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/everest,es8316.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Everest ES8316 audio CODEC + +maintainers: + - Daniel Drake + - Katsuhiro Suzuki + +properties: + compatible: + const: everest,es8316 + + reg: + maxItems: 1 + + clocks: + items: + - description: clock for master clock (MCLK) + + clock-names: + items: + - const: mclk + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + - "#sound-dai-cells" + +additionalProperties: false + +examples: + - | + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + es8316: codec@11 { + compatible = "everest,es8316"; + reg = <0x11>; + clocks = <&clks 10>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt index 8b324f82a7828013c06a1688c80c7316558c47ce..e1365b0ee1e9086eef71730ab59001d4fb5a4bc8 100644 --- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt @@ -6,7 +6,11 @@ a fibre cable. Required properties: - - compatible : Compatible list, must contain "fsl,imx35-spdif". + - compatible : Compatible list, should contain one of the following + compatibles: + "fsl,imx35-spdif", + "fsl,vf610-spdif", + "fsl,imx6sx-spdif", - reg : Offset and length of the register set for the device. diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt index c60a5732d29c15edfcd7e574f292eba802397b41..63ebf52b43e8b51a26ff64fa162985a839fa7e91 100644 --- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt +++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt @@ -34,6 +34,10 @@ The compatible list for this generic sound card currently: "fsl,imx-audio-wm8960" + "fsl,imx-audio-mqs" + + "fsl,imx-audio-wm8524" + Required properties: - compatible : Contains one of entries in the compatible list. @@ -44,6 +48,11 @@ Required properties: - audio-codec : The phandle of an audio codec +Optional properties: + + - audio-asrc : The phandle of ASRC. It can be absent if there's no + need to add ASRC support via DPCM. + - audio-routing : A list of the connections between audio components. Each entry is a pair of strings, the first being the connection's sink, the second being the connection's @@ -60,10 +69,13 @@ Required properties: coexisting in order to support the old bindings of wm8962 and sgtl5000. -Optional properties: - - - audio-asrc : The phandle of ASRC. It can be absent if there's no - need to add ASRC support via DPCM. + - hp-det-gpio : The GPIO that detect headphones are plugged in + - mic-det-gpio : The GPIO that detect microphones are plugged in + - bitclock-master : Indicates dai-link bit clock master; for details see simple-card.yaml. + - frame-master : Indicates dai-link frame master; for details see simple-card.yaml. + - dai-format : audio format, for details see simple-card.yaml. + - frame-inversion : dai-link uses frame clock inversion, for details see simple-card.yaml. + - bitclock-inversion : dai-link uses bit clock inversion, for details see simple-card.yaml. Optional unless SSI is selected as a CPU DAI: diff --git a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2e0bbc1c868abf01aaa5b2da7f7d5c166e607eca --- /dev/null +++ b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2020 Intel Corporation +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/intel,keembay-i2s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Intel KeemBay I2S Device Tree Bindings + +maintainers: + - Sia, Jee Heng + +description: | + Intel KeemBay I2S + +properties: + compatible: + enum: + - intel,keembay-i2s + + "#sound-dai-cells": + const: 0 + + reg: + items: + - description: I2S registers + - description: I2S gen configuration + + reg-names: + items: + - const: i2s-regs + - const: i2s_gen_cfg + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: Module Clock + + clock-names: + items: + - const: osc + - const: apb_clk + +required: + - compatible + - "#sound-dai-cells" + - reg + - clocks + - clock-names + - interrupts + +examples: + - | + #include + #include + #define KEEM_BAY_PSS_AUX_I2S3 + #define KEEM_BAY_PSS_I2S3 + i2s3: i2s@20140000 { + compatible = "intel,keembay-i2s"; + #sound-dai-cells = <0>; + reg = <0x20140000 0x200>, /* I2S registers */ + <0x202a00a4 0x4>; /* I2S gen configuration */ + reg-names = "i2s-regs", "i2s_gen_cfg"; + interrupts = ; + clock-names = "osc", "apb_clk"; + clocks = <&scmi_clk KEEM_BAY_PSS_AUX_I2S3>, <&scmi_clk KEEM_BAY_PSS_I2S3>; + }; diff --git a/Documentation/devicetree/bindings/sound/max98357a.txt b/Documentation/devicetree/bindings/sound/max98357a.txt index 4bce14ce806f3d35fa57d81b8f73454e67fabd11..75db84d06240e3c188fd318bb9099484278ffa0d 100644 --- a/Documentation/devicetree/bindings/sound/max98357a.txt +++ b/Documentation/devicetree/bindings/sound/max98357a.txt @@ -1,9 +1,10 @@ -Maxim MAX98357A audio DAC +Maxim MAX98357A/MAX98360A audio DAC -This node models the Maxim MAX98357A DAC. +This node models the Maxim MAX98357A/MAX98360A DAC. Required properties: -- compatible : "maxim,max98357a" +- compatible : "maxim,max98357a" for MAX98357A. + "maxim,max98360a" for MAX98360A. Optional properties: - sdmode-gpios : GPIO specifier for the chip's SD_MODE pin. @@ -20,3 +21,8 @@ max98357a { compatible = "maxim,max98357a"; sdmode-gpios = <&qcom_pinmux 25 0>; }; + +max98360a { + compatible = "maxim,max98360a"; + sdmode-gpios = <&qcom_pinmux 25 0>; +}; diff --git a/Documentation/devicetree/bindings/sound/maxim,max98390.yaml b/Documentation/devicetree/bindings/sound/maxim,max98390.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e5ac35280da3605a0584b09509b68b48084b3b76 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/maxim,max98390.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/maxim,max98390.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim Integrated MAX98390 Speaker Amplifier with Integrated Dynamic Speaker Management + +maintainers: + - Steve Lee + +properties: + compatible: + const: maxim,max98390 + + reg: + maxItems: 1 + description: I2C address of the device. + + maxim,temperature_calib: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + description: The calculated temperature data was measured while doing the calibration. + minimum: 0 + maximum: 65535 + + maxim,r0_calib: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + description: This is r0 calibration data which was measured in factory mode. + minimum: 1 + maximum: 8388607 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + max98390: amplifier@38 { + compatible = "maxim,max98390"; + reg = <0x38>; + maxim,temperature_calib = <1024>; + maxim,r0_calib = <100232>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/mt6358.txt b/Documentation/devicetree/bindings/sound/mt6358.txt index 5465730013a1ea91c74e5f2321f0e29b4ae29462..59a73ffdf1d34d3fa67c9551896884be3c02a468 100644 --- a/Documentation/devicetree/bindings/sound/mt6358.txt +++ b/Documentation/devicetree/bindings/sound/mt6358.txt @@ -10,9 +10,15 @@ Required properties: - compatible : "mediatek,mt6358-sound". - Avdd-supply : power source of AVDD +Optional properties: +- mediatek,dmic-mode : Indicates how many data pins are used to transmit two + channels of PDM signal. 0 means two wires, 1 means one wire. Default + value is 0. + Example: mt6358_snd { compatible = "mediatek,mt6358-sound"; Avdd-supply = <&mt6358_vaud28_reg>; + mediatek,dmic-mode = <0>; }; diff --git a/Documentation/devicetree/bindings/sound/mt8183-da7219-max98357.txt b/Documentation/devicetree/bindings/sound/mt8183-da7219-max98357.txt index 92ac86f83822024a7be0ccf5c4c78923772ac84c..6787ce8789dd3742273703bba5d37474a33161ec 100644 --- a/Documentation/devicetree/bindings/sound/mt8183-da7219-max98357.txt +++ b/Documentation/devicetree/bindings/sound/mt8183-da7219-max98357.txt @@ -1,15 +1,20 @@ -MT8183 with MT6358, DA7219 and MAX98357 CODECS +MT8183 with MT6358, DA7219, MAX98357, and RT1015 CODECS Required properties: -- compatible : "mediatek,mt8183_da7219_max98357" +- compatible : "mediatek,mt8183_da7219_max98357" for MAX98357A codec + "mediatek,mt8183_da7219_rt1015" for RT1015 codec - mediatek,headset-codec: the phandles of da7219 codecs - mediatek,platform: the phandle of MT8183 ASoC platform +Optional properties: +- mediatek,hdmi-codec: the phandles of HDMI codec + Example: sound { compatible = "mediatek,mt8183_da7219_max98357"; mediatek,headset-codec = <&da7219>; + mediatek,hdmi-codec = <&it6505dptx>; mediatek,platform = <&afe>; }; diff --git a/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt b/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt index decaa013a07e1d5d77c1bc1d5ac938f5363c52af..235eac8aea7bf3d1f946d7e33bfe93f2257037ec 100644 --- a/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt +++ b/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt @@ -1,13 +1,16 @@ -MT8183 with MT6358, TS3A227 and MAX98357 CODECS +MT8183 with MT6358, TS3A227, MAX98357, and RT1015 CODECS Required properties: -- compatible : "mediatek,mt8183_mt6358_ts3a227_max98357" +- compatible : "mediatek,mt8183_mt6358_ts3a227_max98357" for MAX98357A codec + "mediatek,mt8183_mt6358_ts3a227_max98357b" for MAX98357B codec + "mediatek,mt8183_mt6358_ts3a227_rt1015" for RT1015 codec - mediatek,platform: the phandle of MT8183 ASoC platform Optional properties: - mediatek,headset-codec: the phandles of ts3a227 codecs - mediatek,ec-codec: the phandle of EC codecs. See google,cros-ec-codec.txt for more details. +- mediatek,hdmi-codec: the phandles of HDMI codec Example: @@ -15,6 +18,7 @@ Example: compatible = "mediatek,mt8183_mt6358_ts3a227_max98357"; mediatek,headset-codec = <&ts3a227>; mediatek,ec-codec = <&ec_codec>; + mediatek,hdmi-codec = <&it6505dptx>; mediatek,platform = <&afe>; }; diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e620c77d07281fcabdd2a74c2001a692a5e4566b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra186-dspk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Tegra186 DSPK Controller Device Tree Bindings + +description: | + The Digital Speaker Controller (DSPK) can be viewed as a Pulse + Density Modulation (PDM) transmitter that up-samples the input to + the desired sampling rate by interpolation and then converts the + over sampled Pulse Code Modulation (PCM) input to the desired 1-bit + output via Delta Sigma Modulation (DSM). + +maintainers: + - Jon Hunter + - Sameer Pujar + +properties: + $nodename: + pattern: "^dspk@[0-9a-f]*$" + + compatible: + oneOf: + - const: nvidia,tegra186-dspk + - items: + - const: nvidia,tegra194-dspk + - const: nvidia,tegra186-dspk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: dspk + + assigned-clocks: + maxItems: 1 + + assigned-clock-parents: + maxItems: 1 + + assigned-clock-rates: + maxItems: 1 + + sound-name-prefix: + pattern: "^DSPK[1-9]$" + allOf: + - $ref: /schemas/types.yaml#/definitions/string + description: + Used as prefix for sink/source names of the component. Must be a + unique string among multiple instances of the same component. + The name can be "DSPK1" or "DSPKx", where x depends on the maximum + available instances on a Tegra SoC. + +required: + - compatible + - reg + - clocks + - clock-names + - assigned-clocks + - assigned-clock-parents + - sound-name-prefix + +examples: + - | + #include + + dspk@2905000 { + compatible = "nvidia,tegra186-dspk"; + reg = <0x2905000 0x100>; + clocks = <&bpmp TEGRA186_CLK_DSPK1>; + clock-names = "dspk"; + assigned-clocks = <&bpmp TEGRA186_CLK_DSPK1>; + assigned-clock-parents = <&bpmp TEGRA186_CLK_PLL_A_OUT0>; + assigned-clock-rates = <12288000>; + sound-name-prefix = "DSPK1"; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml new file mode 100644 index 0000000000000000000000000000000000000000..41c77f45d2fdcadf17654a47f53aa73054d18c4c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-admaif.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Tegra210 ADMAIF Device Tree Bindings + +description: | + ADMAIF is the interface between ADMA and AHUB. Each ADMA channel + that sends/receives data to/from AHUB must interface through an + ADMAIF channel. ADMA channel sending data to AHUB pairs with ADMAIF + Tx channel and ADMA channel receiving data from AHUB pairs with + ADMAIF Rx channel. + +maintainers: + - Jon Hunter + - Sameer Pujar + +properties: + $nodename: + pattern: "^admaif@[0-9a-f]*$" + + compatible: + oneOf: + - enum: + - nvidia,tegra210-admaif + - nvidia,tegra186-admaif + - items: + - const: nvidia,tegra194-admaif + - const: nvidia,tegra186-admaif + + reg: + maxItems: 1 + + dmas: true + + dma-names: true + +if: + properties: + compatible: + contains: + const: nvidia,tegra210-admaif + +then: + properties: + dmas: + description: + DMA channel specifiers, equally divided for Tx and Rx. + minItems: 1 + maxItems: 20 + dma-names: + items: + pattern: "^[rt]x(10|[1-9])$" + description: + Should be "rx1", "rx2" ... "rx10" for DMA Rx channel + Should be "tx1", "tx2" ... "tx10" for DMA Tx channel + minItems: 1 + maxItems: 20 + +else: + properties: + dmas: + description: + DMA channel specifiers, equally divided for Tx and Rx. + minItems: 1 + maxItems: 40 + dma-names: + items: + pattern: "^[rt]x(1[0-9]|[1-9]|20)$" + description: + Should be "rx1", "rx2" ... "rx20" for DMA Rx channel + Should be "tx1", "tx2" ... "tx20" for DMA Tx channel + minItems: 1 + maxItems: 40 + +required: + - compatible + - reg + - dmas + - dma-names + +examples: + - | + admaif@702d0000 { + compatible = "nvidia,tegra210-admaif"; + reg = <0x702d0000 0x800>; + dmas = <&adma 1>, <&adma 1>, + <&adma 2>, <&adma 2>, + <&adma 3>, <&adma 3>, + <&adma 4>, <&adma 4>, + <&adma 5>, <&adma 5>, + <&adma 6>, <&adma 6>, + <&adma 7>, <&adma 7>, + <&adma 8>, <&adma 8>, + <&adma 9>, <&adma 9>, + <&adma 10>, <&adma 10>; + dma-names = "rx1", "tx1", + "rx2", "tx2", + "rx3", "tx3", + "rx4", "tx4", + "rx5", "tx5", + "rx6", "tx6", + "rx7", "tx7", + "rx8", "tx8", + "rx9", "tx9", + "rx10", "tx10"; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml new file mode 100644 index 0000000000000000000000000000000000000000..44ee9d844ae012428ed12cff3aafe20e98964ede --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml @@ -0,0 +1,136 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-ahub.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Tegra210 AHUB Device Tree Bindings + +description: | + The Audio Hub (AHUB) comprises a collection of hardware accelerators + for audio pre-processing, post-processing and a programmable full + crossbar for routing audio data across these accelerators. It has + external interfaces such as I2S, DMIC, DSPK. It interfaces with ADMA + engine through ADMAIF. + +maintainers: + - Jon Hunter + - Sameer Pujar + +properties: + $nodename: + pattern: "^ahub@[0-9a-f]*$" + + compatible: + oneOf: + - enum: + - nvidia,tegra210-ahub + - nvidia,tegra186-ahub + - items: + - const: nvidia,tegra194-ahub + - const: nvidia,tegra186-ahub + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: ahub + + assigned-clocks: + maxItems: 1 + + assigned-clock-parents: + maxItems: 1 + + assigned-clock-rates: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + ranges: true + +required: + - compatible + - reg + - clocks + - clock-names + - assigned-clocks + - assigned-clock-parents + - "#address-cells" + - "#size-cells" + - ranges + +examples: + - | + #include + + ahub@702d0800 { + compatible = "nvidia,tegra210-ahub"; + reg = <0x702d0800 0x800>; + clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>; + clock-names = "ahub"; + assigned-clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>; + assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x702d0000 0x702d0000 0x0000e400>; + + // All AHUB child nodes below + admaif@702d0000 { + compatible = "nvidia,tegra210-admaif"; + reg = <0x702d0000 0x800>; + dmas = <&adma 1>, <&adma 1>, + <&adma 2>, <&adma 2>, + <&adma 3>, <&adma 3>, + <&adma 4>, <&adma 4>, + <&adma 5>, <&adma 5>, + <&adma 6>, <&adma 6>, + <&adma 7>, <&adma 7>, + <&adma 8>, <&adma 8>, + <&adma 9>, <&adma 9>, + <&adma 10>, <&adma 10>; + dma-names = "rx1", "tx1", + "rx2", "tx2", + "rx3", "tx3", + "rx4", "tx4", + "rx5", "tx5", + "rx6", "tx6", + "rx7", "tx7", + "rx8", "tx8", + "rx9", "tx9", + "rx10", "tx10"; + }; + + i2s@702d1000 { + compatible = "nvidia,tegra210-i2s"; + reg = <0x702d1000 0x100>; + clocks = <&tegra_car TEGRA210_CLK_I2S0>; + clock-names = "i2s"; + assigned-clocks = <&tegra_car TEGRA210_CLK_I2S0>; + assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>; + assigned-clock-rates = <1536000>; + sound-name-prefix = "I2S1"; + }; + + dmic@702d4000 { + compatible = "nvidia,tegra210-dmic"; + reg = <0x702d4000 0x100>; + clocks = <&tegra_car TEGRA210_CLK_DMIC1>; + clock-names = "dmic"; + assigned-clocks = <&tegra_car TEGRA210_CLK_DMIC1>; + assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>; + assigned-clock-rates = <3072000>; + sound-name-prefix = "DMIC1"; + }; + + // More child nodes to follow + }; + +... diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1c14e83f67c758010006ebb8a547d1a10717bf38 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-dmic.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Tegra210 DMIC Controller Device Tree Bindings + +description: | + The Digital MIC (DMIC) Controller is used to interface with Pulse + Density Modulation (PDM) input devices. It converts PDM signals to + Pulse Coded Modulation (PCM) signals. DMIC can be viewed as a PDM + receiver. + +maintainers: + - Jon Hunter + - Sameer Pujar + +properties: + $nodename: + pattern: "^dmic@[0-9a-f]*$" + + compatible: + oneOf: + - const: nvidia,tegra210-dmic + - items: + - enum: + - nvidia,tegra194-dmic + - nvidia,tegra186-dmic + - const: nvidia,tegra210-dmic + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: dmic + + assigned-clocks: + maxItems: 1 + + assigned-clock-parents: + maxItems: 1 + + assigned-clock-rates: + maxItems: 1 + + sound-name-prefix: + pattern: "^DMIC[1-9]$" + allOf: + - $ref: /schemas/types.yaml#/definitions/string + description: + used as prefix for sink/source names of the component. Must be a + unique string among multiple instances of the same component. + The name can be "DMIC1" or "DMIC2" ... "DMICx", where x depends + on the maximum available instances on a Tegra SoC. + +required: + - compatible + - reg + - clocks + - clock-names + - assigned-clocks + - assigned-clock-parents + +examples: + - | + #include + + dmic@702d4000 { + compatible = "nvidia,tegra210-dmic"; + reg = <0x702d4000 0x100>; + clocks = <&tegra_car TEGRA210_CLK_DMIC1>; + clock-names = "dmic"; + assigned-clocks = <&tegra_car TEGRA210_CLK_DMIC1>; + assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>; + assigned-clock-rates = <3072000>; + sound-name-prefix = "DMIC1"; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml new file mode 100644 index 0000000000000000000000000000000000000000..795797001843de053270c9c46a8258fb138a4752 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-i2s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Tegra210 I2S Controller Device Tree Bindings + +description: | + The Inter-IC Sound (I2S) controller implements full-duplex, + bi-directional and single direction point-to-point serial + interfaces. It can interface with I2S compatible devices. + I2S controller can operate both in master and slave mode. + +maintainers: + - Jon Hunter + - Sameer Pujar + +properties: + $nodename: + pattern: "^i2s@[0-9a-f]*$" + + compatible: + oneOf: + - const: nvidia,tegra210-i2s + - items: + - enum: + - nvidia,tegra194-i2s + - nvidia,tegra186-i2s + - const: nvidia,tegra210-i2s + + reg: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 2 + items: + - description: I2S bit clock + - description: + Sync input clock, which can act as clock source to other I/O + modules in AHUB. The Tegra I2S driver sets this clock rate as + per bit clock rate. I/O module which wants to use this clock + as source, can mention this clock as parent in the DT bindings. + This is an optional clock entry, since it is only required when + some other I/O wants to reference from a particular I2Sx + instance. + + clock-names: + minItems: 1 + maxItems: 2 + items: + - const: i2s + - const: sync_input + + assigned-clocks: + minItems: 1 + maxItems: 2 + + assigned-clock-parents: + minItems: 1 + maxItems: 2 + + assigned-clock-rates: + minItems: 1 + maxItems: 2 + + sound-name-prefix: + pattern: "^I2S[1-9]$" + allOf: + - $ref: /schemas/types.yaml#/definitions/string + description: + Used as prefix for sink/source names of the component. Must be a + unique string among multiple instances of the same component. + The name can be "I2S1" or "I2S2" ... "I2Sx", where x depends + on the maximum available instances on a Tegra SoC. + +required: + - compatible + - reg + - clocks + - clock-names + - assigned-clocks + - assigned-clock-parents + +examples: + - | + #include + + i2s@702d1000 { + compatible = "nvidia,tegra210-i2s"; + reg = <0x702d1000 0x100>; + clocks = <&tegra_car TEGRA210_CLK_I2S0>; + clock-names = "i2s"; + assigned-clocks = <&tegra_car TEGRA210_CLK_I2S0>; + assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>; + assigned-clock-rates = <1536000>; + sound-name-prefix = "I2S1"; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/qcom,q6asm.txt b/Documentation/devicetree/bindings/sound/qcom,q6asm.txt index 6b9a88d0ea3feb3e42151cd1419408c94480671d..8c4883becae9f8e2229f0e5cedd7e9910a7d661b 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6asm.txt +++ b/Documentation/devicetree/bindings/sound/qcom,q6asm.txt @@ -39,9 +39,9 @@ configuration of each dai. Must contain the following properties. Usage: Required for Compress offload dais Value type: Definition: Specifies the direction of the dai stream - 0 for both tx and rx - 1 for only tx (Capture/Encode) - 2 for only rx (Playback/Decode) + Q6ASM_DAI_TX_RX (0) for both tx and rx + Q6ASM_DAI_TX (1) for only tx (Capture/Encode) + Q6ASM_DAI_RX (2) for only rx (Playback/Decode) - is-compress-dai: Usage: Required for Compress offload dais @@ -50,6 +50,7 @@ configuration of each dai. Must contain the following properties. = EXAMPLE +#include apr-service@7 { compatible = "qcom,q6asm"; @@ -62,7 +63,7 @@ apr-service@7 { dai@0 { reg = <0>; - direction = <2>; + direction = ; is-compress-dai; }; }; diff --git a/Documentation/devicetree/bindings/sound/renesas,fsi.yaml b/Documentation/devicetree/bindings/sound/renesas,fsi.yaml index 8a4406be387a6b61293fd4af16fe5a51ac2858fc..0dd3f73613999a7c8c070e6c19139b2d6dde0035 100644 --- a/Documentation/devicetree/bindings/sound/renesas,fsi.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,fsi.yaml @@ -43,30 +43,19 @@ properties: '#sound-dai-cells': const: 1 - fsia,spdif-connection: +patternProperties: + "^fsi(a|b),spdif-connection$": $ref: /schemas/types.yaml#/definitions/flag description: FSI is connected by S/PDIF - fsia,stream-mode-support: + "^fsi(a|b),stream-mode-support$": $ref: /schemas/types.yaml#/definitions/flag description: FSI supports 16bit stream mode - fsia,use-internal-clock: + "^fsi(a|b),use-internal-clock$": $ref: /schemas/types.yaml#/definitions/flag description: FSI uses internal clock when master mode - fsib,spdif-connection: - $ref: /schemas/types.yaml#/definitions/flag - description: same as fsia - - fsib,stream-mode-support: - $ref: /schemas/types.yaml#/definitions/flag - description: same as fsia - - fsib,use-internal-clock: - $ref: /schemas/types.yaml#/definitions/flag - description: same as fsia - required: - compatible - reg diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt index 1596f0d1e2fe2bbe1fb3d8b91c262288e260f66a..b39743d3f7c42842254cb9c8219dd2a538cc813c 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt @@ -271,6 +271,7 @@ Required properties: - "renesas,rcar_sound-r8a774a1" (RZ/G2M) - "renesas,rcar_sound-r8a774b1" (RZ/G2N) - "renesas,rcar_sound-r8a774c0" (RZ/G2E) + - "renesas,rcar_sound-r8a774e1" (RZ/G2H) - "renesas,rcar_sound-r8a7778" (R-Car M1A) - "renesas,rcar_sound-r8a7779" (R-Car H1) - "renesas,rcar_sound-r8a7790" (R-Car H2) diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt deleted file mode 100644 index 1ecd75d2032a006f36ef0e2217b8501bca973281..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.txt +++ /dev/null @@ -1,28 +0,0 @@ -* Rockchip Rk3328 internal codec - -Required properties: - -- compatible: "rockchip,rk3328-codec" -- reg: physical base address of the controller and length of memory mapped - region. -- rockchip,grf: the phandle of the syscon node for GRF register. -- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. -- clock-names: should be "pclk". -- spk-depop-time-ms: speak depop time msec. - -Optional properties: - -- mute-gpios: GPIO specifier for external line driver control (typically the - dedicated GPIO_MUTE pin) - -Example for rk3328 internal codec: - -codec: codec@ff410000 { - compatible = "rockchip,rk3328-codec"; - reg = <0x0 0xff410000 0x0 0x1000>; - rockchip,grf = <&grf>; - clocks = <&cru PCLK_ACODEC>; - clock-names = "pclk"; - mute-gpios = <&grf_gpio 0 GPIO_ACTIVE_LOW>; - spk-depop-time-ms = 100; -}; diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5b85ad5e4834c9eb656c27f632ce372d7793ef2b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/rockchip,rk3328-codec.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip rk3328 internal codec + +maintainers: + - Heiko Stuebner + +properties: + compatible: + const: rockchip,rk3328-codec + + reg: + maxItems: 1 + + clocks: + items: + - description: clock for audio codec + - description: clock for I2S master clock + + clock-names: + items: + - const: pclk + - const: mclk + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: + The phandle of the syscon node for the GRF register. + + spk-depop-time-ms: + default: 200 + description: + Speaker depop time in msec. + + mute-gpios: + maxItems: 1 + description: + GPIO specifier for external line driver control (typically the + dedicated GPIO_MUTE pin) + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + - clocks + - clock-names + - rockchip,grf + - "#sound-dai-cells" + +examples: + - | + #include + #include + codec: codec@ff410000 { + compatible = "rockchip,rk3328-codec"; + reg = <0xff410000 0x1000>; + clocks = <&cru PCLK_ACODECPHY>, <&cru SCLK_I2S1>; + clock-names = "pclk", "mclk"; + rockchip,grf = <&grf>; + mute-gpios = <&grf_gpio 0 GPIO_ACTIVE_LOW>; + spk-depop-time-ms = <100>; + #sound-dai-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/sound/rohm,bd28623.txt b/Documentation/devicetree/bindings/sound/rohm,bd28623.txt deleted file mode 100644 index d84557c2686ee1a661467bbac3e28b0ed90331a1..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/rohm,bd28623.txt +++ /dev/null @@ -1,29 +0,0 @@ -ROHM BD28623MUV Class D speaker amplifier for digital input - -This codec does not have any control buses such as I2C, it detect format and -rate of I2S signal automatically. It has two signals that can be connected -to GPIOs: reset and mute. - -Required properties: -- compatible : should be "rohm,bd28623" -- #sound-dai-cells: should be 0. -- VCCA-supply : regulator phandle for the VCCA supply -- VCCP1-supply : regulator phandle for the VCCP1 supply -- VCCP2-supply : regulator phandle for the VCCP2 supply - -Optional properties: -- reset-gpios : GPIO specifier for the active low reset line -- mute-gpios : GPIO specifier for the active low mute line - -Example: - - codec { - compatible = "rohm,bd28623"; - #sound-dai-cells = <0>; - - VCCA-supply = <&vcc_reg>; - VCCP1-supply = <&vcc_reg>; - VCCP2-supply = <&vcc_reg>; - reset-gpios = <&gpio 0 GPIO_ACTIVE_LOW>; - mute-gpios = <&gpio 1 GPIO_ACTIVE_LOW>; - }; diff --git a/Documentation/devicetree/bindings/sound/rohm,bd28623.yaml b/Documentation/devicetree/bindings/sound/rohm,bd28623.yaml new file mode 100644 index 0000000000000000000000000000000000000000..859ce64da1526ac6722175138509bd2277ca487c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rohm,bd28623.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/rohm,bd28623.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ROHM BD28623MUV Class D speaker amplifier for digital input + +description: + This codec does not have any control buses such as I2C, it detect + format and rate of I2S signal automatically. It has two signals + that can be connected to GPIOs reset and mute. + +maintainers: + - Katsuhiro Suzuki + +properties: + compatible: + const: rohm,bd28623 + + "#sound-dai-cells": + const: 0 + + VCCA-supply: + description: + regulator phandle for the VCCA (for analog) power supply + + VCCP1-supply: + description: + regulator phandle for the VCCP1 (for ch1) power supply + + VCCP2-supply: + description: + regulator phandle for the VCCP2 (for ch2) power supply + + reset-gpios: + maxItems: 1 + description: + GPIO specifier for the active low reset line + + mute-gpios: + maxItems: 1 + description: + GPIO specifier for the active low mute line + +required: + - compatible + - VCCA-supply + - VCCP1-supply + - VCCP2-supply + - "#sound-dai-cells" + +additionalProperties: false + +examples: + - | + #include + codec { + compatible = "rohm,bd28623"; + #sound-dai-cells = <0>; + + VCCA-supply = <&vcc_reg>; + VCCP1-supply = <&vcc_reg>; + VCCP2-supply = <&vcc_reg>; + reset-gpios = <&gpio 0 GPIO_ACTIVE_LOW>; + mute-gpios = <&gpio 1 GPIO_ACTIVE_LOW>; + }; diff --git a/Documentation/devicetree/bindings/sound/samsung,aries-wm8994.yaml b/Documentation/devicetree/bindings/sound/samsung,aries-wm8994.yaml new file mode 100644 index 0000000000000000000000000000000000000000..902a0b66628e6226e3b09de8ddebf5ea99af25aa --- /dev/null +++ b/Documentation/devicetree/bindings/sound/samsung,aries-wm8994.yaml @@ -0,0 +1,147 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/samsung,aries-wm8994.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung Aries audio complex with WM8994 codec + +maintainers: + - Jonathan Bakker + +properties: + compatible: + oneOf: + - const: samsung,aries-wm8994 + description: With FM radio and modem master + + - const: samsung,fascinate4g-wm8994 + description: Without FM radio and modem slave + + model: + $ref: /schemas/types.yaml#/definitions/string + description: The user-visible name of this sound complex. + + cpu: + type: object + properties: + sound-dai: + minItems: 2 + maxItems: 2 + $ref: /schemas/types.yaml#/definitions/phandle-array + description: | + phandles to the I2S controller and bluetooth codec, + in that order + + codec: + type: object + properties: + sound-dai: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: phandle to the WM8994 CODEC + + samsung,audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: | + List of the connections between audio + components; each entry is a pair of strings, the first being the + connection's sink, the second being the connection's source; + valid names for sources and sinks are the WM8994's pins (as + documented in its binding), and the jacks on the board - + For samsung,aries-wm8994: HP, SPK, RCV, LINE, Main Mic, Headset Mic, + or FM In + For samsung,fascinate4g-wm8994: HP, SPK, RCV, LINE, Main Mic, + or HeadsetMic + + extcon: + description: Extcon phandle for dock detection + + main-micbias-supply: + description: Supply for the micbias on the main mic + + headset-micbias-supply: + description: Supply for the micbias on the headset mic + + earpath-sel-gpios: + description: GPIO for switching between tv-out and mic paths + + headset-detect-gpios: + description: GPIO for detection of headset insertion + + headset-key-gpios: + description: GPIO for detection of headset key press + + io-channels: + maxItems: 1 + description: IO channel to read micbias voltage for headset detection + + io-channel-names: + const: headset-detect + +required: + - compatible + - model + - cpu + - codec + - samsung,audio-routing + - extcon + - main-micbias-supply + - headset-micbias-supply + - earpath-sel-gpios + - headset-detect-gpios + - headset-key-gpios + +additionalProperties: false + +examples: + - | + #include + + sound { + compatible = "samsung,fascinate4g-wm8994"; + + model = "Fascinate4G"; + + extcon = <&fsa9480>; + + main-micbias-supply = <&main_micbias_reg>; + headset-micbias-supply = <&headset_micbias_reg>; + + earpath-sel-gpios = <&gpj2 6 GPIO_ACTIVE_HIGH>; + + io-channels = <&adc 3>; + io-channel-names = "headset-detect"; + headset-detect-gpios = <&gph0 6 GPIO_ACTIVE_HIGH>; + headset-key-gpios = <&gph3 6 GPIO_ACTIVE_HIGH>; + + samsung,audio-routing = + "HP", "HPOUT1L", + "HP", "HPOUT1R", + + "SPK", "SPKOUTLN", + "SPK", "SPKOUTLP", + + "RCV", "HPOUT2N", + "RCV", "HPOUT2P", + + "LINE", "LINEOUT2N", + "LINE", "LINEOUT2P", + + "IN1LP", "Main Mic", + "IN1LN", "Main Mic", + + "IN1RP", "Headset Mic", + "IN1RN", "Headset Mic"; + + pinctrl-names = "default"; + pinctrl-0 = <&headset_det &earpath_sel>; + + cpu { + sound-dai = <&i2s0>, <&bt_codec>; + }; + + codec { + sound-dai = <&wm8994>; + }; + }; + diff --git a/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml b/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1c755de686f71e3d97e6993815c3516f7fe02d65 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/samsung,midas-audio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung Midas audio complex with WM1811 codec + +maintainers: + - Sylwester Nawrocki + +properties: + compatible: + const: samsung,midas-audio + + model: + $ref: /schemas/types.yaml#/definitions/string + description: The user-visible name of this sound complex. + + cpu: + type: object + properties: + sound-dai: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle to the I2S controller + required: + - sound-dai + + codec: + type: object + properties: + sound-dai: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle to the WM1811 CODEC + required: + - sound-dai + + samsung,audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: | + List of the connections between audio components; each entry is + a pair of strings, the first being the connection's sink, the second + being the connection's source; valid names for sources and sinks are + the WM1811's pins (as documented in its binding), and the jacks + on the board: HP, SPK, Main Mic, Sub Mic, Headset Mic. + + mic-bias-supply: + description: Supply for the micbias on the Main microphone + + submic-bias-supply: + description: Supply for the micbias on the Sub microphone + + fm-sel-gpios: + description: GPIO pin for FM selection + + lineout-sel-gpios: + description: GPIO pin for line out selection + +required: + - compatible + - model + - cpu + - codec + - samsung,audio-routing + - mic-bias-supply + - submic-bias-supply + +additionalProperties: false + +examples: + - | + #include + + sound { + compatible = "samsung,midas-audio"; + model = "Midas"; + + fm-sel-gpios = <&gpaa0 3 GPIO_ACTIVE_HIGH>; + + mic-bias-supply = <&mic_bias_reg>; + submic-bias-supply = <&submic_bias_reg>; + + samsung,audio-routing = + "HP", "HPOUT1L", + "HP", "HPOUT1R", + + "SPK", "SPKOUTLN", + "SPK", "SPKOUTLP", + "SPK", "SPKOUTRN", + "SPK", "SPKOUTRP", + + "RCV", "HPOUT2N", + "RCV", "HPOUT2P", + + "IN1LP", "Main Mic", + "IN1LN", "Main Mic", + "IN1RP", "Sub Mic", + "IN1LP", "Sub Mic"; + + cpu { + sound-dai = <&i2s0>; + }; + + codec { + sound-dai = <&wm1811>; + }; + + }; diff --git a/Documentation/devicetree/bindings/sound/sgtl5000.txt b/Documentation/devicetree/bindings/sound/sgtl5000.txt deleted file mode 100644 index 9d9ff5184939615668ed32164fc92e8dc32873c8..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/sgtl5000.txt +++ /dev/null @@ -1,60 +0,0 @@ -* Freescale SGTL5000 Stereo Codec - -Required properties: -- compatible : "fsl,sgtl5000". - -- reg : the I2C address of the device - -- #sound-dai-cells: must be equal to 0 - -- clocks : the clock provider of SYS_MCLK - -- VDDA-supply : the regulator provider of VDDA - -- VDDIO-supply: the regulator provider of VDDIO - -Optional properties: - -- VDDD-supply : the regulator provider of VDDD - -- micbias-resistor-k-ohms : the bias resistor to be used in kOhms - The resistor can take values of 2k, 4k or 8k. - If set to 0 it will be off. - If this node is not mentioned or if the value is unknown, then - micbias resistor is set to 4K. - -- micbias-voltage-m-volts : the bias voltage to be used in mVolts - The voltage can take values from 1.25V to 3V by 250mV steps - If this node is not mentioned or the value is unknown, then - the value is set to 1.25V. - -- lrclk-strength: the LRCLK pad strength. Possible values are: -0, 1, 2 and 3 as per the table below: - -VDDIO 1.8V 2.5V 3.3V -0 = Disable -1 = 1.66 mA 2.87 mA 4.02 mA -2 = 3.33 mA 5.74 mA 8.03 mA -3 = 4.99 mA 8.61 mA 12.05 mA - -- sclk-strength: the SCLK pad strength. Possible values are: -0, 1, 2 and 3 as per the table below: - -VDDIO 1.8V 2.5V 3.3V -0 = Disable -1 = 1.66 mA 2.87 mA 4.02 mA -2 = 3.33 mA 5.74 mA 8.03 mA -3 = 4.99 mA 8.61 mA 12.05 mA - -Example: - -sgtl5000: codec@a { - compatible = "fsl,sgtl5000"; - reg = <0x0a>; - #sound-dai-cells = <0>; - clocks = <&clks 150>; - micbias-resistor-k-ohms = <2>; - micbias-voltage-m-volts = <2250>; - VDDA-supply = <®_3p3v>; - VDDIO-supply = <®_3p3v>; -}; diff --git a/Documentation/devicetree/bindings/sound/sgtl5000.yaml b/Documentation/devicetree/bindings/sound/sgtl5000.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4f29b63c54d34d625f6d60535adfb457f8c842a1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sgtl5000.yaml @@ -0,0 +1,103 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/sgtl5000.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale SGTL5000 Stereo Codec + +maintainers: + - Fabio Estevam + +properties: + compatible: + const: fsl,sgtl5000 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + + clocks: + items: + - description: the clock provider of SYS_MCLK + + VDDA-supply: + description: the regulator provider of VDDA + + VDDIO-supply: + description: the regulator provider of VDDIO + + VDDD-supply: + description: the regulator provider of VDDD + + micbias-resistor-k-ohms: + description: The bias resistor to be used in kOhms. The resistor can take + values of 2k, 4k or 8k. If set to 0 it will be off. If this node is not + mentioned or if the value is unknown, then micbias resistor is set to + 4k. + $ref: "/schemas/types.yaml#/definitions/uint32" + enum: [ 0, 2, 4, 8 ] + + micbias-voltage-m-volts: + description: The bias voltage to be used in mVolts. The voltage can take + values from 1.25V to 3V by 250mV steps. If this node is not mentioned + or the value is unknown, then the value is set to 1.25V. + $ref: "/schemas/types.yaml#/definitions/uint32" + enum: [ 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000 ] + + lrclk-strength: + description: | + The LRCLK pad strength. Possible values are: 0, 1, 2 and 3 as per the + table below: + + VDDIO 1.8V 2.5V 3.3V + 0 = Disable + 1 = 1.66 mA 2.87 mA 4.02 mA + 2 = 3.33 mA 5.74 mA 8.03 mA + 3 = 4.99 mA 8.61 mA 12.05 mA + $ref: "/schemas/types.yaml#/definitions/uint32" + enum: [ 0, 1, 2, 3 ] + + sclk-strength: + description: | + The SCLK pad strength. Possible values are: 0, 1, 2 and 3 as per the + table below: + + VDDIO 1.8V 2.5V 3.3V + 0 = Disable + 1 = 1.66 mA 2.87 mA 4.02 mA + 2 = 3.33 mA 5.74 mA 8.03 mA + 3 = 4.99 mA 8.61 mA 12.05 mA + $ref: "/schemas/types.yaml#/definitions/uint32" + enum: [ 0, 1, 2, 3 ] + +required: + - compatible + - reg + - "#sound-dai-cells" + - clocks + - VDDA-supply + - VDDIO-supply + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + codec@a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + #sound-dai-cells = <0>; + clocks = <&clks 150>; + micbias-resistor-k-ohms = <2>; + micbias-voltage-m-volts = <2250>; + VDDA-supply = <®_3p3v>; + VDDIO-supply = <®_3p3v>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml b/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4987eb91f2ab961d4e945fc848bd98ea6f56b8b5 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml @@ -0,0 +1,81 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/socionext,uniphier-aio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier AIO audio system + +maintainers: + - + +properties: + compatible: + enum: + - socionext,uniphier-ld11-aio + - socionext,uniphier-ld20-aio + - socionext,uniphier-pxs2-aio + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clock-names: + const: aio + + clocks: + maxItems: 1 + + reset-names: + const: aio + + resets: + maxItems: 1 + + socionext,syscon: + description: | + Specifies a phandle to soc-glue, which is used for changing mode of S/PDIF + signal pin to output from Hi-Z. This property is optional if you use I2S + signal pins only. + $ref: "/schemas/types.yaml#/definitions/phandle" + + "#sound-dai-cells": + const: 1 + +patternProperties: + "^port@[0-9]$": + type: object + properties: + endpoint: true + required: + - endpoint + +additionalProperties: false + +required: + - compatible + - reg + - interrupts + - clock-names + - clocks + - reset-names + - resets + - "#sound-dai-cells" + +examples: + - | + audio@56000000 { + compatible = "socionext,uniphier-ld20-aio"; + reg = <0x56000000 0x80000>; + interrupts = <0 144 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_aout>; + clock-names = "aio"; + clocks = <&sys_clk 40>; + reset-names = "aio"; + resets = <&sys_rst 40>; + #sound-dai-cells = <1>; + socionext,syscon = <&soc_glue>; + }; diff --git a/Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml b/Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml new file mode 100644 index 0000000000000000000000000000000000000000..228168f685cff58ceb9d456988c056568b582e50 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/socionext,uniphier-evea.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UniPhier EVEA SoC-internal sound codec + +maintainers: + - + +properties: + compatible: + const: socionext,uniphier-evea + + reg: + maxItems: 1 + + clock-names: + items: + - const: evea + - const: exiv + + clocks: + minItems: 2 + maxItems: 2 + + reset-names: + items: + - const: evea + - const: exiv + - const: adamv + + resets: + minItems: 3 + maxItems: 3 + + "#sound-dai-cells": + const: 1 + +patternProperties: + "^port@[0-9]$": + type: object + properties: + endpoint: true + required: + - endpoint + +additionalProperties: false + +required: + - compatible + - reg + - clock-names + - clocks + - reset-names + - resets + - "#sound-dai-cells" + +examples: + - | + codec@57900000 { + compatible = "socionext,uniphier-evea"; + reg = <0x57900000 0x1000>; + clock-names = "evea", "exiv"; + clocks = <&sys_clk 41>, <&sys_clk 42>; + reset-names = "evea", "exiv", "adamv"; + resets = <&sys_rst 41>, <&sys_rst 42>, <&adamv_rst 0>; + #sound-dai-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/sound/tas2552.txt b/Documentation/devicetree/bindings/sound/tas2552.txt index 2d71eb05c1d384c72e166d02a46fc2d695cea382..a7eecad83db11b71cde6b39cf8489cc1eab35e2c 100644 --- a/Documentation/devicetree/bindings/sound/tas2552.txt +++ b/Documentation/devicetree/bindings/sound/tas2552.txt @@ -33,4 +33,4 @@ tas2552: tas2552@41 { }; For more product information please see the link below: -http://www.ti.com/product/TAS2552 +https://www.ti.com/product/TAS2552 diff --git a/Documentation/devicetree/bindings/sound/tas2562.txt b/Documentation/devicetree/bindings/sound/tas2562.txt index 94796b547184ba7b534174c05f56c839d96366b6..dc6d7362ded790d0b61d6b5f92d5fead09498237 100644 --- a/Documentation/devicetree/bindings/sound/tas2562.txt +++ b/Documentation/devicetree/bindings/sound/tas2562.txt @@ -11,12 +11,14 @@ Required properties: - compatible: - Should contain "ti,tas2562", "ti,tas2563". - reg: - The i2c address. Should be 0x4c, 0x4d, 0x4e or 0x4f. - ti,imon-slot-no:- TDM TX current sense time slot. + - ti,vmon-slot-no:- TDM TX voltage sense time slot. This slot must always be + greater then ti,imon-slot-no. Optional properties: - interrupt-parent: phandle to the interrupt controller which provides the interrupt. - interrupts: (GPIO) interrupt to which the chip is connected. -- shut-down: GPIO used to control the state of the device. +- shut-down-gpio: GPIO used to control the state of the device. Examples: tas2562@4c { @@ -28,7 +30,8 @@ tas2562@4c { interrupt-parent = <&gpio1>; interrupts = <14>; - shut-down = <&gpio1 15 0>; + shut-down-gpio = <&gpio1 15 0>; ti,imon-slot-no = <0>; + ti,vmon-slot-no = <1>; }; diff --git a/Documentation/devicetree/bindings/sound/tas2562.yaml b/Documentation/devicetree/bindings/sound/tas2562.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8d75a798740b8527b1e996dea1ab9ecb3568a1eb --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tas2562.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2019 Texas Instruments Incorporated +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/sound/tas2562.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Texas Instruments TAS2562 Smart PA + +maintainers: + - Dan Murphy + +description: | + The TAS2562 is a mono, digital input Class-D audio amplifier optimized for + efficiently driving high peak power into small loudspeakers. + Integrated speaker voltage and current sense provides for + real time monitoring of loudspeaker behavior. + +properties: + compatible: + enum: + - ti,tas2562 + - ti,tas2563 + + reg: + maxItems: 1 + description: | + I2C address of the device can be one of these 0x4c, 0x4d, 0x4e or 0x4f + + shut-down-gpios: + description: GPIO used to control the state of the device. + deprecated: true + + shutdown-gpios: + description: GPIO used to control the state of the device. + + interrupts: + maxItems: 1 + + ti,imon-slot-no: + $ref: /schemas/types.yaml#/definitions/uint32 + description: TDM TX current sense time slot. + + '#sound-dai-cells': + const: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + codec: codec@4c { + compatible = "ti,tas2562"; + reg = <0x4c>; + #sound-dai-cells = <1>; + interrupt-parent = <&gpio1>; + interrupts = <14>; + shutdown-gpios = <&gpio1 15 0>; + ti,imon-slot-no = <0>; + }; + }; + diff --git a/Documentation/devicetree/bindings/sound/tas2770.txt b/Documentation/devicetree/bindings/sound/tas2770.txt deleted file mode 100644 index ede6bb3d96371f6b31b6429900c80bef1519f6a3..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/tas2770.txt +++ /dev/null @@ -1,37 +0,0 @@ -Texas Instruments TAS2770 Smart PA - -The TAS2770 is a mono, digital input Class-D audio amplifier optimized for -efficiently driving high peak power into small loudspeakers. -Integrated speaker voltage and current sense provides for -real time monitoring of loudspeaker behavior. - -Required properties: - - - compatible: - Should contain "ti,tas2770". - - reg: - The i2c address. Should contain <0x4c>, <0x4d>,<0x4e>, or <0x4f>. - - #address-cells - Should be <1>. - - #size-cells - Should be <0>. - - ti,asi-format: - Sets TDM RX capture edge. 0->Rising; 1->Falling. - - ti,imon-slot-no:- TDM TX current sense time slot. - - ti,vmon-slot-no:- TDM TX voltage sense time slot. - -Optional properties: - -- interrupt-parent: the phandle to the interrupt controller which provides - the interrupt. -- interrupts: interrupt specification for data-ready. - -Examples: - - tas2770@4c { - compatible = "ti,tas2770"; - reg = <0x4c>; - #address-cells = <1>; - #size-cells = <0>; - interrupt-parent = <&msm_gpio>; - interrupts = <97 0>; - ti,asi-format = <0>; - ti,imon-slot-no = <0>; - ti,vmon-slot-no = <2>; - }; - diff --git a/Documentation/devicetree/bindings/sound/tas2770.yaml b/Documentation/devicetree/bindings/sound/tas2770.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8192450d72dc57d2b5030df349bb4b1b8545844a --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tas2770.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2019-20 Texas Instruments Incorporated +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/sound/tas2770.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Texas Instruments TAS2770 Smart PA + +maintainers: + - Shi Fu + +description: | + The TAS2770 is a mono, digital input Class-D audio amplifier optimized for + efficiently driving high peak power into small loudspeakers. + Integrated speaker voltage and current sense provides for + real time monitoring of loudspeaker behavior. + +properties: + compatible: + enum: + - ti,tas2770 + + reg: + maxItems: 1 + description: | + I2C address of the device can be one of these 0x4c, 0x4d, 0x4e or 0x4f + + reset-gpio: + description: GPIO used to reset the device. + + interrupts: + maxItems: 1 + + ti,imon-slot-no: + $ref: /schemas/types.yaml#/definitions/uint32 + description: TDM TX current sense time slot. + + ti,vmon-slot-no: + $ref: /schemas/types.yaml#/definitions/uint32 + description: TDM TX voltage sense time slot. + + ti,asi-format: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Sets TDM RX capture edge. + enum: + - 0 # Rising edge + - 1 # Falling edge + + '#sound-dai-cells': + const: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + codec: codec@4c { + compatible = "ti,tas2770"; + reg = <0x4c>; + #sound-dai-cells = <1>; + interrupt-parent = <&gpio1>; + interrupts = <14>; + reset-gpio = <&gpio1 15 0>; + ti,imon-slot-no = <0>; + ti,vmon-slot-no = <2>; + }; + }; + diff --git a/Documentation/devicetree/bindings/sound/tas5720.txt b/Documentation/devicetree/bindings/sound/tas5720.txt index 7481653fe8e3eba498667dcebe9afb8d97dc3391..df99ca9451b07c76930333405c703de8cb86eec1 100644 --- a/Documentation/devicetree/bindings/sound/tas5720.txt +++ b/Documentation/devicetree/bindings/sound/tas5720.txt @@ -4,9 +4,9 @@ The TAS5720 serial control bus communicates through the I2C protocol only. The serial bus is also used for periodic codec fault checking/reporting during audio playback. For more product information please see the links below: -http://www.ti.com/product/TAS5720L -http://www.ti.com/product/TAS5720M -http://www.ti.com/product/TAS5722L +https://www.ti.com/product/TAS5720L +https://www.ti.com/product/TAS5720M +https://www.ti.com/product/TAS5722L Required properties: diff --git a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6f2be65034016084f7a30da5bb6a7d197e31a1eb --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ti,j721e-cpb-audio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments J721e Common Processor Board Audio Support + +maintainers: + - Peter Ujfalusi + +description: | + The audio support on the board is using pcm3168a codec connected to McASP10 + serializers in parallel setup. + The pcm3168a SCKI clock is sourced from j721e AUDIO_REFCLK2 pin. + In order to support 48KHz and 44.1KHz family of sampling rates the parent + clock for AUDIO_REFCLK2 needs to be changed between PLL4 (for 48KHz) and + PLL15 (for 44.1KHz). The same PLLs are used for McASP10's AUXCLK clock via + different HSDIVIDER. + + Clocking setup for 48KHz family: + PLL4 ---> PLL4_HSDIV0 ---> MCASP10_AUXCLK ---> McASP10.auxclk + |-> PLL4_HSDIV2 ---> AUDIO_REFCLK2 ---> pcm3168a.SCKI + + Clocking setup for 44.1KHz family: + PLL15 ---> PLL15_HSDIV0 ---> MCASP10_AUXCLK ---> McASP10.auxclk + |-> PLL15_HSDIV2 ---> AUDIO_REFCLK2 ---> pcm3168a.SCKI + +properties: + compatible: + items: + - const: ti,j721e-cpb-audio + + model: + $ref: /schemas/types.yaml#/definitions/string + description: User specified audio sound card name + + ti,cpb-mcasp: + description: phandle to McASP used on CPB + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + + ti,cpb-codec: + description: phandle to the pcm3168a codec used on the CPB + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + + clocks: + items: + - description: AUXCLK clock for McASP used by CPB audio + - description: Parent for CPB_McASP auxclk (for 48KHz) + - description: Parent for CPB_McASP auxclk (for 44.1KHz) + - description: SCKI clock for the pcm3168a codec on CPB + - description: Parent for CPB_SCKI clock (for 48KHz) + - description: Parent for CPB_SCKI clock (for 44.1KHz) + + clock-names: + items: + - const: cpb-mcasp-auxclk + - const: cpb-mcasp-auxclk-48000 + - const: cpb-mcasp-auxclk-44100 + - const: cpb-codec-scki + - const: cpb-codec-scki-48000 + - const: cpb-codec-scki-44100 + +required: + - compatible + - model + - ti,cpb-mcasp + - ti,cpb-codec + - clocks + - clock-names + +additionalProperties: false + +examples: + - |+ + sound { + compatible = "ti,j721e-cpb-audio"; + model = "j721e-cpb"; + + status = "okay"; + + ti,cpb-mcasp = <&mcasp10>; + ti,cpb-codec = <&pcm3168a_1>; + + clocks = <&k3_clks 184 1>, + <&k3_clks 184 2>, <&k3_clks 184 4>, + <&k3_clks 157 371>, + <&k3_clks 157 400>, <&k3_clks 157 401>; + clock-names = "cpb-mcasp-auxclk", + "cpb-mcasp-auxclk-48000", "cpb-mcasp-auxclk-44100", + "cpb-codec-scki", + "cpb-codec-scki-48000", "cpb-codec-scki-44100"; + }; diff --git a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e0b88470a502fb856409b9ddd993e45d51bee06c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml @@ -0,0 +1,150 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ti,j721e-cpb-ivi-audio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments J721e Common Processor Board Audio Support + +maintainers: + - Peter Ujfalusi + +description: | + The Infotainment board plugs into the Common Processor Board, the support of the + extension board is extending the CPB audio support, decribed in: + sound/ti,j721e-cpb-audio.txt + + The audio support on the Infotainment Expansion Board consists of McASP0 + connected to two pcm3168a codecs with dedicated set of serializers to each. + The SCKI for pcm3168a is sourced from j721e AUDIO_REFCLK0 pin. + + In order to support 48KHz and 44.1KHz family of sampling rates the parent clock + for AUDIO_REFCLK0 needs to be changed between PLL4 (for 48KHz) and PLL15 (for + 44.1KHz). The same PLLs are used for McASP0's AUXCLK clock via different + HSDIVIDER. + + Note: the same PLL4 and PLL15 is used by the audio support on the CPB! + + Clocking setup for 48KHz family: + PLL4 ---> PLL4_HSDIV0 ---> MCASP10_AUXCLK ---> McASP10.auxclk + | |-> MCASP0_AUXCLK ---> McASP0.auxclk + | + |-> PLL4_HSDIV2 ---> AUDIO_REFCLK2 ---> pcm3168a.SCKI + |-> AUDIO_REFCLK0 ---> pcm3168a_a/b.SCKI + + Clocking setup for 44.1KHz family: + PLL15 ---> PLL15_HSDIV0 ---> MCASP10_AUXCLK ---> McASP10.auxclk + | |-> MCASP0_AUXCLK ---> McASP0.auxclk + | + |-> PLL15_HSDIV2 ---> AUDIO_REFCLK2 ---> pcm3168a.SCKI + |-> AUDIO_REFCLK0 ---> pcm3168a_a/b.SCKI + +properties: + compatible: + items: + - const: ti,j721e-cpb-ivi-audio + + model: + $ref: /schemas/types.yaml#/definitions/string + description: User specified audio sound card name + + ti,cpb-mcasp: + description: phandle to McASP used on CPB + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + + ti,cpb-codec: + description: phandle to the pcm3168a codec used on the CPB + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + + ti,ivi-mcasp: + description: phandle to McASP used on IVI + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + + ti,ivi-codec-a: + description: phandle to the pcm3168a-A codec on the expansion board + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + + ti,ivi-codec-b: + description: phandle to the pcm3168a-B codec on the expansion board + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + + clocks: + items: + - description: AUXCLK clock for McASP used by CPB audio + - description: Parent for CPB_McASP auxclk (for 48KHz) + - description: Parent for CPB_McASP auxclk (for 44.1KHz) + - description: SCKI clock for the pcm3168a codec on CPB + - description: Parent for CPB_SCKI clock (for 48KHz) + - description: Parent for CPB_SCKI clock (for 44.1KHz) + - description: AUXCLK clock for McASP used by IVI audio + - description: Parent for IVI_McASP auxclk (for 48KHz) + - description: Parent for IVI_McASP auxclk (for 44.1KHz) + - description: SCKI clock for the pcm3168a codec on IVI + - description: Parent for IVI_SCKI clock (for 48KHz) + - description: Parent for IVI_SCKI clock (for 44.1KHz) + + clock-names: + items: + - const: cpb-mcasp-auxclk + - const: cpb-mcasp-auxclk-48000 + - const: cpb-mcasp-auxclk-44100 + - const: cpb-codec-scki + - const: cpb-codec-scki-48000 + - const: cpb-codec-scki-44100 + - const: ivi-mcasp-auxclk + - const: ivi-mcasp-auxclk-48000 + - const: ivi-mcasp-auxclk-44100 + - const: ivi-codec-scki + - const: ivi-codec-scki-48000 + - const: ivi-codec-scki-44100 + +required: + - compatible + - model + - ti,cpb-mcasp + - ti,cpb-codec + - ti,ivi-mcasp + - ti,ivi-codec-a + - ti,ivi-codec-b + - clocks + - clock-names + +additionalProperties: false + +examples: + - |+ + sound { + compatible = "ti,j721e-cpb-ivi-audio"; + model = "j721e-cpb-ivi"; + + status = "okay"; + + ti,cpb-mcasp = <&mcasp10>; + ti,cpb-codec = <&pcm3168a_1>; + + ti,ivi-mcasp = <&mcasp0>; + ti,ivi-codec-a = <&pcm3168a_a>; + ti,ivi-codec-b = <&pcm3168a_b>; + + clocks = <&k3_clks 184 1>, + <&k3_clks 184 2>, <&k3_clks 184 4>, + <&k3_clks 157 371>, + <&k3_clks 157 400>, <&k3_clks 157 401>, + <&k3_clks 174 1>, + <&k3_clks 174 2>, <&k3_clks 174 4>, + <&k3_clks 157 301>, + <&k3_clks 157 330>, <&k3_clks 157 331>; + clock-names = "cpb-mcasp-auxclk", + "cpb-mcasp-auxclk-48000", "cpb-mcasp-auxclk-44100", + "cpb-codec-scki", + "cpb-codec-scki-48000", "cpb-codec-scki-44100", + "ivi-mcasp-auxclk", + "ivi-mcasp-auxclk-48000", "ivi-mcasp-auxclk-44100", + "ivi-codec-scki", + "ivi-codec-scki-48000", "ivi-codec-scki-44100"; + }; diff --git a/Documentation/devicetree/bindings/sound/ti,tas6424.txt b/Documentation/devicetree/bindings/sound/ti,tas6424.txt index eacb54f34188fa6cf10f3ad101b1c70bf590a488..00940c48929968265c467149ac79f38c44ee6908 100644 --- a/Documentation/devicetree/bindings/sound/ti,tas6424.txt +++ b/Documentation/devicetree/bindings/sound/ti,tas6424.txt @@ -19,4 +19,4 @@ tas6424: tas6424@6a { }; For more product information please see the link below: -http://www.ti.com/product/TAS6424-Q1 +https://www.ti.com/product/TAS6424-Q1 diff --git a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml index 2e6ac5d2ee96b55ef5a7616f0e4c278d5ae52d74..e84d4a20c633626364475cf2548eb306585712d8 100644 --- a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml +++ b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml @@ -18,9 +18,9 @@ description: | microphone bias or supply voltage generation. Specifications can be found at: - http://www.ti.com/lit/ds/symlink/tlv320adc3140.pdf - http://www.ti.com/lit/ds/symlink/tlv320adc5140.pdf - http://www.ti.com/lit/ds/symlink/tlv320adc6140.pdf + https://www.ti.com/lit/ds/symlink/tlv320adc3140.pdf + https://www.ti.com/lit/ds/symlink/tlv320adc5140.pdf + https://www.ti.com/lit/ds/symlink/tlv320adc6140.pdf properties: compatible: @@ -108,6 +108,32 @@ properties: maximum: 7 default: [0, 0, 0, 0] +patternProperties: + '^ti,gpo-config-[1-4]$': + $ref: /schemas/types.yaml#/definitions/uint32-array + description: | + Defines the configuration and output driver for the general purpose + output pins (GPO). These values are pairs, the first value is for the + configuration type and the second value is for the output drive type. + The array is defined as + + GPO output configuration can be one of the following: + + 0 - (default) disabled + 1 - GPOX is configured as a general-purpose output (GPO) + 2 - GPOX is configured as a device interrupt output (IRQ) + 3 - GPOX is configured as a secondary ASI output (SDOUT2) + 4 - GPOX is configured as a PDM clock output (PDMCLK) + + GPO output drive configuration for the GPO pins can be one of the following: + + 0d - (default) Hi-Z output + 1d - Drive active low and active high + 2d - Drive active low and weak high + 3d - Drive active low and Hi-Z + 4d - Drive weak low and active high + 5d - Drive Hi-Z and active high + required: - compatible - reg @@ -124,6 +150,8 @@ examples: ti,mic-bias-source = <6>; ti,pdm-edge-select = <0 1 0 1>; ti,gpi-config = <4 5 6 7>; + ti,gpo-config-1 = <0 0>; + ti,gpo-config-2 = <0 0>; reset-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; }; }; diff --git a/Documentation/devicetree/bindings/sound/uniphier,aio.txt b/Documentation/devicetree/bindings/sound/uniphier,aio.txt deleted file mode 100644 index 4ce68ed6f2f2363f90079a1fef368a4bf9abd90d..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/uniphier,aio.txt +++ /dev/null @@ -1,45 +0,0 @@ -Socionext UniPhier SoC audio driver - -The Socionext UniPhier audio subsystem consists of I2S and S/PDIF blocks in -the same register space. - -Required properties: -- compatible : should be one of the following: - "socionext,uniphier-ld11-aio" - "socionext,uniphier-ld20-aio" - "socionext,uniphier-pxs2-aio" -- reg : offset and length of the register set for the device. -- interrupts : should contain I2S or S/PDIF interrupt. -- pinctrl-names : should be "default". -- pinctrl-0 : defined I2S signal pins for an external codec chip. -- clock-names : should include following entries: - "aio" -- clocks : a list of phandle, should contain an entry for each - entry in clock-names. -- reset-names : should include following entries: - "aio" -- resets : a list of phandle, should contain an entry for each - entry in reset-names. -- #sound-dai-cells: should be 1. - -Optional properties: -- socionext,syscon: a phandle, should contain soc-glue. - The soc-glue is used for changing mode of S/PDIF signal pin - to Output from Hi-Z. This property is optional if you use - I2S signal pins only. - -Example: - audio { - compatible = "socionext,uniphier-ld20-aio"; - reg = <0x56000000 0x80000>; - interrupts = <0 144 4>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_aout>; - clock-names = "aio"; - clocks = <&sys_clk 40>; - reset-names = "aio"; - resets = <&sys_rst 40>; - #sound-dai-cells = <1>; - - socionext,syscon = <&sg>; - }; diff --git a/Documentation/devicetree/bindings/sound/uniphier,evea.txt b/Documentation/devicetree/bindings/sound/uniphier,evea.txt deleted file mode 100644 index 3f31b235f18b9bc0a3a82b0058fbde26c6181d6b..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/uniphier,evea.txt +++ /dev/null @@ -1,26 +0,0 @@ -Socionext EVEA - UniPhier SoC internal codec driver - -Required properties: -- compatible : should be "socionext,uniphier-evea". -- reg : offset and length of the register set for the device. -- clock-names : should include following entries: - "evea", "exiv" -- clocks : a list of phandle, should contain an entry for each - entries in clock-names. -- reset-names : should include following entries: - "evea", "exiv", "adamv" -- resets : a list of phandle, should contain reset entries of - reset-names. -- #sound-dai-cells: should be 1. - -Example: - - codec { - compatible = "socionext,uniphier-evea"; - reg = <0x57900000 0x1000>; - clock-names = "evea", "exiv"; - clocks = <&sys_clk 41>, <&sys_clk 42>; - reset-names = "evea", "exiv", "adamv"; - resets = <&sys_rst 41>, <&sys_rst 42>, <&adamv_rst 0>; - #sound-dai-cells = <1>; - }; diff --git a/Documentation/devicetree/bindings/sound/wm8960.txt b/Documentation/devicetree/bindings/sound/wm8960.txt index 6d29ac3750eeea29da05a361b527580e65d6f76f..85d3b287108ce5031015c3b76f522713a0d08b47 100644 --- a/Documentation/devicetree/bindings/sound/wm8960.txt +++ b/Documentation/devicetree/bindings/sound/wm8960.txt @@ -21,6 +21,17 @@ Optional properties: enabled and disabled together with HP_L and HP_R pins in response to jack detect events. + - wlf,hp-cfg: A list of headphone jack detect configuration register values. + The list must be 3 entries long. + hp-cfg[0]: HPSEL[1:0] of R48 (Additional Control 4). + hp-cfg[1]: {HPSWEN:HPSWPOL} of R24 (Additional Control 2). + hp-cfg[2]: {TOCLKSEL:TOEN} of R23 (Additional Control 1). + + - wlf,gpio-cfg: A list of GPIO configuration register values. + The list must be 2 entries long. + gpio-cfg[0]: ALRCGPIO of R9 (Audio interface) + gpio-cfg[1]: {GPIOPOL:GPIOSEL[2:0]} of R48 (Additional Control 4). + Example: wm8960: codec@1a { diff --git a/Documentation/devicetree/bindings/sound/wm8994.txt b/Documentation/devicetree/bindings/sound/wm8994.txt index 367b58ce1bb92051f11239faece35f459ba99db3..8fa947509c10c294a23261e51d79ca08b7c356fd 100644 --- a/Documentation/devicetree/bindings/sound/wm8994.txt +++ b/Documentation/devicetree/bindings/sound/wm8994.txt @@ -68,6 +68,29 @@ Optional properties: - wlf,csnaddr-pd : If present enable the internal pull-down resistor on the CS/ADDR pin. +Pins on the device (for linking into audio routes): + + * IN1LN + * IN1LP + * IN2LN + * IN2LP:VXRN + * IN1RN + * IN1RP + * IN2RN + * IN2RP:VXRP + * SPKOUTLP + * SPKOUTLN + * SPKOUTRP + * SPKOUTRN + * HPOUT1L + * HPOUT1R + * HPOUT2P + * HPOUT2N + * LINEOUT1P + * LINEOUT1N + * LINEOUT2P + * LINEOUT2N + Example: wm8994: codec@1a { diff --git a/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml b/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml index 87369264feb96fcac3ef48ec0613e9730175cabc..44ba6765697d891b219d2fc50d28a0933e269982 100644 --- a/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml +++ b/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml @@ -50,7 +50,7 @@ properties: nvmem-cell-names: const: calibration - # See ./thermal.txt for details + # See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details "#thermal-sensor-cells": enum: - 0 diff --git a/Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt b/Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt index 703979dbd577d7d57754cc192bc718632cc2c809..12fc4ef04837f7cf0c1542d8147498507ba1240e 100644 --- a/Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt @@ -6,7 +6,7 @@ transaction. Required properties: - compatible: "amazon,al-thermal". - reg: The physical base address and length of the sensor's registers. -- #thermal-sensor-cells: Must be 1. See ./thermal.txt for a description. +- #thermal-sensor-cells: Must be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. Example: thermal: thermal { diff --git a/Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.yaml b/Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.yaml index f3e68ed03abf89d290fba1016363959140bf56fd..1ab5070c751d5fc24cda59c832a4d80b3c483725 100644 --- a/Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.yaml @@ -23,7 +23,7 @@ properties: compatible: const: brcm,bcm2711-thermal - # See ./thermal.txt for details + # See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details "#thermal-sensor-cells": const: 0 diff --git a/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt index da8c5b73ad105a5fa5bf1510f5ec1f2d1ab462f9..a3e9ec5dc7ac4c91c8694b42f53f5a16cea96ffd 100644 --- a/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt @@ -7,7 +7,7 @@ compatible: should be one of: "brcm,bcm2835-thermal", "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal" reg: Address range of the thermal registers. clocks: Phandle of the clock used by the thermal sensor. -#thermal-sensor-cells: should be 0 (see thermal.txt) +#thermal-sensor-cells: should be 0 (see Documentation/devicetree/bindings/thermal/thermal-sensor.yaml) Example: diff --git a/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt b/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt index cef716a236f1a94179d5c61bde45c79df0890e8f..4b19d80e6558b8faa4cbac6d413933292a9eb5cd 100644 --- a/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt @@ -9,7 +9,7 @@ by /SOCTHERM/tsensor. - clock-names: Input clock name, should be 'thermal_clk'. - clocks: phandles for clock specified in "clock-names" property. -- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description. +- #thermal-sensor-cells: Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. Example : diff --git a/Documentation/devicetree/bindings/thermal/max77620_thermal.txt b/Documentation/devicetree/bindings/thermal/max77620_thermal.txt index 323a3b3822aacfb8236222933ab916df1e58d340..82ed5d4879666b21b97f340e213d5527af037d6a 100644 --- a/Documentation/devicetree/bindings/thermal/max77620_thermal.txt +++ b/Documentation/devicetree/bindings/thermal/max77620_thermal.txt @@ -8,12 +8,12 @@ below threshold level. Required properties: ------------------- -#thermal-sensor-cells: Please refer - for more details. +#thermal-sensor-cells: For more details, please refer to + The value must be 0. For more details, please refer generic thermal DT binding document -. +. Please refer for mfd DT binding document for the MAX77620. diff --git a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt index f8d7831f39740b16225d730b0e698354c1f4d746..1e249c42fae04b4d7dcf59888b8b9a9a7eb260f0 100644 --- a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt @@ -23,7 +23,7 @@ Required properties: - resets: Reference to the reset controller controlling the thermal controller. - mediatek,auxadc: A phandle to the AUXADC which the thermal controller uses - mediatek,apmixedsys: A phandle to the APMIXEDSYS controller. -- #thermal-sensor-cells : Should be 0. See ./thermal.txt for a description. +- #thermal-sensor-cells : Should be 0. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. Optional properties: - nvmem-cells: A phandle to the calibration data provided by a nvmem device. If diff --git a/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt b/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt index f02f38527a6b6397a73f0c3c3935918c7d1d64fb..db880e7ed713e4f9ebe25be652c116ce5a38219a 100644 --- a/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt +++ b/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt @@ -28,9 +28,10 @@ Required properties : See ../reset/reset.txt for details. - reset-names : Must include the following entries: - soctherm -- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description - of this property. See for a - list of valid values when referring to thermal sensors. +- #thermal-sensor-cells : Should be 1. For a description of this property, see + Documentation/devicetree/bindings/thermal/thermal-sensor.yaml. + See for a list of valid values + when referring to thermal sensors. - throttle-cfgs: A sub-node which is a container of configuration for each hardware throttle events. These events can be set as cooling devices. * throttle events: Sub-nodes must be named as "light" or "heavy". @@ -62,7 +63,8 @@ Required properties : TEGRA_SOCTHERM_THROT_LEVEL_MED (75%), TEGRA_SOCTHERM_THROT_LEVEL_HIGH (85%). - #cooling-cells: Should be 1. This cooling device only support on/off state. - See ./thermal.txt for a description of this property. + For a description of this property see: + Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml Optional properties: The following properties are T210 specific and valid only for OCx throttle events. diff --git a/Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt b/Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt index e17c07be270b7ebfe26c1b45a0d02974b0663d84..fc87f6aa1b8f5393d3d9ff8b7acf65b5221f746f 100644 --- a/Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt @@ -8,7 +8,7 @@ exposed by BPMP. The BPMP thermal node must be located directly inside the main BPMP node. See ../firmware/nvidia,tegra186-bpmp.txt for details of the BPMP binding. -This node represents a thermal sensor. See thermal.txt for details of the +This node represents a thermal sensor. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details of the core thermal binding. Required properties: diff --git a/Documentation/devicetree/bindings/thermal/qcom-spmi-temp-alarm.txt b/Documentation/devicetree/bindings/thermal/qcom-spmi-temp-alarm.txt index 0273a92a2a849bb6bcc8b97f4291124b0eec2044..2d5b2ad03314bc7ea2b03cc5209d68db4ebc6258 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-spmi-temp-alarm.txt +++ b/Documentation/devicetree/bindings/thermal/qcom-spmi-temp-alarm.txt @@ -8,7 +8,7 @@ Required properties: - compatible: Should contain "qcom,spmi-temp-alarm". - reg: Specifies the SPMI address. - interrupts: PMIC temperature alarm interrupt. -- #thermal-sensor-cells: Should be 0. See thermal.txt for a description. +- #thermal-sensor-cells: Should be 0. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. Optional properties: - io-channels: Should contain IIO channel specifier for the ADC channel, diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml index adac01c9d9cd3bcd0cd1c147ebf6a0d8a45ba47d..95462e071ab4791297e6e824063b61391d919af4 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml @@ -23,6 +23,7 @@ properties: items: - enum: - qcom,msm8916-tsens + - qcom,msm8939-tsens - qcom,msm8974-tsens - const: qcom,tsens-v0_1 diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt index c6aac9bcacf1cd673244ba8a3d7dce8b38088889..7f94669e9ebef75694e932df25b1a5517577e180 100644 --- a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt @@ -24,7 +24,7 @@ Required properties: - pinctrl-1 : The "default" pinctrl state, it will be set after reset the TSADC controller. - pinctrl-2 : The "sleep" pinctrl state, it will be in for suspend. -- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description. +- #thermal-sensor-cells : Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description. Optional properties: - rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value. diff --git a/Documentation/devicetree/bindings/thermal/tango-thermal.txt b/Documentation/devicetree/bindings/thermal/tango-thermal.txt index 212198d4b9379b70c3ca7572f4619479541bb487..2c918d742867a72c8e549c9f13728aa3c16bd975 100644 --- a/Documentation/devicetree/bindings/thermal/tango-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/tango-thermal.txt @@ -4,7 +4,7 @@ The SMP8758 SoC includes 3 instances of this temperature sensor (in the CPU, video decoder, and PCIe controller). Required properties: -- #thermal-sensor-cells: Should be 0 (see thermal.txt) +- #thermal-sensor-cells: Should be 0 (see Documentation/devicetree/bindings/thermal/thermal-sensor.yaml) - compatible: "sigma,smp8758-thermal" - reg: Address range of the thermal registers diff --git a/Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt b/Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt index 691a09db2fefca3a13ba655fcb323d69e55c90e4..e136946a2f4fd9f42c2736a6e0926166bdc82e2c 100644 --- a/Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt +++ b/Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt @@ -8,7 +8,7 @@ temperature using voltage-temperature lookup table. Required properties: =================== - compatible: Must be "generic-adc-thermal". -- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description +- #thermal-sensor-cells: Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description of this property. Optional properties: =================== diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt deleted file mode 100644 index f78bec19ca358bc7c22697fecc1b6566717d456f..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/thermal/thermal.txt +++ /dev/null @@ -1,586 +0,0 @@ -* Thermal Framework Device Tree descriptor - -This file describes a generic binding to provide a way of -defining hardware thermal structure using device tree. -A thermal structure includes thermal zones and their components, -such as trip points, polling intervals, sensors and cooling devices -binding descriptors. - -The target of device tree thermal descriptors is to describe only -the hardware thermal aspects. The thermal device tree bindings are -not about how the system must control or which algorithm or policy -must be taken in place. - -There are five types of nodes involved to describe thermal bindings: -- thermal sensors: devices which may be used to take temperature - measurements. -- cooling devices: devices which may be used to dissipate heat. -- trip points: describe key temperatures at which cooling is recommended. The - set of points should be chosen based on hardware limits. -- cooling maps: used to describe links between trip points and cooling devices; -- thermal zones: used to describe thermal data within the hardware; - -The following is a description of each of these node types. - -* Thermal sensor devices - -Thermal sensor devices are nodes providing temperature sensing capabilities on -thermal zones. Typical devices are I2C ADC converters and bandgaps. These are -nodes providing temperature data to thermal zones. Thermal sensor devices may -control one or more internal sensors. - -Required property: -- #thermal-sensor-cells: Used to provide sensor device specific information - Type: unsigned while referring to it. Typically 0 on thermal sensor - Size: one cell nodes with only one sensor, and at least 1 on nodes - with several internal sensors, in order - to identify uniquely the sensor instances within - the IC. See thermal zone binding for more details - on how consumers refer to sensor devices. - -* Cooling device nodes - -Cooling devices are nodes providing control on power dissipation. There -are essentially two ways to provide control on power dissipation. First -is by means of regulating device performance, which is known as passive -cooling. A typical passive cooling is a CPU that has dynamic voltage and -frequency scaling (DVFS), and uses lower frequencies as cooling states. -Second is by means of activating devices in order to remove -the dissipated heat, which is known as active cooling, e.g. regulating -fan speeds. In both cases, cooling devices shall have a way to determine -the state of cooling in which the device is. - -Any cooling device has a range of cooling states (i.e. different levels -of heat dissipation). For example a fan's cooling states correspond to -the different fan speeds possible. Cooling states are referred to by -single unsigned integers, where larger numbers mean greater heat -dissipation. The precise set of cooling states associated with a device -should be defined in a particular device's binding. -For more examples of cooling devices, refer to the example sections below. - -Required properties: -- #cooling-cells: Used to provide cooling device specific information - Type: unsigned while referring to it. Must be at least 2, in order - Size: one cell to specify minimum and maximum cooling state used - in the reference. The first cell is the minimum - cooling state requested and the second cell is - the maximum cooling state requested in the reference. - See Cooling device maps section below for more details - on how consumers refer to cooling devices. - -* Trip points - -The trip node is a node to describe a point in the temperature domain -in which the system takes an action. This node describes just the point, -not the action. - -Required properties: -- temperature: An integer indicating the trip temperature level, - Type: signed in millicelsius. - Size: one cell - -- hysteresis: A low hysteresis value on temperature property (above). - Type: unsigned This is a relative value, in millicelsius. - Size: one cell - -- type: a string containing the trip type. Expected values are: - "active": A trip point to enable active cooling - "passive": A trip point to enable passive cooling - "hot": A trip point to notify emergency - "critical": Hardware not reliable. - Type: string - -* Cooling device maps - -The cooling device maps node is a node to describe how cooling devices -get assigned to trip points of the zone. The cooling devices are expected -to be loaded in the target system. - -Required properties: -- cooling-device: A list of phandles of cooling devices with their specifiers, - Type: phandle + referring to which cooling devices are used in this - cooling specifier binding. In the cooling specifier, the first cell - is the minimum cooling state and the second cell - is the maximum cooling state used in this map. -- trip: A phandle of a trip point node within the same thermal - Type: phandle of zone. - trip point node - -Optional property: -- contribution: The cooling contribution to the thermal zone of the - Type: unsigned referred cooling device at the referred trip point. - Size: one cell The contribution is a ratio of the sum - of all cooling contributions within a thermal zone. - -Note: Using the THERMAL_NO_LIMIT (-1UL) constant in the cooling-device phandle -limit specifier means: -(i) - minimum state allowed for minimum cooling state used in the reference. -(ii) - maximum state allowed for maximum cooling state used in the reference. -Refer to include/dt-bindings/thermal/thermal.h for definition of this constant. - -* Thermal zone nodes - -The thermal zone node is the node containing all the required info -for describing a thermal zone, including its cooling device bindings. The -thermal zone node must contain, apart from its own properties, one sub-node -containing trip nodes and one sub-node containing all the zone cooling maps. - -Required properties: -- polling-delay: The maximum number of milliseconds to wait between polls - Type: unsigned when checking this thermal zone. - Size: one cell - -- polling-delay-passive: The maximum number of milliseconds to wait - Type: unsigned between polls when performing passive cooling. - Size: one cell - -- thermal-sensors: A list of thermal sensor phandles and sensor specifier - Type: list of used while monitoring the thermal zone. - phandles + sensor - specifier - -- trips: A sub-node which is a container of only trip point nodes - Type: sub-node required to describe the thermal zone. - -Optional property: -- cooling-maps: A sub-node which is a container of only cooling device - Type: sub-node map nodes, used to describe the relation between trips - and cooling devices. - -- coefficients: An array of integers (one signed cell) containing - Type: array coefficients to compose a linear relation between - Elem size: one cell the sensors listed in the thermal-sensors property. - Elem type: signed Coefficients defaults to 1, in case this property - is not specified. A simple linear polynomial is used: - Z = c0 * x0 + c1 * x1 + ... + c(n-1) * x(n-1) + cn. - - The coefficients are ordered and they match with sensors - by means of sensor ID. Additional coefficients are - interpreted as constant offset. - -- sustainable-power: An estimate of the sustainable power (in mW) that the - Type: unsigned thermal zone can dissipate at the desired - Size: one cell control temperature. For reference, the - sustainable power of a 4'' phone is typically - 2000mW, while on a 10'' tablet is around - 4500mW. - -Note: The delay properties are bound to the maximum dT/dt (temperature -derivative over time) in two situations for a thermal zone: -(i) - when passive cooling is activated (polling-delay-passive); and -(ii) - when the zone just needs to be monitored (polling-delay) or -when active cooling is activated. - -The maximum dT/dt is highly bound to hardware power consumption and dissipation -capability. The delays should be chosen to account for said max dT/dt, -such that a device does not cross several trip boundaries unexpectedly -between polls. Choosing the right polling delays shall avoid having the -device in temperature ranges that may damage the silicon structures and -reduce silicon lifetime. - -* The thermal-zones node - -The "thermal-zones" node is a container for all thermal zone nodes. It shall -contain only sub-nodes describing thermal zones as in the section -"Thermal zone nodes". The "thermal-zones" node appears under "/". - -* Examples - -Below are several examples on how to use thermal data descriptors -using device tree bindings: - -(a) - CPU thermal zone - -The CPU thermal zone example below describes how to setup one thermal zone -using one single sensor as temperature source and many cooling devices and -power dissipation control sources. - -#include - -cpus { - /* - * Here is an example of describing a cooling device for a DVFS - * capable CPU. The CPU node describes its four OPPs. - * The cooling states possible are 0..3, and they are - * used as OPP indexes. The minimum cooling state is 0, which means - * all four OPPs can be available to the system. The maximum - * cooling state is 3, which means only the lowest OPPs (198MHz@0.85V) - * can be available in the system. - */ - cpu0: cpu@0 { - ... - operating-points = < - /* kHz uV */ - 970000 1200000 - 792000 1100000 - 396000 950000 - 198000 850000 - >; - #cooling-cells = <2>; /* min followed by max */ - }; - ... -}; - -&i2c1 { - ... - /* - * A simple fan controller which supports 10 speeds of operation - * (represented as 0-9). - */ - fan0: fan@48 { - ... - #cooling-cells = <2>; /* min followed by max */ - }; -}; - -ocp { - ... - /* - * A simple IC with a single bandgap temperature sensor. - */ - bandgap0: bandgap@0000ed00 { - ... - #thermal-sensor-cells = <0>; - }; -}; - -thermal-zones { - cpu_thermal: cpu-thermal { - polling-delay-passive = <250>; /* milliseconds */ - polling-delay = <1000>; /* milliseconds */ - - thermal-sensors = <&bandgap0>; - - trips { - cpu_alert0: cpu-alert0 { - temperature = <90000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "active"; - }; - cpu_alert1: cpu-alert1 { - temperature = <100000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - cpu_crit: cpu-crit { - temperature = <125000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu_alert0>; - cooling-device = <&fan0 THERMAL_NO_LIMIT 4>; - }; - map1 { - trip = <&cpu_alert1>; - cooling-device = <&fan0 5 THERMAL_NO_LIMIT>, <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; - }; -}; - -In the example above, the ADC sensor (bandgap0) at address 0x0000ED00 is -used to monitor the zone 'cpu-thermal' using its sole sensor. A fan -device (fan0) is controlled via I2C bus 1, at address 0x48, and has ten -different cooling states 0-9. It is used to remove the heat out of -the thermal zone 'cpu-thermal' using its cooling states -from its minimum to 4, when it reaches trip point 'cpu_alert0' -at 90C, as an example of active cooling. The same cooling device is used at -'cpu_alert1', but from 5 to its maximum state. The cpu@0 device is also -linked to the same thermal zone, 'cpu-thermal', as a passive cooling device, -using all its cooling states at trip point 'cpu_alert1', -which is a trip point at 100C. On the thermal zone 'cpu-thermal', at the -temperature of 125C, represented by the trip point 'cpu_crit', the silicon -is not reliable anymore. - -(b) - IC with several internal sensors - -The example below describes how to deploy several thermal zones based off a -single sensor IC, assuming it has several internal sensors. This is a common -case on SoC designs with several internal IPs that may need different thermal -requirements, and thus may have their own sensor to monitor or detect internal -hotspots in their silicon. - -#include - -ocp { - ... - /* - * A simple IC with several bandgap temperature sensors. - */ - bandgap0: bandgap@0000ed00 { - ... - #thermal-sensor-cells = <1>; - }; -}; - -thermal-zones { - cpu_thermal: cpu-thermal { - polling-delay-passive = <250>; /* milliseconds */ - polling-delay = <1000>; /* milliseconds */ - - /* sensor ID */ - thermal-sensors = <&bandgap0 0>; - - trips { - /* each zone within the SoC may have its own trips */ - cpu_alert: cpu-alert { - temperature = <100000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - cpu_crit: cpu-crit { - temperature = <125000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "critical"; - }; - }; - - cooling-maps { - /* each zone within the SoC may have its own cooling */ - ... - }; - }; - - gpu_thermal: gpu-thermal { - polling-delay-passive = <120>; /* milliseconds */ - polling-delay = <1000>; /* milliseconds */ - - /* sensor ID */ - thermal-sensors = <&bandgap0 1>; - - trips { - /* each zone within the SoC may have its own trips */ - gpu_alert: gpu-alert { - temperature = <90000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - gpu_crit: gpu-crit { - temperature = <105000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "critical"; - }; - }; - - cooling-maps { - /* each zone within the SoC may have its own cooling */ - ... - }; - }; - - dsp_thermal: dsp-thermal { - polling-delay-passive = <50>; /* milliseconds */ - polling-delay = <1000>; /* milliseconds */ - - /* sensor ID */ - thermal-sensors = <&bandgap0 2>; - - trips { - /* each zone within the SoC may have its own trips */ - dsp_alert: dsp-alert { - temperature = <90000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - dsp_crit: gpu-crit { - temperature = <135000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "critical"; - }; - }; - - cooling-maps { - /* each zone within the SoC may have its own cooling */ - ... - }; - }; -}; - -In the example above, there is one bandgap IC which has the capability to -monitor three sensors. The hardware has been designed so that sensors are -placed on different places in the DIE to monitor different temperature -hotspots: one for CPU thermal zone, one for GPU thermal zone and the -other to monitor a DSP thermal zone. - -Thus, there is a need to assign each sensor provided by the bandgap IC -to different thermal zones. This is achieved by means of using the -#thermal-sensor-cells property and using the first cell of the sensor -specifier as sensor ID. In the example, then, is used to -monitor CPU thermal zone, is used to monitor GPU thermal -zone and is used to monitor DSP thermal zone. Each zone -may be uncorrelated, having its own dT/dt requirements, trips -and cooling maps. - - -(c) - Several sensors within one single thermal zone - -The example below illustrates how to use more than one sensor within -one thermal zone. - -#include - -&i2c1 { - ... - /* - * A simple IC with a single temperature sensor. - */ - adc: sensor@49 { - ... - #thermal-sensor-cells = <0>; - }; -}; - -ocp { - ... - /* - * A simple IC with a single bandgap temperature sensor. - */ - bandgap0: bandgap@0000ed00 { - ... - #thermal-sensor-cells = <0>; - }; -}; - -thermal-zones { - cpu_thermal: cpu-thermal { - polling-delay-passive = <250>; /* milliseconds */ - polling-delay = <1000>; /* milliseconds */ - - thermal-sensors = <&bandgap0>, /* cpu */ - <&adc>; /* pcb north */ - - /* hotspot = 100 * bandgap - 120 * adc + 484 */ - coefficients = <100 -120 484>; - - trips { - ... - }; - - cooling-maps { - ... - }; - }; -}; - -In some cases, there is a need to use more than one sensor to extrapolate -a thermal hotspot in the silicon. The above example illustrates this situation. -For instance, it may be the case that a sensor external to CPU IP may be placed -close to CPU hotspot and together with internal CPU sensor, it is used -to determine the hotspot. Assuming this is the case for the above example, -the hypothetical extrapolation rule would be: - hotspot = 100 * bandgap - 120 * adc + 484 - -In other context, the same idea can be used to add fixed offset. For instance, -consider the hotspot extrapolation rule below: - hotspot = 1 * adc + 6000 - -In the above equation, the hotspot is always 6C higher than what is read -from the ADC sensor. The binding would be then: - thermal-sensors = <&adc>; - - /* hotspot = 1 * adc + 6000 */ - coefficients = <1 6000>; - -(d) - Board thermal - -The board thermal example below illustrates how to setup one thermal zone -with many sensors and many cooling devices. - -#include - -&i2c1 { - ... - /* - * An IC with several temperature sensor. - */ - adc_dummy: sensor@50 { - ... - #thermal-sensor-cells = <1>; /* sensor internal ID */ - }; -}; - -thermal-zones { - batt-thermal { - polling-delay-passive = <500>; /* milliseconds */ - polling-delay = <2500>; /* milliseconds */ - - /* sensor ID */ - thermal-sensors = <&adc_dummy 4>; - - trips { - ... - }; - - cooling-maps { - ... - }; - }; - - board_thermal: board-thermal { - polling-delay-passive = <1000>; /* milliseconds */ - polling-delay = <2500>; /* milliseconds */ - - /* sensor ID */ - thermal-sensors = <&adc_dummy 0>, /* pcb top edge */ - <&adc_dummy 1>, /* lcd */ - <&adc_dummy 2>; /* back cover */ - /* - * An array of coefficients describing the sensor - * linear relation. E.g.: - * z = c1*x1 + c2*x2 + c3*x3 - */ - coefficients = <1200 -345 890>; - - sustainable-power = <2500>; - - trips { - /* Trips are based on resulting linear equation */ - cpu_trip: cpu-trip { - temperature = <60000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - gpu_trip: gpu-trip { - temperature = <55000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - } - lcd_trip: lcp-trip { - temperature = <53000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; - crit_trip: crit-trip { - temperature = <68000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu_trip>; - cooling-device = <&cpu0 0 2>; - contribution = <55>; - }; - map1 { - trip = <&gpu_trip>; - cooling-device = <&gpu0 0 2>; - contribution = <20>; - }; - map2 { - trip = <&lcd_trip>; - cooling-device = <&lcd0 5 10>; - contribution = <15>; - }; - }; - }; -}; - -The above example is a mix of previous examples, a sensor IP with several internal -sensors used to monitor different zones, one of them is composed by several sensors and -with different cooling devices. diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml index 4165352a590a181479c6f05a0640689ef7d6bca6..b7e94fe8643fef312d84c34408d3d2e854a65d81 100644 --- a/Documentation/devicetree/bindings/trivial-devices.yaml +++ b/Documentation/devicetree/bindings/trivial-devices.yaml @@ -80,8 +80,6 @@ properties: - fsl,mpl3115 # MPR121: Proximity Capacitive Touch Sensor Controller - fsl,mpr121 - # SGTL5000: Ultra Low-Power Audio Codec - - fsl,sgtl5000 # G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface - gmt,g751 # Infineon IR38064 Voltage Regulator diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 936dad22b47eb605a811faa049fe8576181b0adb..403c17a3ff9b7abfbb7b6474720eab3d7aba2bdc 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -20,7 +20,7 @@ patternProperties: "^(keypad|m25p|max8952|max8997|max8998|mpmc),.*": true "^(pinctrl-single|#pinctrl-single|PowerPC),.*": true "^(pl022|pxa-mmc|rcar_sound|rotary-encoder|s5m8767|sdhci),.*": true - "^(simple-audio-card|simple-graph-card|st-plgpio|st-spics|ts),.*": true + "^(simple-audio-card|st-plgpio|st-spics|ts),.*": true # Keep list in alphabetical order. "^70mai,.*": diff --git a/Documentation/driver-api/generic-counter.rst b/Documentation/driver-api/generic-counter.rst index e622f8f6e56a967cd76013c0acbae7a156e29012..b02c52cd69d61efadb14bbcfd04f73daca518d20 100644 --- a/Documentation/driver-api/generic-counter.rst +++ b/Documentation/driver-api/generic-counter.rst @@ -262,7 +262,7 @@ the system. Counter Counts may be allocated via counter_count structures, and respective Counter Signal associations (Synapses) made via counter_synapse structures. Associated counter_synapse structures are -stored as an array and set to the the synapses array member of the +stored as an array and set to the synapses array member of the respective counter_count structure. These counter_count structures are set to the counts array member of an allocated counter_device structure before the Counter is registered to the system. diff --git a/Documentation/driver-api/iio/buffers.rst b/Documentation/driver-api/iio/buffers.rst index e9036ef9f8f48265b69c3526348ee4c600d11ec5..dd64c9c5fb1ede0c7628e2e365a02fe2bf7e30d5 100644 --- a/Documentation/driver-api/iio/buffers.rst +++ b/Documentation/driver-api/iio/buffers.rst @@ -88,7 +88,7 @@ fields in iio_chan_spec definition:: The driver implementing the accelerometer described above will have the following channel definition:: - struct struct iio_chan_spec accel_channels[] = { + struct iio_chan_spec accel_channels[] = { { .type = IIO_ACCEL, .modified = 1, diff --git a/Documentation/driver-api/serial/n_gsm.rst b/Documentation/driver-api/serial/n_gsm.rst index 286e7ff4d2d9e38ca244f5dceb57cad53be6caf7..87dfcd54a96b1473fb8239165fc10bcee29771a2 100644 --- a/Documentation/driver-api/serial/n_gsm.rst +++ b/Documentation/driver-api/serial/n_gsm.rst @@ -5,7 +5,7 @@ GSM 0710 tty multiplexor HOWTO This line discipline implements the GSM 07.10 multiplexing protocol detailed in the following 3GPP document: - http://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip + https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip This document give some hints on how to use this driver with GPRS and 3G modems connected to a physical serial port. diff --git a/Documentation/filesystems/quota.rst b/Documentation/filesystems/quota.rst index a30cdd47c652a4480b75c5af8ab2194a4be0d415..abd4303c546e42c6594f5c847646087df0996707 100644 --- a/Documentation/filesystems/quota.rst +++ b/Documentation/filesystems/quota.rst @@ -18,7 +18,7 @@ Quota limits (and amount of grace time) are set independently for each filesystem. For more details about quota design, see the documentation in quota-tools package -(http://sourceforge.net/projects/linuxquota). +(https://sourceforge.net/projects/linuxquota). Quota netlink interface ======================= @@ -31,11 +31,11 @@ the above events to userspace. There they can be captured by an application and processed accordingly. The interface uses generic netlink framework (see -http://lwn.net/Articles/208755/ and http://people.suug.ch/~tgr/libnl/ for more -details about this layer). The name of the quota generic netlink interface -is "VFS_DQUOT". Definitions of constants below are in . -Since the quota netlink protocol is not namespace aware, quota netlink messages -are sent only in initial network namespace. +https://lwn.net/Articles/208755/ and http://www.infradead.org/~tgr/libnl/ for +more details about this layer). The name of the quota generic netlink interface +is "VFS_DQUOT". Definitions of constants below are in . Since +the quota netlink protocol is not namespace aware, quota netlink messages are +sent only in initial network namespace. Currently, the interface supports only one message type QUOTA_NL_C_WARNING. This command is used to send a notification about any of the above mentioned diff --git a/Documentation/filesystems/udf.rst b/Documentation/filesystems/udf.rst index d9badbf285b26798426804657e310595f4238f7a..f9489ddbb76759d4dee11541434132e70a9b59fb 100644 --- a/Documentation/filesystems/udf.rst +++ b/Documentation/filesystems/udf.rst @@ -72,4 +72,4 @@ For the latest version and toolset see: Documentation on UDF and ECMA 167 is available FREE from: - http://www.osta.org/ - - http://www.ecma-international.org/ + - https://www.ecma-international.org/ diff --git a/Documentation/scsi/advansys.rst b/Documentation/scsi/advansys.rst index e0367e179696a90790e83deab01b29dbc8b0b0a1..7ea12b100ff4107c203f453a67bd3332138452d3 100644 --- a/Documentation/scsi/advansys.rst +++ b/Documentation/scsi/advansys.rst @@ -125,7 +125,7 @@ The following constants can be defined in the source file. c. klogd is started with the appropriate -c parameter (e.g. klogd -c 8) - This will cause printk() messages to be be displayed on the + This will cause printk() messages to be displayed on the current console. Refer to the klogd(8) and syslogd(8) man pages for details. diff --git a/Documentation/scsi/scsi-parameters.rst b/Documentation/scsi/scsi-parameters.rst index 9aba897c97ac9f1248449d4909dc8dfe092a7842..e5f68b431f5c43445271482b6893911a2d549850 100644 --- a/Documentation/scsi/scsi-parameters.rst +++ b/Documentation/scsi/scsi-parameters.rst @@ -94,7 +94,7 @@ parameters may be changed at runtime by the command (/proc/sys/dev/scsi/logging_level). There is also a nice 'scsi_logging_level' script in the S390-tools package, available for download at - http://www-128.ibm.com/developerworks/linux/linux390/s390-tools-1.5.4.html + https://github.com/ibm-s390-tools/s390-tools/blob/master/scripts/scsi_logging_level scsi_mod.scan= [SCSI] sync (default) scans SCSI busses as they are discovered. async scans them in kernel threads, diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst index 72f97d4b01a784e5d75548a1504d117308948feb..c755b1c5e16f27287fd3884ca0553e3a39104a6a 100644 --- a/Documentation/sound/alsa-configuration.rst +++ b/Documentation/sound/alsa-configuration.rst @@ -309,7 +309,7 @@ pcifix This module supports all ADB PCM channels, ac97 mixer, SPDIF, hardware EQ, mpu401, gameport. A3D and wavetable support are still in development. Development and reverse engineering work is being coordinated at -http://savannah.nongnu.org/projects/openvortex/ +https://savannah.nongnu.org/projects/openvortex/ SPDIF output has a copy of the AC97 codec output, unless you use the ``spdif`` pcm device, which allows raw data passthru. The hardware EQ hardware and SPDIF is only present in the Vortex2 and @@ -1575,7 +1575,7 @@ See Documentation/sound/cards/multisound.sh for important information about this driver. Note that it has been discontinued, but the Voyetra Turtle Beach knowledge base entry for it is still available at -http://www.turtlebeach.com +https://www.turtlebeach.com Module snd-msnd-pinnacle ------------------------ @@ -2703,4 +2703,4 @@ Kernel Bugzilla ALSA Developers ML mailto:alsa-devel@alsa-project.org alsa-info.sh script - http://www.alsa-project.org/alsa-info.sh + https://www.alsa-project.org/alsa-info.sh diff --git a/Documentation/sound/cards/audigy-mixer.rst b/Documentation/sound/cards/audigy-mixer.rst index 86213234435fe3e8271af5b1a13f4eef506689b6..998f76e19cdd69788701ba6a1cb2a359268e396a 100644 --- a/Documentation/sound/cards/audigy-mixer.rst +++ b/Documentation/sound/cards/audigy-mixer.rst @@ -331,7 +331,7 @@ WO 9901953 (A1) Execution and Audio Data Sequencing (Jan. 14, 1999) -US Patents (http://www.uspto.gov/) +US Patents (https://www.uspto.gov/) ---------------------------------- US 5925841 diff --git a/Documentation/sound/cards/sb-live-mixer.rst b/Documentation/sound/cards/sb-live-mixer.rst index bcb62fc99bbb74219f777c42a9fea95eb55a0f8a..eccb0f0ffd0ff865c216bf584ed3e2c4471936f4 100644 --- a/Documentation/sound/cards/sb-live-mixer.rst +++ b/Documentation/sound/cards/sb-live-mixer.rst @@ -336,7 +336,7 @@ WO 9901953 (A1) Execution and Audio Data Sequencing (Jan. 14, 1999) -US Patents (http://www.uspto.gov/) +US Patents (https://www.uspto.gov/) ---------------------------------- US 5925841 diff --git a/Documentation/sound/designs/compress-offload.rst b/Documentation/sound/designs/compress-offload.rst index ad4bfbdacc83517e1196c1ef7f86b7381b6041e2..935f325dbc773a8b63edaf84f86e05315a1e315d 100644 --- a/Documentation/sound/designs/compress-offload.rst +++ b/Documentation/sound/designs/compress-offload.rst @@ -151,6 +151,57 @@ Modifications include: - Addition of encoding options when required (derived from OpenMAX IL) - Addition of rateControlSupported (missing in OpenMAX AL) +State Machine +============= + +The compressed audio stream state machine is described below :: + + +----------+ + | | + | OPEN | + | | + +----------+ + | + | + | compr_set_params() + | + v + compr_free() +----------+ + +------------------------------------| | + | | SETUP | + | +-------------------------| |<-------------------------+ + | | compr_write() +----------+ | + | | ^ | + | | | compr_drain_notify() | + | | | or | + | | | compr_stop() | + | | | | + | | +----------+ | + | | | | | + | | | DRAIN | | + | | | | | + | | +----------+ | + | | ^ | + | | | | + | | | compr_drain() | + | | | | + | v | | + | +----------+ +----------+ | + | | | compr_start() | | compr_stop() | + | | PREPARE |------------------->| RUNNING |--------------------------+ + | | | | | | + | +----------+ +----------+ | + | | | ^ | + | |compr_free() | | | + | | compr_pause() | | compr_resume() | + | | | | | + | v v | | + | +----------+ +----------+ | + | | | | | compr_stop() | + +--->| FREE | | PAUSE |---------------------------+ + | | | | + +----------+ +----------+ + Gapless Playback ================ @@ -199,6 +250,38 @@ Sequence flow for gapless would be: (note: order for partial_drain and write for next track can be reversed as well) +Gapless Playback SM +=================== + +For Gapless, we move from running state to partial drain and back, along +with setting of meta_data and signalling for next track :: + + + +----------+ + compr_drain_notify() | | + +------------------------>| RUNNING | + | | | + | +----------+ + | | + | | + | | compr_next_track() + | | + | V + | +----------+ + | | | + | |NEXT_TRACK| + | | | + | +----------+ + | | + | | + | | compr_partial_drain() + | | + | V + | +----------+ + | | | + +------------------------ | PARTIAL_ | + | DRAIN | + +----------+ Not supported ============= diff --git a/Documentation/sound/designs/procfile.rst b/Documentation/sound/designs/procfile.rst index 29a466851fd2e84ef2415db5501076695bd7f1d1..e9f7e0cbdc5fafc382f17336af82d37c6d9f9898 100644 --- a/Documentation/sound/designs/procfile.rst +++ b/Documentation/sound/designs/procfile.rst @@ -91,7 +91,7 @@ PCM Proc Files ``card*/pcm*/xrun_debug`` This file appears when ``CONFIG_SND_DEBUG=y`` and - ``CONFIG_PCM_XRUN_DEBUG=y``. + ``CONFIG_SND_PCM_XRUN_DEBUG=y``. This shows the status of xrun (= buffer overrun/xrun) and invalid PCM position debug/check of ALSA PCM middle layer. It takes an integer value, can be changed by writing to this diff --git a/Documentation/sound/hd-audio/notes.rst b/Documentation/sound/hd-audio/notes.rst index 0f3109d9abc82f91937e136182e888844b7f48b7..cf4d7158af78367640f0d31c061badd3125ef9f8 100644 --- a/Documentation/sound/hd-audio/notes.rst +++ b/Documentation/sound/hd-audio/notes.rst @@ -42,7 +42,7 @@ If you are interested in the deep debugging of HD-audio, read the HD-audio specification at first. The specification is found on Intel's web page, for example: -* http://www.intel.com/standards/hdaudio/ +* https://www.intel.com/standards/hdaudio/ HD-Audio Controller @@ -728,7 +728,7 @@ version can be found on git repository: The script can be fetched directly from the following URL, too: -* http://www.alsa-project.org/alsa-info.sh +* https://www.alsa-project.org/alsa-info.sh Run this script as root, and it will gather the important information such as the module lists, module parameters, proc file contents @@ -818,7 +818,7 @@ proc-compatible output. The hda-analyzer: -* http://git.alsa-project.org/?p=alsa.git;a=tree;f=hda-analyzer +* https://git.alsa-project.org/?p=alsa.git;a=tree;f=hda-analyzer is a part of alsa.git repository in alsa-project.org: diff --git a/Documentation/sound/kernel-api/alsa-driver-api.rst b/Documentation/sound/kernel-api/alsa-driver-api.rst index 14cd138989e359aed15ea3f6bdfdd1902c854435..c8cc651eccf78e8009435947938d2e1b03994d04 100644 --- a/Documentation/sound/kernel-api/alsa-driver-api.rst +++ b/Documentation/sound/kernel-api/alsa-driver-api.rst @@ -99,7 +99,7 @@ ASoC Core API .. kernel-doc:: include/sound/soc.h .. kernel-doc:: sound/soc/soc-core.c .. kernel-doc:: sound/soc/soc-devres.c -.. kernel-doc:: sound/soc/soc-io.c +.. kernel-doc:: sound/soc/soc-component.c .. kernel-doc:: sound/soc/soc-pcm.c .. kernel-doc:: sound/soc/soc-ops.c .. kernel-doc:: sound/soc/soc-compress.c diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst index fa4968817696a2aa8c5dd1f65cc9f2942ff34823..aa9d5ab183d28f38883e440d7598d3f781815489 100644 --- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst +++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst @@ -3579,7 +3579,7 @@ dependent on the bus. For normal devices, pass the device pointer ``SNDRV_DMA_TYPE_DEV`` type. For the continuous buffer unrelated to the bus can be pre-allocated with ``SNDRV_DMA_TYPE_CONTINUOUS`` type. You can pass NULL to the device pointer in that case, which is the -default mode implying to allocate with ``GFP_KRENEL`` flag. +default mode implying to allocate with ``GFP_KERNEL`` flag. If you need a different GFP flag, you can pass it by encoding the flag into the device pointer via a special macro :c:func:`snd_dma_continuous_data()`. diff --git a/Documentation/sound/soc/dai.rst b/Documentation/sound/soc/dai.rst index 2e99183a7a47a8d2362f5c36e95c2f91a8b62e17..009b07e5a0f38284ff1c57fe62febf6cd99f0ffe 100644 --- a/Documentation/sound/soc/dai.rst +++ b/Documentation/sound/soc/dai.rst @@ -17,7 +17,7 @@ frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97 frame is 21uS long and is divided into 13 time slots. The AC97 specification can be found at : -http://www.intel.com/p/en_US/business/design +https://www.intel.com/p/en_US/business/design I2S diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index fe05201e17bec6b6106c0d42414517db5f91242a..cdfd98155311164e93326fee27d5e08fdff4a86d 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -669,6 +669,10 @@ MSRs that have been set successfully. Defines the vcpu responses to the cpuid instruction. Applications should use the KVM_SET_CPUID2 ioctl if available. +Note, when this IOCTL fails, KVM gives no guarantees that previous valid CPUID +configuration (if there is) is not corrupted. Userspace can get a copy of the +resulting CPUID configuration through KVM_GET_CPUID2 in case. + :: struct kvm_cpuid_entry { @@ -4795,6 +4799,7 @@ hardware_exit_reason. /* KVM_EXIT_FAIL_ENTRY */ struct { __u64 hardware_entry_failure_reason; + __u32 cpu; /* if KVM_LAST_CPU */ } fail_entry; If exit_reason is KVM_EXIT_FAIL_ENTRY, the vcpu could not be run due diff --git a/MAINTAINERS b/MAINTAINERS index 08650958108ee168d37cc9e099b13aefbcb19614..c5a91470c103a393e4f2a3b91978de7aab2bd3bc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2309,7 +2309,7 @@ F: drivers/pci/controller/dwc/pcie-qcom.c F: drivers/phy/qualcomm/ F: drivers/power/*/msm* F: drivers/reset/reset-qcom-* -F: drivers/scsi/ufs/ufs-qcom.* +F: drivers/scsi/ufs/ufs-qcom* F: drivers/spi/spi-geni-qcom.c F: drivers/spi/spi-qcom-qspi.c F: drivers/spi/spi-qup.c @@ -3621,6 +3621,7 @@ M: Selvin Xavier M: Devesh Sharma M: Somnath Kotur M: Sriharsha Basavapatna +M: Naresh Kumar PBS L: linux-rdma@vger.kernel.org S: Supported W: http://www.broadcom.com @@ -4386,6 +4387,12 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/connector/ +CONSOLE SUBSYSTEM +M: Greg Kroah-Hartman +S: Supported +F: drivers/video/console/ +F: include/linux/console* + CONTROL GROUP (CGROUP) M: Tejun Heo M: Li Zefan @@ -9043,6 +9050,14 @@ F: include/dt-bindings/interconnect/ F: include/linux/interconnect-provider.h F: include/linux/interconnect.h +INVENSENSE ICM-426xx IMU DRIVER +M: Jean-Baptiste Maneyrol +L: linux-iio@vger.kernel.org +S: Maintained +W https://invensense.tdk.com/ +F: Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +F: drivers/iio/imu/inv_icm42600/ + INVENSENSE MPU-3050 GYROSCOPE DRIVER M: Linus Walleij L: linux-iio@vger.kernel.org @@ -11418,7 +11433,6 @@ F: Documentation/devicetree/bindings/pwm/atmel-pwm.txt F: drivers/pwm/pwm-atmel.c MICROCHIP SAMA5D2-COMPATIBLE ADC DRIVER -M: Ludovic Desroches M: Eugen Hristev L: linux-iio@vger.kernel.org S: Supported @@ -15485,6 +15499,15 @@ S: Maintained F: drivers/misc/phantom.c F: include/uapi/linux/phantom.h +SENSIRION SCD30 CARBON DIOXIDE SENSOR DRIVER +M: Tomasz Duszynski +S: Maintained +F: Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml +F: drivers/iio/chemical/scd30.h +F: drivers/iio/chemical/scd30_core.c +F: drivers/iio/chemical/scd30_i2c.c +F: drivers/iio/chemical/scd30_serial.c + SENSIRION SPS30 AIR POLLUTION SENSOR DRIVER M: Tomasz Duszynski S: Maintained @@ -16184,6 +16207,16 @@ Q: https://patchwork.kernel.org/project/linux-sparse/list/ B: https://bugzilla.kernel.org/enter_bug.cgi?component=Sparse&product=Tools F: include/linux/compiler.h +SPEAKUP CONSOLE SPEECH DRIVER +M: William Hubbs +M: Chris Brannon +M: Kirk Reiser +M: Samuel Thibault +L: speakup@linux-speakup.org +S: Odd Fixes +W: http://www.linux-speakup.org/ +F: drivers/accessibility/speakup/ + SPEAR CLOCK FRAMEWORK SUPPORT M: Viresh Kumar L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -16371,16 +16404,6 @@ L: linux-fbdev@vger.kernel.org S: Maintained F: drivers/staging/sm750fb/ -STAGING - SPEAKUP CONSOLE SPEECH DRIVER -M: William Hubbs -M: Chris Brannon -M: Kirk Reiser -M: Samuel Thibault -L: speakup@linux-speakup.org -S: Odd Fixes -W: http://www.linux-speakup.org/ -F: drivers/staging/speakup/ - STAGING - VIA VT665X DRIVERS M: Forest Bond S: Odd Fixes @@ -17076,6 +17099,14 @@ F: drivers/thermal/cpufreq_cooling.c F: drivers/thermal/cpuidle_cooling.c F: include/linux/cpu_cooling.h +THERMAL/POWER_ALLOCATOR +M: Lukasz Luba +L: linux-pm@vger.kernel.org +S: Maintained +F: Documentation/driver-api/thermal/power_allocator.rst +F: drivers/thermal/gov_power_allocator.c +F: include/trace/events/thermal_power_allocator.h + THINKPAD ACPI EXTRAS DRIVER M: Henrique de Moraes Holschuh L: ibm-acpi-devel@lists.sourceforge.net diff --git a/arch/arm/boot/dts/motorola-mapphone-common.dtsi b/arch/arm/boot/dts/motorola-mapphone-common.dtsi index 06fbffa81636b3c4a8441833a091ef724d46a7ce..1990239cc6af6cf281ef7e64c174a1094783eab7 100644 --- a/arch/arm/boot/dts/motorola-mapphone-common.dtsi +++ b/arch/arm/boot/dts/motorola-mapphone-common.dtsi @@ -140,13 +140,13 @@ compatible = "audio-graph-card"; label = "Droid 4 Audio"; - simple-graph-card,widgets = + widgets = "Speaker", "Earpiece", "Speaker", "Loudspeaker", "Headphone", "Headphone Jack", "Microphone", "Internal Mic"; - simple-graph-card,routing = + routing = "Earpiece", "EP", "Loudspeaker", "SPKR", "Headphone Jack", "HSL", diff --git a/arch/arm64/include/asm/kvm_coproc.h b/arch/arm64/include/asm/kvm_coproc.h index 0185ee8b8b5e032c2b71d2e7f415bce3d2487800..454373704b8a0ee628d57435181fa8fc18680581 100644 --- a/arch/arm64/include/asm/kvm_coproc.h +++ b/arch/arm64/include/asm/kvm_coproc.h @@ -27,12 +27,12 @@ struct kvm_sys_reg_target_table { void kvm_register_target_sys_reg_table(unsigned int target, struct kvm_sys_reg_target_table *table); -int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run); -int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run); -int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run); -int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run); -int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run); -int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run); +int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu); +int kvm_handle_cp14_32(struct kvm_vcpu *vcpu); +int kvm_handle_cp14_64(struct kvm_vcpu *vcpu); +int kvm_handle_cp15_32(struct kvm_vcpu *vcpu); +int kvm_handle_cp15_64(struct kvm_vcpu *vcpu); +int kvm_handle_sys_reg(struct kvm_vcpu *vcpu); #define kvm_coproc_table_init kvm_sys_reg_table_init void kvm_sys_reg_table_init(void); diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index e21d4a01372fe7413392a866c7f1df6c66354257..f81151ad3d3cd4f8394147d25de02d082b4a48eb 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -97,17 +97,6 @@ struct kvm_arch { bool return_nisv_io_abort_to_user; }; -#define KVM_NR_MEM_OBJS 40 - -/* - * We don't want allocation failures within the mmu code, so we preallocate - * enough memory for a single page fault in a cache. - */ -struct kvm_mmu_memory_cache { - int nobjs; - void *objects[KVM_NR_MEM_OBJS]; -}; - struct kvm_vcpu_fault_info { u32 esr_el2; /* Hyp Syndrom Register */ u64 far_el2; /* Hyp Fault Address Register */ @@ -486,18 +475,15 @@ u64 __kvm_call_hyp(void *hypfn, ...); void force_vm_exit(const cpumask_t *mask); void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot); -int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, - int exception_index); -void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run, - int exception_index); +int handle_exit(struct kvm_vcpu *vcpu, int exception_index); +void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index); /* MMIO helpers */ void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data); unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len); -int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run); -int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, - phys_addr_t fault_ipa); +int kvm_handle_mmio_return(struct kvm_vcpu *vcpu); +int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa); int kvm_perf_init(void); int kvm_perf_teardown(void); diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index b12bfc1f051a5f9a3b542352c86e7c67a9ab972c..40be8f6c7351dc1b16884a6b147111deda9f33d2 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -139,7 +139,7 @@ void kvm_free_stage2_pgd(struct kvm *kvm); int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, phys_addr_t pa, unsigned long size, bool writable); -int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run); +int kvm_handle_guest_abort(struct kvm_vcpu *vcpu); void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/include/asm/kvm_types.h b/arch/arm64/include/asm/kvm_types.h new file mode 100644 index 0000000000000000000000000000000000000000..9a126b9e2d7c99d261f91a1ac616d5dece962a1b --- /dev/null +++ b/arch/arm64/include/asm/kvm_types.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_ARM64_KVM_TYPES_H +#define _ASM_ARM64_KVM_TYPES_H + +#define KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE 40 + +#endif /* _ASM_ARM64_KVM_TYPES_H */ + diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 90cb9056144689a2e0471c1220a7b28492e18775..73e12869afe39b5688e985d0f06d5760137979e5 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -270,6 +270,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) vcpu->arch.target = -1; bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES); + vcpu->arch.mmu_page_cache.gfp_zero = __GFP_ZERO; + /* Set up the timer */ kvm_timer_vcpu_init(vcpu); @@ -658,7 +660,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) return ret; if (run->exit_reason == KVM_EXIT_MMIO) { - ret = kvm_handle_mmio_return(vcpu, run); + ret = kvm_handle_mmio_return(vcpu); if (ret) return ret; } @@ -810,11 +812,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) trace_kvm_exit(ret, kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu)); /* Exit types that need handling before we can be preempted */ - handle_exit_early(vcpu, run, ret); + handle_exit_early(vcpu, ret); preempt_enable(); - ret = handle_exit(vcpu, run, ret); + ret = handle_exit(vcpu, ret); } /* Tell userspace about in-kernel device output levels */ diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 5a02d4c90559e794e833ef0ae07a2ca8207b35eb..1df3beafd73fc544d26dc5f644e90db14ba81a48 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -25,7 +25,7 @@ #define CREATE_TRACE_POINTS #include "trace_handle_exit.h" -typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *); +typedef int (*exit_handle_fn)(struct kvm_vcpu *); static void kvm_handle_guest_serror(struct kvm_vcpu *vcpu, u32 esr) { @@ -33,7 +33,7 @@ static void kvm_handle_guest_serror(struct kvm_vcpu *vcpu, u32 esr) kvm_inject_vabt(vcpu); } -static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int handle_hvc(struct kvm_vcpu *vcpu) { int ret; @@ -50,7 +50,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) return ret; } -static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int handle_smc(struct kvm_vcpu *vcpu) { /* * "If an SMC instruction executed at Non-secure EL1 is @@ -69,7 +69,7 @@ static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) * Guest access to FP/ASIMD registers are routed to this handler only * when the system doesn't support FP/ASIMD. */ -static int handle_no_fpsimd(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int handle_no_fpsimd(struct kvm_vcpu *vcpu) { kvm_inject_undefined(vcpu); return 1; @@ -87,7 +87,7 @@ static int handle_no_fpsimd(struct kvm_vcpu *vcpu, struct kvm_run *run) * world-switches and schedule other host processes until there is an * incoming IRQ or FIQ to the VM. */ -static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int kvm_handle_wfx(struct kvm_vcpu *vcpu) { if (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WFx_ISS_WFE) { trace_kvm_wfx_arm64(*vcpu_pc(vcpu), true); @@ -109,16 +109,16 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run) * kvm_handle_guest_debug - handle a debug exception instruction * * @vcpu: the vcpu pointer - * @run: access to the kvm_run structure for results * * We route all debug exceptions through the same handler. If both the * guest and host are using the same debug facilities it will be up to * userspace to re-inject the correct exception for guest delivery. * - * @return: 0 (while setting run->exit_reason), -1 for error + * @return: 0 (while setting vcpu->run->exit_reason), -1 for error */ -static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu) { + struct kvm_run *run = vcpu->run; u32 hsr = kvm_vcpu_get_hsr(vcpu); int ret = 0; @@ -144,7 +144,7 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run) return ret; } -static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu) { u32 hsr = kvm_vcpu_get_hsr(vcpu); @@ -155,7 +155,7 @@ static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run) return 1; } -static int handle_sve(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int handle_sve(struct kvm_vcpu *vcpu) { /* Until SVE is supported for guests: */ kvm_inject_undefined(vcpu); @@ -167,7 +167,7 @@ static int handle_sve(struct kvm_vcpu *vcpu, struct kvm_run *run) * a NOP). If we get here, it is that we didn't fixup ptrauth on exit, and all * that we can do is give the guest an UNDEF. */ -static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu) { kvm_inject_undefined(vcpu); return 1; @@ -212,7 +212,7 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) * KVM_EXIT_DEBUG, otherwise userspace needs to complete its * emulation first. */ -static int handle_trap_exceptions(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int handle_trap_exceptions(struct kvm_vcpu *vcpu) { int handled; @@ -227,7 +227,7 @@ static int handle_trap_exceptions(struct kvm_vcpu *vcpu, struct kvm_run *run) exit_handle_fn exit_handler; exit_handler = kvm_get_exit_handler(vcpu); - handled = exit_handler(vcpu, run); + handled = exit_handler(vcpu); } return handled; @@ -237,9 +237,10 @@ static int handle_trap_exceptions(struct kvm_vcpu *vcpu, struct kvm_run *run) * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on * proper exit to userspace. */ -int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, - int exception_index) +int handle_exit(struct kvm_vcpu *vcpu, int exception_index) { + struct kvm_run *run = vcpu->run; + if (ARM_SERROR_PENDING(exception_index)) { u8 hsr_ec = ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu)); @@ -265,7 +266,7 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, case ARM_EXCEPTION_EL1_SERROR: return 1; case ARM_EXCEPTION_TRAP: - return handle_trap_exceptions(vcpu, run); + return handle_trap_exceptions(vcpu); case ARM_EXCEPTION_HYP_GONE: /* * EL2 has been reset to the hyp-stub. This happens when a guest @@ -289,8 +290,7 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, } /* For exit types that need handling before we can be preempted */ -void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run, - int exception_index) +void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index) { if (ARM_SERROR_PENDING(exception_index)) { if (this_cpu_has_cap(ARM64_HAS_RAS_EXTN)) { diff --git a/arch/arm64/kvm/mmio.c b/arch/arm64/kvm/mmio.c index 4e0366759726d35e729ad5a9dd09f5f2a0fa72ca..158fbe68261109bdbde8a7df9c3b9f9716ba593c 100644 --- a/arch/arm64/kvm/mmio.c +++ b/arch/arm64/kvm/mmio.c @@ -77,9 +77,8 @@ unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len) * or in-kernel IO emulation * * @vcpu: The VCPU pointer - * @run: The VCPU run struct containing the mmio data */ -int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) +int kvm_handle_mmio_return(struct kvm_vcpu *vcpu) { unsigned long data; unsigned int len; @@ -92,6 +91,8 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) vcpu->mmio_needed = 0; if (!kvm_vcpu_dabt_iswrite(vcpu)) { + struct kvm_run *run = vcpu->run; + len = kvm_vcpu_dabt_get_as(vcpu); data = kvm_mmio_read_buf(run->mmio.data, len); @@ -119,9 +120,9 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) return 0; } -int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, - phys_addr_t fault_ipa) +int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa) { + struct kvm_run *run = vcpu->run; unsigned long data; unsigned long rt; int ret; @@ -188,7 +189,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, if (!is_write) memcpy(run->mmio.data, data_buf, len); vcpu->stat.mmio_exit_kernel++; - kvm_handle_mmio_return(vcpu, run); + kvm_handle_mmio_return(vcpu); return 1; } diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 31058e6e7c2a3a42445df11705c66f2b664b1da9..7a7ddc4558a7697a69ca42b581f11a82e02788dd 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -124,38 +124,6 @@ static void stage2_dissolve_pud(struct kvm *kvm, phys_addr_t addr, pud_t *pudp) put_page(virt_to_page(pudp)); } -static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache, - int min, int max) -{ - void *page; - - BUG_ON(max > KVM_NR_MEM_OBJS); - if (cache->nobjs >= min) - return 0; - while (cache->nobjs < max) { - page = (void *)__get_free_page(GFP_PGTABLE_USER); - if (!page) - return -ENOMEM; - cache->objects[cache->nobjs++] = page; - } - return 0; -} - -static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc) -{ - while (mc->nobjs) - free_page((unsigned long)mc->objects[--mc->nobjs]); -} - -static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) -{ - void *p; - - BUG_ON(!mc || !mc->nobjs); - p = mc->objects[--mc->nobjs]; - return p; -} - static void clear_stage2_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr) { p4d_t *p4d_table __maybe_unused = stage2_p4d_offset(kvm, pgd, 0UL); @@ -1132,7 +1100,7 @@ static p4d_t *stage2_get_p4d(struct kvm *kvm, struct kvm_mmu_memory_cache *cache if (stage2_pgd_none(kvm, *pgd)) { if (!cache) return NULL; - p4d = mmu_memory_cache_alloc(cache); + p4d = kvm_mmu_memory_cache_alloc(cache); stage2_pgd_populate(kvm, pgd, p4d); get_page(virt_to_page(pgd)); } @@ -1150,7 +1118,7 @@ static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache if (stage2_p4d_none(kvm, *p4d)) { if (!cache) return NULL; - pud = mmu_memory_cache_alloc(cache); + pud = kvm_mmu_memory_cache_alloc(cache); stage2_p4d_populate(kvm, p4d, pud); get_page(virt_to_page(p4d)); } @@ -1171,7 +1139,7 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache if (stage2_pud_none(kvm, *pud)) { if (!cache) return NULL; - pmd = mmu_memory_cache_alloc(cache); + pmd = kvm_mmu_memory_cache_alloc(cache); stage2_pud_populate(kvm, pud, pmd); get_page(virt_to_page(pud)); } @@ -1377,7 +1345,7 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, if (stage2_pud_none(kvm, *pud)) { if (!cache) return 0; /* ignore calls from kvm_set_spte_hva */ - pmd = mmu_memory_cache_alloc(cache); + pmd = kvm_mmu_memory_cache_alloc(cache); stage2_pud_populate(kvm, pud, pmd); get_page(virt_to_page(pud)); } @@ -1402,7 +1370,7 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, if (pmd_none(*pmd)) { if (!cache) return 0; /* ignore calls from kvm_set_spte_hva */ - pte = mmu_memory_cache_alloc(cache); + pte = kvm_mmu_memory_cache_alloc(cache); kvm_pmd_populate(pmd, pte); get_page(virt_to_page(pmd)); } @@ -1469,7 +1437,7 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, phys_addr_t addr, end; int ret = 0; unsigned long pfn; - struct kvm_mmu_memory_cache cache = { 0, }; + struct kvm_mmu_memory_cache cache = { 0, __GFP_ZERO, NULL, }; end = (guest_ipa + size + PAGE_SIZE - 1) & PAGE_MASK; pfn = __phys_to_pfn(pa); @@ -1480,9 +1448,8 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, if (writable) pte = kvm_s2pte_mkwrite(pte); - ret = mmu_topup_memory_cache(&cache, - kvm_mmu_cache_min_pages(kvm), - KVM_NR_MEM_OBJS); + ret = kvm_mmu_topup_memory_cache(&cache, + kvm_mmu_cache_min_pages(kvm)); if (ret) goto out; spin_lock(&kvm->mmu_lock); @@ -1496,7 +1463,7 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, } out: - mmu_free_memory_cache(&cache); + kvm_mmu_free_memory_cache(&cache); return ret; } @@ -1882,8 +1849,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, mmap_read_unlock(current->mm); /* We need minimum second+third level pages */ - ret = mmu_topup_memory_cache(memcache, kvm_mmu_cache_min_pages(kvm), - KVM_NR_MEM_OBJS); + ret = kvm_mmu_topup_memory_cache(memcache, kvm_mmu_cache_min_pages(kvm)); if (ret) return ret; @@ -2050,7 +2016,6 @@ out: /** * kvm_handle_guest_abort - handles all 2nd stage aborts * @vcpu: the VCPU pointer - * @run: the kvm_run structure * * Any abort that gets to the host is almost guaranteed to be caused by a * missing second stage translation table entry, which can mean that either the @@ -2059,7 +2024,7 @@ out: * space. The distinction is based on the IPA causing the fault and whether this * memory region has been registered as standard RAM by user space. */ -int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) +int kvm_handle_guest_abort(struct kvm_vcpu *vcpu) { unsigned long fault_status; phys_addr_t fault_ipa; @@ -2138,7 +2103,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) * of the page size. */ fault_ipa |= kvm_vcpu_get_hfar(vcpu) & ((1 << 12) - 1); - ret = io_mem_abort(vcpu, run, fault_ipa); + ret = io_mem_abort(vcpu, fault_ipa); goto out_unlock; } @@ -2307,7 +2272,7 @@ int kvm_test_age_hva(struct kvm *kvm, unsigned long hva) void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu) { - mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); + kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); } phys_addr_t kvm_mmu_get_httbr(void) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index d3196671c590759d8bbad6a4f6b22eb845750034..138961d7ebe391e2f22453ad2520cfe82fd42b52 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -2156,7 +2156,7 @@ static const struct sys_reg_desc *find_reg(const struct sys_reg_params *params, return bsearch((void *)pval, table, num, sizeof(table[0]), match_sys_reg); } -int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run) +int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu) { kvm_inject_undefined(vcpu); return 1; @@ -2335,7 +2335,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu, return 1; } -int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) +int kvm_handle_cp15_64(struct kvm_vcpu *vcpu) { const struct sys_reg_desc *target_specific; size_t num; @@ -2346,7 +2346,7 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) target_specific, num); } -int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) +int kvm_handle_cp15_32(struct kvm_vcpu *vcpu) { const struct sys_reg_desc *target_specific; size_t num; @@ -2357,14 +2357,14 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) target_specific, num); } -int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run) +int kvm_handle_cp14_64(struct kvm_vcpu *vcpu) { return kvm_handle_cp_64(vcpu, cp14_64_regs, ARRAY_SIZE(cp14_64_regs), NULL, 0); } -int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run) +int kvm_handle_cp14_32(struct kvm_vcpu *vcpu) { return kvm_handle_cp_32(vcpu, cp14_regs, ARRAY_SIZE(cp14_regs), @@ -2416,9 +2416,8 @@ static void reset_sys_reg_descs(struct kvm_vcpu *vcpu, /** * kvm_handle_sys_reg -- handles a mrs/msr trap on a guest sys_reg access * @vcpu: The VCPU pointer - * @run: The kvm_run struct */ -int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run) +int kvm_handle_sys_reg(struct kvm_vcpu *vcpu) { struct sys_reg_params params; unsigned long esr = kvm_vcpu_get_hsr(vcpu); diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index dd36cba078bc81d401fd23eb5bee710c057bbfdd..c95fa3a2484cf056c9dc4238980acd896ef13ca6 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2182,6 +2182,7 @@ endchoice config KVM_GUEST bool "KVM Guest Kernel" + depends on CPU_MIPS32_R2 depends on BROKEN_ON_SMP help Select this option if building a guest kernel for KVM (Trap & Emulate) diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index 363e7a89d1738f858d41cd3cca55916077e72c2b..d35eaed1668f1a64f25f63c8d25c4e90cbba2f2f 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -335,17 +335,6 @@ struct kvm_mips_tlb { long tlb_lo[2]; }; -#define KVM_NR_MEM_OBJS 4 - -/* - * We don't want allocation failures within the mmu code, so we preallocate - * enough memory for a single page fault in a cache. - */ -struct kvm_mmu_memory_cache { - int nobjs; - void *objects[KVM_NR_MEM_OBJS]; -}; - #define KVM_MIPS_AUX_FPU 0x1 #define KVM_MIPS_AUX_MSA 0x2 @@ -854,8 +843,8 @@ struct kvm_mips_callbacks { const struct kvm_one_reg *reg, s64 v); int (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu); int (*vcpu_put)(struct kvm_vcpu *vcpu, int cpu); - int (*vcpu_run)(struct kvm_run *run, struct kvm_vcpu *vcpu); - void (*vcpu_reenter)(struct kvm_run *run, struct kvm_vcpu *vcpu); + int (*vcpu_run)(struct kvm_vcpu *vcpu); + void (*vcpu_reenter)(struct kvm_vcpu *vcpu); }; extern struct kvm_mips_callbacks *kvm_mips_callbacks; int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks); @@ -910,7 +899,6 @@ extern int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu, extern enum emulation_result kvm_mips_handle_tlbmiss(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu, bool write_fault); @@ -1021,83 +1009,67 @@ static inline bool kvm_is_ifetch_fault(struct kvm_vcpu_arch *vcpu) extern enum emulation_result kvm_mips_emulate_inst(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); long kvm_mips_guest_exception_base(struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_syscall(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_tlbmiss_ld(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_tlbinv_ld(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_tlbmiss_st(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_tlbinv_st(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_tlbmod(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_fpu_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_handle_ri(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_ri_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_bp_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_trap_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_msafpe_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_fpe_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); extern enum emulation_result kvm_mips_emulate_msadis_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); -extern enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, - struct kvm_run *run); +extern enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu); u32 kvm_mips_read_count(struct kvm_vcpu *vcpu); void kvm_mips_write_count(struct kvm_vcpu *vcpu, u32 count); @@ -1126,26 +1098,21 @@ static inline void kvm_vz_lose_htimer(struct kvm_vcpu *vcpu) {} enum emulation_result kvm_mips_check_privilege(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu); enum emulation_result kvm_mips_emulate_cache(union mips_instruction inst, u32 *opc, u32 cause, - struct kvm_run *run, struct kvm_vcpu *vcpu); enum emulation_result kvm_mips_emulate_CP0(union mips_instruction inst, u32 *opc, u32 cause, - struct kvm_run *run, struct kvm_vcpu *vcpu); enum emulation_result kvm_mips_emulate_store(union mips_instruction inst, u32 cause, - struct kvm_run *run, struct kvm_vcpu *vcpu); enum emulation_result kvm_mips_emulate_load(union mips_instruction inst, u32 cause, - struct kvm_run *run, struct kvm_vcpu *vcpu); /* COP0 */ diff --git a/arch/mips/include/asm/kvm_types.h b/arch/mips/include/asm/kvm_types.h new file mode 100644 index 0000000000000000000000000000000000000000..213754d9ef6bfb618da081e1b1fe94acbc756947 --- /dev/null +++ b/arch/mips/include/asm/kvm_types.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_MIPS_KVM_TYPES_H +#define _ASM_MIPS_KVM_TYPES_H + +#define KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE 4 + +#endif /* _ASM_MIPS_KVM_TYPES_H */ diff --git a/arch/mips/kvm/00README.txt b/arch/mips/kvm/00README.txt deleted file mode 100644 index 51617e481aa38d73b7241bcc4dc449afa7f85113..0000000000000000000000000000000000000000 --- a/arch/mips/kvm/00README.txt +++ /dev/null @@ -1,31 +0,0 @@ -KVM/MIPS Trap & Emulate Release Notes -===================================== - -(1) KVM/MIPS should support MIPS32R2 and beyond. It has been tested on the following platforms: - Malta Board with FPGA based 34K - Sigma Designs TangoX board with a 24K based 8654 SoC. - Malta Board with 74K @ 1GHz - -(2) Both Guest kernel and Guest Userspace execute in UM. - Guest User address space: 0x00000000 -> 0x40000000 - Guest Kernel Unmapped: 0x40000000 -> 0x60000000 - Guest Kernel Mapped: 0x60000000 -> 0x80000000 - - Guest Usermode virtual memory is limited to 1GB. - -(2) 16K Page Sizes: Both Host Kernel and Guest Kernel should have the same page size, currently at least 16K. - Note that due to cache aliasing issues, 4K page sizes are NOT supported. - -(3) No HugeTLB Support - Both the host kernel and Guest kernel should have the page size set to 16K. - This will be implemented in a future release. - -(4) KVM/MIPS does not have support for SMP Guests - Linux-3.7-rc2 based SMP guest hangs due to the following code sequence in the generated TLB handlers: - LL/TLBP/SC. Since the TLBP instruction causes a trap the reservation gets cleared - when we ERET back to the guest. This causes the guest to hang in an infinite loop. - This will be fixed in a future release. - -(5) Use Host FPU - Currently KVM/MIPS emulates a 24K CPU without a FPU. - This will be fixed in a future release diff --git a/arch/mips/kvm/Kconfig b/arch/mips/kvm/Kconfig index 2bf02d849a3a8a50d26d4c0c4c763e6288b004bc..032b3fca6cbba0a352f591c382fb91cca3c6971d 100644 --- a/arch/mips/kvm/Kconfig +++ b/arch/mips/kvm/Kconfig @@ -37,10 +37,11 @@ choice config KVM_MIPS_TE bool "Trap & Emulate" + depends on CPU_MIPS32_R2 help Use trap and emulate to virtualize 32-bit guests in user mode. This does not require any special hardware Virtualization support beyond - standard MIPS32/64 r2 or later, but it does require the guest kernel + standard MIPS32 r2 or later, but it does require the guest kernel to be configured with CONFIG_KVM_GUEST=y so that it resides in the user address segment. diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index d242300cacc04371038bf59d954ccc026a59c3dc..703782355318f1e2209c7a9ce08d8e7135f6a2f0 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -1262,7 +1262,6 @@ unsigned int kvm_mips_config5_wrmask(struct kvm_vcpu *vcpu) enum emulation_result kvm_mips_emulate_CP0(union mips_instruction inst, u32 *opc, u32 cause, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -1597,12 +1596,12 @@ dont_update_pc: enum emulation_result kvm_mips_emulate_store(union mips_instruction inst, u32 cause, - struct kvm_run *run, struct kvm_vcpu *vcpu) { int r; enum emulation_result er; u32 rt; + struct kvm_run *run = vcpu->run; void *data = run->mmio.data; unsigned int imme; unsigned long curr_pc; @@ -1863,7 +1862,7 @@ enum emulation_result kvm_mips_emulate_store(union mips_instruction inst, vcpu->arch.gprs[rt], *(u64 *)data); break; default: - kvm_err("Godson Exteneded GS-Store not yet supported (inst=0x%08x)\n", + kvm_err("Godson Extended GS-Store not yet supported (inst=0x%08x)\n", inst.word); break; } @@ -1896,9 +1895,9 @@ out_fail: } enum emulation_result kvm_mips_emulate_load(union mips_instruction inst, - u32 cause, struct kvm_run *run, - struct kvm_vcpu *vcpu) + u32 cause, struct kvm_vcpu *vcpu) { + struct kvm_run *run = vcpu->run; int r; enum emulation_result er; unsigned long curr_pc; @@ -2107,7 +2106,7 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst, vcpu->mmio_needed = 30; /* signed */ break; default: - kvm_err("Godson Exteneded GS-Load for float not yet supported (inst=0x%08x)\n", + kvm_err("Godson Extended GS-Load for float not yet supported (inst=0x%08x)\n", inst.word); break; } @@ -2128,7 +2127,7 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst, run->mmio.phys_addr, run->mmio.len, run->mmio.data); if (!r) { - kvm_mips_complete_mmio_load(vcpu, run); + kvm_mips_complete_mmio_load(vcpu); vcpu->mmio_needed = 0; return EMULATE_DONE; } @@ -2140,7 +2139,6 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst, static enum emulation_result kvm_mips_guest_cache_op(int (*fn)(unsigned long), unsigned long curr_pc, unsigned long addr, - struct kvm_run *run, struct kvm_vcpu *vcpu, u32 cause) { @@ -2168,13 +2166,13 @@ static enum emulation_result kvm_mips_guest_cache_op(int (*fn)(unsigned long), /* no matching guest TLB */ vcpu->arch.host_cp0_badvaddr = addr; vcpu->arch.pc = curr_pc; - kvm_mips_emulate_tlbmiss_ld(cause, NULL, run, vcpu); + kvm_mips_emulate_tlbmiss_ld(cause, NULL, vcpu); return EMULATE_EXCEPT; case KVM_MIPS_TLBINV: /* invalid matching guest TLB */ vcpu->arch.host_cp0_badvaddr = addr; vcpu->arch.pc = curr_pc; - kvm_mips_emulate_tlbinv_ld(cause, NULL, run, vcpu); + kvm_mips_emulate_tlbinv_ld(cause, NULL, vcpu); return EMULATE_EXCEPT; default: break; @@ -2184,7 +2182,6 @@ static enum emulation_result kvm_mips_guest_cache_op(int (*fn)(unsigned long), enum emulation_result kvm_mips_emulate_cache(union mips_instruction inst, u32 *opc, u32 cause, - struct kvm_run *run, struct kvm_vcpu *vcpu) { enum emulation_result er = EMULATE_DONE; @@ -2274,7 +2271,7 @@ enum emulation_result kvm_mips_emulate_cache(union mips_instruction inst, * guest's behalf. */ er = kvm_mips_guest_cache_op(protected_writeback_dcache_line, - curr_pc, va, run, vcpu, cause); + curr_pc, va, vcpu, cause); if (er != EMULATE_DONE) goto done; #ifdef CONFIG_KVM_MIPS_DYN_TRANS @@ -2287,11 +2284,11 @@ enum emulation_result kvm_mips_emulate_cache(union mips_instruction inst, } else if (op_inst == Hit_Invalidate_I) { /* Perform the icache synchronisation on the guest's behalf */ er = kvm_mips_guest_cache_op(protected_writeback_dcache_line, - curr_pc, va, run, vcpu, cause); + curr_pc, va, vcpu, cause); if (er != EMULATE_DONE) goto done; er = kvm_mips_guest_cache_op(protected_flush_icache_line, - curr_pc, va, run, vcpu, cause); + curr_pc, va, vcpu, cause); if (er != EMULATE_DONE) goto done; @@ -2317,7 +2314,6 @@ done: } enum emulation_result kvm_mips_emulate_inst(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { union mips_instruction inst; @@ -2333,14 +2329,14 @@ enum emulation_result kvm_mips_emulate_inst(u32 cause, u32 *opc, switch (inst.r_format.opcode) { case cop0_op: - er = kvm_mips_emulate_CP0(inst, opc, cause, run, vcpu); + er = kvm_mips_emulate_CP0(inst, opc, cause, vcpu); break; #ifndef CONFIG_CPU_MIPSR6 case cache_op: ++vcpu->stat.cache_exits; trace_kvm_exit(vcpu, KVM_TRACE_EXIT_CACHE); - er = kvm_mips_emulate_cache(inst, opc, cause, run, vcpu); + er = kvm_mips_emulate_cache(inst, opc, cause, vcpu); break; #else case spec3_op: @@ -2348,7 +2344,7 @@ enum emulation_result kvm_mips_emulate_inst(u32 cause, u32 *opc, case cache6_op: ++vcpu->stat.cache_exits; trace_kvm_exit(vcpu, KVM_TRACE_EXIT_CACHE); - er = kvm_mips_emulate_cache(inst, opc, cause, run, + er = kvm_mips_emulate_cache(inst, opc, cause, vcpu); break; default: @@ -2388,7 +2384,6 @@ long kvm_mips_guest_exception_base(struct kvm_vcpu *vcpu) enum emulation_result kvm_mips_emulate_syscall(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2423,7 +2418,6 @@ enum emulation_result kvm_mips_emulate_syscall(u32 cause, enum emulation_result kvm_mips_emulate_tlbmiss_ld(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2467,7 +2461,6 @@ enum emulation_result kvm_mips_emulate_tlbmiss_ld(u32 cause, enum emulation_result kvm_mips_emulate_tlbinv_ld(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2509,7 +2502,6 @@ enum emulation_result kvm_mips_emulate_tlbinv_ld(u32 cause, enum emulation_result kvm_mips_emulate_tlbmiss_st(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2551,7 +2543,6 @@ enum emulation_result kvm_mips_emulate_tlbmiss_st(u32 cause, enum emulation_result kvm_mips_emulate_tlbinv_st(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2592,7 +2583,6 @@ enum emulation_result kvm_mips_emulate_tlbinv_st(u32 cause, enum emulation_result kvm_mips_emulate_tlbmod(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2632,7 +2622,6 @@ enum emulation_result kvm_mips_emulate_tlbmod(u32 cause, enum emulation_result kvm_mips_emulate_fpu_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2661,7 +2650,6 @@ enum emulation_result kvm_mips_emulate_fpu_exc(u32 cause, enum emulation_result kvm_mips_emulate_ri_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2696,7 +2684,6 @@ enum emulation_result kvm_mips_emulate_ri_exc(u32 cause, enum emulation_result kvm_mips_emulate_bp_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2731,7 +2718,6 @@ enum emulation_result kvm_mips_emulate_bp_exc(u32 cause, enum emulation_result kvm_mips_emulate_trap_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2766,7 +2752,6 @@ enum emulation_result kvm_mips_emulate_trap_exc(u32 cause, enum emulation_result kvm_mips_emulate_msafpe_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2801,7 +2786,6 @@ enum emulation_result kvm_mips_emulate_msafpe_exc(u32 cause, enum emulation_result kvm_mips_emulate_fpe_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2836,7 +2820,6 @@ enum emulation_result kvm_mips_emulate_fpe_exc(u32 cause, enum emulation_result kvm_mips_emulate_msadis_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2870,7 +2853,6 @@ enum emulation_result kvm_mips_emulate_msadis_exc(u32 cause, } enum emulation_result kvm_mips_handle_ri(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -2959,12 +2941,12 @@ emulate_ri: * branch target), and pass the RI exception to the guest OS. */ vcpu->arch.pc = curr_pc; - return kvm_mips_emulate_ri_exc(cause, opc, run, vcpu); + return kvm_mips_emulate_ri_exc(cause, opc, vcpu); } -enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, - struct kvm_run *run) +enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu) { + struct kvm_run *run = vcpu->run; unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr]; enum emulation_result er = EMULATE_DONE; @@ -3107,7 +3089,6 @@ done: static enum emulation_result kvm_mips_emulate_exc(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { u32 exccode = (cause >> CAUSEB_EXCCODE) & 0x1f; @@ -3145,7 +3126,6 @@ static enum emulation_result kvm_mips_emulate_exc(u32 cause, enum emulation_result kvm_mips_check_privilege(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu) { enum emulation_result er = EMULATE_DONE; @@ -3227,7 +3207,7 @@ enum emulation_result kvm_mips_check_privilege(u32 cause, } if (er == EMULATE_PRIV_FAIL) - kvm_mips_emulate_exc(cause, opc, run, vcpu); + kvm_mips_emulate_exc(cause, opc, vcpu); return er; } @@ -3241,7 +3221,6 @@ enum emulation_result kvm_mips_check_privilege(u32 cause, */ enum emulation_result kvm_mips_handle_tlbmiss(u32 cause, u32 *opc, - struct kvm_run *run, struct kvm_vcpu *vcpu, bool write_fault) { @@ -3265,9 +3244,9 @@ enum emulation_result kvm_mips_handle_tlbmiss(u32 cause, KVM_ENTRYHI_ASID)); if (index < 0) { if (exccode == EXCCODE_TLBL) { - er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu); + er = kvm_mips_emulate_tlbmiss_ld(cause, opc, vcpu); } else if (exccode == EXCCODE_TLBS) { - er = kvm_mips_emulate_tlbmiss_st(cause, opc, run, vcpu); + er = kvm_mips_emulate_tlbmiss_st(cause, opc, vcpu); } else { kvm_err("%s: invalid exc code: %d\n", __func__, exccode); @@ -3282,10 +3261,10 @@ enum emulation_result kvm_mips_handle_tlbmiss(u32 cause, */ if (!TLB_IS_VALID(*tlb, va)) { if (exccode == EXCCODE_TLBL) { - er = kvm_mips_emulate_tlbinv_ld(cause, opc, run, + er = kvm_mips_emulate_tlbinv_ld(cause, opc, vcpu); } else if (exccode == EXCCODE_TLBS) { - er = kvm_mips_emulate_tlbinv_st(cause, opc, run, + er = kvm_mips_emulate_tlbinv_st(cause, opc, vcpu); } else { kvm_err("%s: invalid exc code: %d\n", __func__, diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index 666d3350b4ac17431a0a8291bc263e91cc5dff16..7de85d2253ff5c436446e46358b8d7e7d5688710 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -450,7 +450,6 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; int r = -EINTR; vcpu_load(vcpu); @@ -459,11 +458,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) if (vcpu->mmio_needed) { if (!vcpu->mmio_is_write) - kvm_mips_complete_mmio_load(vcpu, run); + kvm_mips_complete_mmio_load(vcpu); vcpu->mmio_needed = 0; } - if (run->immediate_exit) + if (vcpu->run->immediate_exit) goto out; lose_fpu(1); @@ -480,7 +479,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) */ smp_store_mb(vcpu->mode, IN_GUEST_MODE); - r = kvm_mips_callbacks->vcpu_run(run, vcpu); + r = kvm_mips_callbacks->vcpu_run(vcpu); trace_kvm_out(vcpu); guest_exit_irqoff(); @@ -1236,7 +1235,7 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) * end up causing an exception to be delivered to the Guest * Kernel */ - er = kvm_mips_check_privilege(cause, opc, run, vcpu); + er = kvm_mips_check_privilege(cause, opc, vcpu); if (er == EMULATE_PRIV_FAIL) { goto skip_emul; } else if (er == EMULATE_FAIL) { @@ -1385,7 +1384,7 @@ skip_emul: */ smp_store_mb(vcpu->mode, IN_GUEST_MODE); - kvm_mips_callbacks->vcpu_reenter(run, vcpu); + kvm_mips_callbacks->vcpu_reenter(vcpu); /* * If FPU / MSA are enabled (i.e. the guest's FPU / MSA context diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c index 49bd160f4d85c52d6ce228618536446b63da7b89..87fa8d8a10310740de792aad3461d9e7af5836d5 100644 --- a/arch/mips/kvm/mmu.c +++ b/arch/mips/kvm/mmu.c @@ -25,41 +25,9 @@ #define KVM_MMU_CACHE_MIN_PAGES 2 #endif -static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache, - int min, int max) -{ - void *page; - - BUG_ON(max > KVM_NR_MEM_OBJS); - if (cache->nobjs >= min) - return 0; - while (cache->nobjs < max) { - page = (void *)__get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - cache->objects[cache->nobjs++] = page; - } - return 0; -} - -static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc) -{ - while (mc->nobjs) - free_page((unsigned long)mc->objects[--mc->nobjs]); -} - -static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) -{ - void *p; - - BUG_ON(!mc || !mc->nobjs); - p = mc->objects[--mc->nobjs]; - return p; -} - void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu) { - mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); + kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); } /** @@ -153,7 +121,7 @@ static pte_t *kvm_mips_walk_pgd(pgd_t *pgd, struct kvm_mmu_memory_cache *cache, if (!cache) return NULL; - new_pmd = mmu_memory_cache_alloc(cache); + new_pmd = kvm_mmu_memory_cache_alloc(cache); pmd_init((unsigned long)new_pmd, (unsigned long)invalid_pte_table); pud_populate(NULL, pud, new_pmd); @@ -164,7 +132,7 @@ static pte_t *kvm_mips_walk_pgd(pgd_t *pgd, struct kvm_mmu_memory_cache *cache, if (!cache) return NULL; - new_pte = mmu_memory_cache_alloc(cache); + new_pte = kvm_mmu_memory_cache_alloc(cache); clear_page(new_pte); pmd_populate_kernel(NULL, pmd, new_pte); } @@ -711,8 +679,7 @@ static int kvm_mips_map_page(struct kvm_vcpu *vcpu, unsigned long gpa, goto out; /* We need a minimum of cached pages ready for page table creation */ - err = mmu_topup_memory_cache(memcache, KVM_MMU_CACHE_MIN_PAGES, - KVM_NR_MEM_OBJS); + err = kvm_mmu_topup_memory_cache(memcache, KVM_MMU_CACHE_MIN_PAGES); if (err) goto out; @@ -796,8 +763,7 @@ static pte_t *kvm_trap_emul_pte_for_gva(struct kvm_vcpu *vcpu, int ret; /* We need a minimum of cached pages ready for page table creation */ - ret = mmu_topup_memory_cache(memcache, KVM_MMU_CACHE_MIN_PAGES, - KVM_NR_MEM_OBJS); + ret = kvm_mmu_topup_memory_cache(memcache, KVM_MMU_CACHE_MIN_PAGES); if (ret) return NULL; diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c index 34ad0b46e6100685bba82c6c0d5ce83f58c8b0c9..f8cba51e1054e939d85444d969047115f85ad719 100644 --- a/arch/mips/kvm/trap_emul.c +++ b/arch/mips/kvm/trap_emul.c @@ -67,7 +67,6 @@ static int kvm_trap_emul_no_handler(struct kvm_vcpu *vcpu) static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; - struct kvm_run *run = vcpu->run; u32 __user *opc = (u32 __user *) vcpu->arch.pc; u32 cause = vcpu->arch.host_cp0_cause; enum emulation_result er = EMULATE_DONE; @@ -81,14 +80,14 @@ static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu) * Unusable/no FPU in guest: * deliver guest COP1 Unusable Exception */ - er = kvm_mips_emulate_fpu_exc(cause, opc, run, vcpu); + er = kvm_mips_emulate_fpu_exc(cause, opc, vcpu); } else { /* Restore FPU state */ kvm_own_fpu(vcpu); er = EMULATE_DONE; } } else { - er = kvm_mips_emulate_inst(cause, opc, run, vcpu); + er = kvm_mips_emulate_inst(cause, opc, vcpu); } switch (er) { @@ -97,12 +96,12 @@ static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu) break; case EMULATE_FAIL: - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; break; case EMULATE_WAIT: - run->exit_reason = KVM_EXIT_INTR; + vcpu->run->exit_reason = KVM_EXIT_INTR; ret = RESUME_HOST; break; @@ -116,8 +115,7 @@ static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu) return ret; } -static int kvm_mips_bad_load(u32 cause, u32 *opc, struct kvm_run *run, - struct kvm_vcpu *vcpu) +static int kvm_mips_bad_load(u32 cause, u32 *opc, struct kvm_vcpu *vcpu) { enum emulation_result er; union mips_instruction inst; @@ -125,7 +123,7 @@ static int kvm_mips_bad_load(u32 cause, u32 *opc, struct kvm_run *run, /* A code fetch fault doesn't count as an MMIO */ if (kvm_is_ifetch_fault(&vcpu->arch)) { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; return RESUME_HOST; } @@ -134,23 +132,22 @@ static int kvm_mips_bad_load(u32 cause, u32 *opc, struct kvm_run *run, opc += 1; err = kvm_get_badinstr(opc, vcpu, &inst.word); if (err) { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; return RESUME_HOST; } /* Emulate the load */ - er = kvm_mips_emulate_load(inst, cause, run, vcpu); + er = kvm_mips_emulate_load(inst, cause, vcpu); if (er == EMULATE_FAIL) { kvm_err("Emulate load from MMIO space failed\n"); - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; } else { - run->exit_reason = KVM_EXIT_MMIO; + vcpu->run->exit_reason = KVM_EXIT_MMIO; } return RESUME_HOST; } -static int kvm_mips_bad_store(u32 cause, u32 *opc, struct kvm_run *run, - struct kvm_vcpu *vcpu) +static int kvm_mips_bad_store(u32 cause, u32 *opc, struct kvm_vcpu *vcpu) { enum emulation_result er; union mips_instruction inst; @@ -161,34 +158,33 @@ static int kvm_mips_bad_store(u32 cause, u32 *opc, struct kvm_run *run, opc += 1; err = kvm_get_badinstr(opc, vcpu, &inst.word); if (err) { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; return RESUME_HOST; } /* Emulate the store */ - er = kvm_mips_emulate_store(inst, cause, run, vcpu); + er = kvm_mips_emulate_store(inst, cause, vcpu); if (er == EMULATE_FAIL) { kvm_err("Emulate store to MMIO space failed\n"); - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; } else { - run->exit_reason = KVM_EXIT_MMIO; + vcpu->run->exit_reason = KVM_EXIT_MMIO; } return RESUME_HOST; } -static int kvm_mips_bad_access(u32 cause, u32 *opc, struct kvm_run *run, +static int kvm_mips_bad_access(u32 cause, u32 *opc, struct kvm_vcpu *vcpu, bool store) { if (store) - return kvm_mips_bad_store(cause, opc, run, vcpu); + return kvm_mips_bad_store(cause, opc, vcpu); else - return kvm_mips_bad_load(cause, opc, run, vcpu); + return kvm_mips_bad_load(cause, opc, vcpu); } static int kvm_trap_emul_handle_tlb_mod(struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; - struct kvm_run *run = vcpu->run; u32 __user *opc = (u32 __user *) vcpu->arch.pc; unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; u32 cause = vcpu->arch.host_cp0_cause; @@ -212,12 +208,12 @@ static int kvm_trap_emul_handle_tlb_mod(struct kvm_vcpu *vcpu) * They would indicate stale host TLB entries. */ if (unlikely(index < 0)) { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; return RESUME_HOST; } tlb = vcpu->arch.guest_tlb + index; if (unlikely(!TLB_IS_VALID(*tlb, badvaddr))) { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; return RESUME_HOST; } @@ -226,23 +222,23 @@ static int kvm_trap_emul_handle_tlb_mod(struct kvm_vcpu *vcpu) * exception. Relay that on to the guest so it can handle it. */ if (!TLB_IS_DIRTY(*tlb, badvaddr)) { - kvm_mips_emulate_tlbmod(cause, opc, run, vcpu); + kvm_mips_emulate_tlbmod(cause, opc, vcpu); return RESUME_GUEST; } if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, badvaddr, true)) /* Not writable, needs handling as MMIO */ - return kvm_mips_bad_store(cause, opc, run, vcpu); + return kvm_mips_bad_store(cause, opc, vcpu); return RESUME_GUEST; } else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) { if (kvm_mips_handle_kseg0_tlb_fault(badvaddr, vcpu, true) < 0) /* Not writable, needs handling as MMIO */ - return kvm_mips_bad_store(cause, opc, run, vcpu); + return kvm_mips_bad_store(cause, opc, vcpu); return RESUME_GUEST; } else { /* host kernel addresses are all handled as MMIO */ - return kvm_mips_bad_store(cause, opc, run, vcpu); + return kvm_mips_bad_store(cause, opc, vcpu); } } @@ -276,7 +272,7 @@ static int kvm_trap_emul_handle_tlb_miss(struct kvm_vcpu *vcpu, bool store) * into the shadow host TLB */ - er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu, store); + er = kvm_mips_handle_tlbmiss(cause, opc, vcpu, store); if (er == EMULATE_DONE) ret = RESUME_GUEST; else { @@ -289,14 +285,14 @@ static int kvm_trap_emul_handle_tlb_miss(struct kvm_vcpu *vcpu, bool store) * not expect to ever get them */ if (kvm_mips_handle_kseg0_tlb_fault(badvaddr, vcpu, store) < 0) - ret = kvm_mips_bad_access(cause, opc, run, vcpu, store); + ret = kvm_mips_bad_access(cause, opc, vcpu, store); } else if (KVM_GUEST_KERNEL_MODE(vcpu) && (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1)) { /* * With EVA we may get a TLB exception instead of an address * error when the guest performs MMIO to KSeg1 addresses. */ - ret = kvm_mips_bad_access(cause, opc, run, vcpu, store); + ret = kvm_mips_bad_access(cause, opc, vcpu, store); } else { kvm_err("Illegal TLB %s fault address , cause %#x, PC: %p, BadVaddr: %#lx\n", store ? "ST" : "LD", cause, opc, badvaddr); @@ -320,7 +316,6 @@ static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu) static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; u32 __user *opc = (u32 __user *) vcpu->arch.pc; unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; u32 cause = vcpu->arch.host_cp0_cause; @@ -328,11 +323,11 @@ static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu) if (KVM_GUEST_KERNEL_MODE(vcpu) && (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1)) { - ret = kvm_mips_bad_store(cause, opc, run, vcpu); + ret = kvm_mips_bad_store(cause, opc, vcpu); } else { kvm_err("Address Error (STORE): cause %#x, PC: %p, BadVaddr: %#lx\n", cause, opc, badvaddr); - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; } return ret; @@ -340,18 +335,17 @@ static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu) static int kvm_trap_emul_handle_addr_err_ld(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; u32 __user *opc = (u32 __user *) vcpu->arch.pc; unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; u32 cause = vcpu->arch.host_cp0_cause; int ret = RESUME_GUEST; if (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1) { - ret = kvm_mips_bad_load(cause, opc, run, vcpu); + ret = kvm_mips_bad_load(cause, opc, vcpu); } else { kvm_err("Address Error (LOAD): cause %#x, PC: %p, BadVaddr: %#lx\n", cause, opc, badvaddr); - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; } return ret; @@ -359,17 +353,16 @@ static int kvm_trap_emul_handle_addr_err_ld(struct kvm_vcpu *vcpu) static int kvm_trap_emul_handle_syscall(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; u32 __user *opc = (u32 __user *) vcpu->arch.pc; u32 cause = vcpu->arch.host_cp0_cause; enum emulation_result er = EMULATE_DONE; int ret = RESUME_GUEST; - er = kvm_mips_emulate_syscall(cause, opc, run, vcpu); + er = kvm_mips_emulate_syscall(cause, opc, vcpu); if (er == EMULATE_DONE) ret = RESUME_GUEST; else { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; } return ret; @@ -377,17 +370,16 @@ static int kvm_trap_emul_handle_syscall(struct kvm_vcpu *vcpu) static int kvm_trap_emul_handle_res_inst(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; u32 __user *opc = (u32 __user *) vcpu->arch.pc; u32 cause = vcpu->arch.host_cp0_cause; enum emulation_result er = EMULATE_DONE; int ret = RESUME_GUEST; - er = kvm_mips_handle_ri(cause, opc, run, vcpu); + er = kvm_mips_handle_ri(cause, opc, vcpu); if (er == EMULATE_DONE) ret = RESUME_GUEST; else { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; } return ret; @@ -395,17 +387,16 @@ static int kvm_trap_emul_handle_res_inst(struct kvm_vcpu *vcpu) static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; u32 __user *opc = (u32 __user *) vcpu->arch.pc; u32 cause = vcpu->arch.host_cp0_cause; enum emulation_result er = EMULATE_DONE; int ret = RESUME_GUEST; - er = kvm_mips_emulate_bp_exc(cause, opc, run, vcpu); + er = kvm_mips_emulate_bp_exc(cause, opc, vcpu); if (er == EMULATE_DONE) ret = RESUME_GUEST; else { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; } return ret; @@ -413,17 +404,16 @@ static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu) static int kvm_trap_emul_handle_trap(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; u32 __user *opc = (u32 __user *)vcpu->arch.pc; u32 cause = vcpu->arch.host_cp0_cause; enum emulation_result er = EMULATE_DONE; int ret = RESUME_GUEST; - er = kvm_mips_emulate_trap_exc(cause, opc, run, vcpu); + er = kvm_mips_emulate_trap_exc(cause, opc, vcpu); if (er == EMULATE_DONE) { ret = RESUME_GUEST; } else { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; } return ret; @@ -431,17 +421,16 @@ static int kvm_trap_emul_handle_trap(struct kvm_vcpu *vcpu) static int kvm_trap_emul_handle_msa_fpe(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; u32 __user *opc = (u32 __user *)vcpu->arch.pc; u32 cause = vcpu->arch.host_cp0_cause; enum emulation_result er = EMULATE_DONE; int ret = RESUME_GUEST; - er = kvm_mips_emulate_msafpe_exc(cause, opc, run, vcpu); + er = kvm_mips_emulate_msafpe_exc(cause, opc, vcpu); if (er == EMULATE_DONE) { ret = RESUME_GUEST; } else { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; } return ret; @@ -449,17 +438,16 @@ static int kvm_trap_emul_handle_msa_fpe(struct kvm_vcpu *vcpu) static int kvm_trap_emul_handle_fpe(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; u32 __user *opc = (u32 __user *)vcpu->arch.pc; u32 cause = vcpu->arch.host_cp0_cause; enum emulation_result er = EMULATE_DONE; int ret = RESUME_GUEST; - er = kvm_mips_emulate_fpe_exc(cause, opc, run, vcpu); + er = kvm_mips_emulate_fpe_exc(cause, opc, vcpu); if (er == EMULATE_DONE) { ret = RESUME_GUEST; } else { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; } return ret; @@ -474,7 +462,6 @@ static int kvm_trap_emul_handle_fpe(struct kvm_vcpu *vcpu) static int kvm_trap_emul_handle_msa_disabled(struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; - struct kvm_run *run = vcpu->run; u32 __user *opc = (u32 __user *) vcpu->arch.pc; u32 cause = vcpu->arch.host_cp0_cause; enum emulation_result er = EMULATE_DONE; @@ -486,10 +473,10 @@ static int kvm_trap_emul_handle_msa_disabled(struct kvm_vcpu *vcpu) * No MSA in guest, or FPU enabled and not in FR=1 mode, * guest reserved instruction exception */ - er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu); + er = kvm_mips_emulate_ri_exc(cause, opc, vcpu); } else if (!(kvm_read_c0_guest_config5(cop0) & MIPS_CONF5_MSAEN)) { /* MSA disabled by guest, guest MSA disabled exception */ - er = kvm_mips_emulate_msadis_exc(cause, opc, run, vcpu); + er = kvm_mips_emulate_msadis_exc(cause, opc, vcpu); } else { /* Restore MSA/FPU state */ kvm_own_msa(vcpu); @@ -502,7 +489,7 @@ static int kvm_trap_emul_handle_msa_disabled(struct kvm_vcpu *vcpu) break; case EMULATE_FAIL: - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; break; @@ -1184,8 +1171,7 @@ void kvm_trap_emul_gva_lockless_end(struct kvm_vcpu *vcpu) local_irq_enable(); } -static void kvm_trap_emul_vcpu_reenter(struct kvm_run *run, - struct kvm_vcpu *vcpu) +static void kvm_trap_emul_vcpu_reenter(struct kvm_vcpu *vcpu) { struct mm_struct *kern_mm = &vcpu->arch.guest_kernel_mm; struct mm_struct *user_mm = &vcpu->arch.guest_user_mm; @@ -1228,7 +1214,7 @@ static void kvm_trap_emul_vcpu_reenter(struct kvm_run *run, check_mmu_context(mm); } -static int kvm_trap_emul_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu) +static int kvm_trap_emul_vcpu_run(struct kvm_vcpu *vcpu) { int cpu = smp_processor_id(); int r; @@ -1237,7 +1223,7 @@ static int kvm_trap_emul_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu) kvm_mips_deliver_interrupts(vcpu, kvm_read_c0_guest_cause(vcpu->arch.cop0)); - kvm_trap_emul_vcpu_reenter(run, vcpu); + kvm_trap_emul_vcpu_reenter(vcpu); /* * We use user accessors to access guest memory, but we don't want to @@ -1255,7 +1241,7 @@ static int kvm_trap_emul_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu) */ kvm_mips_suspend_mm(cpu); - r = vcpu->arch.vcpu_run(run, vcpu); + r = vcpu->arch.vcpu_run(vcpu->run, vcpu); /* We may have migrated while handling guest exits */ cpu = smp_processor_id(); diff --git a/arch/mips/kvm/vz.c b/arch/mips/kvm/vz.c index 9d03bd0a604acbdb26d44c7924e090a5387b3f63..3932f767e93867e0358b33717554143c0c35b8d5 100644 --- a/arch/mips/kvm/vz.c +++ b/arch/mips/kvm/vz.c @@ -874,7 +874,6 @@ static void kvm_write_maari(struct kvm_vcpu *vcpu, unsigned long val) static enum emulation_result kvm_vz_gpsi_cop0(union mips_instruction inst, u32 *opc, u32 cause, - struct kvm_run *run, struct kvm_vcpu *vcpu) { struct mips_coproc *cop0 = vcpu->arch.cop0; @@ -1074,7 +1073,6 @@ static enum emulation_result kvm_vz_gpsi_cop0(union mips_instruction inst, static enum emulation_result kvm_vz_gpsi_cache(union mips_instruction inst, u32 *opc, u32 cause, - struct kvm_run *run, struct kvm_vcpu *vcpu) { enum emulation_result er = EMULATE_DONE; @@ -1217,7 +1215,6 @@ static enum emulation_result kvm_trap_vz_handle_gpsi(u32 cause, u32 *opc, { enum emulation_result er = EMULATE_DONE; struct kvm_vcpu_arch *arch = &vcpu->arch; - struct kvm_run *run = vcpu->run; union mips_instruction inst; int rd, rt, sel; int err; @@ -1233,12 +1230,12 @@ static enum emulation_result kvm_trap_vz_handle_gpsi(u32 cause, u32 *opc, switch (inst.r_format.opcode) { case cop0_op: - er = kvm_vz_gpsi_cop0(inst, opc, cause, run, vcpu); + er = kvm_vz_gpsi_cop0(inst, opc, cause, vcpu); break; #ifndef CONFIG_CPU_MIPSR6 case cache_op: trace_kvm_exit(vcpu, KVM_TRACE_EXIT_CACHE); - er = kvm_vz_gpsi_cache(inst, opc, cause, run, vcpu); + er = kvm_vz_gpsi_cache(inst, opc, cause, vcpu); break; #endif #ifdef CONFIG_CPU_LOONGSON64 @@ -1251,7 +1248,7 @@ static enum emulation_result kvm_trap_vz_handle_gpsi(u32 cause, u32 *opc, #ifdef CONFIG_CPU_MIPSR6 case cache6_op: trace_kvm_exit(vcpu, KVM_TRACE_EXIT_CACHE); - er = kvm_vz_gpsi_cache(inst, opc, cause, run, vcpu); + er = kvm_vz_gpsi_cache(inst, opc, cause, vcpu); break; #endif case rdhwr_op: @@ -1553,7 +1550,6 @@ static int kvm_trap_vz_handle_guest_exit(struct kvm_vcpu *vcpu) */ static int kvm_trap_vz_handle_cop_unusable(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; u32 cause = vcpu->arch.host_cp0_cause; enum emulation_result er = EMULATE_FAIL; int ret = RESUME_GUEST; @@ -1581,7 +1577,7 @@ static int kvm_trap_vz_handle_cop_unusable(struct kvm_vcpu *vcpu) break; case EMULATE_FAIL: - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; break; @@ -1600,8 +1596,6 @@ static int kvm_trap_vz_handle_cop_unusable(struct kvm_vcpu *vcpu) */ static int kvm_trap_vz_handle_msa_disabled(struct kvm_vcpu *vcpu) { - struct kvm_run *run = vcpu->run; - /* * If MSA not present or not exposed to guest or FR=0, the MSA operation * should have been treated as a reserved instruction! @@ -1612,7 +1606,7 @@ static int kvm_trap_vz_handle_msa_disabled(struct kvm_vcpu *vcpu) (read_gc0_status() & (ST0_CU1 | ST0_FR)) == ST0_CU1 || !(read_gc0_config5() & MIPS_CONF5_MSAEN) || vcpu->arch.aux_inuse & KVM_MIPS_AUX_MSA) { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; return RESUME_HOST; } @@ -1648,7 +1642,7 @@ static int kvm_trap_vz_handle_tlb_ld_miss(struct kvm_vcpu *vcpu) } /* Treat as MMIO */ - er = kvm_mips_emulate_load(inst, cause, run, vcpu); + er = kvm_mips_emulate_load(inst, cause, vcpu); if (er == EMULATE_FAIL) { kvm_err("Guest Emulate Load from MMIO space failed: PC: %p, BadVaddr: %#lx\n", opc, badvaddr); @@ -1695,7 +1689,7 @@ static int kvm_trap_vz_handle_tlb_st_miss(struct kvm_vcpu *vcpu) } /* Treat as MMIO */ - er = kvm_mips_emulate_store(inst, cause, run, vcpu); + er = kvm_mips_emulate_store(inst, cause, vcpu); if (er == EMULATE_FAIL) { kvm_err("Guest Emulate Store to MMIO space failed: PC: %p, BadVaddr: %#lx\n", opc, badvaddr); @@ -3242,7 +3236,7 @@ static void kvm_vz_flush_shadow_memslot(struct kvm *kvm, kvm_vz_flush_shadow_all(kvm); } -static void kvm_vz_vcpu_reenter(struct kvm_run *run, struct kvm_vcpu *vcpu) +static void kvm_vz_vcpu_reenter(struct kvm_vcpu *vcpu) { int cpu = smp_processor_id(); int preserve_guest_tlb; @@ -3258,7 +3252,7 @@ static void kvm_vz_vcpu_reenter(struct kvm_run *run, struct kvm_vcpu *vcpu) kvm_vz_vcpu_load_wired(vcpu); } -static int kvm_vz_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu) +static int kvm_vz_vcpu_run(struct kvm_vcpu *vcpu) { int cpu = smp_processor_id(); int r; @@ -3271,7 +3265,7 @@ static int kvm_vz_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu) kvm_vz_vcpu_load_tlb(vcpu, cpu); kvm_vz_vcpu_load_wired(vcpu); - r = vcpu->arch.vcpu_run(run, vcpu); + r = vcpu->arch.vcpu_run(vcpu->run, vcpu); kvm_vz_vcpu_save_wired(vcpu); diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild index dadbcf3a0b1e77a2e62d2586c95302af24e5421e..2d444d09b5533e87d21724c0046def909fa3c0d0 100644 --- a/arch/powerpc/include/asm/Kbuild +++ b/arch/powerpc/include/asm/Kbuild @@ -4,6 +4,7 @@ generated-y += syscall_table_64.h generated-y += syscall_table_c32.h generated-y += syscall_table_spu.h generic-y += export.h +generic-y += kvm_types.h generic-y += local64.h generic-y += mcs_spinlock.h generic-y += vtime.h diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild index 83f6e85de7bc3495de367c56d6cf7df5ab4358d4..319efa0e6d024fecd1e503c9d722079ce1db213e 100644 --- a/arch/s390/include/asm/Kbuild +++ b/arch/s390/include/asm/Kbuild @@ -6,5 +6,6 @@ generated-y += unistd_nr.h generic-y += asm-offsets.h generic-y += export.h +generic-y += kvm_types.h generic-y += local64.h generic-y += mcs_spinlock.h diff --git a/arch/s390/include/asm/diag.h b/arch/s390/include/asm/diag.h index 0036eab14391d35854a9540c5a1d64033f3eab1c..ca8f85b53a902f2368129d0008828b4ec1b7da8a 100644 --- a/arch/s390/include/asm/diag.h +++ b/arch/s390/include/asm/diag.h @@ -298,10 +298,8 @@ struct diag26c_mac_resp { union diag318_info { unsigned long val; struct { - unsigned int cpnc : 8; - unsigned int cpvc_linux : 24; - unsigned char cpvc_distro[3]; - unsigned char zero; + unsigned long cpnc : 8; + unsigned long cpvc : 56; }; }; diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 6ea0820e7c7f05cd8b113bb7c287b592bc69b68f..463c24e26000f0c8acbc830b335d06be258c6033 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -260,7 +260,8 @@ struct kvm_s390_sie_block { __u32 scaol; /* 0x0064 */ __u8 sdf; /* 0x0068 */ __u8 epdx; /* 0x0069 */ - __u8 reserved6a[2]; /* 0x006a */ + __u8 cpnc; /* 0x006a */ + __u8 reserved6b; /* 0x006b */ __u32 todpr; /* 0x006c */ #define GISA_FORMAT1 0x00000001 __u32 gd; /* 0x0070 */ @@ -745,6 +746,7 @@ struct kvm_vcpu_arch { bool gs_enabled; bool skey_enabled; struct kvm_s390_pv_vcpu pv; + union diag318_info diag318_info; }; struct kvm_vm_stat { diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h index 436ec7636927379ff40432478e9f175d886a1e7d..7a6b14874d65c486242982d3bccabc4891b8fbda 100644 --- a/arch/s390/include/uapi/asm/kvm.h +++ b/arch/s390/include/uapi/asm/kvm.h @@ -231,11 +231,13 @@ struct kvm_guest_debug_arch { #define KVM_SYNC_GSCB (1UL << 9) #define KVM_SYNC_BPBC (1UL << 10) #define KVM_SYNC_ETOKEN (1UL << 11) +#define KVM_SYNC_DIAG318 (1UL << 12) #define KVM_SYNC_S390_VALID_FIELDS \ (KVM_SYNC_PREFIX | KVM_SYNC_GPRS | KVM_SYNC_ACRS | KVM_SYNC_CRS | \ KVM_SYNC_ARCH0 | KVM_SYNC_PFAULT | KVM_SYNC_VRS | KVM_SYNC_RICCB | \ - KVM_SYNC_FPRS | KVM_SYNC_GSCB | KVM_SYNC_BPBC | KVM_SYNC_ETOKEN) + KVM_SYNC_FPRS | KVM_SYNC_GSCB | KVM_SYNC_BPBC | KVM_SYNC_ETOKEN | \ + KVM_SYNC_DIAG318) /* length and alignment of the sdnx as a power of two */ #define SDNXC 8 @@ -264,7 +266,8 @@ struct kvm_sync_regs { __u8 reserved2 : 7; __u8 padding1[51]; /* riccb needs to be 64byte aligned */ __u8 riccb[64]; /* runtime instrumentation controls block */ - __u8 padding2[192]; /* sdnx needs to be 256byte aligned */ + __u64 diag318; /* diagnose 0x318 info */ + __u8 padding2[184]; /* sdnx needs to be 256byte aligned */ union { __u8 sdnx[SDNXL]; /* state description annex */ struct { diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 0c4194d407aca255e86af4f0df1f10a8c3ead271..e600f6953d7ceff50264f79e1f99d8d3a163c665 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -1021,8 +1021,7 @@ static void __init setup_control_program_code(void) { union diag318_info diag318_info = { .cpnc = CPNC_LINUX, - .cpvc_linux = 0, - .cpvc_distro = {0}, + .cpvc = 0, }; if (!sclp.has_diag318) diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index d47c19718615e23f61bc4ff642b632506b5d15c7..66da278a67fba4e0567ff415a917a7eada5e4427 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -545,6 +545,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_S390_AIS_MIGRATION: case KVM_CAP_S390_VCPU_RESETS: case KVM_CAP_SET_GUEST_DEBUG: + case KVM_CAP_S390_DIAG318: r = 1; break; case KVM_CAP_S390_HPAGE_1M: @@ -3267,7 +3268,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) KVM_SYNC_ACRS | KVM_SYNC_CRS | KVM_SYNC_ARCH0 | - KVM_SYNC_PFAULT; + KVM_SYNC_PFAULT | + KVM_SYNC_DIAG318; kvm_s390_set_prefix(vcpu, 0); if (test_kvm_facility(vcpu->kvm, 64)) vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB; @@ -3562,6 +3564,7 @@ static void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu) vcpu->arch.sie_block->pp = 0; vcpu->arch.sie_block->fpf &= ~FPF_BPBC; vcpu->arch.sie_block->todpr = 0; + vcpu->arch.sie_block->cpnc = 0; } } @@ -3579,6 +3582,7 @@ static void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu) regs->etoken = 0; regs->etoken_extension = 0; + regs->diag318 = 0; } int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) @@ -3954,33 +3958,31 @@ bool kvm_arch_can_dequeue_async_page_present(struct kvm_vcpu *vcpu) return true; } -static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu) +static bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu) { hva_t hva; struct kvm_arch_async_pf arch; - int rc; if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID) - return 0; + return false; if ((vcpu->arch.sie_block->gpsw.mask & vcpu->arch.pfault_select) != vcpu->arch.pfault_compare) - return 0; + return false; if (psw_extint_disabled(vcpu)) - return 0; + return false; if (kvm_s390_vcpu_has_irq(vcpu, 0)) - return 0; + return false; if (!(vcpu->arch.sie_block->gcr[0] & CR0_SERVICE_SIGNAL_SUBMASK)) - return 0; + return false; if (!vcpu->arch.gmap->pfault_enabled) - return 0; + return false; hva = gfn_to_hva(vcpu->kvm, gpa_to_gfn(current->thread.gmap_addr)); hva += current->thread.gmap_addr & ~PAGE_MASK; if (read_guest_real(vcpu, vcpu->arch.pfault_token, &arch.pfault_token, 8)) - return 0; + return false; - rc = kvm_setup_async_pf(vcpu, current->thread.gmap_addr, hva, &arch); - return rc; + return kvm_setup_async_pf(vcpu, current->thread.gmap_addr, hva, &arch); } static int vcpu_pre_run(struct kvm_vcpu *vcpu) @@ -4175,8 +4177,9 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) return rc; } -static void sync_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) +static void sync_regs_fmt2(struct kvm_vcpu *vcpu) { + struct kvm_run *kvm_run = vcpu->run; struct runtime_instr_cb *riccb; struct gs_cb *gscb; @@ -4196,6 +4199,10 @@ static void sync_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID) kvm_clear_async_pf_completion_queue(vcpu); } + if (kvm_run->kvm_dirty_regs & KVM_SYNC_DIAG318) { + vcpu->arch.diag318_info.val = kvm_run->s.regs.diag318; + vcpu->arch.sie_block->cpnc = vcpu->arch.diag318_info.cpnc; + } /* * If userspace sets the riccb (e.g. after migration) to a valid state, * we should enable RI here instead of doing the lazy enablement. @@ -4242,8 +4249,10 @@ static void sync_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) /* SIE will load etoken directly from SDNX and therefore kvm_run */ } -static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) +static void sync_regs(struct kvm_vcpu *vcpu) { + struct kvm_run *kvm_run = vcpu->run; + if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX) kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix); if (kvm_run->kvm_dirty_regs & KVM_SYNC_CRS) { @@ -4272,7 +4281,7 @@ static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) /* Sync fmt2 only data */ if (likely(!kvm_s390_pv_cpu_is_protected(vcpu))) { - sync_regs_fmt2(vcpu, kvm_run); + sync_regs_fmt2(vcpu); } else { /* * In several places we have to modify our internal view to @@ -4291,12 +4300,15 @@ static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) kvm_run->kvm_dirty_regs = 0; } -static void store_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) +static void store_regs_fmt2(struct kvm_vcpu *vcpu) { + struct kvm_run *kvm_run = vcpu->run; + kvm_run->s.regs.todpr = vcpu->arch.sie_block->todpr; kvm_run->s.regs.pp = vcpu->arch.sie_block->pp; kvm_run->s.regs.gbea = vcpu->arch.sie_block->gbea; kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC; + kvm_run->s.regs.diag318 = vcpu->arch.diag318_info.val; if (MACHINE_HAS_GS) { __ctl_set_bit(2, 4); if (vcpu->arch.gs_enabled) @@ -4312,8 +4324,10 @@ static void store_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) /* SIE will save etoken directly into SDNX and therefore kvm_run */ } -static void store_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) +static void store_regs(struct kvm_vcpu *vcpu) { + struct kvm_run *kvm_run = vcpu->run; + kvm_run->psw_mask = vcpu->arch.sie_block->gpsw.mask; kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr; kvm_run->s.regs.prefix = kvm_s390_get_prefix(vcpu); @@ -4332,7 +4346,7 @@ static void store_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc; current->thread.fpu.regs = vcpu->arch.host_fpregs.regs; if (likely(!kvm_s390_pv_cpu_is_protected(vcpu))) - store_regs_fmt2(vcpu, kvm_run); + store_regs_fmt2(vcpu); } int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) @@ -4370,7 +4384,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) goto out; } - sync_regs(vcpu, kvm_run); + sync_regs(vcpu); enable_cpu_timer_accounting(vcpu); might_fault(); @@ -4392,7 +4406,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) } disable_cpu_timer_accounting(vcpu); - store_regs(vcpu, kvm_run); + store_regs(vcpu); kvm_sigset_deactivate(vcpu); diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index 9e9056cebfcfb8339890ac3b0fe9ab688a70850c..4f3cbf6003a9d4073f02396b703a3f60edcf1c71 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c @@ -548,6 +548,7 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) scb_s->ecd |= scb_o->ecd & ECD_ETOKENF; scb_s->hpid = HPID_VSIE; + scb_s->cpnc = scb_o->cpnc; prepare_ibc(vcpu, vsie_page); rc = shadow_crycb(vcpu, vsie_page); diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 4f2a4ac8a82bbe03f92ebfb338fc91df5d3c3aaf..14ad9f495fe6937a9d0a5a164619a84e82a89859 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -184,11 +184,6 @@ void line_flush_chars(struct tty_struct *tty) line_flush_buffer(tty); } -int line_put_char(struct tty_struct *tty, unsigned char ch) -{ - return line_write(tty, &ch, sizeof(ch)); -} - int line_write(struct tty_struct *tty, const unsigned char *buf, int len) { struct line *line = tty->driver_data; diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h index a151ff5155efe08a645079f146c7b34cc9e6ebb8..01d21e76144f3e14fa81e5598dc26c76520c76b7 100644 --- a/arch/um/drivers/line.h +++ b/arch/um/drivers/line.h @@ -66,7 +66,6 @@ extern int line_setup(char **conf, unsigned nlines, char **def, char *init, char *name); extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); -extern int line_put_char(struct tty_struct *tty, unsigned char ch); extern void line_set_termios(struct tty_struct *tty, struct ktermios * old); extern int line_chars_in_buffer(struct tty_struct *tty); extern void line_flush_buffer(struct tty_struct *tty); diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 26c5716fac0fe8c68600889ca307345fb04d3eee..6476b28d7c5ec0707b62d88fdf71a99b46deff0e 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -95,7 +95,6 @@ static const struct tty_operations ssl_ops = { .open = line_open, .close = line_close, .write = line_write, - .put_char = line_put_char, .write_room = line_write_room, .chars_in_buffer = line_chars_in_buffer, .flush_buffer = line_flush_buffer, diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 0021d7ffb528c387d8378687a56e3508cf0615a4..37b127941e6f1582c78f79c107608bdc0698ed45 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -102,7 +102,6 @@ static const struct tty_operations console_ops = { .install = con_install, .close = line_close, .write = line_write, - .put_char = line_put_char, .write_room = line_write_room, .chars_in_buffer = line_chars_in_buffer, .flush_buffer = line_flush_buffer, diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index fd03cefabd34de8b2327893852a8325f9f7e1663..9a2849527dd753dca5e5404bb04edac377d025f5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -803,6 +803,7 @@ config KVM_GUEST depends on PARAVIRT select PARAVIRT_CLOCK select ARCH_CPUIDLE_HALTPOLL + select X86_HV_CALLBACK_VECTOR default y help This option enables various optimizations for running under the KVM diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index 07533795b8d2aa3e54fe15797bfb5017927a4f03..275e7fd20310f7a237d2d22f790a2c0928c170a9 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h @@ -67,12 +67,12 @@ static inline void kvm_set_cpu_l1tf_flush_l1d(void) __this_cpu_write(irq_stat.kvm_cpu_l1tf_flush_l1d, 1); } -static inline void kvm_clear_cpu_l1tf_flush_l1d(void) +static __always_inline void kvm_clear_cpu_l1tf_flush_l1d(void) { __this_cpu_write(irq_stat.kvm_cpu_l1tf_flush_l1d, 0); } -static inline bool kvm_get_cpu_l1tf_flush_l1d(void) +static __always_inline bool kvm_get_cpu_l1tf_flush_l1d(void) { return __this_cpu_read(irq_stat.kvm_cpu_l1tf_flush_l1d); } diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h index ff198fc2495ee5a48dfd8d0b062c305279dc9dec..a4336619121208135c18fad12be42d90ba9d603e 100644 --- a/arch/x86/include/asm/idtentry.h +++ b/arch/x86/include/asm/idtentry.h @@ -632,6 +632,10 @@ DECLARE_IDTENTRY_SYSVEC(HYPERVISOR_CALLBACK_VECTOR, sysvec_acrn_hv_callback); DECLARE_IDTENTRY_SYSVEC(HYPERVISOR_CALLBACK_VECTOR, sysvec_xen_hvm_callback); #endif +#ifdef CONFIG_KVM_GUEST +DECLARE_IDTENTRY_SYSVEC(HYPERVISOR_CALLBACK_VECTOR, sysvec_kvm_asyncpf_interrupt); +#endif + #undef X86_TRAP_OTHER #endif diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index be5363b2154096d384beadb70107eaa3b459cff8..5ab3af7275d81d2fc1517eb54e315756f47dd1b8 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -193,8 +193,6 @@ struct x86_exception; enum x86_intercept; enum x86_intercept_stage; -#define KVM_NR_MEM_OBJS 40 - #define KVM_NR_DB_REGS 4 #define DR6_BD (1 << 13) @@ -245,15 +243,6 @@ enum x86_intercept_stage; struct kvm_kernel_irq_routing_entry; -/* - * We don't want allocation failures within the mmu code, so we preallocate - * enough memory for a single page fault in a cache. - */ -struct kvm_mmu_memory_cache { - int nobjs; - void *objects[KVM_NR_MEM_OBJS]; -}; - /* * the pages used as guest page table on soft mmu are tracked by * kvm_memory_slot.arch.gfn_track which is 16 bits, so the role bits used @@ -322,43 +311,6 @@ struct kvm_rmap_head { unsigned long val; }; -struct kvm_mmu_page { - struct list_head link; - struct hlist_node hash_link; - struct list_head lpage_disallowed_link; - - bool unsync; - u8 mmu_valid_gen; - bool mmio_cached; - bool lpage_disallowed; /* Can't be replaced by an equiv large page */ - - /* - * The following two entries are used to key the shadow page in the - * hash table. - */ - union kvm_mmu_page_role role; - gfn_t gfn; - - u64 *spt; - /* hold the gfn of each spte inside spt */ - gfn_t *gfns; - int root_count; /* Currently serving as active root */ - unsigned int unsync_children; - struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */ - DECLARE_BITMAP(unsync_child_bitmap, 512); - -#ifdef CONFIG_X86_32 - /* - * Used out of the mmu-lock to avoid reading spte values while an - * update is in progress; see the comments in __get_spte_lockless(). - */ - int clear_spte_count; -#endif - - /* Number of writes since the last time traversal visited this page. */ - atomic_t write_flooding_count; -}; - struct kvm_pio_request { unsigned long linear_rip; unsigned long count; @@ -384,6 +336,8 @@ struct kvm_mmu_root_info { #define KVM_MMU_NUM_PREV_ROOTS 3 +struct kvm_mmu_page; + /* * x86 supports 4 paging modes (5-level 64-bit, 4-level 64-bit, 3-level 32-bit, * and 2-level 32-bit). The kvm_mmu structure abstracts the details of the @@ -580,6 +534,7 @@ struct kvm_vcpu_arch { unsigned long cr3; unsigned long cr4; unsigned long cr4_guest_owned_bits; + unsigned long cr4_guest_rsvd_bits; unsigned long cr8; u32 host_pkru; u32 pkru; @@ -635,7 +590,8 @@ struct kvm_vcpu_arch { struct kvm_mmu *walk_mmu; struct kvm_mmu_memory_cache mmu_pte_list_desc_cache; - struct kvm_mmu_memory_cache mmu_page_cache; + struct kvm_mmu_memory_cache mmu_shadow_page_cache; + struct kvm_mmu_memory_cache mmu_gfn_array_cache; struct kvm_mmu_memory_cache mmu_page_header_cache; /* @@ -683,7 +639,7 @@ struct kvm_vcpu_arch { struct kvm_cpuid_entry2 cpuid_entries[KVM_MAX_CPUID_ENTRIES]; int maxphyaddr; - int tdp_level; + int max_tdp_level; /* emulate context */ @@ -827,6 +783,9 @@ struct kvm_vcpu_arch { /* Flush the L1 Data cache for L1TF mitigation on VMENTER */ bool l1tf_flush_l1d; + /* Host CPU on which VM-entry was most recently attempted */ + unsigned int last_vmentry_cpu; + /* AMD MSRC001_0015 Hardware Configuration */ u64 msr_hwcr; }; @@ -1083,7 +1042,7 @@ struct kvm_x86_ops { void (*hardware_unsetup)(void); bool (*cpu_has_accelerated_tpr)(void); bool (*has_emulated_msr)(u32 index); - void (*cpuid_update)(struct kvm_vcpu *vcpu); + void (*vcpu_after_set_cpuid)(struct kvm_vcpu *vcpu); unsigned int vm_size; int (*vm_init)(struct kvm *kvm); @@ -1098,7 +1057,7 @@ struct kvm_x86_ops { void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu); void (*vcpu_put)(struct kvm_vcpu *vcpu); - void (*update_bp_intercept)(struct kvm_vcpu *vcpu); + void (*update_exception_bitmap)(struct kvm_vcpu *vcpu); int (*get_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr); int (*set_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr); u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg); @@ -1174,10 +1133,10 @@ struct kvm_x86_ops { int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu); int (*set_tss_addr)(struct kvm *kvm, unsigned int addr); int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr); - int (*get_tdp_level)(struct kvm_vcpu *vcpu); u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio); - void (*load_mmu_pgd)(struct kvm_vcpu *vcpu, unsigned long cr3); + void (*load_mmu_pgd)(struct kvm_vcpu *vcpu, unsigned long pgd, + int pgd_level); bool (*has_wbinvd_exit)(void); @@ -1220,7 +1179,6 @@ struct kvm_x86_ops { void (*enable_log_dirty_pt_masked)(struct kvm *kvm, struct kvm_memory_slot *slot, gfn_t offset, unsigned long mask); - int (*write_log_dirty)(struct kvm_vcpu *vcpu, gpa_t l2_gpa); /* pmu operations of sub-arch */ const struct kvm_pmu_ops *pmu_ops; @@ -1281,6 +1239,7 @@ struct kvm_x86_nested_ops { struct kvm_nested_state __user *user_kvm_nested_state, struct kvm_nested_state *kvm_state); bool (*get_vmcs12_pages)(struct kvm_vcpu *vcpu); + int (*write_log_dirty)(struct kvm_vcpu *vcpu, gpa_t l2_gpa); int (*enable_evmcs)(struct kvm_vcpu *vcpu, uint16_t *vmcs_version); @@ -1304,7 +1263,7 @@ struct kvm_arch_async_pf { }; extern u64 __read_mostly host_efer; - +extern bool __read_mostly allow_smaller_maxphyaddr; extern struct kvm_x86_ops kvm_x86_ops; #define __KVM_HAVE_ARCH_VM_ALLOC @@ -1549,20 +1508,8 @@ void kvm_mmu_invpcid_gva(struct kvm_vcpu *vcpu, gva_t gva, unsigned long pcid); void kvm_mmu_new_pgd(struct kvm_vcpu *vcpu, gpa_t new_pgd, bool skip_tlb_flush, bool skip_mmu_sync); -void kvm_configure_mmu(bool enable_tdp, int tdp_page_level); - -static inline gpa_t translate_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access, - struct x86_exception *exception) -{ - return gpa; -} - -static inline struct kvm_mmu_page *page_header(hpa_t shadow_page) -{ - struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT); - - return (struct kvm_mmu_page *)page_private(page); -} +void kvm_configure_mmu(bool enable_tdp, int tdp_max_root_level, + int tdp_huge_page_level); static inline u16 kvm_read_ldt(void) { @@ -1636,7 +1583,15 @@ asmlinkage void kvm_spurious_fault(void); insn "\n\t" \ "jmp 668f \n\t" \ "667: \n\t" \ + "1: \n\t" \ + ".pushsection .discard.instr_begin \n\t" \ + ".long 1b - . \n\t" \ + ".popsection \n\t" \ "call kvm_spurious_fault \n\t" \ + "1: \n\t" \ + ".pushsection .discard.instr_end \n\t" \ + ".long 1b - . \n\t" \ + ".popsection \n\t" \ "668: \n\t" \ _ASM_EXTABLE(666b, 667b) diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h index 49d3a9edb06f64947ee8d6c20b860aed50f068b5..338119852512654b51d6c01befa7af58e6621782 100644 --- a/arch/x86/include/asm/kvm_para.h +++ b/arch/x86/include/asm/kvm_para.h @@ -4,6 +4,7 @@ #include #include +#include #include extern void kvmclock_init(void); @@ -18,7 +19,7 @@ static inline bool kvm_check_and_clear_guest_paused(void) #endif /* CONFIG_KVM_GUEST */ #define KVM_HYPERCALL \ - ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", X86_FEATURE_VMMCALL) + ALTERNATIVE("vmcall", "vmmcall", X86_FEATURE_VMMCALL) /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall * instruction. The hypervisor may replace it with something else but only the diff --git a/arch/x86/include/asm/kvm_types.h b/arch/x86/include/asm/kvm_types.h new file mode 100644 index 0000000000000000000000000000000000000000..08f1b57d3b627b977a3c81ec6d22f2094144db1b --- /dev/null +++ b/arch/x86/include/asm/kvm_types.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_KVM_TYPES_H +#define _ASM_X86_KVM_TYPES_H + +#define KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE 40 + +#endif /* _ASM_X86_KVM_TYPES_H */ diff --git a/arch/x86/include/asm/qspinlock.h b/arch/x86/include/asm/qspinlock.h index 444d6fd9a6d8991bc152721720bb47fc3b258e46..d86ab942219c4277385cc256bbcf4794f38a80df 100644 --- a/arch/x86/include/asm/qspinlock.h +++ b/arch/x86/include/asm/qspinlock.h @@ -32,6 +32,7 @@ extern void native_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val); extern void __pv_init_lock_hash(void); extern void __pv_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val); extern void __raw_callee_save___pv_queued_spin_unlock(struct qspinlock *lock); +extern bool nopvspin; #define queued_spin_unlock queued_spin_unlock /** diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 233c77d056c9f38cad32d696d08499cfc02d5aa1..08320b0b2b276f0ceb82e28b07812d12dfdd0465 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -7,8 +7,11 @@ * Authors: Anthony Liguori */ +#define pr_fmt(fmt) "kvm-guest: " fmt + #include #include +#include #include #include #include @@ -232,16 +235,11 @@ EXPORT_SYMBOL_GPL(kvm_read_and_reset_apf_flags); noinstr bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token) { - u32 reason = kvm_read_and_reset_apf_flags(); + u32 flags = kvm_read_and_reset_apf_flags(); irqentry_state_t state; - switch (reason) { - case KVM_PV_REASON_PAGE_NOT_PRESENT: - case KVM_PV_REASON_PAGE_READY: - break; - default: + if (!flags) return false; - } state = irqentry_enter(regs); instrumentation_begin(); @@ -254,13 +252,13 @@ noinstr bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token) if (unlikely(!(regs->flags & X86_EFLAGS_IF))) panic("Host injected async #PF in interrupt disabled region\n"); - if (reason == KVM_PV_REASON_PAGE_NOT_PRESENT) { + if (flags & KVM_PV_REASON_PAGE_NOT_PRESENT) { if (unlikely(!(user_mode(regs)))) panic("Host injected async #PF in kernel mode\n"); /* Page is swapped out by the host. */ kvm_async_pf_task_wait_schedule(token); } else { - kvm_async_pf_task_wake(token); + WARN_ONCE(1, "Unexpected async PF flags: %x\n", flags); } instrumentation_end(); @@ -268,6 +266,27 @@ noinstr bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token) return true; } +DEFINE_IDTENTRY_SYSVEC(sysvec_kvm_asyncpf_interrupt) +{ + struct pt_regs *old_regs = set_irq_regs(regs); + u32 token; + irqentry_state_t state; + + state = irqentry_enter(regs); + + inc_irq_stat(irq_hv_callback_count); + + if (__this_cpu_read(apf_reason.enabled)) { + token = __this_cpu_read(apf_reason.token); + kvm_async_pf_task_wake(token); + __this_cpu_write(apf_reason.token, 0); + wrmsrl(MSR_KVM_ASYNC_PF_ACK, 1); + } + + irqentry_exit(regs, state); + set_irq_regs(old_regs); +} + static void __init paravirt_ops_setup(void) { pv_info.name = "KVM"; @@ -289,8 +308,8 @@ static void kvm_register_steal_time(void) return; wrmsrl(MSR_KVM_STEAL_TIME, (slow_virt_to_phys(st) | KVM_MSR_ENABLED)); - pr_info("kvm-stealtime: cpu %d, msr %llx\n", - cpu, (unsigned long long) slow_virt_to_phys(st)); + pr_info("stealtime: cpu %d, msr %llx\n", cpu, + (unsigned long long) slow_virt_to_phys(st)); } static DEFINE_PER_CPU_DECRYPTED(unsigned long, kvm_apic_eoi) = KVM_PV_EOI_DISABLED; @@ -311,17 +330,19 @@ static notrace void kvm_guest_apic_eoi_write(u32 reg, u32 val) static void kvm_guest_cpu_init(void) { - if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF) && kvmapf) { - u64 pa; + if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF_INT) && kvmapf) { + u64 pa = slow_virt_to_phys(this_cpu_ptr(&apf_reason)); WARN_ON_ONCE(!static_branch_likely(&kvm_async_pf_enabled)); pa = slow_virt_to_phys(this_cpu_ptr(&apf_reason)); - pa |= KVM_ASYNC_PF_ENABLED; + pa |= KVM_ASYNC_PF_ENABLED | KVM_ASYNC_PF_DELIVERY_AS_INT; if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF_VMEXIT)) pa |= KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT; + wrmsrl(MSR_KVM_ASYNC_PF_INT, HYPERVISOR_CALLBACK_VECTOR); + wrmsrl(MSR_KVM_ASYNC_PF_EN, pa); __this_cpu_write(apf_reason.enabled, 1); pr_info("KVM setup async PF for cpu %d\n", smp_processor_id()); @@ -493,7 +514,8 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector) } else { ret = kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap, (unsigned long)(ipi_bitmap >> BITS_PER_LONG), min, icr); - WARN_ONCE(ret < 0, "KVM: failed to send PV IPI: %ld", ret); + WARN_ONCE(ret < 0, "kvm-guest: failed to send PV IPI: %ld", + ret); min = max = apic_id; ipi_bitmap = 0; } @@ -503,7 +525,8 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector) if (ipi_bitmap) { ret = kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap, (unsigned long)(ipi_bitmap >> BITS_PER_LONG), min, icr); - WARN_ONCE(ret < 0, "KVM: failed to send PV IPI: %ld", ret); + WARN_ONCE(ret < 0, "kvm-guest: failed to send PV IPI: %ld", + ret); } local_irq_restore(flags); @@ -533,7 +556,7 @@ static void kvm_setup_pv_ipi(void) { apic->send_IPI_mask = kvm_send_ipi_mask; apic->send_IPI_mask_allbutself = kvm_send_ipi_mask_allbutself; - pr_info("KVM setup pv IPIs\n"); + pr_info("setup PV IPIs\n"); } static void kvm_smp_send_call_func_ipi(const struct cpumask *mask) @@ -551,13 +574,6 @@ static void kvm_smp_send_call_func_ipi(const struct cpumask *mask) } } -static void __init kvm_smp_prepare_cpus(unsigned int max_cpus) -{ - native_smp_prepare_cpus(max_cpus); - if (kvm_para_has_hint(KVM_HINTS_REALTIME)) - static_branch_disable(&virt_spin_lock_key); -} - static void __init kvm_smp_prepare_boot_cpu(void) { /* @@ -646,19 +662,20 @@ static void __init kvm_guest_init(void) if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) apic_set_eoi_write(kvm_guest_apic_eoi_write); - if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF) && kvmapf) + if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF_INT) && kvmapf) { static_branch_enable(&kvm_async_pf_enabled); + alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, asm_sysvec_kvm_asyncpf_interrupt); + } #ifdef CONFIG_SMP - smp_ops.smp_prepare_cpus = kvm_smp_prepare_cpus; smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu; if (pv_sched_yield_supported()) { smp_ops.send_call_func_ipi = kvm_smp_send_call_func_ipi; - pr_info("KVM setup pv sched yield\n"); + pr_info("setup PV sched yield\n"); } if (cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/kvm:online", kvm_cpu_online, kvm_cpu_down_prepare) < 0) - pr_err("kvm_guest: Failed to install cpu hotplug callbacks\n"); + pr_err("failed to install cpu hotplug callbacks\n"); #else sev_map_percpu_data(); kvm_guest_cpu_init(); @@ -854,16 +871,36 @@ asm( */ void __init kvm_spinlock_init(void) { - /* Does host kernel support KVM_FEATURE_PV_UNHALT? */ - if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT)) + /* + * In case host doesn't support KVM_FEATURE_PV_UNHALT there is still an + * advantage of keeping virt_spin_lock_key enabled: virt_spin_lock() is + * preferred over native qspinlock when vCPU is preempted. + */ + if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT)) { + pr_info("PV spinlocks disabled, no host support\n"); return; + } - if (kvm_para_has_hint(KVM_HINTS_REALTIME)) - return; + /* + * Disable PV spinlocks and use native qspinlock when dedicated pCPUs + * are available. + */ + if (kvm_para_has_hint(KVM_HINTS_REALTIME)) { + pr_info("PV spinlocks disabled with KVM_HINTS_REALTIME hints\n"); + goto out; + } - /* Don't use the pvqspinlock code if there is only 1 vCPU. */ - if (num_possible_cpus() == 1) - return; + if (num_possible_cpus() == 1) { + pr_info("PV spinlocks disabled, single CPU\n"); + goto out; + } + + if (nopvspin) { + pr_info("PV spinlocks disabled, forced by \"nopvspin\" parameter\n"); + goto out; + } + + pr_info("PV spinlocks enabled\n"); __pv_init_lock_hash(); pv_ops.lock.queued_spin_lock_slowpath = __pv_queued_spin_lock_slowpath; @@ -876,6 +913,13 @@ void __init kvm_spinlock_init(void) pv_ops.lock.vcpu_is_preempted = PV_CALLEE_SAVE(__kvm_vcpu_is_preempted); } + /* + * When PV spinlock is enabled which is preferred over + * virt_spin_lock(), virt_spin_lock_key's value is meaningless. + * Just disable it anyway. + */ +out: + static_branch_disable(&virt_spin_lock_key); } #endif /* CONFIG_PARAVIRT_SPINLOCKS */ @@ -895,8 +939,8 @@ static void kvm_enable_host_haltpoll(void *i) void arch_haltpoll_enable(unsigned int cpu) { if (!kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL)) { - pr_err_once("kvm: host does not support poll control\n"); - pr_err_once("kvm: host upgrade recommended\n"); + pr_err_once("host does not support poll control\n"); + pr_err_once("host upgrade recommended\n"); return; } diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 8a294f9747aad2f7feafb945d607d95a4b5d3451..fa873e3e6e90e601c23e03b8c16effece08ac217 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -54,28 +54,38 @@ static u32 xstate_required_size(u64 xstate_bv, bool compacted) #define F feature_bit -int kvm_update_cpuid(struct kvm_vcpu *vcpu) +static int kvm_check_cpuid(struct kvm_vcpu *vcpu) { struct kvm_cpuid_entry2 *best; - struct kvm_lapic *apic = vcpu->arch.apic; - best = kvm_find_cpuid_entry(vcpu, 1, 0); - if (!best) - return 0; + /* + * The existing code assumes virtual address is 48-bit or 57-bit in the + * canonical address checks; exit if it is ever changed. + */ + best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0); + if (best) { + int vaddr_bits = (best->eax & 0xff00) >> 8; + + if (vaddr_bits != 48 && vaddr_bits != 57 && vaddr_bits != 0) + return -EINVAL; + } - /* Update OSXSAVE bit */ - if (boot_cpu_has(X86_FEATURE_XSAVE) && best->function == 0x1) - cpuid_entry_change(best, X86_FEATURE_OSXSAVE, + return 0; +} + +void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu) +{ + struct kvm_cpuid_entry2 *best; + + best = kvm_find_cpuid_entry(vcpu, 1, 0); + if (best) { + /* Update OSXSAVE bit */ + if (boot_cpu_has(X86_FEATURE_XSAVE)) + cpuid_entry_change(best, X86_FEATURE_OSXSAVE, kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE)); - cpuid_entry_change(best, X86_FEATURE_APIC, + cpuid_entry_change(best, X86_FEATURE_APIC, vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE); - - if (apic) { - if (cpuid_entry_has(best, X86_FEATURE_TSC_DEADLINE_TIMER)) - apic->lapic_timer.timer_mode_mask = 3 << 17; - else - apic->lapic_timer.timer_mode_mask = 1 << 17; } best = kvm_find_cpuid_entry(vcpu, 7, 0); @@ -84,31 +94,14 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu) kvm_read_cr4_bits(vcpu, X86_CR4_PKE)); best = kvm_find_cpuid_entry(vcpu, 0xD, 0); - if (!best) { - vcpu->arch.guest_supported_xcr0 = 0; - } else { - vcpu->arch.guest_supported_xcr0 = - (best->eax | ((u64)best->edx << 32)) & supported_xcr0; + if (best) best->ebx = xstate_required_size(vcpu->arch.xcr0, false); - } best = kvm_find_cpuid_entry(vcpu, 0xD, 1); if (best && (cpuid_entry_has(best, X86_FEATURE_XSAVES) || cpuid_entry_has(best, X86_FEATURE_XSAVEC))) best->ebx = xstate_required_size(vcpu->arch.xcr0, true); - /* - * The existing code assumes virtual address is 48-bit or 57-bit in the - * canonical address checks; exit if it is ever changed. - */ - best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0); - if (best) { - int vaddr_bits = (best->eax & 0xff00) >> 8; - - if (vaddr_bits != 48 && vaddr_bits != 57 && vaddr_bits != 0) - return -EINVAL; - } - best = kvm_find_cpuid_entry(vcpu, KVM_CPUID_FEATURES, 0); if (kvm_hlt_in_guest(vcpu->kvm) && best && (best->eax & (1 << KVM_FEATURE_PV_UNHALT))) @@ -121,14 +114,39 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu) vcpu->arch.ia32_misc_enable_msr & MSR_IA32_MISC_ENABLE_MWAIT); } +} + +static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) +{ + struct kvm_lapic *apic = vcpu->arch.apic; + struct kvm_cpuid_entry2 *best; + + kvm_x86_ops.vcpu_after_set_cpuid(vcpu); + + best = kvm_find_cpuid_entry(vcpu, 1, 0); + if (best && apic) { + if (cpuid_entry_has(best, X86_FEATURE_TSC_DEADLINE_TIMER)) + apic->lapic_timer.timer_mode_mask = 3 << 17; + else + apic->lapic_timer.timer_mode_mask = 1 << 17; + + kvm_apic_set_version(vcpu); + } + + best = kvm_find_cpuid_entry(vcpu, 0xD, 0); + if (!best) + vcpu->arch.guest_supported_xcr0 = 0; + else + vcpu->arch.guest_supported_xcr0 = + (best->eax | ((u64)best->edx << 32)) & supported_xcr0; - /* Note, maxphyaddr must be updated before tdp_level. */ vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu); - vcpu->arch.tdp_level = kvm_x86_ops.get_tdp_level(vcpu); kvm_mmu_reset_context(vcpu); kvm_pmu_refresh(vcpu); - return 0; + vcpu->arch.cr4_guest_rsvd_bits = + __cr4_reserved_bits(guest_cpuid_has, vcpu); + kvm_x86_ops.update_exception_bitmap(vcpu); } static int is_efer_nx(void) @@ -203,10 +221,16 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, vcpu->arch.cpuid_entries[i].padding[2] = 0; } vcpu->arch.cpuid_nent = cpuid->nent; + r = kvm_check_cpuid(vcpu); + if (r) { + vcpu->arch.cpuid_nent = 0; + kvfree(cpuid_entries); + goto out; + } + cpuid_fix_nx_cap(vcpu); - kvm_apic_set_version(vcpu); - kvm_x86_ops.cpuid_update(vcpu); - r = kvm_update_cpuid(vcpu); + kvm_update_cpuid_runtime(vcpu); + kvm_vcpu_after_set_cpuid(vcpu); kvfree(cpuid_entries); out: @@ -227,9 +251,14 @@ int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu, cpuid->nent * sizeof(struct kvm_cpuid_entry2))) goto out; vcpu->arch.cpuid_nent = cpuid->nent; - kvm_apic_set_version(vcpu); - kvm_x86_ops.cpuid_update(vcpu); - r = kvm_update_cpuid(vcpu); + r = kvm_check_cpuid(vcpu); + if (r) { + vcpu->arch.cpuid_nent = 0; + goto out; + } + + kvm_update_cpuid_runtime(vcpu); + kvm_vcpu_after_set_cpuid(vcpu); out: return r; } @@ -604,7 +633,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) eax.split.bit_width = cap.bit_width_gp; eax.split.mask_length = cap.events_mask_len; - edx.split.num_counters_fixed = cap.num_counters_fixed; + edx.split.num_counters_fixed = min(cap.num_counters_fixed, MAX_FIXED_COUNTERS); edx.split.bit_width_fixed = cap.bit_width_fixed; edx.split.reserved = 0; diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 05434cd9342ffc6cb33c9edbb758fa60000a953f..3a923ae15f2fb31ff46e3073684e417676dcd62a 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -9,7 +9,7 @@ extern u32 kvm_cpu_caps[NCAPINTS] __read_mostly; void kvm_set_cpu_caps(void); -int kvm_update_cpuid(struct kvm_vcpu *vcpu); +void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu); struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, u32 function, u32 index); int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 4ce2ddd26c0b735d7100a68059f3680f37303af4..5ccbee7165a215f31744073adcb74364939a956d 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -354,7 +354,6 @@ static inline int apic_lvt_nmi_mode(u32 lvt_val) void kvm_apic_set_version(struct kvm_vcpu *vcpu) { struct kvm_lapic *apic = vcpu->arch.apic; - struct kvm_cpuid_entry2 *feat; u32 v = APIC_VERSION; if (!lapic_in_kernel(vcpu)) @@ -367,8 +366,7 @@ void kvm_apic_set_version(struct kvm_vcpu *vcpu) * version first and level-triggered interrupts never get EOIed in * IOAPIC. */ - feat = kvm_find_cpuid_entry(apic->vcpu, 0x1, 0); - if (feat && (feat->ecx & (1 << (X86_FEATURE_X2APIC & 31))) && + if (guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) && !ioapic_in_kernel(vcpu->kvm)) v |= APIC_LVR_DIRECTED_EOI; kvm_lapic_set_reg(apic, APIC_LVR, v); @@ -2068,7 +2066,7 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) case APIC_TDCR: { uint32_t old_divisor = apic->divide_count; - kvm_lapic_set_reg(apic, APIC_TDCR, val); + kvm_lapic_set_reg(apic, APIC_TDCR, val & 0xb); update_divide_count(apic); if (apic->divide_count != old_divisor && apic->lapic_timer.period) { @@ -2085,7 +2083,8 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) case APIC_SELF_IPI: if (apic_x2apic_mode(apic)) { - kvm_lapic_reg_write(apic, APIC_ICR, 0x40000 | (val & 0xff)); + kvm_lapic_reg_write(apic, APIC_ICR, + APIC_DEST_SELF | (val & APIC_VECTOR_MASK)); } else ret = 1; break; @@ -2232,7 +2231,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value) vcpu->arch.apic_base = value; if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE) - kvm_update_cpuid(vcpu); + kvm_update_cpuid_runtime(vcpu); if (!apic) return; diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 444bb9c5454878e00d5fd0bd0692db0c204d01d3..5efc6081ca138ed601e457041ba2cb12f96f6970 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -4,6 +4,7 @@ #include #include "kvm_cache_regs.h" +#include "cpuid.h" #define PT64_PT_BITS 9 #define PT64_ENT_PER_PAGE (1 << PT64_PT_BITS) @@ -57,22 +58,14 @@ void reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context); void kvm_init_mmu(struct kvm_vcpu *vcpu, bool reset_roots); -void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, u32 cr0, u32 cr4, u32 efer); +void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, u32 cr0, u32 cr4, u32 efer, + gpa_t nested_cr3); void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly, bool accessed_dirty, gpa_t new_eptp); bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu); int kvm_handle_page_fault(struct kvm_vcpu *vcpu, u64 error_code, u64 fault_address, char *insn, int insn_len); -static inline unsigned long kvm_mmu_available_pages(struct kvm *kvm) -{ - if (kvm->arch.n_max_mmu_pages > kvm->arch.n_used_mmu_pages) - return kvm->arch.n_max_mmu_pages - - kvm->arch.n_used_mmu_pages; - - return 0; -} - static inline int kvm_mmu_reload(struct kvm_vcpu *vcpu) { if (likely(vcpu->arch.mmu->root_hpa != INVALID_PAGE)) @@ -97,9 +90,13 @@ static inline unsigned long kvm_get_active_pcid(struct kvm_vcpu *vcpu) static inline void kvm_mmu_load_pgd(struct kvm_vcpu *vcpu) { - if (VALID_PAGE(vcpu->arch.mmu->root_hpa)) - kvm_x86_ops.load_mmu_pgd(vcpu, vcpu->arch.mmu->root_hpa | - kvm_get_active_pcid(vcpu)); + u64 root_hpa = vcpu->arch.mmu->root_hpa; + + if (!VALID_PAGE(root_hpa)) + return; + + kvm_x86_ops.load_mmu_pgd(vcpu, root_hpa | kvm_get_active_pcid(vcpu), + vcpu->arch.mmu->shadow_root_level); } int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, @@ -158,6 +155,11 @@ static inline bool is_write_protection(struct kvm_vcpu *vcpu) return kvm_read_cr0_bits(vcpu, X86_CR0_WP); } +static inline bool kvm_mmu_is_illegal_gpa(struct kvm_vcpu *vcpu, gpa_t gpa) +{ + return (gpa >= BIT_ULL(cpuid_maxphyaddr(vcpu))); +} + /* * Check if a given access (described through the I/D, W/R and U/S bits of a * page fault error code pfec) causes a permission fault with the given PTE @@ -218,11 +220,7 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end); -void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn); -void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn); -bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm, - struct kvm_memory_slot *slot, u64 gfn); -int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa); +int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu); int kvm_mmu_post_init_vm(struct kvm *kvm); void kvm_mmu_pre_destroy_vm(struct kvm *kvm); diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index e2e2e5cc7dc6878f707dcbd0b81d55a8e9f999d8..4e03841f053dec97081d421a7720fab88253946d 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -18,6 +18,7 @@ #include "irq.h" #include "ioapic.h" #include "mmu.h" +#include "mmu_internal.h" #include "x86.h" #include "kvm_cache_regs.h" #include "kvm_emulate.h" @@ -91,7 +92,8 @@ module_param_named(flush_on_reuse, force_flush_and_sync_on_reuse, bool, 0644); */ bool tdp_enabled = false; -static int max_page_level __read_mostly; +static int max_huge_page_level __read_mostly; +static int max_tdp_level __read_mostly; enum { AUDIT_PRE_PAGE_FAULT, @@ -515,6 +517,18 @@ static bool check_mmio_spte(struct kvm_vcpu *vcpu, u64 spte) return likely(kvm_gen == spte_gen); } +static gpa_t translate_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access, + struct x86_exception *exception) +{ + /* Check if guest physical address doesn't exceed guest maximum */ + if (kvm_mmu_is_illegal_gpa(vcpu, gpa)) { + exception->error_code |= PFERR_RSVD_MASK; + return UNMAPPED_GVA; + } + + return gpa; +} + /* * Sets the shadow PTE masks used by the MMU. * @@ -676,7 +690,7 @@ union split_spte { static void count_spte_clear(u64 *sptep, u64 spte) { - struct kvm_mmu_page *sp = page_header(__pa(sptep)); + struct kvm_mmu_page *sp = sptep_to_sp(sptep); if (is_shadow_present_pte(spte)) return; @@ -760,7 +774,7 @@ static u64 __update_clear_spte_slow(u64 *sptep, u64 spte) */ static u64 __get_spte_lockless(u64 *sptep) { - struct kvm_mmu_page *sp = page_header(__pa(sptep)); + struct kvm_mmu_page *sp = sptep_to_sp(sptep); union split_spte spte, *orig = (union split_spte *)sptep; int count; @@ -1060,94 +1074,40 @@ static void walk_shadow_page_lockless_end(struct kvm_vcpu *vcpu) local_irq_enable(); } -static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache, - struct kmem_cache *base_cache, int min) -{ - void *obj; - - if (cache->nobjs >= min) - return 0; - while (cache->nobjs < ARRAY_SIZE(cache->objects)) { - obj = kmem_cache_zalloc(base_cache, GFP_KERNEL_ACCOUNT); - if (!obj) - return cache->nobjs >= min ? 0 : -ENOMEM; - cache->objects[cache->nobjs++] = obj; - } - return 0; -} - -static int mmu_memory_cache_free_objects(struct kvm_mmu_memory_cache *cache) -{ - return cache->nobjs; -} - -static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc, - struct kmem_cache *cache) -{ - while (mc->nobjs) - kmem_cache_free(cache, mc->objects[--mc->nobjs]); -} - -static int mmu_topup_memory_cache_page(struct kvm_mmu_memory_cache *cache, - int min) -{ - void *page; - - if (cache->nobjs >= min) - return 0; - while (cache->nobjs < ARRAY_SIZE(cache->objects)) { - page = (void *)__get_free_page(GFP_KERNEL_ACCOUNT); - if (!page) - return cache->nobjs >= min ? 0 : -ENOMEM; - cache->objects[cache->nobjs++] = page; - } - return 0; -} - -static void mmu_free_memory_cache_page(struct kvm_mmu_memory_cache *mc) -{ - while (mc->nobjs) - free_page((unsigned long)mc->objects[--mc->nobjs]); -} - -static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu) +static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu, bool maybe_indirect) { int r; - r = mmu_topup_memory_cache(&vcpu->arch.mmu_pte_list_desc_cache, - pte_list_desc_cache, 8 + PTE_PREFETCH_NUM); + /* 1 rmap, 1 parent PTE per level, and the prefetched rmaps. */ + r = kvm_mmu_topup_memory_cache(&vcpu->arch.mmu_pte_list_desc_cache, + 1 + PT64_ROOT_MAX_LEVEL + PTE_PREFETCH_NUM); if (r) - goto out; - r = mmu_topup_memory_cache_page(&vcpu->arch.mmu_page_cache, 8); + return r; + r = kvm_mmu_topup_memory_cache(&vcpu->arch.mmu_shadow_page_cache, + PT64_ROOT_MAX_LEVEL); if (r) - goto out; - r = mmu_topup_memory_cache(&vcpu->arch.mmu_page_header_cache, - mmu_page_header_cache, 4); -out: - return r; + return r; + if (maybe_indirect) { + r = kvm_mmu_topup_memory_cache(&vcpu->arch.mmu_gfn_array_cache, + PT64_ROOT_MAX_LEVEL); + if (r) + return r; + } + return kvm_mmu_topup_memory_cache(&vcpu->arch.mmu_page_header_cache, + PT64_ROOT_MAX_LEVEL); } static void mmu_free_memory_caches(struct kvm_vcpu *vcpu) { - mmu_free_memory_cache(&vcpu->arch.mmu_pte_list_desc_cache, - pte_list_desc_cache); - mmu_free_memory_cache_page(&vcpu->arch.mmu_page_cache); - mmu_free_memory_cache(&vcpu->arch.mmu_page_header_cache, - mmu_page_header_cache); -} - -static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) -{ - void *p; - - BUG_ON(!mc->nobjs); - p = mc->objects[--mc->nobjs]; - return p; + kvm_mmu_free_memory_cache(&vcpu->arch.mmu_pte_list_desc_cache); + kvm_mmu_free_memory_cache(&vcpu->arch.mmu_shadow_page_cache); + kvm_mmu_free_memory_cache(&vcpu->arch.mmu_gfn_array_cache); + kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_header_cache); } static struct pte_list_desc *mmu_alloc_pte_list_desc(struct kvm_vcpu *vcpu) { - return mmu_memory_cache_alloc(&vcpu->arch.mmu_pte_list_desc_cache); + return kvm_mmu_memory_cache_alloc(&vcpu->arch.mmu_pte_list_desc_cache); } static void mmu_free_pte_list_desc(struct pte_list_desc *pte_list_desc) @@ -1415,10 +1375,10 @@ static struct kvm_rmap_head *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, static bool rmap_can_add(struct kvm_vcpu *vcpu) { - struct kvm_mmu_memory_cache *cache; + struct kvm_mmu_memory_cache *mc; - cache = &vcpu->arch.mmu_pte_list_desc_cache; - return mmu_memory_cache_free_objects(cache); + mc = &vcpu->arch.mmu_pte_list_desc_cache; + return kvm_mmu_memory_cache_nr_free_objects(mc); } static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn) @@ -1426,7 +1386,7 @@ static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn) struct kvm_mmu_page *sp; struct kvm_rmap_head *rmap_head; - sp = page_header(__pa(spte)); + sp = sptep_to_sp(spte); kvm_mmu_page_set_gfn(sp, spte - sp->spt, gfn); rmap_head = gfn_to_rmap(vcpu->kvm, gfn, sp); return pte_list_add(vcpu, spte, rmap_head); @@ -1438,7 +1398,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte) gfn_t gfn; struct kvm_rmap_head *rmap_head; - sp = page_header(__pa(spte)); + sp = sptep_to_sp(spte); gfn = kvm_mmu_page_get_gfn(sp, spte - sp->spt); rmap_head = gfn_to_rmap(kvm, gfn, sp); __pte_list_remove(spte, rmap_head); @@ -1530,7 +1490,7 @@ static void drop_spte(struct kvm *kvm, u64 *sptep) static bool __drop_large_spte(struct kvm *kvm, u64 *sptep) { if (is_large_pte(*sptep)) { - WARN_ON(page_header(__pa(sptep))->role.level == PG_LEVEL_4K); + WARN_ON(sptep_to_sp(sptep)->role.level == PG_LEVEL_4K); drop_spte(kvm, sptep); --kvm->stat.lpages; return true; @@ -1542,7 +1502,7 @@ static bool __drop_large_spte(struct kvm *kvm, u64 *sptep) static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep) { if (__drop_large_spte(vcpu->kvm, sptep)) { - struct kvm_mmu_page *sp = page_header(__pa(sptep)); + struct kvm_mmu_page *sp = sptep_to_sp(sptep); kvm_flush_remote_tlbs_with_address(vcpu->kvm, sp->gfn, KVM_PAGES_PER_HPAGE(sp->role.level)); @@ -1738,21 +1698,6 @@ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm, kvm_mmu_write_protect_pt_masked(kvm, slot, gfn_offset, mask); } -/** - * kvm_arch_write_log_dirty - emulate dirty page logging - * @vcpu: Guest mode vcpu - * - * Emulate arch specific page modification logging for the - * nested hypervisor - */ -int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa) -{ - if (kvm_x86_ops.write_log_dirty) - return kvm_x86_ops.write_log_dirty(vcpu, l2_gpa); - - return 0; -} - bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm, struct kvm_memory_slot *slot, u64 gfn) { @@ -2016,7 +1961,7 @@ static void rmap_recycle(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn) struct kvm_rmap_head *rmap_head; struct kvm_mmu_page *sp; - sp = page_header(__pa(spte)); + sp = sptep_to_sp(spte); rmap_head = gfn_to_rmap(vcpu->kvm, gfn, sp); @@ -2105,10 +2050,10 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, int direct { struct kvm_mmu_page *sp; - sp = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_header_cache); - sp->spt = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache); + sp = kvm_mmu_memory_cache_alloc(&vcpu->arch.mmu_page_header_cache); + sp->spt = kvm_mmu_memory_cache_alloc(&vcpu->arch.mmu_shadow_page_cache); if (!direct) - sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache); + sp->gfns = kvm_mmu_memory_cache_alloc(&vcpu->arch.mmu_gfn_array_cache); set_page_private(virt_to_page(sp->spt), (unsigned long)sp); /* @@ -2138,7 +2083,7 @@ static void mark_unsync(u64 *spte) struct kvm_mmu_page *sp; unsigned int index; - sp = page_header(__pa(spte)); + sp = sptep_to_sp(spte); index = spte - sp->spt; if (__test_and_set_bit(index, sp->unsync_child_bitmap)) return; @@ -2207,7 +2152,7 @@ static int __mmu_unsync_walk(struct kvm_mmu_page *sp, continue; } - child = page_header(ent & PT64_BASE_ADDR_MASK); + child = to_shadow_page(ent & PT64_BASE_ADDR_MASK); if (child->unsync_children) { if (mmu_pages_add(pvec, child, i)) @@ -2258,15 +2203,14 @@ static bool kvm_mmu_prepare_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp, static void kvm_mmu_commit_zap_page(struct kvm *kvm, struct list_head *invalid_list); - -#define for_each_valid_sp(_kvm, _sp, _gfn) \ - hlist_for_each_entry(_sp, \ - &(_kvm)->arch.mmu_page_hash[kvm_page_table_hashfn(_gfn)], hash_link) \ +#define for_each_valid_sp(_kvm, _sp, _list) \ + hlist_for_each_entry(_sp, _list, hash_link) \ if (is_obsolete_sp((_kvm), (_sp))) { \ } else #define for_each_gfn_indirect_valid_sp(_kvm, _sp, _gfn) \ - for_each_valid_sp(_kvm, _sp, _gfn) \ + for_each_valid_sp(_kvm, _sp, \ + &(_kvm)->arch.mmu_page_hash[kvm_page_table_hashfn(_gfn)]) \ if ((_sp)->gfn != (_gfn) || (_sp)->role.direct) {} else static inline bool is_ept_sp(struct kvm_mmu_page *sp) @@ -2464,9 +2408,7 @@ static void __clear_sp_write_flooding_count(struct kvm_mmu_page *sp) static void clear_sp_write_flooding_count(u64 *spte) { - struct kvm_mmu_page *sp = page_header(__pa(spte)); - - __clear_sp_write_flooding_count(sp); + __clear_sp_write_flooding_count(sptep_to_sp(spte)); } static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, @@ -2476,7 +2418,9 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, int direct, unsigned int access) { + bool direct_mmu = vcpu->arch.mmu->direct_map; union kvm_mmu_page_role role; + struct hlist_head *sp_list; unsigned quadrant; struct kvm_mmu_page *sp; bool need_sync = false; @@ -2490,13 +2434,14 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, if (role.direct) role.gpte_is_8_bytes = true; role.access = access; - if (!vcpu->arch.mmu->direct_map - && vcpu->arch.mmu->root_level <= PT32_ROOT_LEVEL) { + if (!direct_mmu && vcpu->arch.mmu->root_level <= PT32_ROOT_LEVEL) { quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level)); quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1; role.quadrant = quadrant; } - for_each_valid_sp(vcpu->kvm, sp, gfn) { + + sp_list = &vcpu->kvm->arch.mmu_page_hash[kvm_page_table_hashfn(gfn)]; + for_each_valid_sp(vcpu->kvm, sp, sp_list) { if (sp->gfn != gfn) { collisions++; continue; @@ -2508,6 +2453,9 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, if (sp->role.word != role.word) continue; + if (direct_mmu) + goto trace_get_page; + if (sp->unsync) { /* The page is good, but __kvm_sync_page might still end * up zapping it. If so, break in order to rebuild it. @@ -2523,6 +2471,8 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); __clear_sp_write_flooding_count(sp); + +trace_get_page: trace_kvm_mmu_get_page(sp, false); goto out; } @@ -2533,8 +2483,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, sp->gfn = gfn; sp->role = role; - hlist_add_head(&sp->hash_link, - &vcpu->kvm->arch.mmu_page_hash[kvm_page_table_hashfn(gfn)]); + hlist_add_head(&sp->hash_link, sp_list); if (!direct) { /* * we should do write protection before syncing pages @@ -2548,7 +2497,6 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, if (level > PG_LEVEL_4K && need_sync) flush |= kvm_sync_pages(vcpu, gfn, &invalid_list); } - clear_page(sp->spt); trace_kvm_mmu_get_page(sp, true); kvm_mmu_flush_or_zap(vcpu, &invalid_list, false, flush); @@ -2657,7 +2605,7 @@ static void validate_direct_spte(struct kvm_vcpu *vcpu, u64 *sptep, * so we should update the spte at this point to get * a new sp with the correct access. */ - child = page_header(*sptep & PT64_BASE_ADDR_MASK); + child = to_shadow_page(*sptep & PT64_BASE_ADDR_MASK); if (child->role.access == direct_access) return; @@ -2679,7 +2627,7 @@ static bool mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp, if (is_large_pte(pte)) --kvm->stat.lpages; } else { - child = page_header(pte & PT64_BASE_ADDR_MASK); + child = to_shadow_page(pte & PT64_BASE_ADDR_MASK); drop_parent_pte(child, spte); } return true; @@ -2757,10 +2705,23 @@ static bool __kvm_mmu_prepare_zap_page(struct kvm *kvm, if (!sp->root_count) { /* Count self */ (*nr_zapped)++; - list_move(&sp->link, invalid_list); + + /* + * Already invalid pages (previously active roots) are not on + * the active page list. See list_del() in the "else" case of + * !sp->root_count. + */ + if (sp->role.invalid) + list_add(&sp->link, invalid_list); + else + list_move(&sp->link, invalid_list); kvm_mod_used_mmu_pages(kvm, -1); } else { - list_move(&sp->link, &kvm->arch.active_mmu_pages); + /* + * Remove the active root from the active page list, the root + * will be explicitly freed when the root_count hits zero. + */ + list_del(&sp->link); /* * Obsolete pages cannot be used on any vCPUs, see the comment @@ -2812,33 +2773,60 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm, } } -static bool prepare_zap_oldest_mmu_page(struct kvm *kvm, - struct list_head *invalid_list) +static unsigned long kvm_mmu_zap_oldest_mmu_pages(struct kvm *kvm, + unsigned long nr_to_zap) { - struct kvm_mmu_page *sp; + unsigned long total_zapped = 0; + struct kvm_mmu_page *sp, *tmp; + LIST_HEAD(invalid_list); + bool unstable; + int nr_zapped; if (list_empty(&kvm->arch.active_mmu_pages)) - return false; + return 0; + +restart: + list_for_each_entry_safe(sp, tmp, &kvm->arch.active_mmu_pages, link) { + /* + * Don't zap active root pages, the page itself can't be freed + * and zapping it will just force vCPUs to realloc and reload. + */ + if (sp->root_count) + continue; + + unstable = __kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list, + &nr_zapped); + total_zapped += nr_zapped; + if (total_zapped >= nr_to_zap) + break; + + if (unstable) + goto restart; + } - sp = list_last_entry(&kvm->arch.active_mmu_pages, - struct kvm_mmu_page, link); - return kvm_mmu_prepare_zap_page(kvm, sp, invalid_list); + kvm_mmu_commit_zap_page(kvm, &invalid_list); + + kvm->stat.mmu_recycled += total_zapped; + return total_zapped; +} + +static inline unsigned long kvm_mmu_available_pages(struct kvm *kvm) +{ + if (kvm->arch.n_max_mmu_pages > kvm->arch.n_used_mmu_pages) + return kvm->arch.n_max_mmu_pages - + kvm->arch.n_used_mmu_pages; + + return 0; } static int make_mmu_pages_available(struct kvm_vcpu *vcpu) { - LIST_HEAD(invalid_list); + unsigned long avail = kvm_mmu_available_pages(vcpu->kvm); - if (likely(kvm_mmu_available_pages(vcpu->kvm) >= KVM_MIN_FREE_MMU_PAGES)) + if (likely(avail >= KVM_MIN_FREE_MMU_PAGES)) return 0; - while (kvm_mmu_available_pages(vcpu->kvm) < KVM_REFILL_PAGES) { - if (!prepare_zap_oldest_mmu_page(vcpu->kvm, &invalid_list)) - break; - - ++vcpu->kvm->stat.mmu_recycled; - } - kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list); + kvm_mmu_zap_oldest_mmu_pages(vcpu->kvm, KVM_REFILL_PAGES - avail); if (!kvm_mmu_available_pages(vcpu->kvm)) return -ENOSPC; @@ -2851,17 +2839,12 @@ static int make_mmu_pages_available(struct kvm_vcpu *vcpu) */ void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned long goal_nr_mmu_pages) { - LIST_HEAD(invalid_list); - spin_lock(&kvm->mmu_lock); if (kvm->arch.n_used_mmu_pages > goal_nr_mmu_pages) { - /* Need to free some mmu pages to achieve the goal. */ - while (kvm->arch.n_used_mmu_pages > goal_nr_mmu_pages) - if (!prepare_zap_oldest_mmu_page(kvm, &invalid_list)) - break; + kvm_mmu_zap_oldest_mmu_pages(kvm, kvm->arch.n_used_mmu_pages - + goal_nr_mmu_pages); - kvm_mmu_commit_zap_page(kvm, &invalid_list); goal_nr_mmu_pages = kvm->arch.n_used_mmu_pages; } @@ -2999,7 +2982,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, if (set_mmio_spte(vcpu, sptep, gfn, pfn, pte_access)) return 0; - sp = page_header(__pa(sptep)); + sp = sptep_to_sp(sptep); if (sp_ad_disabled(sp)) spte |= SPTE_AD_DISABLED_MASK; else if (kvm_vcpu_ad_need_write_protect(vcpu)) @@ -3102,7 +3085,7 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, struct kvm_mmu_page *child; u64 pte = *sptep; - child = page_header(pte & PT64_BASE_ADDR_MASK); + child = to_shadow_page(pte & PT64_BASE_ADDR_MASK); drop_parent_pte(child, sptep); flush = true; } else if (pfn != spte_to_pfn(*sptep)) { @@ -3212,7 +3195,7 @@ static void direct_pte_prefetch(struct kvm_vcpu *vcpu, u64 *sptep) { struct kvm_mmu_page *sp; - sp = page_header(__pa(sptep)); + sp = sptep_to_sp(sptep); /* * Without accessed bits, there's no way to distinguish between @@ -3274,7 +3257,7 @@ static int kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, gfn_t gfn, if (!slot) return PG_LEVEL_4K; - max_level = min(max_level, max_page_level); + max_level = min(max_level, max_huge_page_level); for ( ; max_level > PG_LEVEL_4K; max_level--) { linfo = lpage_info_slot(gfn, slot, max_level); if (!linfo->disallow_lpage) @@ -3520,7 +3503,7 @@ static bool fast_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, if (!is_shadow_present_pte(spte)) break; - sp = page_header(__pa(iterator.sptep)); + sp = sptep_to_sp(iterator.sptep); if (!is_last_spte(spte, sp->role.level)) break; @@ -3607,7 +3590,7 @@ static void mmu_free_root_page(struct kvm *kvm, hpa_t *root_hpa, if (!VALID_PAGE(*root_hpa)) return; - sp = page_header(*root_hpa & PT64_BASE_ADDR_MASK); + sp = to_shadow_page(*root_hpa & PT64_BASE_ADDR_MASK); --sp->root_count; if (!sp->root_count && sp->role.invalid) kvm_mmu_prepare_zap_page(kvm, sp, invalid_list); @@ -3668,7 +3651,7 @@ static int mmu_check_root(struct kvm_vcpu *vcpu, gfn_t root_gfn) { int ret = 0; - if (!kvm_is_visible_gfn(vcpu->kvm, root_gfn)) { + if (!kvm_vcpu_is_visible_gfn(vcpu, root_gfn)) { kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); ret = 1; } @@ -3837,7 +3820,7 @@ void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu) if (vcpu->arch.mmu->root_level >= PT64_ROOT_4LEVEL) { hpa_t root = vcpu->arch.mmu->root_hpa; - sp = page_header(root); + sp = to_shadow_page(root); /* * Even if another CPU was marking the SP as unsync-ed @@ -3871,7 +3854,7 @@ void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu) if (root && VALID_PAGE(root)) { root &= PT64_BASE_ADDR_MASK; - sp = page_header(root); + sp = to_shadow_page(root); mmu_sync_children(vcpu, sp); } } @@ -4045,8 +4028,8 @@ static void shadow_page_table_clear_flood(struct kvm_vcpu *vcpu, gva_t addr) walk_shadow_page_lockless_end(vcpu); } -static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, - gfn_t gfn) +static bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, + gfn_t gfn) { struct kvm_arch_async_pf arch; @@ -4108,16 +4091,16 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, if (page_fault_handle_page_track(vcpu, error_code, gfn)) return RET_PF_EMULATE; - r = mmu_topup_memory_caches(vcpu); + if (fast_page_fault(vcpu, gpa, error_code)) + return RET_PF_RETRY; + + r = mmu_topup_memory_caches(vcpu, false); if (r) return r; if (lpage_disallowed) max_level = PG_LEVEL_4K; - if (fast_page_fault(vcpu, gpa, error_code)) - return RET_PF_RETRY; - mmu_seq = vcpu->kvm->mmu_notifier_seq; smp_rmb(); @@ -4131,7 +4114,8 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, spin_lock(&vcpu->kvm->mmu_lock); if (mmu_notifier_retry(vcpu->kvm, mmu_seq)) goto out_unlock; - if (make_mmu_pages_available(vcpu) < 0) + r = make_mmu_pages_available(vcpu); + if (r) goto out_unlock; r = __direct_map(vcpu, gpa, write, map_writable, max_level, pfn, prefault, is_tdp && lpage_disallowed); @@ -4156,6 +4140,7 @@ int kvm_handle_page_fault(struct kvm_vcpu *vcpu, u64 error_code, u64 fault_address, char *insn, int insn_len) { int r = 1; + u32 flags = vcpu->arch.apf.host_apf_flags; #ifndef CONFIG_X86_64 /* A 64-bit CR2 should be impossible on 32-bit KVM. */ @@ -4164,28 +4149,22 @@ int kvm_handle_page_fault(struct kvm_vcpu *vcpu, u64 error_code, #endif vcpu->arch.l1tf_flush_l1d = true; - switch (vcpu->arch.apf.host_apf_flags) { - default: + if (!flags) { trace_kvm_page_fault(fault_address, error_code); if (kvm_event_needs_reinjection(vcpu)) kvm_mmu_unprotect_page_virt(vcpu, fault_address); r = kvm_mmu_page_fault(vcpu, fault_address, error_code, insn, insn_len); - break; - case KVM_PV_REASON_PAGE_NOT_PRESENT: + } else if (flags & KVM_PV_REASON_PAGE_NOT_PRESENT) { vcpu->arch.apf.host_apf_flags = 0; local_irq_disable(); kvm_async_pf_task_wait_schedule(fault_address); local_irq_enable(); - break; - case KVM_PV_REASON_PAGE_READY: - vcpu->arch.apf.host_apf_flags = 0; - local_irq_disable(); - kvm_async_pf_task_wake(fault_address); - local_irq_enable(); - break; + } else { + WARN_ONCE(1, "Unexpected host async PF flags: %x\n", flags); } + return r; } EXPORT_SYMBOL_GPL(kvm_handle_page_fault); @@ -4227,8 +4206,8 @@ static inline bool is_root_usable(struct kvm_mmu_root_info *root, gpa_t pgd, union kvm_mmu_page_role role) { return (role.direct || pgd == root->pgd) && - VALID_PAGE(root->hpa) && page_header(root->hpa) && - role.word == page_header(root->hpa)->role.word; + VALID_PAGE(root->hpa) && to_shadow_page(root->hpa) && + role.word == to_shadow_page(root->hpa)->role.word; } /* @@ -4277,8 +4256,7 @@ static bool fast_pgd_switch(struct kvm_vcpu *vcpu, gpa_t new_pgd, */ if (mmu->shadow_root_level >= PT64_ROOT_4LEVEL && mmu->root_level >= PT64_ROOT_4LEVEL) - return !mmu_check_root(vcpu, new_pgd >> PAGE_SHIFT) && - cached_root_available(vcpu, new_pgd, new_role); + return cached_root_available(vcpu, new_pgd, new_role); return false; } @@ -4313,7 +4291,7 @@ static void __kvm_mmu_new_pgd(struct kvm_vcpu *vcpu, gpa_t new_pgd, */ vcpu_clear_mmio_info(vcpu, MMIO_GVA_ANY); - __clear_sp_write_flooding_count(page_header(vcpu->arch.mmu->root_hpa)); + __clear_sp_write_flooding_count(to_shadow_page(vcpu->arch.mmu->root_hpa)); } void kvm_mmu_new_pgd(struct kvm_vcpu *vcpu, gpa_t new_pgd, bool skip_tlb_flush, @@ -4869,13 +4847,22 @@ static union kvm_mmu_role kvm_calc_mmu_role_common(struct kvm_vcpu *vcpu, return role; } +static inline int kvm_mmu_get_tdp_level(struct kvm_vcpu *vcpu) +{ + /* Use 5-level TDP if and only if it's useful/necessary. */ + if (max_tdp_level == 5 && cpuid_maxphyaddr(vcpu) <= 48) + return 4; + + return max_tdp_level; +} + static union kvm_mmu_role kvm_calc_tdp_mmu_root_page_role(struct kvm_vcpu *vcpu, bool base_only) { union kvm_mmu_role role = kvm_calc_mmu_role_common(vcpu, base_only); role.base.ad_disabled = (shadow_accessed_mask == 0); - role.base.level = vcpu->arch.tdp_level; + role.base.level = kvm_mmu_get_tdp_level(vcpu); role.base.direct = true; role.base.gpte_is_8_bytes = true; @@ -4884,7 +4871,7 @@ kvm_calc_tdp_mmu_root_page_role(struct kvm_vcpu *vcpu, bool base_only) static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) { - struct kvm_mmu *context = vcpu->arch.mmu; + struct kvm_mmu *context = &vcpu->arch.root_mmu; union kvm_mmu_role new_role = kvm_calc_tdp_mmu_root_page_role(vcpu, false); @@ -4896,7 +4883,7 @@ static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) context->sync_page = nonpaging_sync_page; context->invlpg = NULL; context->update_pte = nonpaging_update_pte; - context->shadow_root_level = vcpu->arch.tdp_level; + context->shadow_root_level = kvm_mmu_get_tdp_level(vcpu); context->direct_map = true; context->get_guest_pgd = get_cr3; context->get_pdptr = kvm_pdptr_read; @@ -4931,7 +4918,7 @@ static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) } static union kvm_mmu_role -kvm_calc_shadow_mmu_root_page_role(struct kvm_vcpu *vcpu, bool base_only) +kvm_calc_shadow_root_page_role_common(struct kvm_vcpu *vcpu, bool base_only) { union kvm_mmu_role role = kvm_calc_mmu_role_common(vcpu, base_only); @@ -4939,9 +4926,19 @@ kvm_calc_shadow_mmu_root_page_role(struct kvm_vcpu *vcpu, bool base_only) !is_write_protection(vcpu); role.base.smap_andnot_wp = role.ext.cr4_smap && !is_write_protection(vcpu); - role.base.direct = !is_paging(vcpu); role.base.gpte_is_8_bytes = !!is_pae(vcpu); + return role; +} + +static union kvm_mmu_role +kvm_calc_shadow_mmu_root_page_role(struct kvm_vcpu *vcpu, bool base_only) +{ + union kvm_mmu_role role = + kvm_calc_shadow_root_page_role_common(vcpu, base_only); + + role.base.direct = !is_paging(vcpu); + if (!is_long_mode(vcpu)) role.base.level = PT32E_ROOT_LEVEL; else if (is_la57_mode(vcpu)) @@ -4952,15 +4949,10 @@ kvm_calc_shadow_mmu_root_page_role(struct kvm_vcpu *vcpu, bool base_only) return role; } -void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, u32 cr0, u32 cr4, u32 efer) +static void shadow_mmu_init_context(struct kvm_vcpu *vcpu, struct kvm_mmu *context, + u32 cr0, u32 cr4, u32 efer, + union kvm_mmu_role new_role) { - struct kvm_mmu *context = vcpu->arch.mmu; - union kvm_mmu_role new_role = - kvm_calc_shadow_mmu_root_page_role(vcpu, false); - - if (new_role.as_u64 == context->mmu_role.as_u64) - return; - if (!(cr0 & X86_CR0_PG)) nonpaging_init_context(vcpu, context); else if (efer & EFER_LMA) @@ -4973,7 +4965,43 @@ void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, u32 cr0, u32 cr4, u32 efer) context->mmu_role.as_u64 = new_role.as_u64; reset_shadow_zero_bits_mask(vcpu, context); } -EXPORT_SYMBOL_GPL(kvm_init_shadow_mmu); + +static void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, u32 cr0, u32 cr4, u32 efer) +{ + struct kvm_mmu *context = &vcpu->arch.root_mmu; + union kvm_mmu_role new_role = + kvm_calc_shadow_mmu_root_page_role(vcpu, false); + + if (new_role.as_u64 != context->mmu_role.as_u64) + shadow_mmu_init_context(vcpu, context, cr0, cr4, efer, new_role); +} + +static union kvm_mmu_role +kvm_calc_shadow_npt_root_page_role(struct kvm_vcpu *vcpu) +{ + union kvm_mmu_role role = + kvm_calc_shadow_root_page_role_common(vcpu, false); + + role.base.direct = false; + role.base.level = kvm_mmu_get_tdp_level(vcpu); + + return role; +} + +void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, u32 cr0, u32 cr4, u32 efer, + gpa_t nested_cr3) +{ + struct kvm_mmu *context = &vcpu->arch.guest_mmu; + union kvm_mmu_role new_role = kvm_calc_shadow_npt_root_page_role(vcpu); + + context->shadow_root_level = new_role.base.level; + + __kvm_mmu_new_pgd(vcpu, nested_cr3, new_role.base, false, false); + + if (new_role.as_u64 != context->mmu_role.as_u64) + shadow_mmu_init_context(vcpu, context, cr0, cr4, efer, new_role); +} +EXPORT_SYMBOL_GPL(kvm_init_shadow_npt_mmu); static union kvm_mmu_role kvm_calc_shadow_ept_root_page_role(struct kvm_vcpu *vcpu, bool accessed_dirty, @@ -5007,7 +5035,7 @@ kvm_calc_shadow_ept_root_page_role(struct kvm_vcpu *vcpu, bool accessed_dirty, void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly, bool accessed_dirty, gpa_t new_eptp) { - struct kvm_mmu *context = vcpu->arch.mmu; + struct kvm_mmu *context = &vcpu->arch.guest_mmu; u8 level = vmx_eptp_page_walk_level(new_eptp); union kvm_mmu_role new_role = kvm_calc_shadow_ept_root_page_role(vcpu, accessed_dirty, @@ -5041,7 +5069,7 @@ EXPORT_SYMBOL_GPL(kvm_init_shadow_ept_mmu); static void init_kvm_softmmu(struct kvm_vcpu *vcpu) { - struct kvm_mmu *context = vcpu->arch.mmu; + struct kvm_mmu *context = &vcpu->arch.root_mmu; kvm_init_shadow_mmu(vcpu, kvm_read_cr0_bits(vcpu, X86_CR0_PG), @@ -5151,7 +5179,7 @@ int kvm_mmu_load(struct kvm_vcpu *vcpu) { int r; - r = mmu_topup_memory_caches(vcpu); + r = mmu_topup_memory_caches(vcpu, !vcpu->arch.mmu->direct_map); if (r) goto out; r = mmu_alloc_roots(vcpu); @@ -5345,7 +5373,7 @@ static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, * or not since pte prefetch is skiped if it does not have * enough objects in the cache. */ - mmu_topup_memory_caches(vcpu); + mmu_topup_memory_caches(vcpu, true); spin_lock(&vcpu->kvm->mmu_lock); @@ -5553,23 +5581,25 @@ void kvm_mmu_invpcid_gva(struct kvm_vcpu *vcpu, gva_t gva, unsigned long pcid) } EXPORT_SYMBOL_GPL(kvm_mmu_invpcid_gva); -void kvm_configure_mmu(bool enable_tdp, int tdp_page_level) +void kvm_configure_mmu(bool enable_tdp, int tdp_max_root_level, + int tdp_huge_page_level) { tdp_enabled = enable_tdp; + max_tdp_level = tdp_max_root_level; /* - * max_page_level reflects the capabilities of KVM's MMU irrespective + * max_huge_page_level reflects KVM's MMU capabilities irrespective * of kernel support, e.g. KVM may be capable of using 1GB pages when * the kernel is not. But, KVM never creates a page size greater than * what is used by the kernel for any given HVA, i.e. the kernel's * capabilities are ultimately consulted by kvm_mmu_hugepage_adjust(). */ if (tdp_enabled) - max_page_level = tdp_page_level; + max_huge_page_level = tdp_huge_page_level; else if (boot_cpu_has(X86_FEATURE_GBPAGES)) - max_page_level = PG_LEVEL_1G; + max_huge_page_level = PG_LEVEL_1G; else - max_page_level = PG_LEVEL_2M; + max_huge_page_level = PG_LEVEL_2M; } EXPORT_SYMBOL_GPL(kvm_configure_mmu); @@ -5665,7 +5695,7 @@ static int alloc_mmu_pages(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu) * SVM's 32-bit NPT support, TDP paging doesn't use PAE paging and can * skip allocating the PDP table. */ - if (tdp_enabled && vcpu->arch.tdp_level > PT32E_ROOT_LEVEL) + if (tdp_enabled && kvm_mmu_get_tdp_level(vcpu) > PT32E_ROOT_LEVEL) return 0; page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_DMA32); @@ -5684,6 +5714,14 @@ int kvm_mmu_create(struct kvm_vcpu *vcpu) uint i; int ret; + vcpu->arch.mmu_pte_list_desc_cache.kmem_cache = pte_list_desc_cache; + vcpu->arch.mmu_pte_list_desc_cache.gfp_zero = __GFP_ZERO; + + vcpu->arch.mmu_page_header_cache.kmem_cache = mmu_page_header_cache; + vcpu->arch.mmu_page_header_cache.gfp_zero = __GFP_ZERO; + + vcpu->arch.mmu_shadow_page_cache.gfp_zero = __GFP_ZERO; + vcpu->arch.mmu = &vcpu->arch.root_mmu; vcpu->arch.walk_mmu = &vcpu->arch.root_mmu; @@ -5732,12 +5770,11 @@ restart: break; /* - * Skip invalid pages with a non-zero root count, zapping pages - * with a non-zero root count will never succeed, i.e. the page - * will get thrown back on active_mmu_pages and we'll get stuck - * in an infinite loop. + * Invalid pages should never land back on the list of active + * pages. Skip the bogus page, otherwise we'll get stuck in an + * infinite loop if the page gets put back on the list (again). */ - if (sp->role.invalid && sp->root_count) + if (WARN_ON(sp->role.invalid)) continue; /* @@ -5904,7 +5941,7 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm, restart: for_each_rmap_spte(rmap_head, &iter, sptep) { - sp = page_header(__pa(sptep)); + sp = sptep_to_sp(sptep); pfn = spte_to_pfn(*sptep); /* @@ -6015,7 +6052,7 @@ void kvm_mmu_zap_all(struct kvm *kvm) spin_lock(&kvm->mmu_lock); restart: list_for_each_entry_safe(sp, node, &kvm->arch.active_mmu_pages, link) { - if (sp->role.invalid && sp->root_count) + if (WARN_ON(sp->role.invalid)) continue; if (__kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list, &ign)) goto restart; @@ -6092,9 +6129,7 @@ mmu_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) goto unlock; } - if (prepare_zap_oldest_mmu_page(kvm, &invalid_list)) - freed++; - kvm_mmu_commit_zap_page(kvm, &invalid_list); + freed = kvm_mmu_zap_oldest_mmu_pages(kvm, sc->nr_to_scan); unlock: spin_unlock(&kvm->mmu_lock); diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu/mmu_audit.c similarity index 96% rename from arch/x86/kvm/mmu_audit.c rename to arch/x86/kvm/mmu/mmu_audit.c index 9d2844f87f6dbd5545372b4e832a51ba42824fd3..c8d51a37e2ce609f39267119bd69fc97a2749adc 100644 --- a/arch/x86/kvm/mmu_audit.c +++ b/arch/x86/kvm/mmu/mmu_audit.c @@ -45,7 +45,7 @@ static void __mmu_spte_walk(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, !is_last_spte(ent[i], level)) { struct kvm_mmu_page *child; - child = page_header(ent[i] & PT64_BASE_ADDR_MASK); + child = to_shadow_page(ent[i] & PT64_BASE_ADDR_MASK); __mmu_spte_walk(vcpu, child, fn, level - 1); } } @@ -62,7 +62,7 @@ static void mmu_spte_walk(struct kvm_vcpu *vcpu, inspect_spte_fn fn) if (vcpu->arch.mmu->root_level >= PT64_ROOT_4LEVEL) { hpa_t root = vcpu->arch.mmu->root_hpa; - sp = page_header(root); + sp = to_shadow_page(root); __mmu_spte_walk(vcpu, sp, fn, vcpu->arch.mmu->root_level); return; } @@ -72,7 +72,7 @@ static void mmu_spte_walk(struct kvm_vcpu *vcpu, inspect_spte_fn fn) if (root && VALID_PAGE(root)) { root &= PT64_BASE_ADDR_MASK; - sp = page_header(root); + sp = to_shadow_page(root); __mmu_spte_walk(vcpu, sp, fn, 2); } } @@ -97,7 +97,7 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level) kvm_pfn_t pfn; hpa_t hpa; - sp = page_header(__pa(sptep)); + sp = sptep_to_sp(sptep); if (sp->unsync) { if (level != PG_LEVEL_4K) { @@ -132,7 +132,7 @@ static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep) struct kvm_memory_slot *slot; gfn_t gfn; - rev_sp = page_header(__pa(sptep)); + rev_sp = sptep_to_sp(sptep); gfn = kvm_mmu_page_get_gfn(rev_sp, sptep - rev_sp->spt); slots = kvm_memslots_for_spte_role(kvm, rev_sp->role); @@ -165,7 +165,7 @@ static void audit_sptes_have_rmaps(struct kvm_vcpu *vcpu, u64 *sptep, int level) static void audit_spte_after_sync(struct kvm_vcpu *vcpu, u64 *sptep, int level) { - struct kvm_mmu_page *sp = page_header(__pa(sptep)); + struct kvm_mmu_page *sp = sptep_to_sp(sptep); if (vcpu->kvm->arch.audit_point == AUDIT_POST_SYNC && sp->unsync) audit_printk(vcpu->kvm, "meet unsync sp(%p) after sync " diff --git a/arch/x86/kvm/mmu/mmu_internal.h b/arch/x86/kvm/mmu/mmu_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..3acf3b8eb469db315af618b8d841fc2ea5d2b169 --- /dev/null +++ b/arch/x86/kvm/mmu/mmu_internal.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __KVM_X86_MMU_INTERNAL_H +#define __KVM_X86_MMU_INTERNAL_H + +#include + +#include + +struct kvm_mmu_page { + struct list_head link; + struct hlist_node hash_link; + struct list_head lpage_disallowed_link; + + bool unsync; + u8 mmu_valid_gen; + bool mmio_cached; + bool lpage_disallowed; /* Can't be replaced by an equiv large page */ + + /* + * The following two entries are used to key the shadow page in the + * hash table. + */ + union kvm_mmu_page_role role; + gfn_t gfn; + + u64 *spt; + /* hold the gfn of each spte inside spt */ + gfn_t *gfns; + int root_count; /* Currently serving as active root */ + unsigned int unsync_children; + struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */ + DECLARE_BITMAP(unsync_child_bitmap, 512); + +#ifdef CONFIG_X86_32 + /* + * Used out of the mmu-lock to avoid reading spte values while an + * update is in progress; see the comments in __get_spte_lockless(). + */ + int clear_spte_count; +#endif + + /* Number of writes since the last time traversal visited this page. */ + atomic_t write_flooding_count; +}; + +static inline struct kvm_mmu_page *to_shadow_page(hpa_t shadow_page) +{ + struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT); + + return (struct kvm_mmu_page *)page_private(page); +} + +static inline struct kvm_mmu_page *sptep_to_sp(u64 *sptep) +{ + return to_shadow_page(__pa(sptep)); +} + +void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn); +void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn); +bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm, + struct kvm_memory_slot *slot, u64 gfn); + +#endif /* __KVM_X86_MMU_INTERNAL_H */ diff --git a/arch/x86/kvm/mmutrace.h b/arch/x86/kvm/mmu/mmutrace.h similarity index 99% rename from arch/x86/kvm/mmutrace.h rename to arch/x86/kvm/mmu/mmutrace.h index ffcd96fc02d0a4892ee4573d9a7a2791f4cf0c69..9d15bc0c535b4ba9c0a16cdc8b9216d717e7f0a3 100644 --- a/arch/x86/kvm/mmutrace.h +++ b/arch/x86/kvm/mmu/mmutrace.h @@ -387,7 +387,7 @@ TRACE_EVENT( #endif /* _TRACE_KVMMMU_H */ #undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_PATH mmu #undef TRACE_INCLUDE_FILE #define TRACE_INCLUDE_FILE mmutrace diff --git a/arch/x86/kvm/mmu/page_track.c b/arch/x86/kvm/mmu/page_track.c index a7bcde34d1f2a092f601d069ba58d2f06b91f9b4..a84a141a2ad291faa32f7f0bb4175d6316a7da9a 100644 --- a/arch/x86/kvm/mmu/page_track.c +++ b/arch/x86/kvm/mmu/page_track.c @@ -16,7 +16,7 @@ #include -#include "mmu.h" +#include "mmu_internal.h" void kvm_page_track_free_memslot(struct kvm_memory_slot *slot) { diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h index 275564a0ebdb764e726a569e6a7e7937bb5e27b3..4dd6b1e5b8cf7238c038c2842b2a0fe4edcb18dc 100644 --- a/arch/x86/kvm/mmu/paging_tmpl.h +++ b/arch/x86/kvm/mmu/paging_tmpl.h @@ -260,7 +260,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu, !(pte & PT_GUEST_DIRTY_MASK)) { trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte)); #if PTTYPE == PTTYPE_EPT - if (kvm_arch_write_log_dirty(vcpu, addr)) + if (kvm_x86_ops.nested_ops->write_log_dirty(vcpu, addr)) return -EINVAL; #endif pte |= PT_GUEST_DIRTY_MASK; @@ -596,7 +596,7 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw, u64 *spte; int i; - sp = page_header(__pa(sptep)); + sp = sptep_to_sp(sptep); if (sp->role.level > PG_LEVEL_4K) return; @@ -789,10 +789,6 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gpa_t addr, u32 error_code, pgprintk("%s: addr %lx err %x\n", __func__, addr, error_code); - r = mmu_topup_memory_caches(vcpu); - if (r) - return r; - /* * If PFEC.RSVD is set, this is a shadow page fault. * The bit needs to be cleared before walking guest page tables. @@ -820,6 +816,10 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gpa_t addr, u32 error_code, return RET_PF_EMULATE; } + r = mmu_topup_memory_caches(vcpu, true); + if (r) + return r; + vcpu->arch.write_fault_to_shadow_pgtable = false; is_self_change_mapping = FNAME(is_self_change_mapping)(vcpu, @@ -866,7 +866,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gpa_t addr, u32 error_code, goto out_unlock; kvm_mmu_audit(vcpu, AUDIT_PRE_PAGE_FAULT); - if (make_mmu_pages_available(vcpu) < 0) + r = make_mmu_pages_available(vcpu); + if (r) goto out_unlock; r = FNAME(fetch)(vcpu, addr, &walker, write_fault, max_level, pfn, map_writable, prefault, lpage_disallowed); @@ -903,7 +904,7 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva, hpa_t root_hpa) * No need to check return value here, rmap_can_add() can * help us to skip pte prefetch later. */ - mmu_topup_memory_caches(vcpu); + mmu_topup_memory_caches(vcpu, true); if (!VALID_PAGE(root_hpa)) { WARN_ON(1); @@ -915,7 +916,7 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva, hpa_t root_hpa) level = iterator.level; sptep = iterator.sptep; - sp = page_header(__pa(sptep)); + sp = sptep_to_sp(sptep); if (is_last_spte(*sptep, level)) { pt_element_t gpte; gpa_t pte_gpa; diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index b86346903f2e83236149092eb807c3bb3af61383..67741d2a030851b9424406921755cdad8d30cfc7 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -372,6 +372,11 @@ int kvm_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned idx, u64 *data) if (!pmc) return 1; + if (!(kvm_read_cr4(vcpu) & X86_CR4_PCE) && + (kvm_x86_ops.get_cpl(vcpu) != 0) && + (kvm_read_cr0(vcpu) & X86_CR0_PE)) + return 1; + *data = pmc_read_counter(pmc) & mask; return 0; } diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index ab85eed8a6cc43c0a316558508e2cf6f7c207cf9..067fef51760c4702c8d0ec5c7ff1d51ae00b5d93 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -15,6 +15,8 @@ #define VMWARE_BACKDOOR_PMC_REAL_TIME 0x10001 #define VMWARE_BACKDOOR_PMC_APPARENT_TIME 0x10002 +#define MAX_FIXED_COUNTERS 3 + struct kvm_event_hw_type_mapping { u8 eventsel; u8 unit_mask; diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index e80daa98682f5e6ba30ccfc906dfaec94ef4e55b..ac830cd508305fc0255c3de5a6a6fabd42159052 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -665,7 +665,7 @@ void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu) } else { vmcb->control.int_ctl &= ~AVIC_ENABLE_MASK; } - mark_dirty(vmcb, VMCB_AVIC); + vmcb_mark_dirty(vmcb, VMCB_AVIC); svm_set_pi_irte_mode(vcpu, activated); } diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 6bceafb19108453c483de82631fcb825e4f39701..fb68467e60496aa5bc2abd2f8fa5dfd85e257ebd 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -48,13 +48,6 @@ static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu, svm->vmcb->control.exit_info_1 &= ~0xffffffffULL; svm->vmcb->control.exit_info_1 |= fault->error_code; - /* - * The present bit is always zero for page structure faults on real - * hardware. - */ - if (svm->vmcb->control.exit_info_1 & (2ULL << 32)) - svm->vmcb->control.exit_info_1 &= ~1; - nested_svm_vmexit(svm); } @@ -87,11 +80,11 @@ static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu) WARN_ON(mmu_is_nested(vcpu)); vcpu->arch.mmu = &vcpu->arch.guest_mmu; - kvm_init_shadow_mmu(vcpu, X86_CR0_PG, hsave->save.cr4, hsave->save.efer); + kvm_init_shadow_npt_mmu(vcpu, X86_CR0_PG, hsave->save.cr4, hsave->save.efer, + svm->nested.ctl.nested_cr3); vcpu->arch.mmu->get_guest_pgd = nested_svm_get_tdp_cr3; vcpu->arch.mmu->get_pdptr = nested_svm_get_tdp_pdptr; vcpu->arch.mmu->inject_page_fault = nested_svm_inject_npf_exit; - vcpu->arch.mmu->shadow_root_level = vcpu->arch.tdp_level; reset_shadow_zero_bits_mask(vcpu, vcpu->arch.mmu); vcpu->arch.walk_mmu = &vcpu->arch.nested_mmu; } @@ -106,7 +99,7 @@ void recalc_intercepts(struct vcpu_svm *svm) { struct vmcb_control_area *c, *h, *g; - mark_dirty(svm->vmcb, VMCB_INTERCEPTS); + vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS); if (!is_guest_mode(&svm->vcpu)) return; @@ -222,8 +215,9 @@ static bool nested_vmcb_check_controls(struct vmcb_control_area *control) return true; } -static bool nested_vmcb_checks(struct vmcb *vmcb) +static bool nested_vmcb_checks(struct vcpu_svm *svm, struct vmcb *vmcb) { + bool nested_vmcb_lma; if ((vmcb->save.efer & EFER_SVME) == 0) return false; @@ -231,6 +225,30 @@ static bool nested_vmcb_checks(struct vmcb *vmcb) (vmcb->save.cr0 & X86_CR0_NW)) return false; + if (!kvm_dr6_valid(vmcb->save.dr6) || !kvm_dr7_valid(vmcb->save.dr7)) + return false; + + nested_vmcb_lma = + (vmcb->save.efer & EFER_LME) && + (vmcb->save.cr0 & X86_CR0_PG); + + if (!nested_vmcb_lma) { + if (vmcb->save.cr4 & X86_CR4_PAE) { + if (vmcb->save.cr3 & MSR_CR3_LEGACY_PAE_RESERVED_MASK) + return false; + } else { + if (vmcb->save.cr3 & MSR_CR3_LEGACY_RESERVED_MASK) + return false; + } + } else { + if (!(vmcb->save.cr4 & X86_CR4_PAE) || + !(vmcb->save.cr0 & X86_CR0_PE) || + (vmcb->save.cr3 & MSR_CR3_LONG_RESERVED_MASK)) + return false; + } + if (kvm_valid_cr4(&svm->vcpu, vmcb->save.cr4)) + return false; + return nested_vmcb_check_controls(&vmcb->control); } @@ -258,7 +276,7 @@ void sync_nested_vmcb_control(struct vcpu_svm *svm) /* Only a few fields of int_ctl are written by the processor. */ mask = V_IRQ_MASK | V_TPR_MASK; if (!(svm->nested.ctl.int_ctl & V_INTR_MASKING_MASK) && - is_intercept(svm, INTERCEPT_VINTR)) { + svm_is_intercept(svm, INTERCEPT_VINTR)) { /* * In order to request an interrupt window, L0 is usurping * svm->vmcb->control.int_ctl and possibly setting V_IRQ @@ -310,6 +328,42 @@ static void nested_vmcb_save_pending_event(struct vcpu_svm *svm, nested_vmcb->control.exit_int_info = exit_int_info; } +static inline bool nested_npt_enabled(struct vcpu_svm *svm) +{ + return svm->nested.ctl.nested_ctl & SVM_NESTED_CTL_NP_ENABLE; +} + +/* + * Load guest's/host's cr3 on nested vmentry or vmexit. @nested_npt is true + * if we are emulating VM-Entry into a guest with NPT enabled. + */ +static int nested_svm_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, + bool nested_npt) +{ + if (cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 63)) + return -EINVAL; + + if (!nested_npt && is_pae_paging(vcpu) && + (cr3 != kvm_read_cr3(vcpu) || pdptrs_changed(vcpu))) { + if (!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3)) + return -EINVAL; + } + + /* + * TODO: optimize unconditional TLB flush/MMU sync here and in + * kvm_init_shadow_npt_mmu(). + */ + if (!nested_npt) + kvm_mmu_new_pgd(vcpu, cr3, false, false); + + vcpu->arch.cr3 = cr3; + kvm_register_mark_available(vcpu, VCPU_EXREG_CR3); + + kvm_init_mmu(vcpu, false); + + return 0; +} + static void nested_prepare_vmcb_save(struct vcpu_svm *svm, struct vmcb *nested_vmcb) { /* Load the nested guest state */ @@ -323,8 +377,6 @@ static void nested_prepare_vmcb_save(struct vcpu_svm *svm, struct vmcb *nested_v svm_set_efer(&svm->vcpu, nested_vmcb->save.efer); svm_set_cr0(&svm->vcpu, nested_vmcb->save.cr0); svm_set_cr4(&svm->vcpu, nested_vmcb->save.cr4); - (void)kvm_set_cr3(&svm->vcpu, nested_vmcb->save.cr3); - svm->vmcb->save.cr2 = svm->vcpu.arch.cr2 = nested_vmcb->save.cr2; kvm_rax_write(&svm->vcpu, nested_vmcb->save.rax); kvm_rsp_write(&svm->vcpu, nested_vmcb->save.rsp); @@ -342,13 +394,9 @@ static void nested_prepare_vmcb_save(struct vcpu_svm *svm, struct vmcb *nested_v static void nested_prepare_vmcb_control(struct vcpu_svm *svm) { const u32 mask = V_INTR_MASKING_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK; - if (svm->nested.ctl.nested_ctl & SVM_NESTED_CTL_NP_ENABLE) - nested_svm_init_mmu_context(&svm->vcpu); - - /* Guest paging mode is active - reset mmu */ - kvm_mmu_reset_context(&svm->vcpu); - svm_flush_tlb(&svm->vcpu); + if (nested_npt_enabled(svm)) + nested_svm_init_mmu_context(&svm->vcpu); svm->vmcb->control.tsc_offset = svm->vcpu.arch.tsc_offset = svm->vcpu.arch.l1_tsc_offset + svm->nested.ctl.tsc_offset; @@ -375,18 +423,27 @@ static void nested_prepare_vmcb_control(struct vcpu_svm *svm) */ recalc_intercepts(svm); - mark_all_dirty(svm->vmcb); + vmcb_mark_all_dirty(svm->vmcb); } -void enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb_gpa, +int enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb_gpa, struct vmcb *nested_vmcb) { + int ret; + svm->nested.vmcb = vmcb_gpa; load_nested_vmcb_control(svm, &nested_vmcb->control); nested_prepare_vmcb_save(svm, nested_vmcb); nested_prepare_vmcb_control(svm); + ret = nested_svm_load_cr3(&svm->vcpu, nested_vmcb->save.cr3, + nested_npt_enabled(svm)); + if (ret) + return ret; + svm_set_gif(svm, true); + + return 0; } int nested_svm_vmrun(struct vcpu_svm *svm) @@ -416,7 +473,7 @@ int nested_svm_vmrun(struct vcpu_svm *svm) nested_vmcb = map.hva; - if (!nested_vmcb_checks(nested_vmcb)) { + if (!nested_vmcb_checks(svm, nested_vmcb)) { nested_vmcb->control.exit_code = SVM_EXIT_ERR; nested_vmcb->control.exit_code_hi = 0; nested_vmcb->control.exit_info_1 = 0; @@ -464,16 +521,22 @@ int nested_svm_vmrun(struct vcpu_svm *svm) copy_vmcb_control_area(&hsave->control, &vmcb->control); svm->nested.nested_run_pending = 1; - enter_svm_guest_mode(svm, vmcb_gpa, nested_vmcb); - if (!nested_svm_vmrun_msrpm(svm)) { - svm->vmcb->control.exit_code = SVM_EXIT_ERR; - svm->vmcb->control.exit_code_hi = 0; - svm->vmcb->control.exit_info_1 = 0; - svm->vmcb->control.exit_info_2 = 0; + if (enter_svm_guest_mode(svm, vmcb_gpa, nested_vmcb)) + goto out_exit_err; - nested_svm_vmexit(svm); - } + if (nested_svm_vmrun_msrpm(svm)) + goto out; + +out_exit_err: + svm->nested.nested_run_pending = 0; + + svm->vmcb->control.exit_code = SVM_EXIT_ERR; + svm->vmcb->control.exit_code_hi = 0; + svm->vmcb->control.exit_info_1 = 0; + svm->vmcb->control.exit_info_2 = 0; + + nested_svm_vmexit(svm); out: kvm_vcpu_unmap(&svm->vcpu, &map, true); @@ -585,12 +648,6 @@ int nested_svm_vmexit(struct vcpu_svm *svm) svm_set_efer(&svm->vcpu, hsave->save.efer); svm_set_cr0(&svm->vcpu, hsave->save.cr0 | X86_CR0_PE); svm_set_cr4(&svm->vcpu, hsave->save.cr4); - if (npt_enabled) { - svm->vmcb->save.cr3 = hsave->save.cr3; - svm->vcpu.arch.cr3 = hsave->save.cr3; - } else { - (void)kvm_set_cr3(&svm->vcpu, hsave->save.cr3); - } kvm_rax_write(&svm->vcpu, hsave->save.rax); kvm_rsp_write(&svm->vcpu, hsave->save.rsp); kvm_rip_write(&svm->vcpu, hsave->save.rip); @@ -598,7 +655,7 @@ int nested_svm_vmexit(struct vcpu_svm *svm) svm->vmcb->save.cpl = 0; svm->vmcb->control.exit_int_info = 0; - mark_all_dirty(svm->vmcb); + vmcb_mark_all_dirty(svm->vmcb); trace_kvm_nested_vmexit_inject(nested_vmcb->control.exit_code, nested_vmcb->control.exit_info_1, @@ -610,8 +667,13 @@ int nested_svm_vmexit(struct vcpu_svm *svm) kvm_vcpu_unmap(&svm->vcpu, &map, true); nested_svm_uninit_mmu_context(&svm->vcpu); - kvm_mmu_reset_context(&svm->vcpu); - kvm_mmu_load(&svm->vcpu); + + rc = nested_svm_load_cr3(&svm->vcpu, hsave->save.cr3, false); + if (rc) + return 1; + + if (npt_enabled) + svm->vmcb->save.cr3 = hsave->save.cr3; /* * Drop what we picked up for L2 via svm_complete_interrupts() so it diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 5573a97f1520110c77beea38dae241c7edd64046..402dc4234e397861daef0be131a61118c8f2681a 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -313,13 +313,15 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, int write) { struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; - unsigned long npages, npinned, size; + unsigned long npages, size; + int npinned; unsigned long locked, lock_limit; struct page **pages; unsigned long first, last; + int ret; if (ulen == 0 || uaddr + ulen < uaddr) - return NULL; + return ERR_PTR(-EINVAL); /* Calculate number of pages. */ first = (uaddr & PAGE_MASK) >> PAGE_SHIFT; @@ -330,9 +332,12 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; if (locked > lock_limit && !capable(CAP_IPC_LOCK)) { pr_err("SEV: %lu locked pages exceed the lock limit of %lu.\n", locked, lock_limit); - return NULL; + return ERR_PTR(-ENOMEM); } + if (WARN_ON_ONCE(npages > INT_MAX)) + return ERR_PTR(-EINVAL); + /* Avoid using vmalloc for smaller buffers. */ size = npages * sizeof(struct page *); if (size > PAGE_SIZE) @@ -341,12 +346,13 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, pages = kmalloc(size, GFP_KERNEL_ACCOUNT); if (!pages) - return NULL; + return ERR_PTR(-ENOMEM); /* Pin the user virtual address. */ - npinned = get_user_pages_fast(uaddr, npages, write ? FOLL_WRITE : 0, pages); + npinned = pin_user_pages_fast(uaddr, npages, write ? FOLL_WRITE : 0, pages); if (npinned != npages) { pr_err("SEV: Failure locking %lu pages.\n", npages); + ret = -ENOMEM; goto err; } @@ -357,10 +363,10 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, err: if (npinned > 0) - release_pages(pages, npinned); + unpin_user_pages(pages, npinned); kvfree(pages); - return NULL; + return ERR_PTR(ret); } static void sev_unpin_memory(struct kvm *kvm, struct page **pages, @@ -368,7 +374,7 @@ static void sev_unpin_memory(struct kvm *kvm, struct page **pages, { struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; - release_pages(pages, npages); + unpin_user_pages(pages, npages); kvfree(pages); sev->pages_locked -= npages; } @@ -434,8 +440,8 @@ static int sev_launch_update_data(struct kvm *kvm, struct kvm_sev_cmd *argp) /* Lock the user memory. */ inpages = sev_pin_memory(kvm, vaddr, size, &npages, 1); - if (!inpages) { - ret = -ENOMEM; + if (IS_ERR(inpages)) { + ret = PTR_ERR(inpages); goto e_free; } @@ -789,13 +795,13 @@ static int sev_dbg_crypt(struct kvm *kvm, struct kvm_sev_cmd *argp, bool dec) /* lock userspace source and destination page */ src_p = sev_pin_memory(kvm, vaddr & PAGE_MASK, PAGE_SIZE, &n, 0); - if (!src_p) - return -EFAULT; + if (IS_ERR(src_p)) + return PTR_ERR(src_p); dst_p = sev_pin_memory(kvm, dst_vaddr & PAGE_MASK, PAGE_SIZE, &n, 1); - if (!dst_p) { + if (IS_ERR(dst_p)) { sev_unpin_memory(kvm, src_p, n); - return -EFAULT; + return PTR_ERR(dst_p); } /* @@ -860,8 +866,8 @@ static int sev_launch_secret(struct kvm *kvm, struct kvm_sev_cmd *argp) return -EFAULT; pages = sev_pin_memory(kvm, params.guest_uaddr, params.guest_len, &n, 1); - if (!pages) - return -ENOMEM; + if (IS_ERR(pages)) + return PTR_ERR(pages); /* * The secret must be copied into contiguous memory region, lets verify @@ -987,8 +993,8 @@ int svm_register_enc_region(struct kvm *kvm, return -ENOMEM; region->pages = sev_pin_memory(kvm, range->addr, range->size, ®ion->npages, 1); - if (!region->pages) { - ret = -ENOMEM; + if (IS_ERR(region->pages)) { + ret = PTR_ERR(region->pages); goto e_free; } @@ -1180,11 +1186,10 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu) * 2) or this VMCB was executed on different host CPU in previous VMRUNs. */ if (sd->sev_vmcbs[asid] == svm->vmcb && - svm->last_cpu == cpu) + svm->vcpu.arch.last_vmentry_cpu == cpu) return; - svm->last_cpu = cpu; sd->sev_vmcbs[asid] = svm->vmcb; svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ASID; - mark_dirty(svm->vmcb, VMCB_ASID); + vmcb_mark_dirty(svm->vmcb, VMCB_ASID); } diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 5bbf76189afa4e554187ec8d8acc5bc5560b3513..03dd7bac80348857b378be2edff0382302ed6e2a 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -254,7 +254,7 @@ static inline void invlpga(unsigned long addr, u32 asid) asm volatile (__ex("invlpga %1, %0") : : "c"(asid), "a"(addr)); } -static int get_npt_level(struct kvm_vcpu *vcpu) +static int get_max_npt_level(void) { #ifdef CONFIG_X86_64 return PT64_ROOT_4LEVEL; @@ -282,7 +282,7 @@ void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) } svm->vmcb->save.efer = efer | EFER_SVME; - mark_dirty(svm->vmcb, VMCB_CR); + vmcb_mark_dirty(svm->vmcb, VMCB_CR); } static int is_external_interrupt(u32 info) @@ -713,7 +713,7 @@ static void grow_ple_window(struct kvm_vcpu *vcpu) pause_filter_count_max); if (control->pause_filter_count != old) { - mark_dirty(svm->vmcb, VMCB_INTERCEPTS); + vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS); trace_kvm_ple_window_update(vcpu->vcpu_id, control->pause_filter_count, old); } @@ -731,7 +731,7 @@ static void shrink_ple_window(struct kvm_vcpu *vcpu) pause_filter_count_shrink, pause_filter_count); if (control->pause_filter_count != old) { - mark_dirty(svm->vmcb, VMCB_INTERCEPTS); + vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS); trace_kvm_ple_window_update(vcpu->vcpu_id, control->pause_filter_count, old); } @@ -885,7 +885,7 @@ static __init int svm_hardware_setup(void) if (npt_enabled && !npt) npt_enabled = false; - kvm_configure_mmu(npt_enabled, PG_LEVEL_1G); + kvm_configure_mmu(npt_enabled, get_max_npt_level(), PG_LEVEL_1G); pr_info("kvm: Nested Paging %sabled\n", npt_enabled ? "en" : "dis"); if (nrips) { @@ -924,6 +924,21 @@ static __init int svm_hardware_setup(void) svm_set_cpu_caps(); + /* + * It seems that on AMD processors PTE's accessed bit is + * being set by the CPU hardware before the NPF vmexit. + * This is not expected behaviour and our tests fail because + * of it. + * A workaround here is to disable support for + * GUEST_MAXPHYADDR < HOST_MAXPHYADDR if NPT is enabled. + * In this case userspace can know if there is support using + * KVM_CAP_SMALLER_MAXPHYADDR extension and decide how to handle + * it + * If future AMD CPU models change the behaviour described above, + * this variable can be changed accordingly + */ + allow_smaller_maxphyaddr = !npt_enabled; + return 0; err: @@ -966,7 +981,7 @@ static u64 svm_write_l1_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) svm->vmcb->control.tsc_offset = offset + g_tsc_offset; - mark_dirty(svm->vmcb, VMCB_INTERCEPTS); + vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS); return svm->vmcb->control.tsc_offset; } @@ -1002,38 +1017,38 @@ static void init_vmcb(struct vcpu_svm *svm) if (enable_vmware_backdoor) set_exception_intercept(svm, GP_VECTOR); - set_intercept(svm, INTERCEPT_INTR); - set_intercept(svm, INTERCEPT_NMI); - set_intercept(svm, INTERCEPT_SMI); - set_intercept(svm, INTERCEPT_SELECTIVE_CR0); - set_intercept(svm, INTERCEPT_RDPMC); - set_intercept(svm, INTERCEPT_CPUID); - set_intercept(svm, INTERCEPT_INVD); - set_intercept(svm, INTERCEPT_INVLPG); - set_intercept(svm, INTERCEPT_INVLPGA); - set_intercept(svm, INTERCEPT_IOIO_PROT); - set_intercept(svm, INTERCEPT_MSR_PROT); - set_intercept(svm, INTERCEPT_TASK_SWITCH); - set_intercept(svm, INTERCEPT_SHUTDOWN); - set_intercept(svm, INTERCEPT_VMRUN); - set_intercept(svm, INTERCEPT_VMMCALL); - set_intercept(svm, INTERCEPT_VMLOAD); - set_intercept(svm, INTERCEPT_VMSAVE); - set_intercept(svm, INTERCEPT_STGI); - set_intercept(svm, INTERCEPT_CLGI); - set_intercept(svm, INTERCEPT_SKINIT); - set_intercept(svm, INTERCEPT_WBINVD); - set_intercept(svm, INTERCEPT_XSETBV); - set_intercept(svm, INTERCEPT_RDPRU); - set_intercept(svm, INTERCEPT_RSM); + svm_set_intercept(svm, INTERCEPT_INTR); + svm_set_intercept(svm, INTERCEPT_NMI); + svm_set_intercept(svm, INTERCEPT_SMI); + svm_set_intercept(svm, INTERCEPT_SELECTIVE_CR0); + svm_set_intercept(svm, INTERCEPT_RDPMC); + svm_set_intercept(svm, INTERCEPT_CPUID); + svm_set_intercept(svm, INTERCEPT_INVD); + svm_set_intercept(svm, INTERCEPT_INVLPG); + svm_set_intercept(svm, INTERCEPT_INVLPGA); + svm_set_intercept(svm, INTERCEPT_IOIO_PROT); + svm_set_intercept(svm, INTERCEPT_MSR_PROT); + svm_set_intercept(svm, INTERCEPT_TASK_SWITCH); + svm_set_intercept(svm, INTERCEPT_SHUTDOWN); + svm_set_intercept(svm, INTERCEPT_VMRUN); + svm_set_intercept(svm, INTERCEPT_VMMCALL); + svm_set_intercept(svm, INTERCEPT_VMLOAD); + svm_set_intercept(svm, INTERCEPT_VMSAVE); + svm_set_intercept(svm, INTERCEPT_STGI); + svm_set_intercept(svm, INTERCEPT_CLGI); + svm_set_intercept(svm, INTERCEPT_SKINIT); + svm_set_intercept(svm, INTERCEPT_WBINVD); + svm_set_intercept(svm, INTERCEPT_XSETBV); + svm_set_intercept(svm, INTERCEPT_RDPRU); + svm_set_intercept(svm, INTERCEPT_RSM); if (!kvm_mwait_in_guest(svm->vcpu.kvm)) { - set_intercept(svm, INTERCEPT_MONITOR); - set_intercept(svm, INTERCEPT_MWAIT); + svm_set_intercept(svm, INTERCEPT_MONITOR); + svm_set_intercept(svm, INTERCEPT_MWAIT); } if (!kvm_hlt_in_guest(svm->vcpu.kvm)) - set_intercept(svm, INTERCEPT_HLT); + svm_set_intercept(svm, INTERCEPT_HLT); control->iopm_base_pa = __sme_set(iopm_base); control->msrpm_base_pa = __sme_set(__pa(svm->msrpm)); @@ -1077,7 +1092,7 @@ static void init_vmcb(struct vcpu_svm *svm) if (npt_enabled) { /* Setup VMCB for Nested Paging */ control->nested_ctl |= SVM_NESTED_CTL_NP_ENABLE; - clr_intercept(svm, INTERCEPT_INVLPG); + svm_clr_intercept(svm, INTERCEPT_INVLPG); clr_exception_intercept(svm, PF_VECTOR); clr_cr_intercept(svm, INTERCEPT_CR3_READ); clr_cr_intercept(svm, INTERCEPT_CR3_WRITE); @@ -1094,9 +1109,9 @@ static void init_vmcb(struct vcpu_svm *svm) control->pause_filter_count = pause_filter_count; if (pause_filter_thresh) control->pause_filter_thresh = pause_filter_thresh; - set_intercept(svm, INTERCEPT_PAUSE); + svm_set_intercept(svm, INTERCEPT_PAUSE); } else { - clr_intercept(svm, INTERCEPT_PAUSE); + svm_clr_intercept(svm, INTERCEPT_PAUSE); } if (kvm_vcpu_apicv_active(&svm->vcpu)) @@ -1107,14 +1122,14 @@ static void init_vmcb(struct vcpu_svm *svm) * in VMCB and clear intercepts to avoid #VMEXIT. */ if (vls) { - clr_intercept(svm, INTERCEPT_VMLOAD); - clr_intercept(svm, INTERCEPT_VMSAVE); + svm_clr_intercept(svm, INTERCEPT_VMLOAD); + svm_clr_intercept(svm, INTERCEPT_VMSAVE); svm->vmcb->control.virt_ext |= VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK; } if (vgif) { - clr_intercept(svm, INTERCEPT_STGI); - clr_intercept(svm, INTERCEPT_CLGI); + svm_clr_intercept(svm, INTERCEPT_STGI); + svm_clr_intercept(svm, INTERCEPT_CLGI); svm->vmcb->control.int_ctl |= V_GIF_ENABLE_MASK; } @@ -1123,7 +1138,7 @@ static void init_vmcb(struct vcpu_svm *svm) clr_exception_intercept(svm, UD_VECTOR); } - mark_all_dirty(svm->vmcb); + vmcb_mark_all_dirty(svm->vmcb); enable_gif(svm); @@ -1257,7 +1272,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) if (unlikely(cpu != vcpu->cpu)) { svm->asid_generation = 0; - mark_all_dirty(svm->vmcb); + vmcb_mark_all_dirty(svm->vmcb); } #ifdef CONFIG_X86_64 @@ -1356,7 +1371,7 @@ static void svm_set_vintr(struct vcpu_svm *svm) /* The following fields are ignored when AVIC is enabled */ WARN_ON(kvm_vcpu_apicv_active(&svm->vcpu)); - set_intercept(svm, INTERCEPT_VINTR); + svm_set_intercept(svm, INTERCEPT_VINTR); /* * This is just a dummy VINTR to actually cause a vmexit to happen. @@ -1367,13 +1382,13 @@ static void svm_set_vintr(struct vcpu_svm *svm) control->int_ctl &= ~V_INTR_PRIO_MASK; control->int_ctl |= V_IRQ_MASK | ((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT); - mark_dirty(svm->vmcb, VMCB_INTR); + vmcb_mark_dirty(svm->vmcb, VMCB_INTR); } static void svm_clear_vintr(struct vcpu_svm *svm) { const u32 mask = V_TPR_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK | V_INTR_MASKING_MASK; - clr_intercept(svm, INTERCEPT_VINTR); + svm_clr_intercept(svm, INTERCEPT_VINTR); /* Drop int_ctl fields related to VINTR injection. */ svm->vmcb->control.int_ctl &= mask; @@ -1385,7 +1400,7 @@ static void svm_clear_vintr(struct vcpu_svm *svm) svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl & ~mask; } - mark_dirty(svm->vmcb, VMCB_INTR); + vmcb_mark_dirty(svm->vmcb, VMCB_INTR); } static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg) @@ -1503,7 +1518,7 @@ static void svm_set_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt) svm->vmcb->save.idtr.limit = dt->size; svm->vmcb->save.idtr.base = dt->address ; - mark_dirty(svm->vmcb, VMCB_DT); + vmcb_mark_dirty(svm->vmcb, VMCB_DT); } static void svm_get_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt) @@ -1520,7 +1535,7 @@ static void svm_set_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt) svm->vmcb->save.gdtr.limit = dt->size; svm->vmcb->save.gdtr.base = dt->address ; - mark_dirty(svm->vmcb, VMCB_DT); + vmcb_mark_dirty(svm->vmcb, VMCB_DT); } static void update_cr0_intercept(struct vcpu_svm *svm) @@ -1531,7 +1546,7 @@ static void update_cr0_intercept(struct vcpu_svm *svm) *hcr0 = (*hcr0 & ~SVM_CR0_SELECTIVE_MASK) | (gcr0 & SVM_CR0_SELECTIVE_MASK); - mark_dirty(svm->vmcb, VMCB_CR); + vmcb_mark_dirty(svm->vmcb, VMCB_CR); if (gcr0 == *hcr0) { clr_cr_intercept(svm, INTERCEPT_CR0_READ); @@ -1572,7 +1587,7 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED)) cr0 &= ~(X86_CR0_CD | X86_CR0_NW); svm->vmcb->save.cr0 = cr0; - mark_dirty(svm->vmcb, VMCB_CR); + vmcb_mark_dirty(svm->vmcb, VMCB_CR); update_cr0_intercept(svm); } @@ -1592,7 +1607,7 @@ int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) cr4 |= X86_CR4_PAE; cr4 |= host_cr4_mce; to_svm(vcpu)->vmcb->save.cr4 = cr4; - mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR); + vmcb_mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR); return 0; } @@ -1624,10 +1639,10 @@ static void svm_set_segment(struct kvm_vcpu *vcpu, /* This is symmetric with svm_get_segment() */ svm->vmcb->save.cpl = (var->dpl & 3); - mark_dirty(svm->vmcb, VMCB_SEG); + vmcb_mark_dirty(svm->vmcb, VMCB_SEG); } -static void update_bp_intercept(struct kvm_vcpu *vcpu) +static void update_exception_bitmap(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -1636,8 +1651,7 @@ static void update_bp_intercept(struct kvm_vcpu *vcpu) if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) { if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) set_exception_intercept(svm, BP_VECTOR); - } else - vcpu->guest_debug = 0; + } } static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd) @@ -1651,7 +1665,7 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd) svm->asid_generation = sd->asid_generation; svm->vmcb->control.asid = sd->next_asid++; - mark_dirty(svm->vmcb, VMCB_ASID); + vmcb_mark_dirty(svm->vmcb, VMCB_ASID); } static void svm_set_dr6(struct vcpu_svm *svm, unsigned long value) @@ -1660,7 +1674,7 @@ static void svm_set_dr6(struct vcpu_svm *svm, unsigned long value) if (unlikely(value != vmcb->save.dr6)) { vmcb->save.dr6 = value; - mark_dirty(vmcb, VMCB_DR); + vmcb_mark_dirty(vmcb, VMCB_DR); } } @@ -1687,7 +1701,7 @@ static void svm_set_dr7(struct kvm_vcpu *vcpu, unsigned long value) struct vcpu_svm *svm = to_svm(vcpu); svm->vmcb->save.dr7 = value; - mark_dirty(svm->vmcb, VMCB_DR); + vmcb_mark_dirty(svm->vmcb, VMCB_DR); } static int pf_interception(struct vcpu_svm *svm) @@ -2000,8 +2014,8 @@ void svm_set_gif(struct vcpu_svm *svm, bool value) * again while processing KVM_REQ_EVENT if needed. */ if (vgif_enabled(svm)) - clr_intercept(svm, INTERCEPT_STGI); - if (is_intercept(svm, INTERCEPT_VINTR)) + svm_clr_intercept(svm, INTERCEPT_STGI); + if (svm_is_intercept(svm, INTERCEPT_VINTR)) svm_clear_vintr(svm); enable_gif(svm); @@ -2162,7 +2176,7 @@ static int cpuid_interception(struct vcpu_svm *svm) static int iret_interception(struct vcpu_svm *svm) { ++svm->vcpu.stat.nmi_window_exits; - clr_intercept(svm, INTERCEPT_IRET); + svm_clr_intercept(svm, INTERCEPT_IRET); svm->vcpu.arch.hflags |= HF_IRET_MASK; svm->nmi_iret_rip = kvm_rip_read(&svm->vcpu); kvm_make_request(KVM_REQ_EVENT, &svm->vcpu); @@ -2358,8 +2372,10 @@ static int svm_get_msr_feature(struct kvm_msr_entry *msr) if (boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) msr->data |= MSR_F10H_DECFG_LFENCE_SERIALIZE; break; + case MSR_IA32_PERF_CAPABILITIES: + return 0; default: - return 1; + return KVM_MSR_RET_INVALID; } return 0; @@ -2512,7 +2528,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) return 1; vcpu->arch.pat = data; svm->vmcb->save.g_pat = data; - mark_dirty(svm->vmcb, VMCB_NPT); + vmcb_mark_dirty(svm->vmcb, VMCB_NPT); break; case MSR_IA32_SPEC_CTRL: if (!msr->host_initiated && @@ -2522,7 +2538,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) !guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD)) return 1; - if (data & ~kvm_spec_ctrl_valid_bits(vcpu)) + if (kvm_spec_ctrl_test_value(data)) return 1; svm->spec_ctrl = data; @@ -2617,7 +2633,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) return 1; svm->vmcb->save.dbgctl = data; - mark_dirty(svm->vmcb, VMCB_LBR); + vmcb_mark_dirty(svm->vmcb, VMCB_LBR); if (data & (1ULL<<0)) svm_enable_lbrv(svm); else @@ -2947,6 +2963,7 @@ static int handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY; kvm_run->fail_entry.hardware_entry_failure_reason = svm->vmcb->control.exit_code; + kvm_run->fail_entry.cpu = vcpu->arch.last_vmentry_cpu; dump_vmcb(vcpu); return 0; } @@ -2970,8 +2987,9 @@ static int handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON; - vcpu->run->internal.ndata = 1; + vcpu->run->internal.ndata = 2; vcpu->run->internal.data[0] = exit_code; + vcpu->run->internal.data[1] = vcpu->arch.last_vmentry_cpu; return 0; } @@ -2992,21 +3010,18 @@ static int handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) static void reload_tss(struct kvm_vcpu *vcpu) { - int cpu = raw_smp_processor_id(); + struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu); - struct svm_cpu_data *sd = per_cpu(svm_data, cpu); sd->tss_desc->type = 9; /* available 32/64-bit TSS */ load_TR_desc(); } static void pre_svm_run(struct vcpu_svm *svm) { - int cpu = raw_smp_processor_id(); - - struct svm_cpu_data *sd = per_cpu(svm_data, cpu); + struct svm_cpu_data *sd = per_cpu(svm_data, svm->vcpu.cpu); if (sev_guest(svm->vcpu.kvm)) - return pre_sev_run(svm, cpu); + return pre_sev_run(svm, svm->vcpu.cpu); /* FIXME: handle wraparound of asid_generation */ if (svm->asid_generation != sd->asid_generation) @@ -3019,7 +3034,7 @@ static void svm_inject_nmi(struct kvm_vcpu *vcpu) svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI; vcpu->arch.hflags |= HF_NMI_MASK; - set_intercept(svm, INTERCEPT_IRET); + svm_set_intercept(svm, INTERCEPT_IRET); ++vcpu->stat.nmi_injections; } @@ -3040,7 +3055,7 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) { struct vcpu_svm *svm = to_svm(vcpu); - if (svm_nested_virtualize_tpr(vcpu)) + if (nested_svm_virtualize_tpr(vcpu)) return; clr_cr_intercept(svm, INTERCEPT_CR8_WRITE); @@ -3096,10 +3111,10 @@ static void svm_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked) if (masked) { svm->vcpu.arch.hflags |= HF_NMI_MASK; - set_intercept(svm, INTERCEPT_IRET); + svm_set_intercept(svm, INTERCEPT_IRET); } else { svm->vcpu.arch.hflags &= ~HF_NMI_MASK; - clr_intercept(svm, INTERCEPT_IRET); + svm_clr_intercept(svm, INTERCEPT_IRET); } } @@ -3179,7 +3194,7 @@ static void enable_nmi_window(struct kvm_vcpu *vcpu) if (!gif_set(svm)) { if (vgif_enabled(svm)) - set_intercept(svm, INTERCEPT_STGI); + svm_set_intercept(svm, INTERCEPT_STGI); return; /* STGI will cause a vm exit */ } @@ -3234,7 +3249,7 @@ static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); - if (svm_nested_virtualize_tpr(vcpu)) + if (nested_svm_virtualize_tpr(vcpu)) return; if (!is_cr_intercept(svm, INTERCEPT_CR8_WRITE)) { @@ -3248,7 +3263,7 @@ static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu) struct vcpu_svm *svm = to_svm(vcpu); u64 cr8; - if (svm_nested_virtualize_tpr(vcpu) || + if (nested_svm_virtualize_tpr(vcpu) || kvm_vcpu_apicv_active(vcpu)) return; @@ -3344,6 +3359,60 @@ static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu) void __svm_vcpu_run(unsigned long vmcb_pa, unsigned long *regs); +static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, + struct vcpu_svm *svm) +{ + /* + * VMENTER enables interrupts (host state), but the kernel state is + * interrupts disabled when this is invoked. Also tell RCU about + * it. This is the same logic as for exit_to_user_mode(). + * + * This ensures that e.g. latency analysis on the host observes + * guest mode as interrupt enabled. + * + * guest_enter_irqoff() informs context tracking about the + * transition to guest mode and if enabled adjusts RCU state + * accordingly. + */ + instrumentation_begin(); + trace_hardirqs_on_prepare(); + lockdep_hardirqs_on_prepare(CALLER_ADDR0); + instrumentation_end(); + + guest_enter_irqoff(); + lockdep_hardirqs_on(CALLER_ADDR0); + + __svm_vcpu_run(svm->vmcb_pa, (unsigned long *)&svm->vcpu.arch.regs); + +#ifdef CONFIG_X86_64 + native_wrmsrl(MSR_GS_BASE, svm->host.gs_base); +#else + loadsegment(fs, svm->host.fs); +#ifndef CONFIG_X86_32_LAZY_GS + loadsegment(gs, svm->host.gs); +#endif +#endif + + /* + * VMEXIT disables interrupts (host state), but tracing and lockdep + * have them in state 'on' as recorded before entering guest mode. + * Same as enter_from_user_mode(). + * + * guest_exit_irqoff() restores host context and reinstates RCU if + * enabled and required. + * + * This needs to be done before the below as native_read_msr() + * contains a tracepoint and x86_spec_ctrl_restore_host() calls + * into world and some more. + */ + lockdep_hardirqs_off(CALLER_ADDR0); + guest_exit_irqoff(); + + instrumentation_begin(); + trace_hardirqs_off_finish(); + instrumentation_end(); +} + static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) { fastpath_t exit_fastpath; @@ -3399,16 +3468,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) */ x86_spec_ctrl_set_guest(svm->spec_ctrl, svm->virt_spec_ctrl); - __svm_vcpu_run(svm->vmcb_pa, (unsigned long *)&svm->vcpu.arch.regs); - -#ifdef CONFIG_X86_64 - wrmsrl(MSR_GS_BASE, svm->host.gs_base); -#else - loadsegment(fs, svm->host.fs); -#ifndef CONFIG_X86_32_LAZY_GS - loadsegment(gs, svm->host.gs); -#endif -#endif + svm_vcpu_enter_exit(vcpu, svm); /* * We do not use IBRS in the kernel. If this vCPU has used the @@ -3477,11 +3537,12 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) SVM_EXIT_EXCP_BASE + MC_VECTOR)) svm_handle_mce(svm); - mark_all_clean(svm->vmcb); + vmcb_mark_all_clean(svm->vmcb); return exit_fastpath; } -static void svm_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long root) +static void svm_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long root, + int root_level) { struct vcpu_svm *svm = to_svm(vcpu); unsigned long cr3; @@ -3489,7 +3550,7 @@ static void svm_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long root) cr3 = __sme_set(root); if (npt_enabled) { svm->vmcb->control.nested_cr3 = cr3; - mark_dirty(svm->vmcb, VMCB_NPT); + vmcb_mark_dirty(svm->vmcb, VMCB_NPT); /* Loading L2's CR3 is handled by enter_svm_guest_mode. */ if (!test_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail)) @@ -3498,7 +3559,7 @@ static void svm_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long root) } svm->vmcb->save.cr3 = cr3; - mark_dirty(svm->vmcb, VMCB_CR); + vmcb_mark_dirty(svm->vmcb, VMCB_CR); } static int is_disabled(void) @@ -3551,7 +3612,7 @@ static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio) return 0; } -static void svm_cpuid_update(struct kvm_vcpu *vcpu) +static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -3843,6 +3904,7 @@ static int svm_pre_leave_smm(struct kvm_vcpu *vcpu, const char *smstate) struct kvm_host_map map; u64 guest; u64 vmcb; + int ret = 0; guest = GET_SMSTATE(u64, smstate, 0x7ed8); vmcb = GET_SMSTATE(u64, smstate, 0x7ee0); @@ -3851,10 +3913,11 @@ static int svm_pre_leave_smm(struct kvm_vcpu *vcpu, const char *smstate) if (kvm_vcpu_map(&svm->vcpu, gpa_to_gfn(vmcb), &map) == -EINVAL) return 1; nested_vmcb = map.hva; - enter_svm_guest_mode(svm, vmcb, nested_vmcb); + ret = enter_svm_guest_mode(svm, vmcb, nested_vmcb); kvm_vcpu_unmap(&svm->vcpu, &map, true); } - return 0; + + return ret; } static void enable_smi_window(struct kvm_vcpu *vcpu) @@ -3863,7 +3926,7 @@ static void enable_smi_window(struct kvm_vcpu *vcpu) if (!gif_set(svm)) { if (vgif_enabled(svm)) - set_intercept(svm, INTERCEPT_STGI); + svm_set_intercept(svm, INTERCEPT_STGI); /* STGI will cause a vm exit */ } else { /* We must be in SMM; RSM will cause a vmexit anyway. */ @@ -3992,7 +4055,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { .vcpu_blocking = svm_vcpu_blocking, .vcpu_unblocking = svm_vcpu_unblocking, - .update_bp_intercept = update_bp_intercept, + .update_exception_bitmap = update_exception_bitmap, .get_msr_feature = svm_get_msr_feature, .get_msr = svm_get_msr, .set_msr = svm_set_msr, @@ -4049,12 +4112,11 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { .set_tss_addr = svm_set_tss_addr, .set_identity_map_addr = svm_set_identity_map_addr, - .get_tdp_level = get_npt_level, .get_mt_mask = svm_get_mt_mask, .get_exit_info = svm_get_exit_info, - .cpuid_update = svm_cpuid_update, + .vcpu_after_set_cpuid = svm_vcpu_after_set_cpuid, .has_wbinvd_exit = svm_has_wbinvd_exit, diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 6ac4c00a5d826927ea703b679c19320a458a9a85..a798e17317094fe0a59a973607a4fb184f0d069a 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -81,7 +81,7 @@ struct kvm_svm { struct kvm_vcpu; -struct nested_state { +struct svm_nested_state { struct vmcb *hsave; u64 hsave_msr; u64 vm_cr_msr; @@ -133,7 +133,7 @@ struct vcpu_svm { ulong nmi_iret_rip; - struct nested_state nested; + struct svm_nested_state nested; bool nmi_singlestep; u64 nmi_singlestep_guest_rflags; @@ -158,9 +158,6 @@ struct vcpu_svm { */ struct list_head ir_list; spinlock_t ir_list_lock; - - /* which host CPU was used for running this vcpu */ - unsigned int last_cpu; }; struct svm_cpu_data { @@ -188,18 +185,18 @@ static inline struct kvm_svm *to_kvm_svm(struct kvm *kvm) return container_of(kvm, struct kvm_svm, kvm); } -static inline void mark_all_dirty(struct vmcb *vmcb) +static inline void vmcb_mark_all_dirty(struct vmcb *vmcb) { vmcb->control.clean = 0; } -static inline void mark_all_clean(struct vmcb *vmcb) +static inline void vmcb_mark_all_clean(struct vmcb *vmcb) { vmcb->control.clean = ((1 << VMCB_DIRTY_MAX) - 1) & ~VMCB_ALWAYS_DIRTY_MASK; } -static inline void mark_dirty(struct vmcb *vmcb, int bit) +static inline void vmcb_mark_dirty(struct vmcb *vmcb, int bit) { vmcb->control.clean &= ~(1 << bit); } @@ -293,7 +290,7 @@ static inline void clr_exception_intercept(struct vcpu_svm *svm, int bit) recalc_intercepts(svm); } -static inline void set_intercept(struct vcpu_svm *svm, int bit) +static inline void svm_set_intercept(struct vcpu_svm *svm, int bit) { struct vmcb *vmcb = get_host_vmcb(svm); @@ -302,7 +299,7 @@ static inline void set_intercept(struct vcpu_svm *svm, int bit) recalc_intercepts(svm); } -static inline void clr_intercept(struct vcpu_svm *svm, int bit) +static inline void svm_clr_intercept(struct vcpu_svm *svm, int bit) { struct vmcb *vmcb = get_host_vmcb(svm); @@ -311,7 +308,7 @@ static inline void clr_intercept(struct vcpu_svm *svm, int bit) recalc_intercepts(svm); } -static inline bool is_intercept(struct vcpu_svm *svm, int bit) +static inline bool svm_is_intercept(struct vcpu_svm *svm, int bit) { return (svm->vmcb->control.intercept & (1ULL << bit)) != 0; } @@ -346,7 +343,10 @@ static inline bool gif_set(struct vcpu_svm *svm) } /* svm.c */ -#define MSR_INVALID 0xffffffffU +#define MSR_CR3_LEGACY_RESERVED_MASK 0xfe7U +#define MSR_CR3_LEGACY_PAE_RESERVED_MASK 0x7U +#define MSR_CR3_LONG_RESERVED_MASK 0xfff0000000000fe7U +#define MSR_INVALID 0xffffffffU u32 svm_msrpm_offset(u32 msr); void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer); @@ -365,7 +365,7 @@ void svm_set_gif(struct vcpu_svm *svm, bool value); #define NESTED_EXIT_DONE 1 /* Exit caused nested vmexit */ #define NESTED_EXIT_CONTINUE 2 /* Further checks needed */ -static inline bool svm_nested_virtualize_tpr(struct kvm_vcpu *vcpu) +static inline bool nested_svm_virtualize_tpr(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -387,8 +387,8 @@ static inline bool nested_exit_on_nmi(struct vcpu_svm *svm) return (svm->nested.ctl.intercept & (1ULL << INTERCEPT_NMI)); } -void enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb_gpa, - struct vmcb *nested_vmcb); +int enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb_gpa, + struct vmcb *nested_vmcb); void svm_leave_nested(struct vcpu_svm *svm); int nested_svm_vmrun(struct vcpu_svm *svm); void nested_svm_vmloadsave(struct vmcb *from_vmcb, struct vmcb *to_vmcb); @@ -420,7 +420,7 @@ extern int avic; static inline void avic_update_vapic_bar(struct vcpu_svm *svm, u64 data) { svm->vmcb->control.avic_vapic_bar = data & VMCB_AVIC_APIC_BAR_MASK; - mark_dirty(svm->vmcb, VMCB_AVIC); + vmcb_mark_dirty(svm->vmcb, VMCB_AVIC); } static inline bool avic_vcpu_is_running(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index bf944334003aefa2cc5f1ffe3de34e61a1e6ceb3..1ec1ac40e3280a7f4eed4202354cb69e2d760c77 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -27,7 +27,7 @@ #define VCPU_R15 __VCPU_REGS_R15 * WORD_SIZE #endif - .text +.section .noinstr.text, "ax" /** * __svm_vcpu_run - Run a vCPU via a transition to SVM guest mode diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 11e4df5600183af206a0f5fab4adb93108bef6e4..23b58c28a1c926f461cb87c9ee1f03a310f23e25 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -171,15 +171,6 @@ static int nested_vmx_failInvalid(struct kvm_vcpu *vcpu) static int nested_vmx_failValid(struct kvm_vcpu *vcpu, u32 vm_instruction_error) { - struct vcpu_vmx *vmx = to_vmx(vcpu); - - /* - * failValid writes the error number to the current VMCS, which - * can't be done if there isn't a current VMCS. - */ - if (vmx->nested.current_vmptr == -1ull && !vmx->nested.hv_evmcs) - return nested_vmx_failInvalid(vcpu); - vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu) & ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_SF | X86_EFLAGS_OF)) @@ -192,6 +183,20 @@ static int nested_vmx_failValid(struct kvm_vcpu *vcpu, return kvm_skip_emulated_instruction(vcpu); } +static int nested_vmx_fail(struct kvm_vcpu *vcpu, u32 vm_instruction_error) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + + /* + * failValid writes the error number to the current VMCS, which + * can't be done if there isn't a current VMCS. + */ + if (vmx->nested.current_vmptr == -1ull && !vmx->nested.hv_evmcs) + return nested_vmx_failInvalid(vcpu); + + return nested_vmx_failValid(vcpu, vm_instruction_error); +} + static void nested_vmx_abort(struct kvm_vcpu *vcpu, u32 indicator) { /* TODO: not to reset guest simply here. */ @@ -2157,7 +2162,8 @@ static void prepare_vmcs02_constant_state(struct vcpu_vmx *vmx) * consistency checks. */ if (enable_ept && nested_early_check) - vmcs_write64(EPT_POINTER, construct_eptp(&vmx->vcpu, 0)); + vmcs_write64(EPT_POINTER, + construct_eptp(&vmx->vcpu, 0, PT64_ROOT_4LEVEL)); /* All VMFUNCs are currently emulated through L0 vmexits. */ if (cpu_has_vmx_vmfunc()) @@ -2433,22 +2439,28 @@ static void prepare_vmcs02_rare(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12) /* * Whether page-faults are trapped is determined by a combination of - * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF. - * If enable_ept, L0 doesn't care about page faults and we should - * set all of these to L1's desires. However, if !enable_ept, L0 does - * care about (at least some) page faults, and because it is not easy - * (if at all possible?) to merge L0 and L1's desires, we simply ask - * to exit on each and every L2 page fault. This is done by setting - * MASK=MATCH=0 and (see below) EB.PF=1. + * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF. If L0 + * doesn't care about page faults then we should set all of these to + * L1's desires. However, if L0 does care about (some) page faults, it + * is not easy (if at all possible?) to merge L0 and L1's desires, we + * simply ask to exit on each and every L2 page fault. This is done by + * setting MASK=MATCH=0 and (see below) EB.PF=1. * Note that below we don't need special code to set EB.PF beyond the * "or"ing of the EB of vmcs01 and vmcs12, because when enable_ept, * vmcs01's EB.PF is 0 so the "or" will take vmcs12's value, and when * !enable_ept, EB.PF is 1, so the "or" will always be 1. */ - vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, - enable_ept ? vmcs12->page_fault_error_code_mask : 0); - vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, - enable_ept ? vmcs12->page_fault_error_code_match : 0); + if (vmx_need_pf_intercept(&vmx->vcpu)) { + /* + * TODO: if both L0 and L1 need the same MASK and MATCH, + * go ahead and use it? + */ + vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0); + vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0); + } else { + vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, vmcs12->page_fault_error_code_mask); + vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, vmcs12->page_fault_error_code_match); + } if (cpu_has_vmx_apicv()) { vmcs_write64(EOI_EXIT_BITMAP0, vmcs12->eoi_exit_bitmap0); @@ -3205,6 +3217,43 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu) return true; } +static int nested_vmx_write_pml_buffer(struct kvm_vcpu *vcpu, gpa_t gpa) +{ + struct vmcs12 *vmcs12; + struct vcpu_vmx *vmx = to_vmx(vcpu); + gpa_t dst; + + if (WARN_ON_ONCE(!is_guest_mode(vcpu))) + return 0; + + if (WARN_ON_ONCE(vmx->nested.pml_full)) + return 1; + + /* + * Check if PML is enabled for the nested guest. Whether eptp bit 6 is + * set is already checked as part of A/D emulation. + */ + vmcs12 = get_vmcs12(vcpu); + if (!nested_cpu_has_pml(vmcs12)) + return 0; + + if (vmcs12->guest_pml_index >= PML_ENTITY_NUM) { + vmx->nested.pml_full = true; + return 1; + } + + gpa &= ~0xFFFull; + dst = vmcs12->pml_address + sizeof(u64) * vmcs12->guest_pml_index; + + if (kvm_write_guest_page(vcpu->kvm, gpa_to_gfn(dst), &gpa, + offset_in_page(dst), sizeof(gpa))) + return 0; + + vmcs12->guest_pml_index--; + + return 0; +} + /* * Intel's VMX Instruction Reference specifies a common set of prerequisites * for running VMX instructions (except VMXON, whose prerequisites are @@ -3456,19 +3505,18 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) * when using the merged vmcs02. */ if (interrupt_shadow & KVM_X86_SHADOW_INT_MOV_SS) - return nested_vmx_failValid(vcpu, - VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS); + return nested_vmx_fail(vcpu, VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS); if (vmcs12->launch_state == launch) - return nested_vmx_failValid(vcpu, + return nested_vmx_fail(vcpu, launch ? VMXERR_VMLAUNCH_NONCLEAR_VMCS : VMXERR_VMRESUME_NONLAUNCHED_VMCS); if (nested_vmx_check_controls(vcpu, vmcs12)) - return nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); + return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); if (nested_vmx_check_host_state(vcpu, vmcs12)) - return nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_HOST_STATE_FIELD); + return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_HOST_STATE_FIELD); /* * We're finally done with prerequisite checking, and can start with @@ -3517,7 +3565,7 @@ vmentry_failed: if (status == NVMX_VMENTRY_VMEXIT) return 1; WARN_ON_ONCE(status != NVMX_VMENTRY_VMFAIL); - return nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); + return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); } /* @@ -4460,7 +4508,7 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason, * flag and the VM-instruction error field of the VMCS * accordingly, and skip the emulated instruction. */ - (void)nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); + (void)nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); /* * Restore L1's host state to KVM's software model. We're here @@ -4760,8 +4808,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu) } if (vmx->nested.vmxon) - return nested_vmx_failValid(vcpu, - VMXERR_VMXON_IN_VMX_ROOT_OPERATION); + return nested_vmx_fail(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION); if ((vmx->msr_ia32_feature_control & VMXON_NEEDED_FEATURES) != VMXON_NEEDED_FEATURES) { @@ -4852,12 +4899,10 @@ static int handle_vmclear(struct kvm_vcpu *vcpu) return r; if (!page_address_valid(vcpu, vmptr)) - return nested_vmx_failValid(vcpu, - VMXERR_VMCLEAR_INVALID_ADDRESS); + return nested_vmx_fail(vcpu, VMXERR_VMCLEAR_INVALID_ADDRESS); if (vmptr == vmx->nested.vmxon_ptr) - return nested_vmx_failValid(vcpu, - VMXERR_VMCLEAR_VMXON_POINTER); + return nested_vmx_fail(vcpu, VMXERR_VMCLEAR_VMXON_POINTER); /* * When Enlightened VMEntry is enabled on the calling CPU we treat @@ -4927,8 +4972,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu) offset = vmcs_field_to_offset(field); if (offset < 0) - return nested_vmx_failValid(vcpu, - VMXERR_UNSUPPORTED_VMCS_COMPONENT); + return nested_vmx_fail(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); if (!is_guest_mode(vcpu) && is_vmcs12_ext_field(field)) copy_vmcs02_to_vmcs12_rare(vcpu, vmcs12); @@ -5031,8 +5075,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) offset = vmcs_field_to_offset(field); if (offset < 0) - return nested_vmx_failValid(vcpu, - VMXERR_UNSUPPORTED_VMCS_COMPONENT); + return nested_vmx_fail(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); /* * If the vCPU supports "VMWRITE to any supported field in the @@ -5040,8 +5083,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) */ if (vmcs_field_readonly(field) && !nested_cpu_has_vmwrite_any_field(vcpu)) - return nested_vmx_failValid(vcpu, - VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT); + return nested_vmx_fail(vcpu, VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT); /* * Ensure vmcs12 is up-to-date before any VMWRITE that dirties @@ -5116,12 +5158,10 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) return r; if (!page_address_valid(vcpu, vmptr)) - return nested_vmx_failValid(vcpu, - VMXERR_VMPTRLD_INVALID_ADDRESS); + return nested_vmx_fail(vcpu, VMXERR_VMPTRLD_INVALID_ADDRESS); if (vmptr == vmx->nested.vmxon_ptr) - return nested_vmx_failValid(vcpu, - VMXERR_VMPTRLD_VMXON_POINTER); + return nested_vmx_fail(vcpu, VMXERR_VMPTRLD_VMXON_POINTER); /* Forbid normal VMPTRLD if Enlightened version was used */ if (vmx->nested.hv_evmcs) @@ -5138,7 +5178,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) * given physical address won't match the required * VMCS12_REVISION identifier. */ - return nested_vmx_failValid(vcpu, + return nested_vmx_fail(vcpu, VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID); } @@ -5148,7 +5188,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) (new_vmcs12->hdr.shadow_vmcs && !nested_cpu_has_vmx_shadow_vmcs(vcpu))) { kvm_vcpu_unmap(vcpu, &map, false); - return nested_vmx_failValid(vcpu, + return nested_vmx_fail(vcpu, VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID); } @@ -5233,8 +5273,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) types = (vmx->nested.msrs.ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6; if (type >= 32 || !(types & (1 << type))) - return nested_vmx_failValid(vcpu, - VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); + return nested_vmx_fail(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); /* According to the Intel VMX instruction reference, the memory * operand is read even if it isn't needed (e.g., for type==global) @@ -5255,7 +5294,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) switch (type) { case VMX_EPT_EXTENT_CONTEXT: if (!nested_vmx_check_eptp(vcpu, operand.eptp)) - return nested_vmx_failValid(vcpu, + return nested_vmx_fail(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); roots_to_free = 0; @@ -5315,7 +5354,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) VMX_VPID_EXTENT_SUPPORTED_MASK) >> 8; if (type >= 32 || !(types & (1 << type))) - return nested_vmx_failValid(vcpu, + return nested_vmx_fail(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); /* according to the intel vmx instruction reference, the memory @@ -5329,7 +5368,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) return vmx_handle_memory_failure(vcpu, r, &e); if (operand.vpid >> 16) - return nested_vmx_failValid(vcpu, + return nested_vmx_fail(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); vpid02 = nested_get_vpid02(vcpu); @@ -5337,14 +5376,14 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) case VMX_VPID_EXTENT_INDIVIDUAL_ADDR: if (!operand.vpid || is_noncanonical_address(operand.gla, vcpu)) - return nested_vmx_failValid(vcpu, + return nested_vmx_fail(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); vpid_sync_vcpu_addr(vpid02, operand.gla); break; case VMX_VPID_EXTENT_SINGLE_CONTEXT: case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL: if (!operand.vpid) - return nested_vmx_failValid(vcpu, + return nested_vmx_fail(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); vpid_sync_context(vpid02); break; @@ -6333,7 +6372,8 @@ void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps) /* * secondary cpu-based controls. Do not include those that - * depend on CPUID bits, they are added later by vmx_cpuid_update. + * depend on CPUID bits, they are added later by + * vmx_vcpu_after_set_cpuid. */ if (msrs->procbased_ctls_high & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2, @@ -6514,6 +6554,7 @@ struct kvm_x86_nested_ops vmx_nested_ops = { .get_state = vmx_get_nested_state, .set_state = vmx_set_nested_state, .get_vmcs12_pages = nested_get_vmcs12_pages, + .write_log_dirty = nested_vmx_write_pml_buffer, .enable_evmcs = nested_enable_evmcs, .get_evmcs_version = nested_get_evmcs_version, }; diff --git a/arch/x86/kvm/vmx/ops.h b/arch/x86/kvm/vmx/ops.h index 5f1ac002b4b676232a326e993be25e75b59238e8..692b0c31c9c82d1bbf1f48b7e4c5362be543720b 100644 --- a/arch/x86/kvm/vmx/ops.h +++ b/arch/x86/kvm/vmx/ops.h @@ -146,7 +146,9 @@ do { \ : : op1 : "cc" : error, fault); \ return; \ error: \ + instrumentation_begin(); \ insn##_error(error_args); \ + instrumentation_end(); \ return; \ fault: \ kvm_spurious_fault(); \ @@ -161,7 +163,9 @@ do { \ : : op1, op2 : "cc" : error, fault); \ return; \ error: \ + instrumentation_begin(); \ insn##_error(error_args); \ + instrumentation_end(); \ return; \ fault: \ kvm_spurious_fault(); \ diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index bdcce65c7a1de72c77a19ce385c6f7e401d2b7f2..a886a47daebdadffa556e44e8e9dd6848abbe733 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -180,9 +180,6 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) case MSR_CORE_PERF_GLOBAL_OVF_CTRL: ret = pmu->version > 1; break; - case MSR_IA32_PERF_CAPABILITIES: - ret = 1; - break; default: ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) || get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0) || @@ -224,12 +221,6 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_CORE_PERF_GLOBAL_OVF_CTRL: msr_info->data = pmu->global_ovf_ctrl; return 0; - case MSR_IA32_PERF_CAPABILITIES: - if (!msr_info->host_initiated && - !guest_cpuid_has(vcpu, X86_FEATURE_PDCM)) - return 1; - msr_info->data = vcpu->arch.perf_capabilities; - return 0; default: if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) { @@ -289,14 +280,6 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) return 0; } break; - case MSR_IA32_PERF_CAPABILITIES: - if (!msr_info->host_initiated) - return 1; - if (guest_cpuid_has(vcpu, X86_FEATURE_PDCM) ? - (data & ~vmx_get_perf_capabilities()) : data) - return 1; - vcpu->arch.perf_capabilities = data; - return 0; default: if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) { diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S index e0a182cb3cdddd662af694ce06544d5c01b0ae32..799db084a336b40e126f03f0003e28373e153ac9 100644 --- a/arch/x86/kvm/vmx/vmenter.S +++ b/arch/x86/kvm/vmx/vmenter.S @@ -27,7 +27,7 @@ #define VCPU_R15 __VCPU_REGS_R15 * WORD_SIZE #endif - .text +.section .noinstr.text, "ax" /** * vmx_vmenter - VM-Enter the current loaded VMCS @@ -234,6 +234,9 @@ SYM_FUNC_START(__vmx_vcpu_run) jmp 1b SYM_FUNC_END(__vmx_vcpu_run) + +.section .text, "ax" + /** * vmread_error_trampoline - Trampoline from inline asm to vmread_error() * @field: VMCS field encoding that failed diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 559634b59d2a25c0a0e48eebfb2464ead9b6fdba..46ba2e03a8926d7a3d47463b5661ecd857aa76fb 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -781,7 +781,7 @@ void update_exception_bitmap(struct kvm_vcpu *vcpu) eb |= 1u << BP_VECTOR; if (to_vmx(vcpu)->rmode.vm86_active) eb = ~0; - if (enable_ept) + if (!vmx_need_pf_intercept(vcpu)) eb &= ~(1u << PF_VECTOR); /* When we are running a nested L2 guest and L1 specified for it a @@ -1816,7 +1816,7 @@ static int vmx_get_msr_feature(struct kvm_msr_entry *msr) msr->data = vmx_get_perf_capabilities(); return 0; default: - return 1; + return KVM_MSR_RET_INVALID; } } @@ -2063,7 +2063,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) !guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL)) return 1; - if (data & ~kvm_spec_ctrl_valid_bits(vcpu)) + if (kvm_spec_ctrl_test_value(data)) return 1; vmx->spec_ctrl = data; @@ -2934,14 +2934,16 @@ static void vmx_flush_tlb_all(struct kvm_vcpu *vcpu) static void vmx_flush_tlb_current(struct kvm_vcpu *vcpu) { - u64 root_hpa = vcpu->arch.mmu->root_hpa; + struct kvm_mmu *mmu = vcpu->arch.mmu; + u64 root_hpa = mmu->root_hpa; /* No flush required if the current context is invalid. */ if (!VALID_PAGE(root_hpa)) return; if (enable_ept) - ept_sync_context(construct_eptp(vcpu, root_hpa)); + ept_sync_context(construct_eptp(vcpu, root_hpa, + mmu->shadow_root_level)); else if (!is_guest_mode(vcpu)) vpid_sync_context(to_vmx(vcpu)->vpid); else @@ -3064,26 +3066,19 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) vmx->emulation_required = emulation_required(vcpu); } -static int vmx_get_tdp_level(struct kvm_vcpu *vcpu) +static int vmx_get_max_tdp_level(void) { - if (cpu_has_vmx_ept_5levels() && (cpuid_maxphyaddr(vcpu) > 48)) + if (cpu_has_vmx_ept_5levels()) return 5; return 4; } -static int get_ept_level(struct kvm_vcpu *vcpu) -{ - if (is_guest_mode(vcpu) && nested_cpu_has_ept(get_vmcs12(vcpu))) - return vmx_eptp_page_walk_level(nested_ept_get_eptp(vcpu)); - - return vmx_get_tdp_level(vcpu); -} - -u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa) +u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa, + int root_level) { u64 eptp = VMX_EPTP_MT_WB; - eptp |= (get_ept_level(vcpu) == 5) ? VMX_EPTP_PWL_5 : VMX_EPTP_PWL_4; + eptp |= (root_level == 5) ? VMX_EPTP_PWL_5 : VMX_EPTP_PWL_4; if (enable_ept_ad_bits && (!is_guest_mode(vcpu) || nested_ept_ad_enabled(vcpu))) @@ -3093,7 +3088,8 @@ u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa) return eptp; } -void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long pgd) +static void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long pgd, + int pgd_level) { struct kvm *kvm = vcpu->kvm; bool update_guest_cr3 = true; @@ -3101,7 +3097,7 @@ void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long pgd) u64 eptp; if (enable_ept) { - eptp = construct_eptp(vcpu, pgd); + eptp = construct_eptp(vcpu, pgd, pgd_level); vmcs_write64(EPT_POINTER, eptp); if (kvm_x86_ops.tlb_remote_flush) { @@ -4356,6 +4352,16 @@ static void init_vmcs(struct vcpu_vmx *vmx) vmx->pt_desc.guest.output_mask = 0x7F; vmcs_write64(GUEST_IA32_RTIT_CTL, 0); } + + /* + * If EPT is enabled, #PF is only trapped if MAXPHYADDR is mismatched + * between guest and host. In that case we only care about present + * faults. + */ + if (enable_ept) { + vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, PFERR_PRESENT_MASK); + vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, PFERR_PRESENT_MASK); + } } static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) @@ -4782,18 +4788,25 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu) !(is_page_fault(intr_info) && !(error_code & PFERR_RSVD_MASK))) { vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_SIMUL_EX; - vcpu->run->internal.ndata = 3; + vcpu->run->internal.ndata = 4; vcpu->run->internal.data[0] = vect_info; vcpu->run->internal.data[1] = intr_info; vcpu->run->internal.data[2] = error_code; + vcpu->run->internal.data[3] = vcpu->arch.last_vmentry_cpu; return 0; } if (is_page_fault(intr_info)) { cr2 = vmx_get_exit_qual(vcpu); - /* EPT won't cause page fault directly */ - WARN_ON_ONCE(!vcpu->arch.apf.host_apf_flags && enable_ept); - return kvm_handle_page_fault(vcpu, error_code, cr2, NULL, 0); + if (enable_ept && !vcpu->arch.apf.host_apf_flags) { + /* + * EPT will cause page fault only if we need to + * detect illegal GPAs. + */ + kvm_fixup_and_inject_pf_error(vcpu, cr2, error_code); + return 1; + } else + return kvm_handle_page_fault(vcpu, error_code, cr2, NULL, 0); } ex_no = intr_info & INTR_INFO_VECTOR_MASK; @@ -5309,6 +5322,18 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu) PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK; vcpu->arch.exit_qualification = exit_qualification; + + /* + * Check that the GPA doesn't exceed physical memory limits, as that is + * a guest page fault. We have to emulate the instruction here, because + * if the illegal address is that of a paging structure, then + * EPT_VIOLATION_ACC_WRITE bit is set. Alternatively, if supported we + * would also use advanced VM-exit information for EPT violations to + * reconstruct the page fault error code. + */ + if (unlikely(kvm_mmu_is_illegal_gpa(vcpu, gpa))) + return kvm_emulate_instruction(vcpu, 0); + return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0); } @@ -6005,6 +6030,7 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY; vcpu->run->fail_entry.hardware_entry_failure_reason = exit_reason; + vcpu->run->fail_entry.cpu = vcpu->arch.last_vmentry_cpu; return 0; } @@ -6013,6 +6039,7 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY; vcpu->run->fail_entry.hardware_entry_failure_reason = vmcs_read32(VM_INSTRUCTION_ERROR); + vcpu->run->fail_entry.cpu = vcpu->arch.last_vmentry_cpu; return 0; } @@ -6039,6 +6066,8 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) vcpu->run->internal.data[3] = vmcs_read64(GUEST_PHYSICAL_ADDRESS); } + vcpu->run->internal.data[vcpu->run->internal.ndata++] = + vcpu->arch.last_vmentry_cpu; return 0; } @@ -6094,8 +6123,9 @@ unexpected_vmexit: vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON; - vcpu->run->internal.ndata = 1; + vcpu->run->internal.ndata = 2; vcpu->run->internal.data[0] = exit_reason; + vcpu->run->internal.data[1] = vcpu->arch.last_vmentry_cpu; return 0; } @@ -6109,7 +6139,7 @@ unexpected_vmexit: * information but as all relevant affected CPUs have 32KiB L1D cache size * there is no point in doing so. */ -static void vmx_l1d_flush(struct kvm_vcpu *vcpu) +static noinstr void vmx_l1d_flush(struct kvm_vcpu *vcpu) { int size = PAGE_SIZE << L1D_CACHE_ORDER; @@ -6142,7 +6172,7 @@ static void vmx_l1d_flush(struct kvm_vcpu *vcpu) vcpu->stat.l1d_flush++; if (static_cpu_has(X86_FEATURE_FLUSH_L1D)) { - wrmsrl(MSR_IA32_FLUSH_CMD, L1D_FLUSH); + native_wrmsrl(MSR_IA32_FLUSH_CMD, L1D_FLUSH); return; } @@ -6628,7 +6658,7 @@ static void vmx_update_hv_timer(struct kvm_vcpu *vcpu) } } -void vmx_update_host_rsp(struct vcpu_vmx *vmx, unsigned long host_rsp) +void noinstr vmx_update_host_rsp(struct vcpu_vmx *vmx, unsigned long host_rsp) { if (unlikely(host_rsp != vmx->loaded_vmcs->host_state.rsp)) { vmx->loaded_vmcs->host_state.rsp = host_rsp; @@ -6650,6 +6680,63 @@ static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu) bool __vmx_vcpu_run(struct vcpu_vmx *vmx, unsigned long *regs, bool launched); +static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu, + struct vcpu_vmx *vmx) +{ + /* + * VMENTER enables interrupts (host state), but the kernel state is + * interrupts disabled when this is invoked. Also tell RCU about + * it. This is the same logic as for exit_to_user_mode(). + * + * This ensures that e.g. latency analysis on the host observes + * guest mode as interrupt enabled. + * + * guest_enter_irqoff() informs context tracking about the + * transition to guest mode and if enabled adjusts RCU state + * accordingly. + */ + instrumentation_begin(); + trace_hardirqs_on_prepare(); + lockdep_hardirqs_on_prepare(CALLER_ADDR0); + instrumentation_end(); + + guest_enter_irqoff(); + lockdep_hardirqs_on(CALLER_ADDR0); + + /* L1D Flush includes CPU buffer clear to mitigate MDS */ + if (static_branch_unlikely(&vmx_l1d_should_flush)) + vmx_l1d_flush(vcpu); + else if (static_branch_unlikely(&mds_user_clear)) + mds_clear_cpu_buffers(); + + if (vcpu->arch.cr2 != native_read_cr2()) + native_write_cr2(vcpu->arch.cr2); + + vmx->fail = __vmx_vcpu_run(vmx, (unsigned long *)&vcpu->arch.regs, + vmx->loaded_vmcs->launched); + + vcpu->arch.cr2 = native_read_cr2(); + + /* + * VMEXIT disables interrupts (host state), but tracing and lockdep + * have them in state 'on' as recorded before entering guest mode. + * Same as enter_from_user_mode(). + * + * guest_exit_irqoff() restores host context and reinstates RCU if + * enabled and required. + * + * This needs to be done before the below as native_read_msr() + * contains a tracepoint and x86_spec_ctrl_restore_host() calls + * into world and some more. + */ + lockdep_hardirqs_off(CALLER_ADDR0); + guest_exit_irqoff(); + + instrumentation_begin(); + trace_hardirqs_off_finish(); + instrumentation_end(); +} + static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu) { fastpath_t exit_fastpath; @@ -6724,19 +6811,8 @@ reenter_guest: */ x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0); - /* L1D Flush includes CPU buffer clear to mitigate MDS */ - if (static_branch_unlikely(&vmx_l1d_should_flush)) - vmx_l1d_flush(vcpu); - else if (static_branch_unlikely(&mds_user_clear)) - mds_clear_cpu_buffers(); - - if (vcpu->arch.cr2 != read_cr2()) - write_cr2(vcpu->arch.cr2); - - vmx->fail = __vmx_vcpu_run(vmx, (unsigned long *)&vcpu->arch.regs, - vmx->loaded_vmcs->launched); - - vcpu->arch.cr2 = read_cr2(); + /* The actual VMENTER/EXIT is in the .noinstr.text section. */ + vmx_vcpu_enter_exit(vcpu, vmx); /* * We do not use IBRS in the kernel. If this vCPU has used the @@ -7229,7 +7305,7 @@ static void update_intel_pt_cfg(struct kvm_vcpu *vcpu) vmx->pt_desc.ctl_bitmask &= ~(0xfULL << (32 + i * 4)); } -static void vmx_cpuid_update(struct kvm_vcpu *vcpu) +static void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); @@ -7478,42 +7554,6 @@ static void vmx_flush_log_dirty(struct kvm *kvm) kvm_flush_pml_buffers(kvm); } -static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu, gpa_t gpa) -{ - struct vmcs12 *vmcs12; - struct vcpu_vmx *vmx = to_vmx(vcpu); - gpa_t dst; - - if (is_guest_mode(vcpu)) { - WARN_ON_ONCE(vmx->nested.pml_full); - - /* - * Check if PML is enabled for the nested guest. - * Whether eptp bit 6 is set is already checked - * as part of A/D emulation. - */ - vmcs12 = get_vmcs12(vcpu); - if (!nested_cpu_has_pml(vmcs12)) - return 0; - - if (vmcs12->guest_pml_index >= PML_ENTITY_NUM) { - vmx->nested.pml_full = true; - return 1; - } - - gpa &= ~0xFFFull; - dst = vmcs12->pml_address + sizeof(u64) * vmcs12->guest_pml_index; - - if (kvm_write_guest_page(vcpu->kvm, gpa_to_gfn(dst), &gpa, - offset_in_page(dst), sizeof(gpa))) - return 0; - - vmcs12->guest_pml_index--; - } - - return 0; -} - static void vmx_enable_log_dirty_pt_masked(struct kvm *kvm, struct kvm_memory_slot *memslot, gfn_t offset, unsigned long mask) @@ -7858,7 +7898,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { .vcpu_load = vmx_vcpu_load, .vcpu_put = vmx_vcpu_put, - .update_bp_intercept = update_exception_bitmap, + .update_exception_bitmap = update_exception_bitmap, .get_msr_feature = vmx_get_msr_feature, .get_msr = vmx_get_msr, .set_msr = vmx_set_msr, @@ -7918,12 +7958,11 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { .set_tss_addr = vmx_set_tss_addr, .set_identity_map_addr = vmx_set_identity_map_addr, - .get_tdp_level = vmx_get_tdp_level, .get_mt_mask = vmx_get_mt_mask, .get_exit_info = vmx_get_exit_info, - .cpuid_update = vmx_cpuid_update, + .vcpu_after_set_cpuid = vmx_vcpu_after_set_cpuid, .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit, @@ -7942,7 +7981,6 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { .slot_disable_log_dirty = vmx_slot_disable_log_dirty, .flush_log_dirty = vmx_flush_log_dirty, .enable_log_dirty_pt_masked = vmx_enable_log_dirty_pt_masked, - .write_log_dirty = vmx_write_pml_buffer, .pre_block = vmx_pre_block, .post_block = vmx_post_block, @@ -8070,7 +8108,7 @@ static __init int hardware_setup(void) ept_lpage_level = PG_LEVEL_2M; else ept_lpage_level = PG_LEVEL_4K; - kvm_configure_mmu(enable_ept, ept_lpage_level); + kvm_configure_mmu(enable_ept, vmx_get_max_tdp_level(), ept_lpage_level); /* * Only enable PML when hardware supports PML feature, and both EPT @@ -8265,6 +8303,13 @@ static int __init vmx_init(void) #endif vmx_check_vmcs12_offsets(); + /* + * Intel processors don't have problems with + * GUEST_MAXPHYADDR < HOST_MAXPHYADDR so enable + * it for VMX by default + */ + allow_smaller_maxphyaddr = true; + return 0; } module_init(vmx_init); diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 639798e4a6ca74a41a59824f936d59a0a6412589..26175a4759fa5f8eef34b443dcb3fd6415b4f6b6 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -11,6 +11,7 @@ #include "kvm_cache_regs.h" #include "ops.h" #include "vmcs.h" +#include "cpuid.h" extern const u32 vmx_msr_index[]; @@ -337,11 +338,11 @@ void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer); void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4); void set_cr4_guest_host_mask(struct vcpu_vmx *vmx); -void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long cr3); void ept_save_pdptrs(struct kvm_vcpu *vcpu); void vmx_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg); void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg); -u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa); +u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa, + int root_level); void update_exception_bitmap(struct kvm_vcpu *vcpu); void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu); bool vmx_nmi_blocked(struct kvm_vcpu *vcpu); @@ -536,8 +537,6 @@ static inline struct vmcs *alloc_vmcs(bool shadow) GFP_KERNEL_ACCOUNT); } -u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa); - static inline void decache_tsc_multiplier(struct vcpu_vmx *vmx) { vmx->current_tsc_ratio = vmx->vcpu.arch.tsc_scaling_ratio; @@ -550,6 +549,11 @@ static inline bool vmx_has_waitpkg(struct vcpu_vmx *vmx) SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE; } +static inline bool vmx_need_pf_intercept(struct kvm_vcpu *vcpu) +{ + return !enable_ept || cpuid_maxphyaddr(vcpu) < boot_cpu_data.x86_phys_bits; +} + void dump_vmcs(void); #endif /* __KVM_X86_VMX_H */ diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 21d5e7a7ffd0015819182e0fef28b809c9b69e64..12ea77f99ff350d48c2b61d68687cc4cacfe7183 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -188,6 +188,9 @@ static struct kvm_shared_msrs __percpu *shared_msrs; u64 __read_mostly host_efer; EXPORT_SYMBOL_GPL(host_efer); +bool __read_mostly allow_smaller_maxphyaddr; +EXPORT_SYMBOL_GPL(allow_smaller_maxphyaddr); + static u64 __read_mostly host_xss; u64 __read_mostly supported_xss; EXPORT_SYMBOL_GPL(supported_xss); @@ -244,6 +247,29 @@ static struct kmem_cache *x86_fpu_cache; static struct kmem_cache *x86_emulator_cache; +/* + * When called, it means the previous get/set msr reached an invalid msr. + * Return 0 if we want to ignore/silent this failed msr access, or 1 if we want + * to fail the caller. + */ +static int kvm_msr_ignored_check(struct kvm_vcpu *vcpu, u32 msr, + u64 data, bool write) +{ + const char *op = write ? "wrmsr" : "rdmsr"; + + if (ignore_msrs) { + if (report_ignored_msrs) + vcpu_unimpl(vcpu, "ignored %s: 0x%x data 0x%llx\n", + op, msr, data); + /* Mask the error */ + return 0; + } else { + vcpu_debug_ratelimited(vcpu, "unhandled %s: 0x%x data 0x%llx\n", + op, msr, data); + return 1; + } +} + static struct kmem_cache *kvm_alloc_emulator_cache(void) { unsigned int useroffset = offsetof(struct x86_emulate_ctxt, src); @@ -380,7 +406,7 @@ int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info) } EXPORT_SYMBOL_GPL(kvm_set_apic_base); -asmlinkage __visible void kvm_spurious_fault(void) +asmlinkage __visible noinstr void kvm_spurious_fault(void) { /* Fault while not rebooting. We want the trace. */ BUG_ON(!kvm_rebooting); @@ -776,6 +802,7 @@ EXPORT_SYMBOL_GPL(pdptrs_changed); int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) { unsigned long old_cr0 = kvm_read_cr0(vcpu); + unsigned long pdptr_bits = X86_CR0_CD | X86_CR0_NW | X86_CR0_PG; unsigned long update_bits = X86_CR0_PG | X86_CR0_WP; cr0 |= X86_CR0_ET; @@ -793,9 +820,9 @@ int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) if ((cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PE)) return 1; - if (!is_paging(vcpu) && (cr0 & X86_CR0_PG)) { + if (cr0 & X86_CR0_PG) { #ifdef CONFIG_X86_64 - if ((vcpu->arch.efer & EFER_LME)) { + if (!is_paging(vcpu) && (vcpu->arch.efer & EFER_LME)) { int cs_db, cs_l; if (!is_pae(vcpu)) @@ -805,8 +832,8 @@ int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) return 1; } else #endif - if (is_pae(vcpu) && !load_pdptrs(vcpu, vcpu->arch.walk_mmu, - kvm_read_cr3(vcpu))) + if (is_pae(vcpu) && ((cr0 ^ old_cr0) & pdptr_bits) && + !load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu))) return 1; } @@ -917,7 +944,7 @@ static int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) vcpu->arch.xcr0 = xcr0; if ((xcr0 ^ old_xcr0) & XFEATURE_MASK_EXTEND) - kvm_update_cpuid(vcpu); + kvm_update_cpuid_runtime(vcpu); return 0; } @@ -932,37 +959,17 @@ int kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) } EXPORT_SYMBOL_GPL(kvm_set_xcr); -#define __cr4_reserved_bits(__cpu_has, __c) \ -({ \ - u64 __reserved_bits = CR4_RESERVED_BITS; \ - \ - if (!__cpu_has(__c, X86_FEATURE_XSAVE)) \ - __reserved_bits |= X86_CR4_OSXSAVE; \ - if (!__cpu_has(__c, X86_FEATURE_SMEP)) \ - __reserved_bits |= X86_CR4_SMEP; \ - if (!__cpu_has(__c, X86_FEATURE_SMAP)) \ - __reserved_bits |= X86_CR4_SMAP; \ - if (!__cpu_has(__c, X86_FEATURE_FSGSBASE)) \ - __reserved_bits |= X86_CR4_FSGSBASE; \ - if (!__cpu_has(__c, X86_FEATURE_PKU)) \ - __reserved_bits |= X86_CR4_PKE; \ - if (!__cpu_has(__c, X86_FEATURE_LA57)) \ - __reserved_bits |= X86_CR4_LA57; \ - if (!__cpu_has(__c, X86_FEATURE_UMIP)) \ - __reserved_bits |= X86_CR4_UMIP; \ - __reserved_bits; \ -}) - -static int kvm_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) +int kvm_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) { if (cr4 & cr4_reserved_bits) return -EINVAL; - if (cr4 & __cr4_reserved_bits(guest_cpuid_has, vcpu)) + if (cr4 & vcpu->arch.cr4_guest_rsvd_bits) return -EINVAL; return 0; } +EXPORT_SYMBOL_GPL(kvm_valid_cr4); int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) { @@ -1001,7 +1008,7 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) kvm_mmu_reset_context(vcpu); if ((cr4 ^ old_cr4) & (X86_CR4_OSXSAVE | X86_CR4_PKE)) - kvm_update_cpuid(vcpu); + kvm_update_cpuid_runtime(vcpu); return 0; } @@ -1111,7 +1118,7 @@ static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) case 4: /* fall through */ case 6: - if (val & 0xffffffff00000000ULL) + if (!kvm_dr6_valid(val)) return -1; /* #GP */ vcpu->arch.dr6 = (val & DR6_VOLATILE) | kvm_dr6_fixed(vcpu); break; @@ -1390,8 +1397,7 @@ static int kvm_get_msr_feature(struct kvm_msr_entry *msr) rdmsrl_safe(msr->index, &msr->data); break; default: - if (kvm_x86_ops.get_msr_feature(msr)) - return 1; + return kvm_x86_ops.get_msr_feature(msr); } return 0; } @@ -1403,6 +1409,13 @@ static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data) msr.index = index; r = kvm_get_msr_feature(&msr); + + if (r == KVM_MSR_RET_INVALID) { + /* Unconditionally clear the output for simplicity */ + *data = 0; + r = kvm_msr_ignored_check(vcpu, index, 0, false); + } + if (r) return r; @@ -1517,6 +1530,17 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data, return kvm_x86_ops.set_msr(vcpu, &msr); } +static int kvm_set_msr_ignored_check(struct kvm_vcpu *vcpu, + u32 index, u64 data, bool host_initiated) +{ + int ret = __kvm_set_msr(vcpu, index, data, host_initiated); + + if (ret == KVM_MSR_RET_INVALID) + ret = kvm_msr_ignored_check(vcpu, index, data, true); + + return ret; +} + /* * Read the MSR specified by @index into @data. Select MSR specific fault * checks are bypassed if @host_initiated is %true. @@ -1538,15 +1562,29 @@ int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data, return ret; } +static int kvm_get_msr_ignored_check(struct kvm_vcpu *vcpu, + u32 index, u64 *data, bool host_initiated) +{ + int ret = __kvm_get_msr(vcpu, index, data, host_initiated); + + if (ret == KVM_MSR_RET_INVALID) { + /* Unconditionally clear *data for simplicity */ + *data = 0; + ret = kvm_msr_ignored_check(vcpu, index, 0, false); + } + + return ret; +} + int kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data) { - return __kvm_get_msr(vcpu, index, data, false); + return kvm_get_msr_ignored_check(vcpu, index, data, false); } EXPORT_SYMBOL_GPL(kvm_get_msr); int kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data) { - return __kvm_set_msr(vcpu, index, data, false); + return kvm_set_msr_ignored_check(vcpu, index, data, false); } EXPORT_SYMBOL_GPL(kvm_set_msr); @@ -1666,12 +1704,12 @@ EXPORT_SYMBOL_GPL(handle_fastpath_set_msr_irqoff); */ static int do_get_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data) { - return __kvm_get_msr(vcpu, index, data, true); + return kvm_get_msr_ignored_check(vcpu, index, data, true); } static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data) { - return __kvm_set_msr(vcpu, index, *data, true); + return kvm_set_msr_ignored_check(vcpu, index, *data, true); } #ifdef CONFIG_X86_64 @@ -2823,6 +2861,20 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) return 1; vcpu->arch.arch_capabilities = data; break; + case MSR_IA32_PERF_CAPABILITIES: { + struct kvm_msr_entry msr_ent = {.index = msr, .data = 0}; + + if (!msr_info->host_initiated) + return 1; + if (guest_cpuid_has(vcpu, X86_FEATURE_PDCM) && kvm_get_msr_feature(&msr_ent)) + return 1; + if (data & ~msr_ent.data) + return 1; + + vcpu->arch.perf_capabilities = data; + + return 0; + } case MSR_EFER: return set_efer(vcpu, msr_info); case MSR_K7_HWCR: @@ -2882,7 +2934,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) if (!guest_cpuid_has(vcpu, X86_FEATURE_XMM3)) return 1; vcpu->arch.ia32_misc_enable_msr = data; - kvm_update_cpuid(vcpu); + kvm_update_cpuid_runtime(vcpu); } else { vcpu->arch.ia32_misc_enable_msr = data; } @@ -3067,17 +3119,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) return xen_hvm_config(vcpu, data); if (kvm_pmu_is_valid_msr(vcpu, msr)) return kvm_pmu_set_msr(vcpu, msr_info); - if (!ignore_msrs) { - vcpu_debug_ratelimited(vcpu, "unhandled wrmsr: 0x%x data 0x%llx\n", - msr, data); - return 1; - } else { - if (report_ignored_msrs) - vcpu_unimpl(vcpu, - "ignored wrmsr: 0x%x data 0x%llx\n", - msr, data); - break; - } + return KVM_MSR_RET_INVALID; } return 0; } @@ -3173,6 +3215,12 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) return 1; msr_info->data = vcpu->arch.arch_capabilities; break; + case MSR_IA32_PERF_CAPABILITIES: + if (!msr_info->host_initiated && + !guest_cpuid_has(vcpu, X86_FEATURE_PDCM)) + return 1; + msr_info->data = vcpu->arch.perf_capabilities; + break; case MSR_IA32_POWER_CTL: msr_info->data = vcpu->arch.msr_ia32_power_ctl; break; @@ -3332,17 +3380,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) default: if (kvm_pmu_is_valid_msr(vcpu, msr_info->index)) return kvm_pmu_get_msr(vcpu, msr_info); - if (!ignore_msrs) { - vcpu_debug_ratelimited(vcpu, "unhandled rdmsr: 0x%x\n", - msr_info->index); - return 1; - } else { - if (report_ignored_msrs) - vcpu_unimpl(vcpu, "ignored rdmsr: 0x%x\n", - msr_info->index); - msr_info->data = 0; - } - break; + return KVM_MSR_RET_INVALID; } return 0; } @@ -3477,6 +3515,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_MSR_PLATFORM_INFO: case KVM_CAP_EXCEPTION_PAYLOAD: case KVM_CAP_SET_GUEST_DEBUG: + case KVM_CAP_LAST_CPU: r = 1; break; case KVM_CAP_SYNC_REGS: @@ -3539,6 +3578,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_HYPERV_ENLIGHTENED_VMCS: r = kvm_x86_ops.nested_ops->enable_evmcs != NULL; break; + case KVM_CAP_SMALLER_MAXPHYADDR: + r = (int) allow_smaller_maxphyaddr; + break; default: break; } @@ -8155,7 +8197,7 @@ static void enter_smm(struct kvm_vcpu *vcpu) kvm_x86_ops.set_efer(vcpu, 0); #endif - kvm_update_cpuid(vcpu); + kvm_update_cpuid_runtime(vcpu); kvm_mmu_reset_context(vcpu); } @@ -8507,7 +8549,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) } trace_kvm_entry(vcpu->vcpu_id); - guest_enter_irqoff(); fpregs_assert_state_consistent(); if (test_thread_flag(TIF_NEED_FPU_LOAD)) @@ -8549,6 +8590,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) if (hw_breakpoint_active()) hw_breakpoint_restore(); + vcpu->arch.last_vmentry_cpu = vcpu->cpu; vcpu->arch.last_guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc()); vcpu->mode = OUTSIDE_GUEST_MODE; @@ -8569,7 +8611,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) local_irq_disable(); kvm_after_interrupt(vcpu); - guest_exit_irqoff(); if (lapic_in_kernel(vcpu)) { s64 delta = vcpu->arch.apic->lapic_timer.advance_expire_delta; if (delta != S64_MIN) { @@ -9174,7 +9215,7 @@ static int __set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) (X86_CR4_OSXSAVE | X86_CR4_PKE)); kvm_x86_ops.set_cr4(vcpu, sregs->cr4); if (cpuid_update_needed) - kvm_update_cpuid(vcpu); + kvm_update_cpuid_runtime(vcpu); idx = srcu_read_lock(&vcpu->kvm->srcu); if (is_pae_paging(vcpu)) { @@ -9278,7 +9319,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, */ kvm_set_rflags(vcpu, rflags); - kvm_x86_ops.update_bp_intercept(vcpu); + kvm_x86_ops.update_exception_bitmap(vcpu); r = 0; @@ -9476,7 +9517,6 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) fx_init(vcpu); vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu); - vcpu->arch.tdp_level = kvm_x86_ops.get_tdp_level(vcpu); vcpu->arch.pat = MSR_IA32_CR_PAT_DEFAULT; @@ -10673,28 +10713,53 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvm_arch_no_poll); -u64 kvm_spec_ctrl_valid_bits(struct kvm_vcpu *vcpu) + +int kvm_spec_ctrl_test_value(u64 value) { - uint64_t bits = SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD; + /* + * test that setting IA32_SPEC_CTRL to given value + * is allowed by the host processor + */ - /* The STIBP bit doesn't fault even if it's not advertised */ - if (!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) && - !guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS)) - bits &= ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP); - if (!boot_cpu_has(X86_FEATURE_SPEC_CTRL) && - !boot_cpu_has(X86_FEATURE_AMD_IBRS)) - bits &= ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP); + u64 saved_value; + unsigned long flags; + int ret = 0; - if (!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL_SSBD) && - !guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD)) - bits &= ~SPEC_CTRL_SSBD; - if (!boot_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) && - !boot_cpu_has(X86_FEATURE_AMD_SSBD)) - bits &= ~SPEC_CTRL_SSBD; + local_irq_save(flags); + + if (rdmsrl_safe(MSR_IA32_SPEC_CTRL, &saved_value)) + ret = 1; + else if (wrmsrl_safe(MSR_IA32_SPEC_CTRL, value)) + ret = 1; + else + wrmsrl(MSR_IA32_SPEC_CTRL, saved_value); + + local_irq_restore(flags); - return bits; + return ret; +} +EXPORT_SYMBOL_GPL(kvm_spec_ctrl_test_value); + +void kvm_fixup_and_inject_pf_error(struct kvm_vcpu *vcpu, gva_t gva, u16 error_code) +{ + struct x86_exception fault; + + if (!(error_code & PFERR_PRESENT_MASK) || + vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, error_code, &fault) != UNMAPPED_GVA) { + /* + * If vcpu->arch.walk_mmu->gva_to_gpa succeeded, the page + * tables probably do not match the TLB. Just proceed + * with the error code that the processor gave. + */ + fault.vector = PF_VECTOR; + fault.error_code_valid = true; + fault.error_code = error_code; + fault.nested_page_fault = false; + fault.address = gva; + } + vcpu->arch.walk_mmu->inject_page_fault(vcpu, &fault); } -EXPORT_SYMBOL_GPL(kvm_spec_ctrl_valid_bits); +EXPORT_SYMBOL_GPL(kvm_fixup_and_inject_pf_error); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_exit); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_fast_mmio); diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 6eb62e97e59faab3a81c901b3e2a6a0ed50947fa..995ab696dcf0691203c04a12a418c300b9955af0 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -272,6 +272,7 @@ int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata); bool kvm_mtrr_check_gfn_range_consistency(struct kvm_vcpu *vcpu, gfn_t gfn, int page_num); bool kvm_vector_hashing_enabled(void); +void kvm_fixup_and_inject_pf_error(struct kvm_vcpu *vcpu, gva_t gva, u16 error_code); int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, int emulation_type, void *insn, int insn_len); fastpath_t handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu); @@ -360,10 +361,41 @@ static inline bool kvm_dr7_valid(u64 data) /* Bits [63:32] are reserved */ return !(data >> 32); } +static inline bool kvm_dr6_valid(u64 data) +{ + /* Bits [63:32] are reserved */ + return !(data >> 32); +} void kvm_load_guest_xsave_state(struct kvm_vcpu *vcpu); void kvm_load_host_xsave_state(struct kvm_vcpu *vcpu); -u64 kvm_spec_ctrl_valid_bits(struct kvm_vcpu *vcpu); +int kvm_spec_ctrl_test_value(u64 value); +int kvm_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4); bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu); +#define KVM_MSR_RET_INVALID 2 + +#define __cr4_reserved_bits(__cpu_has, __c) \ +({ \ + u64 __reserved_bits = CR4_RESERVED_BITS; \ + \ + if (!__cpu_has(__c, X86_FEATURE_XSAVE)) \ + __reserved_bits |= X86_CR4_OSXSAVE; \ + if (!__cpu_has(__c, X86_FEATURE_SMEP)) \ + __reserved_bits |= X86_CR4_SMEP; \ + if (!__cpu_has(__c, X86_FEATURE_SMAP)) \ + __reserved_bits |= X86_CR4_SMAP; \ + if (!__cpu_has(__c, X86_FEATURE_FSGSBASE)) \ + __reserved_bits |= X86_CR4_FSGSBASE; \ + if (!__cpu_has(__c, X86_FEATURE_PKU)) \ + __reserved_bits |= X86_CR4_PKE; \ + if (!__cpu_has(__c, X86_FEATURE_LA57)) \ + __reserved_bits |= X86_CR4_LA57; \ + if (!__cpu_has(__c, X86_FEATURE_UMIP)) \ + __reserved_bits |= X86_CR4_UMIP; \ + if (!__cpu_has(__c, X86_FEATURE_VMX)) \ + __reserved_bits |= X86_CR4_VMXE; \ + __reserved_bits; \ +}) + #endif diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 6deb49094c605815ce35a9f71a3589f687017b6f..799f4eba0a621f7296516506a57ff8b0fd5ba948 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -114,9 +114,8 @@ PV_CALLEE_SAVE_REGS_THUNK(xen_vcpu_stolen); */ void __init xen_init_spinlocks(void) { - /* Don't need to use pvqspinlock code if there is only 1 vCPU. */ - if (num_possible_cpus() == 1) + if (num_possible_cpus() == 1 || nopvspin) xen_pvspin = false; if (!xen_pvspin) { @@ -137,6 +136,7 @@ void __init xen_init_spinlocks(void) static __init int xen_parse_nopvspin(char *arg) { + pr_notice("\"xen_nopvspin\" is deprecated, please use \"nopvspin\" instead\n"); xen_pvspin = false; return 0; } diff --git a/block/blk-pm.c b/block/blk-pm.c index 1adc1cd748b4038d8bb441d76fa9ca277d333c0c..b85234d758f7b2d6d75734fe9d74a0e5e03bdcc2 100644 --- a/block/blk-pm.c +++ b/block/blk-pm.c @@ -164,9 +164,8 @@ EXPORT_SYMBOL(blk_pre_runtime_resume); * * Description: * Update the queue's runtime status according to the return value of the - * device's runtime_resume function. If it is successfully resumed, process - * the requests that are queued into the device's queue when it is resuming - * and then mark last busy and initiate autosuspend for it. + * device's runtime_resume function. If the resume was successful, call + * blk_set_runtime_active() to do the real work of restarting the queue. * * This function should be called near the end of the device's * runtime_resume callback. @@ -175,19 +174,13 @@ void blk_post_runtime_resume(struct request_queue *q, int err) { if (!q->dev) return; - - spin_lock_irq(&q->queue_lock); if (!err) { - q->rpm_status = RPM_ACTIVE; - pm_runtime_mark_last_busy(q->dev); - pm_request_autosuspend(q->dev); + blk_set_runtime_active(q); } else { + spin_lock_irq(&q->queue_lock); q->rpm_status = RPM_SUSPENDED; + spin_unlock_irq(&q->queue_lock); } - spin_unlock_irq(&q->queue_lock); - - if (!err) - blk_clear_pm_only(q); } EXPORT_SYMBOL(blk_post_runtime_resume); @@ -204,15 +197,25 @@ EXPORT_SYMBOL(blk_post_runtime_resume); * This function can be used in driver's resume hook to correct queue * runtime PM status and re-enable peeking requests from the queue. It * should be called before first request is added to the queue. + * + * This function is also called by blk_post_runtime_resume() for successful + * runtime resumes. It does everything necessary to restart the queue. */ void blk_set_runtime_active(struct request_queue *q) { - if (q->dev) { - spin_lock_irq(&q->queue_lock); - q->rpm_status = RPM_ACTIVE; - pm_runtime_mark_last_busy(q->dev); - pm_request_autosuspend(q->dev); - spin_unlock_irq(&q->queue_lock); - } + int old_status; + + if (!q->dev) + return; + + spin_lock_irq(&q->queue_lock); + old_status = q->rpm_status; + q->rpm_status = RPM_ACTIVE; + pm_runtime_mark_last_busy(q->dev); + pm_request_autosuspend(q->dev); + spin_unlock_irq(&q->queue_lock); + + if (old_status != RPM_ACTIVE) + blk_clear_pm_only(q); } EXPORT_SYMBOL(blk_set_runtime_active); diff --git a/drivers/accessibility/Kconfig b/drivers/accessibility/Kconfig index f10c17dc1dee35ce76bdcf176386556210f5ea92..6b2f79d1f1b81c7bfb31d89a9aa52d135be6c6c0 100644 --- a/drivers/accessibility/Kconfig +++ b/drivers/accessibility/Kconfig @@ -31,4 +31,6 @@ config A11Y_BRAILLE_CONSOLE If unsure, say N. +source "drivers/accessibility/speakup/Kconfig" + endif # ACCESSIBILITY diff --git a/drivers/accessibility/Makefile b/drivers/accessibility/Makefile index e8c182f82c44f797e5a2bd6e405ffffaaef40279..83360308653077ba092b16fa0c6f7d03a3e1271b 100644 --- a/drivers/accessibility/Makefile +++ b/drivers/accessibility/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y += braille/ +obj-$(CONFIG_SPEAKUP) += speakup/ diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c index a8f7c278b69185514af153b64166c342dd42de23..c2b452af68068465abeb06abdc4ebbbd8acd21d3 100644 --- a/drivers/accessibility/braille/braille_console.c +++ b/drivers/accessibility/braille/braille_console.c @@ -109,16 +109,16 @@ static void braille_write(u16 *buf) /* Follow the VC cursor*/ static void vc_follow_cursor(struct vc_data *vc) { - vc_x = vc->vc_x - (vc->vc_x % WIDTH); - vc_y = vc->vc_y; - lastvc_x = vc->vc_x; - lastvc_y = vc->vc_y; + vc_x = vc->state.x - (vc->state.x % WIDTH); + vc_y = vc->state.y; + lastvc_x = vc->state.x; + lastvc_y = vc->state.y; } /* Maybe the VC cursor moved, if so follow it */ static void vc_maybe_cursor_moved(struct vc_data *vc) { - if (vc->vc_x != lastvc_x || vc->vc_y != lastvc_y) + if (vc->state.x != lastvc_x || vc->state.y != lastvc_y) vc_follow_cursor(vc); } diff --git a/drivers/staging/speakup/DefaultKeyAssignments b/drivers/accessibility/speakup/DefaultKeyAssignments similarity index 100% rename from drivers/staging/speakup/DefaultKeyAssignments rename to drivers/accessibility/speakup/DefaultKeyAssignments diff --git a/drivers/staging/speakup/Kconfig b/drivers/accessibility/speakup/Kconfig similarity index 100% rename from drivers/staging/speakup/Kconfig rename to drivers/accessibility/speakup/Kconfig diff --git a/drivers/staging/speakup/Makefile b/drivers/accessibility/speakup/Makefile similarity index 100% rename from drivers/staging/speakup/Makefile rename to drivers/accessibility/speakup/Makefile diff --git a/drivers/accessibility/speakup/TODO b/drivers/accessibility/speakup/TODO new file mode 100644 index 0000000000000000000000000000000000000000..d4ca093bf0bd2754147a4dc207ee0317ae68e357 --- /dev/null +++ b/drivers/accessibility/speakup/TODO @@ -0,0 +1,22 @@ +Speakup project home: http://www.linux-speakup.org + +Mailing List: speakup@linux-speakup.org + +Speakup is a kernel based screen review package for the linux operating +system. It allows blind users to interact with applications on the +linux console by means of synthetic speech. + +Currently, speakup has one issue we know of. + +It seems to only happen on SMP systems. It seems that text in the output buffer +gets garbled because a lock is not set. This bug happens regularly, but no one +has been able to find a situation which produces it consistently. + +Patches, suggestions, corrections, etc, are definitely welcome. + +We prefer that you contact us on the mailing list; however, if you do +not want to subscribe to a mailing list, send your email to all of the +following: + +okash.khawaja@gmail.com, w.d.hubbs@gmail.com, chris@the-brannons.com, +kirk@reisers.ca and samuel.thibault@ens-lyon.org. diff --git a/drivers/staging/speakup/buffers.c b/drivers/accessibility/speakup/buffers.c similarity index 100% rename from drivers/staging/speakup/buffers.c rename to drivers/accessibility/speakup/buffers.c diff --git a/drivers/staging/speakup/devsynth.c b/drivers/accessibility/speakup/devsynth.c similarity index 100% rename from drivers/staging/speakup/devsynth.c rename to drivers/accessibility/speakup/devsynth.c diff --git a/drivers/staging/speakup/fakekey.c b/drivers/accessibility/speakup/fakekey.c similarity index 100% rename from drivers/staging/speakup/fakekey.c rename to drivers/accessibility/speakup/fakekey.c diff --git a/drivers/staging/speakup/i18n.c b/drivers/accessibility/speakup/i18n.c similarity index 100% rename from drivers/staging/speakup/i18n.c rename to drivers/accessibility/speakup/i18n.c diff --git a/drivers/staging/speakup/i18n.h b/drivers/accessibility/speakup/i18n.h similarity index 100% rename from drivers/staging/speakup/i18n.h rename to drivers/accessibility/speakup/i18n.h diff --git a/drivers/staging/speakup/keyhelp.c b/drivers/accessibility/speakup/keyhelp.c similarity index 100% rename from drivers/staging/speakup/keyhelp.c rename to drivers/accessibility/speakup/keyhelp.c diff --git a/drivers/staging/speakup/kobjects.c b/drivers/accessibility/speakup/kobjects.c similarity index 100% rename from drivers/staging/speakup/kobjects.c rename to drivers/accessibility/speakup/kobjects.c diff --git a/drivers/staging/speakup/main.c b/drivers/accessibility/speakup/main.c similarity index 98% rename from drivers/staging/speakup/main.c rename to drivers/accessibility/speakup/main.c index 02471d932d71f698bb596380f4cbceabef74bd12..ddfd12afe3b9a6f1303ef39108a2f2ba7611ac95 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/accessibility/speakup/main.c @@ -263,8 +263,8 @@ static unsigned char get_attributes(struct vc_data *vc, u16 *pos) static void speakup_date(struct vc_data *vc) { - spk_x = spk_cx = vc->vc_x; - spk_y = spk_cy = vc->vc_y; + spk_x = spk_cx = vc->state.x; + spk_y = spk_cy = vc->state.y; spk_pos = spk_cp = vc->vc_pos; spk_old_attr = spk_attr; spk_attr = get_attributes(vc, (u_short *)spk_pos); @@ -1551,9 +1551,9 @@ static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag) */ is_cursor = value + 1; old_cursor_pos = vc->vc_pos; - old_cursor_x = vc->vc_x; - old_cursor_y = vc->vc_y; - speakup_console[vc->vc_num]->ht.cy = vc->vc_y; + old_cursor_x = vc->state.x; + old_cursor_y = vc->state.y; + speakup_console[vc->vc_num]->ht.cy = vc->state.y; cursor_con = vc->vc_num; if (cursor_track == CT_Highlight) reset_highlight_buffers(vc); @@ -1574,8 +1574,8 @@ static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len) i = 0; if (speakup_console[vc_num]->ht.highsize[bi] == 0) { speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos; - speakup_console[vc_num]->ht.rx[bi] = vc->vc_x; - speakup_console[vc_num]->ht.ry[bi] = vc->vc_y; + speakup_console[vc_num]->ht.rx[bi] = vc->state.x; + speakup_console[vc_num]->ht.ry[bi] = vc->state.y; } while ((hi < COLOR_BUFFER_SIZE) && (i < len)) { if (ic[i] > 32) { @@ -1664,9 +1664,9 @@ static int speak_highlight(struct vc_data *vc) return 0; hc = get_highlight_color(vc); if (hc != -1) { - d = vc->vc_y - speakup_console[vc_num]->ht.cy; + d = vc->state.y - speakup_console[vc_num]->ht.cy; if ((d == 1) || (d == -1)) - if (speakup_console[vc_num]->ht.ry[hc] != vc->vc_y) + if (speakup_console[vc_num]->ht.ry[hc] != vc->state.y) return 0; spk_parked |= 0x01; spk_do_flush(); @@ -1693,8 +1693,8 @@ static void cursor_done(struct timer_list *unused) } speakup_date(vc); if (win_enabled) { - if (vc->vc_x >= win_left && vc->vc_x <= win_right && - vc->vc_y >= win_top && vc->vc_y <= win_bottom) { + if (vc->state.x >= win_left && vc->state.x <= win_right && + vc->state.y >= win_top && vc->state.y <= win_bottom) { spk_keydown = 0; is_cursor = 0; goto out; @@ -1757,7 +1757,7 @@ static void speakup_con_write(struct vc_data *vc, u16 *str, int len) if (!spin_trylock_irqsave(&speakup_info.spinlock, flags)) /* Speakup output, discard */ return; - if (spk_bell_pos && spk_keydown && (vc->vc_x == spk_bell_pos - 1)) + if (spk_bell_pos && spk_keydown && (vc->state.x == spk_bell_pos - 1)) bleep(3); if ((is_cursor) || (cursor_track == read_all_mode)) { if (cursor_track == CT_Highlight) @@ -1766,8 +1766,8 @@ static void speakup_con_write(struct vc_data *vc, u16 *str, int len) return; } if (win_enabled) { - if (vc->vc_x >= win_left && vc->vc_x <= win_right && - vc->vc_y >= win_top && vc->vc_y <= win_bottom) { + if (vc->state.x >= win_left && vc->state.x <= win_right && + vc->state.y >= win_top && vc->state.y <= win_bottom) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); return; } diff --git a/drivers/staging/speakup/selection.c b/drivers/accessibility/speakup/selection.c similarity index 100% rename from drivers/staging/speakup/selection.c rename to drivers/accessibility/speakup/selection.c diff --git a/drivers/staging/speakup/serialio.c b/drivers/accessibility/speakup/serialio.c similarity index 100% rename from drivers/staging/speakup/serialio.c rename to drivers/accessibility/speakup/serialio.c diff --git a/drivers/staging/speakup/serialio.h b/drivers/accessibility/speakup/serialio.h similarity index 100% rename from drivers/staging/speakup/serialio.h rename to drivers/accessibility/speakup/serialio.h diff --git a/drivers/staging/speakup/speakup.h b/drivers/accessibility/speakup/speakup.h similarity index 100% rename from drivers/staging/speakup/speakup.h rename to drivers/accessibility/speakup/speakup.h diff --git a/drivers/staging/speakup/speakup_acnt.h b/drivers/accessibility/speakup/speakup_acnt.h similarity index 100% rename from drivers/staging/speakup/speakup_acnt.h rename to drivers/accessibility/speakup/speakup_acnt.h diff --git a/drivers/staging/speakup/speakup_acntpc.c b/drivers/accessibility/speakup/speakup_acntpc.c similarity index 100% rename from drivers/staging/speakup/speakup_acntpc.c rename to drivers/accessibility/speakup/speakup_acntpc.c diff --git a/drivers/staging/speakup/speakup_acntsa.c b/drivers/accessibility/speakup/speakup_acntsa.c similarity index 100% rename from drivers/staging/speakup/speakup_acntsa.c rename to drivers/accessibility/speakup/speakup_acntsa.c diff --git a/drivers/staging/speakup/speakup_apollo.c b/drivers/accessibility/speakup/speakup_apollo.c similarity index 100% rename from drivers/staging/speakup/speakup_apollo.c rename to drivers/accessibility/speakup/speakup_apollo.c diff --git a/drivers/staging/speakup/speakup_audptr.c b/drivers/accessibility/speakup/speakup_audptr.c similarity index 100% rename from drivers/staging/speakup/speakup_audptr.c rename to drivers/accessibility/speakup/speakup_audptr.c diff --git a/drivers/staging/speakup/speakup_bns.c b/drivers/accessibility/speakup/speakup_bns.c similarity index 100% rename from drivers/staging/speakup/speakup_bns.c rename to drivers/accessibility/speakup/speakup_bns.c diff --git a/drivers/staging/speakup/speakup_decext.c b/drivers/accessibility/speakup/speakup_decext.c similarity index 100% rename from drivers/staging/speakup/speakup_decext.c rename to drivers/accessibility/speakup/speakup_decext.c diff --git a/drivers/staging/speakup/speakup_decpc.c b/drivers/accessibility/speakup/speakup_decpc.c similarity index 100% rename from drivers/staging/speakup/speakup_decpc.c rename to drivers/accessibility/speakup/speakup_decpc.c diff --git a/drivers/staging/speakup/speakup_dectlk.c b/drivers/accessibility/speakup/speakup_dectlk.c similarity index 100% rename from drivers/staging/speakup/speakup_dectlk.c rename to drivers/accessibility/speakup/speakup_dectlk.c diff --git a/drivers/staging/speakup/speakup_dtlk.c b/drivers/accessibility/speakup/speakup_dtlk.c similarity index 100% rename from drivers/staging/speakup/speakup_dtlk.c rename to drivers/accessibility/speakup/speakup_dtlk.c diff --git a/drivers/staging/speakup/speakup_dtlk.h b/drivers/accessibility/speakup/speakup_dtlk.h similarity index 100% rename from drivers/staging/speakup/speakup_dtlk.h rename to drivers/accessibility/speakup/speakup_dtlk.h diff --git a/drivers/staging/speakup/speakup_dummy.c b/drivers/accessibility/speakup/speakup_dummy.c similarity index 100% rename from drivers/staging/speakup/speakup_dummy.c rename to drivers/accessibility/speakup/speakup_dummy.c diff --git a/drivers/staging/speakup/speakup_keypc.c b/drivers/accessibility/speakup/speakup_keypc.c similarity index 100% rename from drivers/staging/speakup/speakup_keypc.c rename to drivers/accessibility/speakup/speakup_keypc.c diff --git a/drivers/staging/speakup/speakup_ltlk.c b/drivers/accessibility/speakup/speakup_ltlk.c similarity index 100% rename from drivers/staging/speakup/speakup_ltlk.c rename to drivers/accessibility/speakup/speakup_ltlk.c diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/accessibility/speakup/speakup_soft.c similarity index 100% rename from drivers/staging/speakup/speakup_soft.c rename to drivers/accessibility/speakup/speakup_soft.c diff --git a/drivers/staging/speakup/speakup_spkout.c b/drivers/accessibility/speakup/speakup_spkout.c similarity index 100% rename from drivers/staging/speakup/speakup_spkout.c rename to drivers/accessibility/speakup/speakup_spkout.c diff --git a/drivers/staging/speakup/speakup_txprt.c b/drivers/accessibility/speakup/speakup_txprt.c similarity index 100% rename from drivers/staging/speakup/speakup_txprt.c rename to drivers/accessibility/speakup/speakup_txprt.c diff --git a/drivers/staging/speakup/speakupmap.h b/drivers/accessibility/speakup/speakupmap.h similarity index 100% rename from drivers/staging/speakup/speakupmap.h rename to drivers/accessibility/speakup/speakupmap.h diff --git a/drivers/staging/speakup/speakupmap.map b/drivers/accessibility/speakup/speakupmap.map similarity index 100% rename from drivers/staging/speakup/speakupmap.map rename to drivers/accessibility/speakup/speakupmap.map diff --git a/drivers/staging/speakup/spk_priv.h b/drivers/accessibility/speakup/spk_priv.h similarity index 100% rename from drivers/staging/speakup/spk_priv.h rename to drivers/accessibility/speakup/spk_priv.h diff --git a/drivers/staging/speakup/spk_priv_keyinfo.h b/drivers/accessibility/speakup/spk_priv_keyinfo.h similarity index 100% rename from drivers/staging/speakup/spk_priv_keyinfo.h rename to drivers/accessibility/speakup/spk_priv_keyinfo.h diff --git a/drivers/staging/speakup/spk_ttyio.c b/drivers/accessibility/speakup/spk_ttyio.c similarity index 100% rename from drivers/staging/speakup/spk_ttyio.c rename to drivers/accessibility/speakup/spk_ttyio.c diff --git a/drivers/staging/speakup/spk_types.h b/drivers/accessibility/speakup/spk_types.h similarity index 100% rename from drivers/staging/speakup/spk_types.h rename to drivers/accessibility/speakup/spk_types.h diff --git a/drivers/staging/speakup/synth.c b/drivers/accessibility/speakup/synth.c similarity index 100% rename from drivers/staging/speakup/synth.c rename to drivers/accessibility/speakup/synth.c diff --git a/drivers/staging/speakup/thread.c b/drivers/accessibility/speakup/thread.c similarity index 100% rename from drivers/staging/speakup/thread.c rename to drivers/accessibility/speakup/thread.c diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/accessibility/speakup/varhandlers.c similarity index 100% rename from drivers/staging/speakup/varhandlers.c rename to drivers/accessibility/speakup/varhandlers.c diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 19067a5e52934e6fb356448fe13457409176e58a..12c0ece746f04ac763bf2630185d40fe9ac36fe7 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -172,7 +172,6 @@ struct acpi_thermal { struct acpi_thermal_trips trips; struct acpi_handle_list devices; struct thermal_zone_device *thermal_zone; - int tz_enabled; int kelvin_offset; /* in millidegrees */ struct work_struct thermal_check_work; }; @@ -500,9 +499,6 @@ static void acpi_thermal_check(void *data) { struct acpi_thermal *tz = data; - if (!tz->tz_enabled) - return; - thermal_zone_device_update(tz->thermal_zone, THERMAL_EVENT_UNSPECIFIED); } @@ -526,50 +522,6 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp) return 0; } -static int thermal_get_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode *mode) -{ - struct acpi_thermal *tz = thermal->devdata; - - if (!tz) - return -EINVAL; - - *mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED : - THERMAL_DEVICE_DISABLED; - - return 0; -} - -static int thermal_set_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode mode) -{ - struct acpi_thermal *tz = thermal->devdata; - int enable; - - if (!tz) - return -EINVAL; - - /* - * enable/disable thermal management from ACPI thermal driver - */ - if (mode == THERMAL_DEVICE_ENABLED) - enable = 1; - else if (mode == THERMAL_DEVICE_DISABLED) { - enable = 0; - pr_warn("thermal zone will be disabled\n"); - } else - return -EINVAL; - - if (enable != tz->tz_enabled) { - tz->tz_enabled = enable; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "%s kernel ACPI thermal control\n", - tz->tz_enabled ? "Enable" : "Disable")); - acpi_thermal_check(tz); - } - return 0; -} - static int thermal_get_trip_type(struct thermal_zone_device *thermal, int trip, enum thermal_trip_type *type) { @@ -856,8 +808,6 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = { .bind = acpi_thermal_bind_cooling_device, .unbind = acpi_thermal_unbind_cooling_device, .get_temp = thermal_get_temp, - .get_mode = thermal_get_mode, - .set_mode = thermal_set_mode, .get_trip_type = thermal_get_trip_type, .get_trip_temp = thermal_get_trip_temp, .get_crit_temp = thermal_get_crit_temp, @@ -901,23 +851,39 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) result = sysfs_create_link(&tz->device->dev.kobj, &tz->thermal_zone->device.kobj, "thermal_zone"); if (result) - return result; + goto unregister_tzd; result = sysfs_create_link(&tz->thermal_zone->device.kobj, &tz->device->dev.kobj, "device"); if (result) - return result; + goto remove_tz_link; status = acpi_bus_attach_private_data(tz->device->handle, tz->thermal_zone); - if (ACPI_FAILURE(status)) - return -ENODEV; + if (ACPI_FAILURE(status)) { + result = -ENODEV; + goto remove_dev_link; + } - tz->tz_enabled = 1; + result = thermal_zone_device_enable(tz->thermal_zone); + if (result) + goto acpi_bus_detach; dev_info(&tz->device->dev, "registered as thermal_zone%d\n", tz->thermal_zone->id); + return 0; + +acpi_bus_detach: + acpi_bus_detach_private_data(tz->device->handle); +remove_dev_link: + sysfs_remove_link(&tz->thermal_zone->device.kobj, "device"); +remove_tz_link: + sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone"); +unregister_tzd: + thermal_zone_device_unregister(tz->thermal_zone); + + return result; } static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz) diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c index d58278ae9e4ad53a79b63471ac3f4aa8b6f806f4..5aee0f54635140385cf7430008c1659fd9420a35 100644 --- a/drivers/auxdisplay/charlcd.c +++ b/drivers/auxdisplay/charlcd.c @@ -485,24 +485,19 @@ static inline int handle_lcd_special_code(struct charlcd *lcd) shift = 0; value = 0; while (*esc && cgoffset < 8) { + int half; + shift ^= 4; - if (*esc >= '0' && *esc <= '9') { - value |= (*esc - '0') << shift; - } else if (*esc >= 'A' && *esc <= 'F') { - value |= (*esc - 'A' + 10) << shift; - } else if (*esc >= 'a' && *esc <= 'f') { - value |= (*esc - 'a' + 10) << shift; - } else { - esc++; + + half = hex_to_bin(*esc++); + if (half < 0) continue; - } + value |= half << shift; if (shift == 0) { cgbytes[cgoffset++] = value; value = 0; } - - esc++; } lcd->ops->write_cmd(lcd, LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8)); diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c index d22cfae1b0198922c212ee08d491393f904bb3de..78766b6ec271a3dc191cf1f4582c82c560e6ee73 100644 --- a/drivers/counter/104-quad-8.c +++ b/drivers/counter/104-quad-8.c @@ -1554,7 +1554,6 @@ static int quad8_probe(struct device *dev, unsigned int id) indio_dev->num_channels = ARRAY_SIZE(quad8_channels); indio_dev->channels = quad8_channels; indio_dev->name = dev_name(dev); - indio_dev->dev.parent = dev; /* Initialize Counter device and driver data */ quad8iio = iio_priv(indio_dev); diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index c80fa76bb531159f38d53adb67e296692f2a682d..2de53ab0dd252be4bb89f018b0827d3bf1fd6627 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -70,4 +70,15 @@ config FTM_QUADDEC To compile this driver as a module, choose M here: the module will be called ftm-quaddec. +config MICROCHIP_TCB_CAPTURE + tristate "Microchip Timer Counter Capture driver" + depends on HAS_IOMEM && OF + select REGMAP_MMIO + help + Select this option to enable the Microchip Timer Counter Block + capture driver. + + To compile this driver as a module, choose M here: the + module will be called microchip-tcb-capture. + endif # COUNTER diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile index 55142d1f4c436b04657f658e7e9e2c479ecf7567..0a393f71e4813a7efabb873d137dd02c45014db6 100644 --- a/drivers/counter/Makefile +++ b/drivers/counter/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_STM32_TIMER_CNT) += stm32-timer-cnt.o obj-$(CONFIG_STM32_LPTIMER_CNT) += stm32-lptimer-cnt.o obj-$(CONFIG_TI_EQEP) += ti-eqep.o obj-$(CONFIG_FTM_QUADDEC) += ftm-quaddec.o +obj-$(CONFIG_MICROCHIP_TCB_CAPTURE) += microchip-tcb-capture.o diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c new file mode 100644 index 0000000000000000000000000000000000000000..f7b7743ddb947cee00e2d92b8aa576634751ab0a --- /dev/null +++ b/drivers/counter/microchip-tcb-capture.c @@ -0,0 +1,397 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** + * Copyright (C) 2020 Microchip + * + * Author: Kamel Bouhara + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ATMEL_TC_CMR_MASK (ATMEL_TC_LDRA_RISING | ATMEL_TC_LDRB_FALLING | \ + ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_LDBDIS | \ + ATMEL_TC_LDBSTOP) + +#define ATMEL_TC_QDEN BIT(8) +#define ATMEL_TC_POSEN BIT(9) + +struct mchp_tc_data { + const struct atmel_tcb_config *tc_cfg; + struct counter_device counter; + struct regmap *regmap; + int qdec_mode; + int num_channels; + int channel[2]; + bool trig_inverted; +}; + +enum mchp_tc_count_function { + MCHP_TC_FUNCTION_INCREASE, + MCHP_TC_FUNCTION_QUADRATURE, +}; + +static enum counter_count_function mchp_tc_count_functions[] = { + [MCHP_TC_FUNCTION_INCREASE] = COUNTER_COUNT_FUNCTION_INCREASE, + [MCHP_TC_FUNCTION_QUADRATURE] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4, +}; + +enum mchp_tc_synapse_action { + MCHP_TC_SYNAPSE_ACTION_NONE = 0, + MCHP_TC_SYNAPSE_ACTION_RISING_EDGE, + MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE, + MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE +}; + +static enum counter_synapse_action mchp_tc_synapse_actions[] = { + [MCHP_TC_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, + [MCHP_TC_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, + [MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, + [MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES, +}; + +static struct counter_signal mchp_tc_count_signals[] = { + { + .id = 0, + .name = "Channel A", + }, + { + .id = 1, + .name = "Channel B", + } +}; + +static struct counter_synapse mchp_tc_count_synapses[] = { + { + .actions_list = mchp_tc_synapse_actions, + .num_actions = ARRAY_SIZE(mchp_tc_synapse_actions), + .signal = &mchp_tc_count_signals[0] + }, + { + .actions_list = mchp_tc_synapse_actions, + .num_actions = ARRAY_SIZE(mchp_tc_synapse_actions), + .signal = &mchp_tc_count_signals[1] + } +}; + +static int mchp_tc_count_function_get(struct counter_device *counter, + struct counter_count *count, + size_t *function) +{ + struct mchp_tc_data *const priv = counter->priv; + + if (priv->qdec_mode) + *function = MCHP_TC_FUNCTION_QUADRATURE; + else + *function = MCHP_TC_FUNCTION_INCREASE; + + return 0; +} + +static int mchp_tc_count_function_set(struct counter_device *counter, + struct counter_count *count, + size_t function) +{ + struct mchp_tc_data *const priv = counter->priv; + u32 bmr, cmr; + + regmap_read(priv->regmap, ATMEL_TC_BMR, &bmr); + regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr); + + /* Set capture mode */ + cmr &= ~ATMEL_TC_WAVE; + + switch (function) { + case MCHP_TC_FUNCTION_INCREASE: + priv->qdec_mode = 0; + /* Set highest rate based on whether soc has gclk or not */ + bmr &= ~(ATMEL_TC_QDEN | ATMEL_TC_POSEN); + if (priv->tc_cfg->has_gclk) + cmr |= ATMEL_TC_TIMER_CLOCK2; + else + cmr |= ATMEL_TC_TIMER_CLOCK1; + /* Setup the period capture mode */ + cmr |= ATMEL_TC_CMR_MASK; + cmr &= ~(ATMEL_TC_ABETRG | ATMEL_TC_XC0); + break; + case MCHP_TC_FUNCTION_QUADRATURE: + if (!priv->tc_cfg->has_qdec) + return -EINVAL; + /* In QDEC mode settings both channels 0 and 1 are required */ + if (priv->num_channels < 2 || priv->channel[0] != 0 || + priv->channel[1] != 1) { + pr_err("Invalid channels number or id for quadrature mode\n"); + return -EINVAL; + } + priv->qdec_mode = 1; + bmr |= ATMEL_TC_QDEN | ATMEL_TC_POSEN; + cmr |= ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_ABETRG | ATMEL_TC_XC0; + break; + } + + regmap_write(priv->regmap, ATMEL_TC_BMR, bmr); + regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), cmr); + + /* Enable clock and trigger counter */ + regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], CCR), + ATMEL_TC_CLKEN | ATMEL_TC_SWTRG); + + if (priv->qdec_mode) { + regmap_write(priv->regmap, + ATMEL_TC_REG(priv->channel[1], CMR), cmr); + regmap_write(priv->regmap, + ATMEL_TC_REG(priv->channel[1], CCR), + ATMEL_TC_CLKEN | ATMEL_TC_SWTRG); + } + + return 0; +} + +static int mchp_tc_count_signal_read(struct counter_device *counter, + struct counter_signal *signal, + enum counter_signal_value *val) +{ + struct mchp_tc_data *const priv = counter->priv; + bool sigstatus; + u32 sr; + + regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], SR), &sr); + + if (priv->trig_inverted) + sigstatus = (sr & ATMEL_TC_MTIOB); + else + sigstatus = (sr & ATMEL_TC_MTIOA); + + *val = sigstatus ? COUNTER_SIGNAL_HIGH : COUNTER_SIGNAL_LOW; + + return 0; +} + +static int mchp_tc_count_action_get(struct counter_device *counter, + struct counter_count *count, + struct counter_synapse *synapse, + size_t *action) +{ + struct mchp_tc_data *const priv = counter->priv; + u32 cmr; + + regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr); + + *action = MCHP_TC_SYNAPSE_ACTION_NONE; + + if (cmr & ATMEL_TC_ETRGEDG_NONE) + *action = MCHP_TC_SYNAPSE_ACTION_NONE; + else if (cmr & ATMEL_TC_ETRGEDG_RISING) + *action = MCHP_TC_SYNAPSE_ACTION_RISING_EDGE; + else if (cmr & ATMEL_TC_ETRGEDG_FALLING) + *action = MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE; + else if (cmr & ATMEL_TC_ETRGEDG_BOTH) + *action = MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE; + + return 0; +} + +static int mchp_tc_count_action_set(struct counter_device *counter, + struct counter_count *count, + struct counter_synapse *synapse, + size_t action) +{ + struct mchp_tc_data *const priv = counter->priv; + u32 edge = ATMEL_TC_ETRGEDG_NONE; + + /* QDEC mode is rising edge only */ + if (priv->qdec_mode) + return -EINVAL; + + switch (action) { + case MCHP_TC_SYNAPSE_ACTION_NONE: + edge = ATMEL_TC_ETRGEDG_NONE; + break; + case MCHP_TC_SYNAPSE_ACTION_RISING_EDGE: + edge = ATMEL_TC_ETRGEDG_RISING; + break; + case MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE: + edge = ATMEL_TC_ETRGEDG_FALLING; + break; + case MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE: + edge = ATMEL_TC_ETRGEDG_BOTH; + break; + } + + return regmap_write_bits(priv->regmap, + ATMEL_TC_REG(priv->channel[0], CMR), + ATMEL_TC_ETRGEDG, edge); +} + +static int mchp_tc_count_read(struct counter_device *counter, + struct counter_count *count, + unsigned long *val) +{ + struct mchp_tc_data *const priv = counter->priv; + u32 cnt; + + regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CV), &cnt); + *val = cnt; + + return 0; +} + +static struct counter_count mchp_tc_counts[] = { + { + .id = 0, + .name = "Timer Counter", + .functions_list = mchp_tc_count_functions, + .num_functions = ARRAY_SIZE(mchp_tc_count_functions), + .synapses = mchp_tc_count_synapses, + .num_synapses = ARRAY_SIZE(mchp_tc_count_synapses), + }, +}; + +static struct counter_ops mchp_tc_ops = { + .signal_read = mchp_tc_count_signal_read, + .count_read = mchp_tc_count_read, + .function_get = mchp_tc_count_function_get, + .function_set = mchp_tc_count_function_set, + .action_get = mchp_tc_count_action_get, + .action_set = mchp_tc_count_action_set +}; + +static const struct atmel_tcb_config tcb_rm9200_config = { + .counter_width = 16, +}; + +static const struct atmel_tcb_config tcb_sam9x5_config = { + .counter_width = 32, +}; + +static const struct atmel_tcb_config tcb_sama5d2_config = { + .counter_width = 32, + .has_gclk = true, + .has_qdec = true, +}; + +static const struct atmel_tcb_config tcb_sama5d3_config = { + .counter_width = 32, + .has_qdec = true, +}; + +static const struct of_device_id atmel_tc_of_match[] = { + { .compatible = "atmel,at91rm9200-tcb", .data = &tcb_rm9200_config, }, + { .compatible = "atmel,at91sam9x5-tcb", .data = &tcb_sam9x5_config, }, + { .compatible = "atmel,sama5d2-tcb", .data = &tcb_sama5d2_config, }, + { .compatible = "atmel,sama5d3-tcb", .data = &tcb_sama5d3_config, }, + { /* sentinel */ } +}; + +static void mchp_tc_clk_remove(void *ptr) +{ + clk_disable_unprepare((struct clk *)ptr); +} + +static int mchp_tc_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct atmel_tcb_config *tcb_config; + const struct of_device_id *match; + struct mchp_tc_data *priv; + char clk_name[7]; + struct regmap *regmap; + struct clk *clk[3]; + int channel; + int ret, i; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + + match = of_match_node(atmel_tc_of_match, np->parent); + tcb_config = match->data; + if (!tcb_config) { + dev_err(&pdev->dev, "No matching parent node found\n"); + return -ENODEV; + } + + regmap = syscon_node_to_regmap(np->parent); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + /* max. channels number is 2 when in QDEC mode */ + priv->num_channels = of_property_count_u32_elems(np, "reg"); + if (priv->num_channels < 0) { + dev_err(&pdev->dev, "Invalid or missing channel\n"); + return -EINVAL; + } + + /* Register channels and initialize clocks */ + for (i = 0; i < priv->num_channels; i++) { + ret = of_property_read_u32_index(np, "reg", i, &channel); + if (ret < 0 || channel > 2) + return -ENODEV; + + priv->channel[i] = channel; + + snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel); + + clk[i] = of_clk_get_by_name(np->parent, clk_name); + if (IS_ERR(clk[i])) { + /* Fallback to t0_clk */ + clk[i] = of_clk_get_by_name(np->parent, "t0_clk"); + if (IS_ERR(clk[i])) + return PTR_ERR(clk[i]); + } + + ret = clk_prepare_enable(clk[i]); + if (ret) + return ret; + + ret = devm_add_action_or_reset(&pdev->dev, + mchp_tc_clk_remove, + clk[i]); + if (ret) + return ret; + + dev_dbg(&pdev->dev, + "Initialized capture mode on channel %d\n", + channel); + } + + priv->tc_cfg = tcb_config; + priv->regmap = regmap; + priv->counter.name = dev_name(&pdev->dev); + priv->counter.parent = &pdev->dev; + priv->counter.ops = &mchp_tc_ops; + priv->counter.num_counts = ARRAY_SIZE(mchp_tc_counts); + priv->counter.counts = mchp_tc_counts; + priv->counter.num_signals = ARRAY_SIZE(mchp_tc_count_signals); + priv->counter.signals = mchp_tc_count_signals; + priv->counter.priv = priv; + + return devm_counter_register(&pdev->dev, &priv->counter); +} + +static const struct of_device_id mchp_tc_dt_ids[] = { + { .compatible = "microchip,tcb-capture", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mchp_tc_dt_ids); + +static struct platform_driver mchp_tc_driver = { + .probe = mchp_tc_probe, + .driver = { + .name = "microchip-tcb-capture", + .of_match_table = mchp_tc_dt_ids, + }, +}; +module_platform_driver(mchp_tc_driver); + +MODULE_AUTHOR("Kamel Bouhara "); +MODULE_DESCRIPTION("Microchip TCB Capture driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c index 8e276eb655f58c617f204c3f5558af76bfb1081d..fd6828e2d34f532629217c5167d188c6e4241e2f 100644 --- a/drivers/counter/stm32-lptimer-cnt.c +++ b/drivers/counter/stm32-lptimer-cnt.c @@ -648,7 +648,6 @@ static int stm32_lptim_cnt_probe(struct platform_device *pdev) /* Initialize IIO device */ indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &stm32_lptim_cnt_iio_info; if (ddata->has_encoder) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 79ae17cd463c3693937b690c463e22d95d3cefe5..20d367bfc77ba25936b9bc69d1eda6ae4e1954a5 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -922,6 +922,107 @@ int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, u32 size) } EXPORT_SYMBOL(qcom_scm_ocmem_unlock); +/** + * qcom_scm_ice_available() - Is the ICE key programming interface available? + * + * Return: true iff the SCM calls wrapped by qcom_scm_ice_invalidate_key() and + * qcom_scm_ice_set_key() are available. + */ +bool qcom_scm_ice_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES, + QCOM_SCM_ES_INVALIDATE_ICE_KEY) && + __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES, + QCOM_SCM_ES_CONFIG_SET_ICE_KEY); +} +EXPORT_SYMBOL(qcom_scm_ice_available); + +/** + * qcom_scm_ice_invalidate_key() - Invalidate an inline encryption key + * @index: the keyslot to invalidate + * + * The UFSHCI standard defines a standard way to do this, but it doesn't work on + * these SoCs; only this SCM call does. + * + * Return: 0 on success; -errno on failure. + */ +int qcom_scm_ice_invalidate_key(u32 index) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_INVALIDATE_ICE_KEY, + .arginfo = QCOM_SCM_ARGS(1), + .args[0] = index, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + return qcom_scm_call(__scm->dev, &desc, NULL); +} +EXPORT_SYMBOL(qcom_scm_ice_invalidate_key); + +/** + * qcom_scm_ice_set_key() - Set an inline encryption key + * @index: the keyslot into which to set the key + * @key: the key to program + * @key_size: the size of the key in bytes + * @cipher: the encryption algorithm the key is for + * @data_unit_size: the encryption data unit size, i.e. the size of each + * individual plaintext and ciphertext. Given in 512-byte + * units, e.g. 1 = 512 bytes, 8 = 4096 bytes, etc. + * + * Program a key into a keyslot of Qualcomm ICE (Inline Crypto Engine), where it + * can then be used to encrypt/decrypt UFS I/O requests inline. + * + * The UFSHCI standard defines a standard way to do this, but it doesn't work on + * these SoCs; only this SCM call does. + * + * Return: 0 on success; -errno on failure. + */ +int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, + enum qcom_scm_ice_cipher cipher, u32 data_unit_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_CONFIG_SET_ICE_KEY, + .arginfo = QCOM_SCM_ARGS(5, QCOM_SCM_VAL, QCOM_SCM_RW, + QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL), + .args[0] = index, + .args[2] = key_size, + .args[3] = cipher, + .args[4] = data_unit_size, + .owner = ARM_SMCCC_OWNER_SIP, + }; + void *keybuf; + dma_addr_t key_phys; + int ret; + + /* + * 'key' may point to vmalloc()'ed memory, but we need to pass a + * physical address that's been properly flushed. The sanctioned way to + * do this is by using the DMA API. But as is best practice for crypto + * keys, we also must wipe the key after use. This makes kmemdup() + + * dma_map_single() not clearly correct, since the DMA API can use + * bounce buffers. Instead, just use dma_alloc_coherent(). Programming + * keys is normally rare and thus not performance-critical. + */ + + keybuf = dma_alloc_coherent(__scm->dev, key_size, &key_phys, + GFP_KERNEL); + if (!keybuf) + return -ENOMEM; + memcpy(keybuf, key, key_size); + desc.args[1] = key_phys; + + ret = qcom_scm_call(__scm->dev, &desc, NULL); + + memzero_explicit(keybuf, key_size); + + dma_free_coherent(__scm->dev, key_size, keybuf, key_phys); + return ret; +} +EXPORT_SYMBOL(qcom_scm_ice_set_key); + /** * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. * diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index d9ed670da222c8f9b910bb8ed43e7d0cbfadeacf..38ea614d29fea28a47d4ebcd5b6746c188f3bba1 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -103,6 +103,10 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, #define QCOM_SCM_OCMEM_LOCK_CMD 0x01 #define QCOM_SCM_OCMEM_UNLOCK_CMD 0x02 +#define QCOM_SCM_SVC_ES 0x10 /* Enterprise Security */ +#define QCOM_SCM_ES_INVALIDATE_ICE_KEY 0x03 +#define QCOM_SCM_ES_CONFIG_SET_ICE_KEY 0x04 + #define QCOM_SCM_SVC_HDCP 0x11 #define QCOM_SCM_HDCP_INVOKE 0x01 diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index 19d8ae59ea035589ab5906f30dcb16dfba5c7bb8..33fd33f953ec465b70b077f5ea832eef3606a6d8 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -672,8 +672,8 @@ static void sii902x_audio_shutdown(struct device *dev, void *data) clk_disable_unprepare(sii902x->audio.mclk); } -static int sii902x_audio_digital_mute(struct device *dev, - void *data, bool enable) +static int sii902x_audio_mute(struct device *dev, void *data, + bool enable, int direction) { struct sii902x *sii902x = dev_get_drvdata(dev); @@ -724,9 +724,10 @@ static int sii902x_audio_get_dai_id(struct snd_soc_component *component, static const struct hdmi_codec_ops sii902x_audio_codec_ops = { .hw_params = sii902x_audio_hw_params, .audio_shutdown = sii902x_audio_shutdown, - .digital_mute = sii902x_audio_digital_mute, + .mute_stream = sii902x_audio_mute, .get_eld = sii902x_audio_get_eld, .get_dai_id = sii902x_audio_get_dai_id, + .no_capture_mute = 1, }; static int sii902x_audio_codec_init(struct sii902x *sii902x, diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 8c3f5b21eff44bbc89c3460debf694c9ed4d0ca5..c5ba32fca5f36d60a29342861be54efec40e4995 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1605,7 +1605,8 @@ static int hdmi_audio_hw_params(struct device *dev, void *data, return 0; } -static int hdmi_audio_digital_mute(struct device *dev, void *data, bool mute) +static int hdmi_audio_mute(struct device *dev, void *data, + bool mute, int direction) { struct hdmi_context *hdata = dev_get_drvdata(dev); @@ -1635,8 +1636,9 @@ static int hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf, static const struct hdmi_codec_ops audio_codec_ops = { .hw_params = hdmi_audio_hw_params, .audio_shutdown = hdmi_audio_shutdown, - .digital_mute = hdmi_audio_digital_mute, + .mute_stream = hdmi_audio_mute, .get_eld = hdmi_audio_get_eld, + .no_capture_mute = 1, }; static int hdmi_register_audio_device(struct hdmi_context *hdata) diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 50fd119a52763402a608c1782de84c4342954787..b7ec6c374fbda29784b4622b505fc97a39f06d62 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1133,8 +1133,8 @@ static void tda998x_audio_shutdown(struct device *dev, void *data) mutex_unlock(&priv->audio_mutex); } -static int tda998x_audio_digital_mute(struct device *dev, void *data, - bool enable) +static int tda998x_audio_mute_stream(struct device *dev, void *data, + bool enable, int direction) { struct tda998x_priv *priv = dev_get_drvdata(dev); @@ -1162,8 +1162,9 @@ static int tda998x_audio_get_eld(struct device *dev, void *data, static const struct hdmi_codec_ops audio_codec_ops = { .hw_params = tda998x_audio_hw_params, .audio_shutdown = tda998x_audio_shutdown, - .digital_mute = tda998x_audio_digital_mute, + .mute_stream = tda998x_audio_mute_stream, .get_eld = tda998x_audio_get_eld, + .no_capture_mute = 1, }; static int tda998x_audio_codec_init(struct tda998x_priv *priv, diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 95591262ac36cc989724d9dc15e9bcb42e45a50b..f2e9b429960b98954fa3540d43f842995c7f87bb 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1643,7 +1643,8 @@ static void mtk_hdmi_audio_shutdown(struct device *dev, void *data) } static int -mtk_hdmi_audio_digital_mute(struct device *dev, void *data, bool enable) +mtk_hdmi_audio_mute(struct device *dev, void *data, + bool enable, int direction) { struct mtk_hdmi *hdmi = dev_get_drvdata(dev); @@ -1684,9 +1685,10 @@ static const struct hdmi_codec_ops mtk_hdmi_audio_codec_ops = { .hw_params = mtk_hdmi_audio_hw_params, .audio_startup = mtk_hdmi_audio_startup, .audio_shutdown = mtk_hdmi_audio_shutdown, - .digital_mute = mtk_hdmi_audio_digital_mute, + .mute_stream = mtk_hdmi_audio_mute, .get_eld = mtk_hdmi_audio_get_eld, .hook_plugged_cb = mtk_hdmi_audio_hook_plugged_cb, + .no_capture_mute = 1, }; static int mtk_hdmi_register_audio_driver(struct device *dev) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index c634b95b50f7518040abe6ecf888812dc35c72af..a4a45daf93f2b322e2eb455e0dcc7e0194ffbbd7 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -817,8 +817,8 @@ out: mutex_unlock(&dp->lock); } -static int cdn_dp_audio_digital_mute(struct device *dev, void *data, - bool enable) +static int cdn_dp_audio_mute_stream(struct device *dev, void *data, + bool enable, int direction) { struct cdn_dp_device *dp = dev_get_drvdata(dev); int ret; @@ -849,8 +849,9 @@ static int cdn_dp_audio_get_eld(struct device *dev, void *data, static const struct hdmi_codec_ops audio_codec_ops = { .hw_params = cdn_dp_audio_hw_params, .audio_shutdown = cdn_dp_audio_shutdown, - .digital_mute = cdn_dp_audio_digital_mute, + .mute_stream = cdn_dp_audio_mute_stream, .get_eld = cdn_dp_audio_get_eld, + .no_capture_mute = 1, }; static int cdn_dp_audio_codec_init(struct cdn_dp_device *dp, diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 5b15c4974e6b5235fd1e32bc0cc7b46ee492e891..008f07923bbc9f385f28bf02d61e574f8284aa67 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -1191,7 +1191,8 @@ static int hdmi_audio_hw_params(struct device *dev, return 0; } -static int hdmi_audio_digital_mute(struct device *dev, void *data, bool enable) +static int hdmi_audio_mute(struct device *dev, void *data, + bool enable, int direction) { struct sti_hdmi *hdmi = dev_get_drvdata(dev); @@ -1219,8 +1220,9 @@ static int hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf, size static const struct hdmi_codec_ops audio_codec_ops = { .hw_params = hdmi_audio_hw_params, .audio_shutdown = hdmi_audio_shutdown, - .digital_mute = hdmi_audio_digital_mute, + .mute_stream = hdmi_audio_mute, .get_eld = hdmi_audio_get_eld, + .no_capture_mute = 1, }; static int sti_hdmi_register_audio_driver(struct device *dev, diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c index 76a16d997a23b221b8b57af29a316bfcd840e6a1..cd79ca0a92a952532e1f031bbec7f53f4585409b 100644 --- a/drivers/gpu/drm/zte/zx_hdmi.c +++ b/drivers/gpu/drm/zte/zx_hdmi.c @@ -439,8 +439,8 @@ static int zx_hdmi_audio_hw_params(struct device *dev, return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_AUDIO); } -static int zx_hdmi_audio_digital_mute(struct device *dev, void *data, - bool enable) +static int zx_hdmi_audio_mute(struct device *dev, void *data, + bool enable, int direction) { struct zx_hdmi *hdmi = dev_get_drvdata(dev); @@ -468,8 +468,9 @@ static const struct hdmi_codec_ops zx_hdmi_codec_ops = { .audio_startup = zx_hdmi_audio_startup, .hw_params = zx_hdmi_audio_hw_params, .audio_shutdown = zx_hdmi_audio_shutdown, - .digital_mute = zx_hdmi_audio_digital_mute, + .mute_stream = zx_hdmi_audio_mute, .get_eld = zx_hdmi_audio_get_eld, + .no_capture_mute = 1, }; static struct hdmi_codec_pdata zx_hdmi_codec_pdata = { diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 1080637ca40ebc5b339b1ce8b6882fef8214a23b..2e0c62c3915508ea9fa7cda5c0425d36ba560326 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -116,18 +116,24 @@ config BMA400 tristate "Bosch BMA400 3-Axis Accelerometer Driver" select REGMAP select BMA400_I2C if I2C + select BMA400_SPI if SPI help Say Y here if you want to build a driver for the Bosch BMA400 triaxial acceleration sensor. To compile this driver as a module, choose M here: the module will be called bma400_core and you will also get - bma400_i2c if I2C is enabled. + bma400_i2c if I2C is enabled and bma400_spi if SPI is + enabled. config BMA400_I2C tristate depends on BMA400 +config BMA400_SPI + tristate + depends on BMA400 + config BMC150_ACCEL tristate "Bosch BMC150 Accelerometer Driver" select IIO_BUFFER diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 3a051cf37f409636fb06f7807844b34a56739822..4f6c1ebe13b0fcee29d13043474c35d9ef0c1058 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_BMA180) += bma180.o obj-$(CONFIG_BMA220) += bma220_spi.o obj-$(CONFIG_BMA400) += bma400_core.o obj-$(CONFIG_BMA400_I2C) += bma400_i2c.o +obj-$(CONFIG_BMA400_SPI) += bma400_spi.o obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c index 4154e7396bbe76f83bb6ffe68a87d8940f02086e..59a24c355a1ab6a101c888672f2d0e8d4aefb14d 100644 --- a/drivers/iio/accel/adis16201.c +++ b/drivers/iio/accel/adis16201.c @@ -271,7 +271,6 @@ static int adis16201_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16201_info; indio_dev->channels = adis16201_channels; diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c index 31d45e7c54857a5d5e1e3c7d93bd2654ef6fc373..3d5538e2f76ed0cbd76bb33d6bc5cf032f761bc7 100644 --- a/drivers/iio/accel/adis16209.c +++ b/drivers/iio/accel/adis16209.c @@ -282,7 +282,6 @@ static int adis16209_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16209_info; indio_dev->channels = adis16209_channels; indio_dev->num_channels = ARRAY_SIZE(adis16209_channels); diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 9c269799e6c1c13e156fe6ac00b67dc03579cc0b..31286653006517c73d16f82a0ff06aa2859267d4 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -4,7 +4,7 @@ * * Copyright (c) 2017 Eva Rachel Retuya * - * Datasheet: http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf + * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf */ #include @@ -246,7 +246,6 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, return ret; } - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &adxl345_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c index 60daf04ce1889f01225d68eead697a8d9610ea90..e7e316b75e8702ecab14cdfa4b072dbdc725d243 100644 --- a/drivers/iio/accel/adxl372.c +++ b/drivers/iio/accel/adxl372.c @@ -795,13 +795,9 @@ static int adxl372_buffer_postenable(struct iio_dev *indio_dev) unsigned int mask; int i, ret; - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret < 0) - return ret; - ret = adxl372_set_interrupts(st, ADXL372_INT1_MAP_FIFO_FULL_MSK, 0); if (ret < 0) - goto err; + return ret; mask = *indio_dev->active_scan_mask; @@ -810,10 +806,8 @@ static int adxl372_buffer_postenable(struct iio_dev *indio_dev) break; } - if (i == ARRAY_SIZE(adxl372_axis_lookup_table)) { - ret = -EINVAL; - goto err; - } + if (i == ARRAY_SIZE(adxl372_axis_lookup_table)) + return -EINVAL; st->fifo_format = adxl372_axis_lookup_table[i].fifo_format; st->fifo_set_size = bitmap_weight(indio_dev->active_scan_mask, @@ -833,14 +827,10 @@ static int adxl372_buffer_postenable(struct iio_dev *indio_dev) if (ret < 0) { st->fifo_mode = ADXL372_FIFO_BYPASSED; adxl372_set_interrupts(st, 0, 0); - goto err; + return ret; } return 0; - -err: - iio_triggered_buffer_predisable(indio_dev); - return ret; } static int adxl372_buffer_predisable(struct iio_dev *indio_dev) @@ -851,7 +841,7 @@ static int adxl372_buffer_predisable(struct iio_dev *indio_dev) st->fifo_mode = ADXL372_FIFO_BYPASSED; adxl372_configure_fifo(st); - return iio_triggered_buffer_predisable(indio_dev); + return 0; } static const struct iio_buffer_setup_ops adxl372_buffer_ops = { @@ -938,7 +928,6 @@ int adxl372_probe(struct device *dev, struct regmap *regmap, indio_dev->channels = adxl372_channels; indio_dev->num_channels = ARRAY_SIZE(adxl372_channels); indio_dev->available_scan_masks = adxl372_channel_masks; - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &adxl372_info; indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 265722e4b13f4034a92961d763c454f2cd395225..5b7a467c7b271b74f1b63a3c49eed061e5ca1412 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -1038,7 +1038,6 @@ static int bma180_probe(struct i2c_client *client, goto err_chip_disable; mutex_init(&data->mutex); - indio_dev->dev.parent = dev; indio_dev->channels = data->part_info->channels; indio_dev->num_channels = data->part_info->num_channels; indio_dev->name = id->name; diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index cae905039cb626edf6835db6b91c13386a977d21..da8b36cc8628968d0b7c5d1eff55e03cd6aaee10 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -237,7 +237,6 @@ static int bma220_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); mutex_init(&data->lock); - indio_dev->dev.parent = &spi->dev; indio_dev->info = &bma220_info; indio_dev->name = BMA220_DEVICE_NAME; indio_dev->modes = INDIO_DIRECT_MODE; @@ -309,12 +308,14 @@ static const struct spi_device_id bma220_spi_id[] = { {} }; +#ifdef CONFIG_ACPI static const struct acpi_device_id bma220_acpi_id[] = { {"BMA0220", 0}, {} }; MODULE_DEVICE_TABLE(spi, bma220_spi_id); +#endif static struct spi_driver bma220_driver = { .driver = { diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c index cc77f89c048bca1b6ef1d7c88d14b4e352b93ed2..7eeba80e32cb55ddaead9718cf228a31c0f0a87f 100644 --- a/drivers/iio/accel/bma400_core.c +++ b/drivers/iio/accel/bma400_core.c @@ -816,7 +816,6 @@ int bma400_probe(struct device *dev, struct regmap *regmap, const char *name) return ret; mutex_init(&data->mutex); - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &bma400_info; indio_dev->channels = bma400_channels; diff --git a/drivers/iio/accel/bma400_spi.c b/drivers/iio/accel/bma400_spi.c new file mode 100644 index 0000000000000000000000000000000000000000..7c2825904e0832c0e2afd954667fd5420fef550b --- /dev/null +++ b/drivers/iio/accel/bma400_spi.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * SPI IIO driver for Bosch BMA400 triaxial acceleration sensor. + * + * Copyright 2020 Dan Robertson + * + */ +#include +#include +#include +#include +#include +#include + +#include "bma400.h" + +#define BMA400_MAX_SPI_READ 2 +#define BMA400_SPI_READ_BUFFER_SIZE (BMA400_MAX_SPI_READ + 1) + +static int bma400_regmap_spi_read(void *context, + const void *reg, size_t reg_size, + void *val, size_t val_size) +{ + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + u8 result[BMA400_SPI_READ_BUFFER_SIZE]; + ssize_t status; + + if (val_size > BMA400_MAX_SPI_READ) + return -EINVAL; + + status = spi_write_then_read(spi, reg, 1, result, val_size + 1); + if (status) + return status; + + /* + * From the BMA400 datasheet: + * + * > For a basic read operation two bytes have to be read and the first + * > has to be dropped and the second byte must be interpreted. + */ + memcpy(val, result + 1, val_size); + + return 0; +} + +static int bma400_regmap_spi_write(void *context, const void *data, + size_t count) +{ + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + + return spi_write(spi, data, count); +} + +static struct regmap_bus bma400_regmap_bus = { + .read = bma400_regmap_spi_read, + .write = bma400_regmap_spi_write, + .read_flag_mask = BIT(7), + .max_raw_read = BMA400_MAX_SPI_READ, +}; + +static int bma400_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct regmap *regmap; + unsigned int val; + int ret; + + regmap = devm_regmap_init(&spi->dev, &bma400_regmap_bus, + &spi->dev, &bma400_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "failed to create regmap\n"); + return PTR_ERR(regmap); + } + + /* + * Per the bma400 datasheet, the first SPI read may + * return garbage. As the datasheet recommends, the + * chip ID register will be read here and checked + * again in the following probe. + */ + ret = regmap_read(regmap, BMA400_CHIP_ID_REG, &val); + if (ret) + dev_err(&spi->dev, "Failed to read chip id register\n"); + + return bma400_probe(&spi->dev, regmap, id->name); +} + +static int bma400_spi_remove(struct spi_device *spi) +{ + return bma400_remove(&spi->dev); +} + +static const struct spi_device_id bma400_spi_ids[] = { + { "bma400", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, bma400_spi_ids); + +static const struct of_device_id bma400_of_spi_match[] = { + { .compatible = "bosch,bma400" }, + { } +}; +MODULE_DEVICE_TABLE(of, bma400_of_spi_match); + +static struct spi_driver bma400_spi_driver = { + .driver = { + .name = "bma400", + .of_match_table = bma400_of_spi_match, + }, + .probe = bma400_spi_probe, + .remove = bma400_spi_remove, + .id_table = bma400_spi_ids, +}; + +module_spi_driver(bma400_spi_driver); +MODULE_AUTHOR("Dan Robertson "); +MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor (SPI)"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index 121b4e89f038c7782d86d8aaee0fd6ba0043721a..24864d9dfab5d09e274c5d9529676af300f58c78 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -1411,7 +1411,7 @@ static int bmc150_accel_buffer_postenable(struct iio_dev *indio_dev) int ret = 0; if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) - return iio_triggered_buffer_postenable(indio_dev); + return 0; mutex_lock(&data->mutex); @@ -1443,7 +1443,7 @@ static int bmc150_accel_buffer_predisable(struct iio_dev *indio_dev) struct bmc150_accel_data *data = iio_priv(indio_dev); if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) - return iio_triggered_buffer_predisable(indio_dev); + return 0; mutex_lock(&data->mutex); @@ -1574,7 +1574,6 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, mutex_init(&data->mutex); - indio_dev->dev.parent = dev; indio_dev->channels = data->chip_info->channels; indio_dev->num_channels = data->chip_info->num_channels; indio_dev->name = name ? name : data->chip_info->name; diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c index 2532b9ad33842501e8b00b3138dd60b956376552..b6f3471b62dcf478b2e6cbdc6245f16fac955649 100644 --- a/drivers/iio/accel/cros_ec_accel_legacy.c +++ b/drivers/iio/accel/cros_ec_accel_legacy.c @@ -33,6 +33,11 @@ */ #define ACCEL_LEGACY_NSCALE 9586168 +/* + * Sensor frequency is hard-coded to 10Hz. + */ +static const int cros_ec_legacy_sample_freq[] = { 10, 0 }; + static int cros_ec_accel_legacy_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask, s16 *data) { @@ -96,6 +101,11 @@ static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev, *val = 0; ret = IIO_VAL_INT; break; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = cros_ec_legacy_sample_freq[0]; + *val2 = cros_ec_legacy_sample_freq[1]; + ret = IIO_VAL_INT_PLUS_MICRO; + break; default: ret = cros_ec_sensors_core_read(st, chan, val, val2, mask); @@ -120,9 +130,39 @@ static int cros_ec_accel_legacy_write(struct iio_dev *indio_dev, return -EINVAL; } +/** + * cros_ec_accel_legacy_read_avail() - get available values + * @indio_dev: pointer to state information for device + * @chan: channel specification structure table + * @vals: list of available values + * @type: type of data returned + * @length: number of data returned in the array + * @mask: specifies which values to be requested + * + * Return: an error code or IIO_AVAIL_LIST + */ +static int cros_ec_accel_legacy_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, + int *type, + int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *length = ARRAY_SIZE(cros_ec_legacy_sample_freq); + *vals = cros_ec_legacy_sample_freq; + *type = IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_LIST; + } + + return -EINVAL; +} + static const struct iio_info cros_ec_accel_legacy_info = { .read_raw = &cros_ec_accel_legacy_read, .write_raw = &cros_ec_accel_legacy_write, + .read_avail = &cros_ec_accel_legacy_read_avail, }; /* @@ -142,7 +182,11 @@ static const struct iio_info cros_ec_accel_legacy_info = { .info_mask_separate = \ BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_CALIBBIAS), \ - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .ext_info = cros_ec_sensors_ext_info, \ .scan_type = { \ .sign = 's', \ diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c index 227bea2d738b15f0ec6581fd1e0552010214364f..4472dde6899ecfe253d5eb3b5f40998917e7861a 100644 --- a/drivers/iio/accel/da280.c +++ b/drivers/iio/accel/da280.c @@ -120,7 +120,6 @@ static int da280_probe(struct i2c_client *client, data->client = client; i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; indio_dev->info = &da280_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = da280_channels; diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c index c20979249a48b5e3902fd9ce826ee9ec31e3a726..3b3df620ba272323ab5033af4f338c7bc5ee3486 100644 --- a/drivers/iio/accel/da311.c +++ b/drivers/iio/accel/da311.c @@ -231,7 +231,6 @@ static int da311_probe(struct i2c_client *client, data->client = client; i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; indio_dev->info = &da311_info; indio_dev->name = "da311"; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/accel/dmard06.c b/drivers/iio/accel/dmard06.c index ef89bded7390bc6d3dc63df8a657119794aca341..de2868c28d954c97ea31e37689ac7e75bda72e1e 100644 --- a/drivers/iio/accel/dmard06.c +++ b/drivers/iio/accel/dmard06.c @@ -161,7 +161,6 @@ static int dmard06_probe(struct i2c_client *client, dmard06->chip_id = ret; i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; indio_dev->name = DMARD06_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = dmard06_channels; diff --git a/drivers/iio/accel/dmard09.c b/drivers/iio/accel/dmard09.c index 2d666cd69b29f6fd65d96c743aebcc63b3561326..e6e28c9647776e97012b6a7cf053857a1bad5251 100644 --- a/drivers/iio/accel/dmard09.c +++ b/drivers/iio/accel/dmard09.c @@ -116,7 +116,6 @@ static int dmard09_probe(struct i2c_client *client, } i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; indio_dev->name = DMARD09_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = dmard09_channels; diff --git a/drivers/iio/accel/dmard10.c b/drivers/iio/accel/dmard10.c index 71c852b8bb3ec4cd76440dd91abe5e792e483e85..90206f015857da7db26fb8d7a6d567eee9ad4eb6 100644 --- a/drivers/iio/accel/dmard10.c +++ b/drivers/iio/accel/dmard10.c @@ -196,7 +196,6 @@ static int dmard10_probe(struct i2c_client *client, data->client = client; i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; indio_dev->info = &dmard10_info; indio_dev->name = "dmard10"; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 0ec0533448bc549c3128adbe4b49af63c82fb248..4c5e594024f8ca0c9a0d91fda8e695446f2a5de3 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -384,7 +384,6 @@ static int hid_accel_3d_probe(struct platform_device *pdev) goto error_free_dev_mem; } - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &accel_3d_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index c9924a65c32a0ea8c9ec67bea06a208ba56429ea..beb38d9d607dc4fac58660826f5c6473c94c9bba 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1027,9 +1027,7 @@ static const struct iio_chan_spec kxcjk1013_channels[] = { static const struct iio_buffer_setup_ops kxcjk1013_buffer_setup_ops = { .preenable = kxcjk1013_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, .postdisable = kxcjk1013_buffer_postdisable, - .predisable = iio_triggered_buffer_predisable, }; static const struct iio_info kxcjk1013_info = { @@ -1311,7 +1309,6 @@ static int kxcjk1013_probe(struct i2c_client *client, mutex_init(&data->mutex); - indio_dev->dev.parent = &client->dev; indio_dev->channels = kxcjk1013_channels; indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels); indio_dev->available_scan_masks = kxcjk1013_scan_masks; diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 0b876b2dc5bd4d3c4d37cc03a57945aa72871595..66b2e4cf24cfab91f1a5a559d5f52fd97a58ce3b 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -252,8 +252,6 @@ static int kxsd9_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops kxsd9_buffer_setup_ops = { .preenable = kxsd9_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = kxsd9_buffer_postdisable, }; @@ -411,7 +409,6 @@ int kxsd9_common_probe(struct device *dev, indio_dev->channels = kxsd9_channels; indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels); indio_dev->name = name; - indio_dev->dev.parent = dev; indio_dev->info = &kxsd9_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->available_scan_masks = kxsd9_scan_masks; diff --git a/drivers/iio/accel/mc3230.c b/drivers/iio/accel/mc3230.c index 02b3d25b3d9605bf60b7f24c45faa284a5f446ce..46e4283fc037562dfae535f3ce9216358f6e41c1 100644 --- a/drivers/iio/accel/mc3230.c +++ b/drivers/iio/accel/mc3230.c @@ -132,7 +132,6 @@ static int mc3230_probe(struct i2c_client *client, data->client = client; i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; indio_dev->info = &mc3230_info; indio_dev->name = "mc3230"; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/accel/mma7455_core.c b/drivers/iio/accel/mma7455_core.c index 8b5a6aff9bf4b72bd36873bc4d55cd08f4a63235..7e99bcb3398dff1356fbb8094f40eaa4d4437054 100644 --- a/drivers/iio/accel/mma7455_core.c +++ b/drivers/iio/accel/mma7455_core.c @@ -260,7 +260,6 @@ int mma7455_core_probe(struct device *dev, struct regmap *regmap, indio_dev->info = &mma7455_info; indio_dev->name = name; - indio_dev->dev.parent = dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mma7455_channels; indio_dev->num_channels = ARRAY_SIZE(mma7455_channels); diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c index 7faf6d8657aea1fd27b3be52fb351d82cc36e2a9..b3c9136d51ec74a90a7c70bcc7c877e086d7ab4d 100644 --- a/drivers/iio/accel/mma7660.c +++ b/drivers/iio/accel/mma7660.c @@ -188,7 +188,6 @@ static int mma7660_probe(struct i2c_client *client, mutex_init(&data->lock); data->mode = MMA7660_MODE_STANDBY; - indio_dev->dev.parent = &client->dev; indio_dev->info = &mma7660_info; indio_dev->name = MMA7660_DRIVER_NAME; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 813bca7cfc3ed95ff571350b7ff85e5f15d0d60b..ba27f86731314dc770048160430265d05332db7c 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -1592,7 +1592,6 @@ static int mma8452_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); indio_dev->info = &mma8452_info; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = data->chip_info->channels; indio_dev->num_channels = data->chip_info->num_channels; diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index 99e4a21ca9421819379741bd187d7daf1eac73f0..08a2303cc9df3c08022bb32730faa41c01f49816 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -473,7 +473,6 @@ static int mma9551_probe(struct i2c_client *client, mutex_init(&data->mutex); - indio_dev->dev.parent = &client->dev; indio_dev->channels = mma9551_channels; indio_dev->num_channels = ARRAY_SIZE(mma9551_channels); indio_dev->name = name; diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index 312070dcf035ad15564f4c8f0fe780c582c404fc..c15908faa38167b0d6ff68d53ceca8de0ed2d403 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -1103,7 +1103,6 @@ static int mma9553_probe(struct i2c_client *client, if (ret < 0) return ret; - indio_dev->dev.parent = &client->dev; indio_dev->channels = mma9553_channels; indio_dev->num_channels = ARRAY_SIZE(mma9553_channels); indio_dev->name = name; diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c index 9d07642c0de106df7941d33cfcf55ceb72f037b0..f877263dc6efbdf4535a179b5b0b8fa94136de47 100644 --- a/drivers/iio/accel/mxc4005.c +++ b/drivers/iio/accel/mxc4005.c @@ -416,7 +416,6 @@ static int mxc4005_probe(struct i2c_client *client, mutex_init(&data->mutex); - indio_dev->dev.parent = &client->dev; indio_dev->channels = mxc4005_channels; indio_dev->num_channels = ARRAY_SIZE(mxc4005_channels); indio_dev->available_scan_masks = mxc4005_scan_masks; @@ -474,12 +473,14 @@ static int mxc4005_probe(struct i2c_client *client, static const struct acpi_device_id mxc4005_acpi_match[] = { {"MXC4005", 0}, + {"MXC6655", 0}, { }, }; MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match); static const struct i2c_device_id mxc4005_id[] = { {"mxc4005", 0}, + {"mxc6655", 0}, { }, }; MODULE_DEVICE_TABLE(i2c, mxc4005_id); diff --git a/drivers/iio/accel/mxc6255.c b/drivers/iio/accel/mxc6255.c index f532f8643aa4b60473dc9f1e821f2e8ff33f6003..9aeeadc420d310c13b9ab27af0fd2dd5e252f4f2 100644 --- a/drivers/iio/accel/mxc6255.c +++ b/drivers/iio/accel/mxc6255.c @@ -138,7 +138,6 @@ static int mxc6255_probe(struct i2c_client *client, data->regmap = regmap; indio_dev->name = MXC6255_DRV_NAME; - indio_dev->dev.parent = &client->dev; indio_dev->channels = mxc6255_channels; indio_dev->num_channels = ARRAY_SIZE(mxc6255_channels); indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index 6e429072e44a489b6ccd11a2085580d80449c533..194738660523d45b88560776803e5e2da11f463a 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -186,9 +186,9 @@ struct sca3000_state { * @option_mode_2_freq: option mode 2 sampling frequency * @option_mode_2_3db_freq: 3db cutoff frequency of the low pass filter for * the second option mode. - * @mod_det_mult_xz: Bit wise multipliers to calculate the threshold + * @mot_det_mult_xz: Bit wise multipliers to calculate the threshold * for motion detection in the x and z axis. - * @mod_det_mult_y: Bit wise multipliers to calculate the threshold + * @mot_det_mult_y: Bit wise multipliers to calculate the threshold * for motion detection in the y axis. * * This structure is used to hold information about the functionality of a given @@ -859,9 +859,9 @@ error_ret: */ static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq); -/** +/* * sca3000_read_event_value() - query of a threshold or period - **/ + */ static int sca3000_read_event_value(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, @@ -1100,9 +1100,9 @@ done: return IRQ_HANDLED; } -/** +/* * sca3000_read_event_config() what events are enabled - **/ + */ static int sca3000_read_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, @@ -1467,7 +1467,6 @@ static int sca3000_probe(struct spi_device *spi) st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi) ->driver_data]; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &sca3000_info; if (st->info->temp_output) { diff --git a/drivers/iio/accel/ssp_accel_sensor.c b/drivers/iio/accel/ssp_accel_sensor.c index c32647abce203ca93f6404ca6782f7a79b9fa68a..474477e91b5eace7ad6307684d9f333c21089524 100644 --- a/drivers/iio/accel/ssp_accel_sensor.c +++ b/drivers/iio/accel/ssp_accel_sensor.c @@ -108,8 +108,6 @@ static int ssp_accel_probe(struct platform_device *pdev) spd->type = SSP_ACCELEROMETER_SENSOR; indio_dev->name = ssp_accel_device_name; - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &ssp_accel_iio_info; indio_dev->modes = INDIO_BUFFER_SOFTWARE; indio_dev->channels = ssp_acc_channels; diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c index b5c814ef16379d85b4e3097fd7afc079b7158c92..492263589e0447a5ef93d3e1d9370f65255ad811 100644 --- a/drivers/iio/accel/st_accel_buffer.c +++ b/drivers/iio/accel/st_accel_buffer.c @@ -33,13 +33,9 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev) { int err; - err = iio_triggered_buffer_postenable(indio_dev); - if (err < 0) - return err; - err = st_sensors_set_axis_enable(indio_dev, indio_dev->active_scan_mask[0]); if (err < 0) - goto st_accel_buffer_predisable; + return err; err = st_sensors_set_enable(indio_dev, true); if (err < 0) @@ -49,27 +45,19 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev) st_accel_buffer_enable_all_axis: st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); -st_accel_buffer_predisable: - iio_triggered_buffer_predisable(indio_dev); return err; } static int st_accel_buffer_predisable(struct iio_dev *indio_dev) { - int err, err2; + int err; err = st_sensors_set_enable(indio_dev, false); if (err < 0) - goto st_accel_buffer_predisable; - - err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); - -st_accel_buffer_predisable: - err2 = iio_triggered_buffer_predisable(indio_dev); - if (!err) - err = err2; + return err; - return err; + return st_sensors_set_axis_enable(indio_dev, + ST_SENSORS_ENABLE_ALL_AXIS); } static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = { diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c index 58c160ccdee71cce1fa267a87cd7b163f2722b6d..3b59887a8581bcd49a925a290ebe7cbe6d6d58a3 100644 --- a/drivers/iio/accel/stk8312.c +++ b/drivers/iio/accel/stk8312.c @@ -492,8 +492,6 @@ static int stk8312_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops stk8312_buffer_setup_ops = { .preenable = stk8312_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = stk8312_buffer_postdisable, }; @@ -515,7 +513,6 @@ static int stk8312_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &stk8312_info; indio_dev->name = STK8312_DRIVER_NAME; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c index c70ddec29eb49ffebed0306e15cebed5e25c1f59..3ead378b02c9b395ffa22ed520b7a287d8763499 100644 --- a/drivers/iio/accel/stk8ba50.c +++ b/drivers/iio/accel/stk8ba50.c @@ -376,8 +376,6 @@ static int stk8ba50_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops stk8ba50_buffer_setup_ops = { .preenable = stk8ba50_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = stk8ba50_buffer_postdisable, }; @@ -399,7 +397,6 @@ static int stk8ba50_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &stk8ba50_info; indio_dev->name = STK8BA50_DRIVER_NAME; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index ff3569635ce0d4f6178ad5eb2926f4047b615c88..66d9cc07315735f45a716b3dcda0f45804b889d4 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -294,7 +294,7 @@ config ASPEED_ADC config AT91_ADC tristate "Atmel AT91 ADC" - depends on ARCH_AT91 + depends on ARCH_AT91 || COMPILE_TEST depends on INPUT && SYSFS select IIO_BUFFER select IIO_TRIGGERED_BUFFER @@ -500,6 +500,7 @@ config INA2XX_ADC config INGENIC_ADC tristate "Ingenic JZ47xx SoCs ADC driver" depends on MIPS || COMPILE_TEST + select IIO_BUFFER help Say yes here to build support for the Ingenic JZ47xx SoCs ADC unit. diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c index fd5b18d7f0c204bf664bdab61b461df51f1cbfdc..7fdc5d2d1d35c152cb4d3f5fe6484a6a381a0c68 100644 --- a/drivers/iio/adc/ab8500-gpadc.c +++ b/drivers/iio/adc/ab8500-gpadc.c @@ -1163,8 +1163,6 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) pm_runtime_put(dev); - indio_dev->dev.parent = dev; - indio_dev->dev.of_node = np; indio_dev->name = "ab8500-gpadc"; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ab8500_gpadc_info; diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c index 33c40357bd5e32d0a22ab8275c260779fe3accf0..63b4d6ea4566a022f780a31e7480a11670887bad 100644 --- a/drivers/iio/adc/ad7091r-base.c +++ b/drivers/iio/adc/ad7091r-base.c @@ -224,7 +224,6 @@ int ad7091r_probe(struct device *dev, const char *name, st->chip_info = chip_info; st->map = map; - iio_dev->dev.parent = dev; iio_dev->name = name; iio_dev->info = &ad7091r_info; iio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index a3c0647a539124dabd65608aa3d59fa08042d4c8..8dce06e9e69c5a34fdf4341bfbb336c307fb27d1 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,15 @@ #define AD7124_ADC_CTRL_MODE_MSK GENMASK(5, 2) #define AD7124_ADC_CTRL_MODE(x) FIELD_PREP(AD7124_ADC_CTRL_MODE_MSK, x) +/* AD7124 ID */ +#define AD7124_DEVICE_ID_MSK GENMASK(7, 4) +#define AD7124_DEVICE_ID_GET(x) FIELD_GET(AD7124_DEVICE_ID_MSK, x) +#define AD7124_SILICON_REV_MSK GENMASK(3, 0) +#define AD7124_SILICON_REV_GET(x) FIELD_GET(AD7124_SILICON_REV_MSK, x) + +#define CHIPID_AD7124_4 0x0 +#define CHIPID_AD7124_8 0x1 + /* AD7124_CHANNEL_X */ #define AD7124_CHANNEL_EN_MSK BIT(15) #define AD7124_CHANNEL_EN(x) FIELD_PREP(AD7124_CHANNEL_EN_MSK, x) @@ -120,6 +130,8 @@ static const char * const ad7124_ref_names[] = { }; struct ad7124_chip_info { + const char *name; + unsigned int chip_id; unsigned int num_inputs; }; @@ -165,9 +177,13 @@ static const struct iio_chan_spec ad7124_channel_template = { static struct ad7124_chip_info ad7124_chip_info_tbl[] = { [ID_AD7124_4] = { + .name = "ad7127-4", + .chip_id = CHIPID_AD7124_4, .num_inputs = 8, }, [ID_AD7124_8] = { + .name = "ad7127-8", + .chip_id = CHIPID_AD7124_8, .num_inputs = 16, }, }; @@ -503,6 +519,34 @@ static int ad7124_soft_reset(struct ad7124_state *st) return -EIO; } +static int ad7124_check_chip_id(struct ad7124_state *st) +{ + unsigned int readval, chip_id, silicon_rev; + int ret; + + ret = ad_sd_read_reg(&st->sd, AD7124_ID, 1, &readval); + if (ret < 0) + return ret; + + chip_id = AD7124_DEVICE_ID_GET(readval); + silicon_rev = AD7124_SILICON_REV_GET(readval); + + if (chip_id != st->chip_info->chip_id) { + dev_err(&st->sd.spi->dev, + "Chip ID mismatch: expected %u, got %u\n", + st->chip_info->chip_id, chip_id); + return -ENODEV; + } + + if (silicon_rev == 0) { + dev_err(&st->sd.spi->dev, + "Silicon revision empty. Chip may not be present\n"); + return -ENODEV; + } + + return 0; +} + static int ad7124_init_channel_vref(struct ad7124_state *st, unsigned int channel_number) { @@ -665,26 +709,28 @@ static int ad7124_setup(struct ad7124_state *st) static int ad7124_probe(struct spi_device *spi) { - const struct spi_device_id *id; + const struct ad7124_chip_info *info; struct ad7124_state *st; struct iio_dev *indio_dev; int i, ret; + info = of_device_get_match_data(&spi->dev); + if (!info) + return -ENODEV; + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); - id = spi_get_device_id(spi); - st->chip_info = &ad7124_chip_info_tbl[id->driver_data]; + st->chip_info = info; ad_sd_init(&st->sd, indio_dev, spi, &ad7124_sigma_delta_info); spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->name = st->chip_info->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ad7124_info; @@ -722,6 +768,10 @@ static int ad7124_probe(struct spi_device *spi) if (ret < 0) goto error_clk_disable_unprepare; + ret = ad7124_check_chip_id(st); + if (ret) + goto error_clk_disable_unprepare; + ret = ad7124_setup(st); if (ret < 0) goto error_clk_disable_unprepare; @@ -769,16 +819,11 @@ static int ad7124_remove(struct spi_device *spi) return 0; } -static const struct spi_device_id ad7124_id_table[] = { - { "ad7124-4", ID_AD7124_4 }, - { "ad7124-8", ID_AD7124_8 }, - {} -}; -MODULE_DEVICE_TABLE(spi, ad7124_id_table); - static const struct of_device_id ad7124_of_match[] = { - { .compatible = "adi,ad7124-4" }, - { .compatible = "adi,ad7124-8" }, + { .compatible = "adi,ad7124-4", + .data = &ad7124_chip_info_tbl[ID_AD7124_4], }, + { .compatible = "adi,ad7124-8", + .data = &ad7124_chip_info_tbl[ID_AD7124_8], }, { }, }; MODULE_DEVICE_TABLE(of, ad7124_of_match); @@ -790,7 +835,6 @@ static struct spi_driver ad71124_driver = { }, .probe = ad7124_probe, .remove = ad7124_remove, - .id_table = ad7124_id_table, }; module_spi_driver(ad71124_driver); diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index 08ba1a8f05eb347f1614c78006f84a7015888470..2ed580521d815a0b869a63275fa9ab197f5da9e2 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -908,15 +908,6 @@ static int ad7192_channels_config(struct iio_dev *indio_dev) return 0; } -static const struct of_device_id ad7192_of_match[] = { - { .compatible = "adi,ad7190", .data = &ad7192_chip_info_tbl[ID_AD7190] }, - { .compatible = "adi,ad7192", .data = &ad7192_chip_info_tbl[ID_AD7192] }, - { .compatible = "adi,ad7193", .data = &ad7192_chip_info_tbl[ID_AD7193] }, - { .compatible = "adi,ad7195", .data = &ad7192_chip_info_tbl[ID_AD7195] }, - {} -}; -MODULE_DEVICE_TABLE(of, ad7192_of_match); - static int ad7192_probe(struct spi_device *spi) { struct ad7192_state *st; @@ -970,7 +961,6 @@ static int ad7192_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); st->chip_info = of_device_get_match_data(&spi->dev); - indio_dev->dev.parent = &spi->dev; indio_dev->name = st->chip_info->name; indio_dev->modes = INDIO_DIRECT_MODE; @@ -1050,6 +1040,15 @@ static int ad7192_remove(struct spi_device *spi) return 0; } +static const struct of_device_id ad7192_of_match[] = { + { .compatible = "adi,ad7190", .data = &ad7192_chip_info_tbl[ID_AD7190] }, + { .compatible = "adi,ad7192", .data = &ad7192_chip_info_tbl[ID_AD7192] }, + { .compatible = "adi,ad7193", .data = &ad7192_chip_info_tbl[ID_AD7193] }, + { .compatible = "adi,ad7195", .data = &ad7192_chip_info_tbl[ID_AD7195] }, + {} +}; +MODULE_DEVICE_TABLE(of, ad7192_of_match); + static struct spi_driver ad7192_driver = { .driver = { .name = "ad7192", diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index c8524f0988835584c27933b36d6d2188eb6e921b..a8ec3efd659eda9654ecbbf18014ca5c5d7a684a 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -74,8 +74,6 @@ static int ad7266_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { .preenable = &ad7266_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, .postdisable = &ad7266_postdisable, }; @@ -437,8 +435,6 @@ static int ad7266_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); st->spi = spi; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ad7266_info; diff --git a/drivers/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c index b2b137fed246a86bf5d31aba096a1ef4adb5b3c8..62fde2aad28204a8a9e4b6890915a57f1a11f45d 100644 --- a/drivers/iio/adc/ad7291.c +++ b/drivers/iio/adc/ad7291.c @@ -502,8 +502,6 @@ static int ad7291_probe(struct i2c_client *client, indio_dev->channels = ad7291_channels; indio_dev->num_channels = ARRAY_SIZE(ad7291_channels); - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->info = &ad7291_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ad7292.c b/drivers/iio/adc/ad7292.c index 6595fd19628800b15f70d1c9fac43c3abf5fcf49..2eafbe7ac7c7bef6bdffa28a6fa4feb86a2c6d83 100644 --- a/drivers/iio/adc/ad7292.c +++ b/drivers/iio/adc/ad7292.c @@ -304,7 +304,6 @@ static int ad7292_probe(struct spi_device *spi) st->vref_mv = 1250; } - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ad7292_info; diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c index dc8d8c5f6ad3637527da4595ac19a4aea3304954..48d43cb0f932cf48b32aaf4e21b2616152dfb45e 100644 --- a/drivers/iio/adc/ad7298.c +++ b/drivers/iio/adc/ad7298.c @@ -98,9 +98,9 @@ static const struct iio_chan_spec ad7298_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(8), }; -/** +/* * ad7298_update_scan_mode() setup the spi transfer buffer for the new scan mask - **/ + */ static int ad7298_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *active_scan_mask) { @@ -144,12 +144,12 @@ static int ad7298_update_scan_mode(struct iio_dev *indio_dev, return 0; } -/** +/* * ad7298_trigger_handler() bh of trigger launched polling to ring buffer * * Currently there is no option in this driver to disable the saving of * timestamps within the ring. - **/ + */ static irqreturn_t ad7298_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; @@ -312,8 +312,6 @@ static int ad7298_probe(struct spi_device *spi) st->spi = spi; indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ad7298_channels; indio_dev->num_channels = ARRAY_SIZE(ad7298_channels); diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c index 4e816d714ad217446bec4c48bf8692318d754cd4..66c55ae67791b76a22f7a17951a9e0ba4bdb5f21 100644 --- a/drivers/iio/adc/ad7476.c +++ b/drivers/iio/adc/ad7476.c @@ -300,9 +300,6 @@ static int ad7476_probe(struct spi_device *spi) st->spi = spi; - /* Establish that the iio_dev is a child of the spi device */ - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->chip_info->channel; diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index e4683a68522a4502957887e475f951e5be74e53b..ee7b108688b33537095874e988c07905c63f56a2 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -499,7 +499,6 @@ static int ad7606_buffer_postenable(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); - iio_triggered_buffer_postenable(indio_dev); gpiod_set_value(st->gpio_convst, 1); return 0; @@ -511,7 +510,7 @@ static int ad7606_buffer_predisable(struct iio_dev *indio_dev) gpiod_set_value(st->gpio_convst, 0); - return iio_triggered_buffer_predisable(indio_dev); + return 0; } static const struct iio_buffer_setup_ops ad7606_buffer_ops = { @@ -614,7 +613,6 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, if (ret) return ret; - indio_dev->dev.parent = dev; if (st->gpio_os) { if (st->gpio_range) indio_dev->info = &ad7606_info_os_and_range; diff --git a/drivers/iio/adc/ad7766.c b/drivers/iio/adc/ad7766.c index bc388ea41754729aea638e7c3e9efcd5a8d7063e..b6b6765be7b49b25e9bea6603f73dbc62866fd9b 100644 --- a/drivers/iio/adc/ad7766.c +++ b/drivers/iio/adc/ad7766.c @@ -178,8 +178,6 @@ static const struct ad7766_chip_info ad7766_chip_info[] = { static const struct iio_buffer_setup_ops ad7766_buffer_setup_ops = { .preenable = &ad7766_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, .postdisable = &ad7766_postdisable, }; @@ -242,7 +240,6 @@ static int ad7766_probe(struct spi_device *spi) if (IS_ERR(ad7766->pd_gpio)) return PTR_ERR(ad7766->pd_gpio); - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ad7766_channels; diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c index 0d132708c4295abab1af6e719bfb6205cd314376..0e93b0766eb45b5d87464ef395998d7c2a141533 100644 --- a/drivers/iio/adc/ad7768-1.c +++ b/drivers/iio/adc/ad7768-1.c @@ -490,7 +490,6 @@ static int ad7768_buffer_postenable(struct iio_dev *indio_dev) { struct ad7768_state *st = iio_priv(indio_dev); - iio_triggered_buffer_postenable(indio_dev); /* * Write a 1 to the LSB of the INTERFACE_FORMAT register to enter * continuous read mode. Subsequent data reads do not require an @@ -502,17 +501,12 @@ static int ad7768_buffer_postenable(struct iio_dev *indio_dev) static int ad7768_buffer_predisable(struct iio_dev *indio_dev) { struct ad7768_state *st = iio_priv(indio_dev); - int ret; /* * To exit continuous read mode, perform a single read of the ADC_DATA * reg (0x2C), which allows further configuration of the device. */ - ret = ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3); - if (ret < 0) - return ret; - - return iio_triggered_buffer_predisable(indio_dev); + return ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3); } static const struct iio_buffer_setup_ops ad7768_buffer_ops = { @@ -584,7 +578,6 @@ static int ad7768_probe(struct spi_device *spi) indio_dev->channels = ad7768_channels; indio_dev->num_channels = ARRAY_SIZE(ad7768_channels); - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad7768_info; indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED; diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c index b33fe6c3907e560254eaf8271c85bc56217f3984..42e7e8e595d18b6f82ab544491719821eca60586 100644 --- a/drivers/iio/adc/ad7780.c +++ b/drivers/iio/adc/ad7780.c @@ -320,7 +320,6 @@ static int ad7780_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = &st->chip_info->channel; diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 48432b6f60027025288bed62c47e69365ab7a823..d57ad966e17c166b1aa57c204c18907e9c28187a 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -425,8 +425,6 @@ static int ad7791_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->info->channels; diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 808485f42415c5e5723e39e54f3ccd30f6c72e8b..5e980a06258e64753b8f0b8320c75bb4c847e92c 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -818,8 +818,6 @@ static int ad7793_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->chip_info->channels; diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c index c6a3428e950a9318f229ae69d736fc4be7bb84f2..037bcb47693c1e4c244e3d1867febd152e0bed9d 100644 --- a/drivers/iio/adc/ad7887.c +++ b/drivers/iio/adc/ad7887.c @@ -109,7 +109,7 @@ static int ad7887_ring_postdisable(struct iio_dev *indio_dev) return spi_sync(st->spi, &st->msg[AD7887_CH0]); } -/** +/* * ad7887_trigger_handler() bh of trigger launched polling to ring buffer * * Currently there is no option in this driver to disable the saving of @@ -136,8 +136,6 @@ done: static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = { .preenable = &ad7887_ring_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, .postdisable = &ad7887_ring_postdisable, }; @@ -264,9 +262,6 @@ static int ad7887_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); st->spi = spi; - /* Estabilish that the iio_dev is a child of the spi device */ - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad7887_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c index 1d124c87c6acee9dd1ae161aeacfdd3cc425191b..a2cc966580540734e15a7685b046dce8e2f1503b 100644 --- a/drivers/iio/adc/ad7923.c +++ b/drivers/iio/adc/ad7923.c @@ -151,9 +151,9 @@ static const struct ad7923_chip_info ad7923_chip_info[] = { }, }; -/** +/* * ad7923_update_scan_mode() setup the spi transfer buffer for the new scan mask - **/ + */ static int ad7923_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *active_scan_mask) { @@ -192,12 +192,12 @@ static int ad7923_update_scan_mode(struct iio_dev *indio_dev, return 0; } -/** +/* * ad7923_trigger_handler() bh of trigger launched polling to ring buffer * * Currently there is no option in this driver to disable the saving of * timestamps within the ring. - **/ + */ static irqreturn_t ad7923_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; @@ -315,8 +315,6 @@ static int ad7923_probe(struct spi_device *spi) info = &ad7923_chip_info[spi_get_device_id(spi)->driver_data]; indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = info->channels; indio_dev->num_channels = info->num_channels; diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c index 2c6f60edb7ced4c6258dcc4f2791ddd80d83bb97..d9566a83988aab7d8ba6715edf8c829f6ceebbdc 100644 --- a/drivers/iio/adc/ad7949.c +++ b/drivers/iio/adc/ad7949.c @@ -3,7 +3,7 @@ * * Copyright (C) 2018 CMC NV * - * http://www.analog.com/media/en/technical-documentation/data-sheets/AD7949.pdf + * https://www.analog.com/media/en/technical-documentation/data-sheets/AD7949.pdf */ #include @@ -243,8 +243,6 @@ static int ad7949_spi_probe(struct spi_device *spi) return -ENOMEM; } - indio_dev->dev.parent = dev; - indio_dev->dev.of_node = dev->of_node; indio_dev->info = &ad7949_spi_info; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index ef013af1aec07b47041002e76ebbf3ecbf6d73aa..1575b7670207873a3938ed29ae7421b68fdfb7f9 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -182,7 +182,7 @@ static int ad799x_update_config(struct ad799x_state *st, u16 config) return 0; } -/** +/* * ad799x_trigger_handler() bh of trigger launched polling to ring buffer * * Currently there is no option in this driver to disable the saving of @@ -814,8 +814,6 @@ static int ad799x_probe(struct i2c_client *client, st->client = client; - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->name = id->name; indio_dev->info = st->chip_config->info; diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index dd3d54b3bc8bba19612451e4546a326181fc3512..86039e9ecaca1b46aca1a57402403e36bf0985ba 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -345,10 +345,6 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev) unsigned int channel; int ret; - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret < 0) - return ret; - channel = find_first_bit(indio_dev->active_scan_mask, indio_dev->masklength); ret = ad_sigma_delta_set_channel(sigma_delta, @@ -402,7 +398,6 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p) unsigned int reg_size; unsigned int data_reg; uint8_t data[16]; - int ret; memset(data, 0x00, 16); @@ -419,14 +414,12 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p) case 4: case 2: case 1: - ret = ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, - &data[0]); + ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, &data[0]); break; case 3: /* We store 24 bit samples in a 32 bit word. Keep the upper * byte set to zero. */ - ret = ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, - &data[1]); + ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, &data[1]); break; } @@ -441,7 +434,6 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p) static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = { .postenable = &ad_sd_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, .postdisable = &ad_sd_buffer_postdisable, .validate_scan_mask = &iio_validate_scan_mask_onehot, }; diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c index 7af8f0510535a25d2560b942127c0b1e9885fcc8..86b6b65916ee23483d4eb35e3040d61b752ac18d 100644 --- a/drivers/iio/adc/adi-axi-adc.c +++ b/drivers/iio/adc/adi-axi-adc.c @@ -435,7 +435,6 @@ static int adi_axi_adc_probe(struct platform_device *pdev) } indio_dev->info = &adi_axi_adc_info; - indio_dev->dev.parent = &pdev->dev; indio_dev->name = "adi-axi-adc"; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->num_channels = conv->chip_info->num_channels; diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index 1e5375235cfedad2226017dc3520d7db48c6bb5b..19efaa41bc344b6def9d03bc59efbe62c6e64d82 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -252,7 +252,6 @@ static int aspeed_adc_probe(struct platform_device *pdev) model_data = of_device_get_match_data(&pdev->dev); indio_dev->name = model_data->model_name; - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &aspeed_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = aspeed_adc_iio_channels; diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 9abbbdcc74200288e5a5f1336b14c04e9797a208..de9583d6cddd7aec50779a954b9eb027b578c1ab 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -347,7 +347,7 @@ struct at91_adc_trigger { }; /** - * at91_adc_dma - at91-sama5d2 dma information struct + * struct at91_adc_dma - at91-sama5d2 dma information struct * @dma_chan: the dma channel acquired * @rx_buf: dma coherent allocated area * @rx_dma_buf: dma handler for the buffer @@ -369,7 +369,7 @@ struct at91_adc_dma { }; /** - * at91_adc_touch - at91-sama5d2 touchscreen information struct + * struct at91_adc_touch - at91-sama5d2 touchscreen information struct * @sample_period_val: the value for periodic trigger interval * @touching: is the pen touching the screen or not * @x_pos: temporary placeholder for pressure computation @@ -402,6 +402,7 @@ struct at91_adc_state { wait_queue_head_t wq_data_available; struct at91_adc_dma dma_st; struct at91_adc_touch touch_st; + struct iio_dev *indio_dev; u16 buffer[AT91_BUFFER_MAX_HWORDS]; /* * lock to prevent concurrent 'single conversion' requests through @@ -642,13 +643,13 @@ static u16 at91_adc_touch_pos(struct at91_adc_state *st, int reg) /* first half of register is the x or y, second half is the scale */ val = at91_adc_readl(st, reg); if (!val) - dev_dbg(&iio_priv_to_dev(st)->dev, "pos is 0\n"); + dev_dbg(&st->indio_dev->dev, "pos is 0\n"); pos = val & AT91_SAMA5D2_XYZ_MASK; result = (pos << AT91_SAMA5D2_MAX_POS_BITS) - pos; scale = (val >> 16) & AT91_SAMA5D2_XYZ_MASK; if (scale == 0) { - dev_err(&iio_priv_to_dev(st)->dev, "scale is 0\n"); + dev_err(&st->indio_dev->dev, "scale is 0\n"); return 0; } result /= scale; @@ -937,14 +938,6 @@ static int at91_adc_buffer_preenable(struct iio_dev *indio_dev) return 0; } -static int at91_adc_buffer_postenable(struct iio_dev *indio_dev) -{ - if (at91_adc_current_chan_is_touch(indio_dev)) - return 0; - - return iio_triggered_buffer_postenable(indio_dev); -} - static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev) { struct at91_adc_state *st = iio_priv(indio_dev); @@ -995,19 +988,9 @@ static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev) return 0; } -static int at91_adc_buffer_predisable(struct iio_dev *indio_dev) -{ - if (at91_adc_current_chan_is_touch(indio_dev)) - return 0; - - return iio_triggered_buffer_predisable(indio_dev); -} - static const struct iio_buffer_setup_ops at91_buffer_setup_ops = { .preenable = &at91_adc_buffer_preenable, .postdisable = &at91_adc_buffer_postdisable, - .postenable = &at91_adc_buffer_postenable, - .predisable = &at91_adc_buffer_predisable, }; static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio, @@ -1204,9 +1187,9 @@ static unsigned at91_adc_startup_time(unsigned startup_time_min, return i; } -static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq) +static void at91_adc_setup_samp_freq(struct iio_dev *indio_dev, unsigned freq) { - struct iio_dev *indio_dev = iio_priv_to_dev(st); + struct at91_adc_state *st = iio_priv(indio_dev); unsigned f_per, prescal, startup, mr; f_per = clk_get_rate(st->per_clk); @@ -1275,9 +1258,9 @@ static void at91_adc_pen_detect_interrupt(struct at91_adc_state *st) st->touch_st.touching = true; } -static void at91_adc_no_pen_detect_interrupt(struct at91_adc_state *st) +static void at91_adc_no_pen_detect_interrupt(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = iio_priv_to_dev(st); + struct at91_adc_state *st = iio_priv(indio_dev); at91_adc_writel(st, AT91_SAMA5D2_TRGR, AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER); @@ -1297,7 +1280,7 @@ static void at91_adc_workq_handler(struct work_struct *workq) struct at91_adc_touch, workq); struct at91_adc_state *st = container_of(touch_st, struct at91_adc_state, touch_st); - struct iio_dev *indio_dev = iio_priv_to_dev(st); + struct iio_dev *indio_dev = st->indio_dev; iio_push_to_buffers(indio_dev, st->buffer); } @@ -1318,7 +1301,7 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private) at91_adc_pen_detect_interrupt(st); } else if ((status & AT91_SAMA5D2_IER_NOPEN)) { /* nopen detected IRQ */ - at91_adc_no_pen_detect_interrupt(st); + at91_adc_no_pen_detect_interrupt(indio); } else if ((status & AT91_SAMA5D2_ISR_PENS) && ((status & rdy_mask) == rdy_mask)) { /* periodic trigger IRQ - during pen sense */ @@ -1486,7 +1469,7 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev, val > st->soc_info.max_sample_rate) return -EINVAL; - at91_adc_setup_samp_freq(st, val); + at91_adc_setup_samp_freq(indio_dev, val); return 0; default: return -EINVAL; @@ -1624,8 +1607,10 @@ static int at91_adc_update_scan_mode(struct iio_dev *indio_dev, return 0; } -static void at91_adc_hw_init(struct at91_adc_state *st) +static void at91_adc_hw_init(struct iio_dev *indio_dev) { + struct at91_adc_state *st = iio_priv(indio_dev); + at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); /* @@ -1635,7 +1620,7 @@ static void at91_adc_hw_init(struct at91_adc_state *st) at91_adc_writel(st, AT91_SAMA5D2_MR, AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH); - at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); + at91_adc_setup_samp_freq(indio_dev, st->soc_info.min_sample_rate); /* configure extended mode register */ at91_adc_config_emr(st); @@ -1710,7 +1695,6 @@ static int at91_adc_probe(struct platform_device *pdev) if (!indio_dev) return -ENOMEM; - indio_dev->dev.parent = &pdev->dev; indio_dev->name = dev_name(&pdev->dev); indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; indio_dev->info = &at91_adc_info; @@ -1718,6 +1702,7 @@ static int at91_adc_probe(struct platform_device *pdev) indio_dev->num_channels = ARRAY_SIZE(at91_adc_channels); st = iio_priv(indio_dev); + st->indio_dev = indio_dev; bitmap_set(&st->touch_st.channels_bitmask, AT91_SAMA5D2_TOUCH_X_CHAN_IDX, 1); @@ -1829,7 +1814,7 @@ static int at91_adc_probe(struct platform_device *pdev) goto vref_disable; } - at91_adc_hw_init(st); + at91_adc_hw_init(indio_dev); ret = clk_prepare_enable(st->per_clk); if (ret) @@ -1945,7 +1930,7 @@ static __maybe_unused int at91_adc_resume(struct device *dev) if (ret) goto vref_disable_resume; - at91_adc_hw_init(st); + at91_adc_hw_init(indio_dev); /* reconfiguring trigger hardware state */ if (!iio_buffer_enabled(indio_dev)) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 0368b6dc6d60a9a1439a31efcfacdde5e163887b..9b2c548fae957118c45df126235c3c1787981a53 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -157,7 +157,7 @@ * struct at91_adc_reg_desc - Various informations relative to registers * @channel_base: Base offset for the channel data registers * @drdy_mask: Mask of the DRDY field in the relevant registers - (Interruptions registers mostly) + * (Interruptions registers mostly) * @status_register: Offset of the Interrupt Status Register * @trigger_register: Offset of the Trigger setup register * @mr_prescal_mask: Mask of the PRESCAL field in the adc MR register @@ -287,13 +287,13 @@ static void handle_adc_eoc_trigger(int irq, struct iio_dev *idev) } } -static int at91_ts_sample(struct at91_adc_state *st) +static int at91_ts_sample(struct iio_dev *idev) { + struct at91_adc_state *st = iio_priv(idev); unsigned int xscale, yscale, reg, z1, z2; unsigned int x, y, pres, xpos, ypos; unsigned int rxp = 1; unsigned int factor = 1000; - struct iio_dev *idev = iio_priv_to_dev(st); unsigned int xyz_mask_bits = st->res; unsigned int xyz_mask = (1 << xyz_mask_bits) - 1; @@ -449,7 +449,7 @@ static irqreturn_t at91_adc_9x5_interrupt(int irq, void *private) if (status & AT91_ADC_ISR_PENS) { /* validate data by pen contact */ - at91_ts_sample(st); + at91_ts_sample(idev); } else { /* triggered by event that is no pen contact, just read * them to clean the interrupt and discard all. @@ -737,10 +737,10 @@ static int at91_adc_read_raw(struct iio_dev *idev, return -EINVAL; } -static int at91_adc_of_get_resolution(struct at91_adc_state *st, +static int at91_adc_of_get_resolution(struct iio_dev *idev, struct platform_device *pdev) { - struct iio_dev *idev = iio_priv_to_dev(st); + struct at91_adc_state *st = iio_priv(idev); struct device_node *np = pdev->dev.of_node; int count, i, ret = 0; char *res_name, *s; @@ -866,10 +866,10 @@ static int at91_adc_probe_dt_ts(struct device_node *node, } } -static int at91_adc_probe_dt(struct at91_adc_state *st, +static int at91_adc_probe_dt(struct iio_dev *idev, struct platform_device *pdev) { - struct iio_dev *idev = iio_priv_to_dev(st); + struct at91_adc_state *st = iio_priv(idev); struct device_node *node = pdev->dev.of_node; struct device_node *trig_node; int i = 0, ret; @@ -910,7 +910,7 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, } st->vref_mv = prop; - ret = at91_adc_of_get_resolution(st, pdev); + ret = at91_adc_of_get_resolution(idev, pdev); if (ret) goto error_ret; @@ -1010,9 +1010,9 @@ static void atmel_ts_close(struct input_dev *dev) at91_adc_writel(st, AT91_ADC_IDR, AT91RL_ADC_IER_PEN); } -static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz) +static int at91_ts_hw_init(struct iio_dev *idev, u32 adc_clk_khz) { - struct iio_dev *idev = iio_priv_to_dev(st); + struct at91_adc_state *st = iio_priv(idev); u32 reg = 0; u32 tssctim = 0; int i = 0; @@ -1085,11 +1085,11 @@ static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz) return 0; } -static int at91_ts_register(struct at91_adc_state *st, +static int at91_ts_register(struct iio_dev *idev, struct platform_device *pdev) { + struct at91_adc_state *st = iio_priv(idev); struct input_dev *input; - struct iio_dev *idev = iio_priv_to_dev(st); int ret; input = input_allocate_device(); @@ -1161,7 +1161,7 @@ static int at91_adc_probe(struct platform_device *pdev) st = iio_priv(idev); if (pdev->dev.of_node) - ret = at91_adc_probe_dt(st, pdev); + ret = at91_adc_probe_dt(idev, pdev); else ret = at91_adc_probe_pdata(st, pdev); @@ -1172,7 +1172,6 @@ static int at91_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, idev); - idev->dev.parent = &pdev->dev; idev->name = dev_name(&pdev->dev); idev->modes = INDIO_DIRECT_MODE; idev->info = &at91_adc_info; @@ -1301,11 +1300,11 @@ static int at91_adc_probe(struct platform_device *pdev) goto error_disable_adc_clk; } } else { - ret = at91_ts_register(st, pdev); + ret = at91_ts_register(idev, pdev); if (ret) goto error_disable_adc_clk; - at91_ts_hw_init(st, adc_clk_khz); + at91_ts_hw_init(idev, adc_clk_khz); } ret = iio_device_register(idev); diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c index 88059480da17c3ec526cefd7175f6998aef176ca..798ff2d896916be62a50129d936897ee937fdb9f 100644 --- a/drivers/iio/adc/axp20x_adc.c +++ b/drivers/iio/adc/axp20x_adc.c @@ -668,8 +668,6 @@ static int axp20x_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); info->regmap = axp20x_dev->regmap; - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->modes = INDIO_DIRECT_MODE; if (!pdev->dev.of_node) { diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 8ea2aed6d6f5a2179f5d6b0cc51abf4f42fa93ad..5f5e8b39e4d227417060fecff9d732060ae8d89e 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -271,7 +271,6 @@ static int axp288_adc_probe(struct platform_device *pdev) return ret; } - indio_dev->dev.parent = &pdev->dev; indio_dev->name = pdev->name; indio_dev->channels = axp288_adc_channels; indio_dev->num_channels = ARRAY_SIZE(axp288_adc_channels); diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c index 5e396104ac86785328b38a5a052d7e3d87bab33c..936da32faa9d26c4e58252b1c1a2632f0f73b3c0 100644 --- a/drivers/iio/adc/bcm_iproc_adc.c +++ b/drivers/iio/adc/bcm_iproc_adc.c @@ -573,8 +573,6 @@ static int iproc_adc_probe(struct platform_device *pdev) } indio_dev->name = "iproc-static-adc"; - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &iproc_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = iproc_adc_iio_channels; diff --git a/drivers/iio/adc/berlin2-adc.c b/drivers/iio/adc/berlin2-adc.c index 72d8fa94ab31c54b54fdfa3b4f8338c08ba01735..8b04b95b7b7ae033e8e3f1be1350b4dd4f793b4a 100644 --- a/drivers/iio/adc/berlin2-adc.c +++ b/drivers/iio/adc/berlin2-adc.c @@ -321,7 +321,6 @@ static int berlin2_adc_probe(struct platform_device *pdev) init_waitqueue_head(&priv->wq); mutex_init(&priv->lock); - indio_dev->dev.parent = &pdev->dev; indio_dev->name = dev_name(&pdev->dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &berlin2_adc_info; diff --git a/drivers/iio/adc/cc10001_adc.c b/drivers/iio/adc/cc10001_adc.c index fe9257624f166eee823ed1b2b7438c060cb9dd5a..e16ac935693b64af354a79971e2b92dc432f2e0f 100644 --- a/drivers/iio/adc/cc10001_adc.c +++ b/drivers/iio/adc/cc10001_adc.c @@ -334,7 +334,6 @@ static int cc10001_adc_probe(struct platform_device *pdev) if (ret) return ret; - indio_dev->dev.parent = &pdev->dev; indio_dev->name = dev_name(&pdev->dev); indio_dev->info = &cc10001_adc_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c index 5086a337f4c9af8bc91cdf37bb6a5826b37aa0a7..84a1733e5913f438c53538cb18817d6283fb18cd 100644 --- a/drivers/iio/adc/cpcap-adc.c +++ b/drivers/iio/adc/cpcap-adc.c @@ -15,9 +15,9 @@ #include #include #include -#include -#include +#include #include +#include #include #include @@ -82,7 +82,7 @@ #define CPCAP_ADC_MAX_RETRIES 5 /* Calibration */ -/** +/* * struct cpcap_adc_ato - timing settings for cpcap adc * * Unfortunately no cpcap documentation available, please document when @@ -121,7 +121,7 @@ struct cpcap_adc { bool done; }; -/** +/* * enum cpcap_adc_channel - cpcap adc channels */ enum cpcap_adc_channel { @@ -152,7 +152,7 @@ enum cpcap_adc_channel { CPCAP_ADC_CHANNEL_NUM, }; -/** +/* * enum cpcap_adc_timing - cpcap adc timing options * * CPCAP_ADC_TIMING_IMM seems to be immediate with no timings. @@ -955,22 +955,10 @@ MODULE_DEVICE_TABLE(of, cpcap_adc_id_table); static int cpcap_adc_probe(struct platform_device *pdev) { - const struct of_device_id *match; struct cpcap_adc *ddata; struct iio_dev *indio_dev; int error; - match = of_match_device(of_match_ptr(cpcap_adc_id_table), - &pdev->dev); - if (!match) - return -EINVAL; - - if (!match->data) { - dev_err(&pdev->dev, "no configuration data found\n"); - - return -ENODEV; - } - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*ddata)); if (!indio_dev) { dev_err(&pdev->dev, "failed to allocate iio device\n"); @@ -978,15 +966,15 @@ static int cpcap_adc_probe(struct platform_device *pdev) return -ENOMEM; } ddata = iio_priv(indio_dev); - ddata->ato = match->data; + ddata->ato = device_get_match_data(&pdev->dev); + if (!ddata->ato) + return -ENODEV; ddata->dev = &pdev->dev; mutex_init(&ddata->lock); init_waitqueue_head(&ddata->wq_data_avail); indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->channels = cpcap_adc_channels; indio_dev->num_channels = ARRAY_SIZE(cpcap_adc_channels); indio_dev->name = dev_name(&pdev->dev); @@ -1029,7 +1017,7 @@ static int cpcap_adc_probe(struct platform_device *pdev) static struct platform_driver cpcap_adc_driver = { .driver = { .name = "cpcap_adc", - .of_match_table = of_match_ptr(cpcap_adc_id_table), + .of_match_table = cpcap_adc_id_table, }, .probe = cpcap_adc_probe, }; diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c index ae8bcc32f63d94be10396f75a075e6535cc9dd73..7a7a54a7ed764419e788891b33e21735bf724099 100644 --- a/drivers/iio/adc/da9150-gpadc.c +++ b/drivers/iio/adc/da9150-gpadc.c @@ -354,8 +354,6 @@ static int da9150_gpadc_probe(struct platform_device *pdev) } indio_dev->name = dev_name(dev); - indio_dev->dev.parent = dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &da9150_gpadc_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = da9150_gpadc_channels; diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c index 65c7c9329b1c31dfd03b93aebd54dda901dd2b7a..0d53ef18e0459ce204889a8dfb18e360e44b4854 100644 --- a/drivers/iio/adc/dln2-adc.c +++ b/drivers/iio/adc/dln2-adc.c @@ -524,10 +524,6 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev) u16 conflict; unsigned int trigger_chan; - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret) - return ret; - mutex_lock(&dln2->mutex); /* Enable ADC */ @@ -541,7 +537,6 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev) (int)conflict); ret = -EBUSY; } - iio_triggered_buffer_predisable(indio_dev); return ret; } @@ -555,7 +550,6 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev) mutex_unlock(&dln2->mutex); if (ret < 0) { dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); - iio_triggered_buffer_predisable(indio_dev); return ret; } } else { @@ -568,7 +562,7 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev) static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev) { - int ret, ret2; + int ret; struct dln2_adc *dln2 = iio_priv(indio_dev); mutex_lock(&dln2->mutex); @@ -586,10 +580,6 @@ static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev) if (ret < 0) dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); - ret2 = iio_triggered_buffer_predisable(indio_dev); - if (ret == 0) - ret = ret2; - return ret; } @@ -652,7 +642,6 @@ static int dln2_adc_probe(struct platform_device *pdev) IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(dln2->iio_channels[i], i); indio_dev->name = DLN2_ADC_MOD_NAME; - indio_dev->dev.parent = dev; indio_dev->info = &dln2_adc_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = dln2->iio_channels; diff --git a/drivers/iio/adc/envelope-detector.c b/drivers/iio/adc/envelope-detector.c index 28f3d6758eb5f51a03dc246d20077afe2ee3a1e4..2a4fd3bb64cfbf72b2893132ab92df847df91ef9 100644 --- a/drivers/iio/adc/envelope-detector.c +++ b/drivers/iio/adc/envelope-detector.c @@ -343,8 +343,6 @@ static int envelope_detector_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&env->comp_timeout, envelope_detector_timeout); indio_dev->name = dev_name(dev); - indio_dev->dev.parent = dev; - indio_dev->dev.of_node = dev->of_node; indio_dev->info = &envelope_detector_info; indio_dev->channels = &envelope_detector_iio_channel; indio_dev->num_channels = 1; diff --git a/drivers/iio/adc/ep93xx_adc.c b/drivers/iio/adc/ep93xx_adc.c index 5c97e8a511f24c745c0c4883ba6dd03411ea9c1d..c08ab3c6dfafd489d1b15b531e997f577cd0e5c1 100644 --- a/drivers/iio/adc/ep93xx_adc.c +++ b/drivers/iio/adc/ep93xx_adc.c @@ -170,7 +170,6 @@ static int ep93xx_adc_probe(struct platform_device *pdev) return PTR_ERR(priv->base); } - iiodev->dev.parent = &pdev->dev; iiodev->name = dev_name(&pdev->dev); iiodev->modes = INDIO_DIRECT_MODE; iiodev->info = &ep93xx_adc_info; diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index 6bda4f4d89feab27f5a66c14b08e6c4f39c28966..7d23b6c3328414d12a7b708d171cbbf772311311 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -867,8 +867,6 @@ static int exynos_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &exynos_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = exynos_adc_iio_channels; diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index b0a4dc88ba9b99155d7b546917082efb73e9c2ec..8cb51cf7a81645cd29052f9b9b49c693c408cf77 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -350,7 +350,6 @@ static int mx25_gcq_probe(struct platform_device *pdev) goto err_clk_unprepare; } - indio_dev->dev.parent = &pdev->dev; indio_dev->channels = mx25_gcq_channels; indio_dev->num_channels = ARRAY_SIZE(mx25_gcq_channels); indio_dev->info = &mx25_gcq_iio_info; diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index 8da45bf36d36054b4234f2358b0f91d7591176ee..074c30970465ab045f3784ee3ffb97d3f9c11c2e 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -15,9 +15,7 @@ #include #include #include -#include -#include -#include +#include #include #include @@ -488,8 +486,6 @@ static int hi8435_probe(struct spi_device *spi) spi_set_drvdata(spi, idev); mutex_init(&priv->lock); - idev->dev.parent = &spi->dev; - idev->dev.of_node = spi->dev.of_node; idev->name = spi_get_device_id(spi)->name; idev->modes = INDIO_DIRECT_MODE; idev->info = &hi8435_info; @@ -542,7 +538,7 @@ MODULE_DEVICE_TABLE(spi, hi8435_id); static struct spi_driver hi8435_driver = { .driver = { .name = DRV_NAME, - .of_match_table = of_match_ptr(hi8435_dt_ids), + .of_match_table = hi8435_dt_ids, }, .probe = hi8435_probe, .id_table = hi8435_id, diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c index c8686558429b9c45c9769991d1c8031607281b36..6a173531d355bab573dd874db2cd9fdbeb3c5af1 100644 --- a/drivers/iio/adc/hx711.c +++ b/drivers/iio/adc/hx711.c @@ -551,7 +551,6 @@ static int hx711_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); indio_dev->name = "hx711"; - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &hx711_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = hx711_chan_spec; diff --git a/drivers/iio/adc/imx7d_adc.c b/drivers/iio/adc/imx7d_adc.c index 2a2fbf788e9567a78a67032744c9de2bcd7aa30c..4969a5f941e33a3569b83030dfa48ce36a47120d 100644 --- a/drivers/iio/adc/imx7d_adc.c +++ b/drivers/iio/adc/imx7d_adc.c @@ -515,7 +515,6 @@ static int imx7d_adc_probe(struct platform_device *pdev) init_completion(&info->completion); indio_dev->name = dev_name(dev); - indio_dev->dev.parent = dev; indio_dev->info = &imx7d_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = imx7d_adc_iio_channels; diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index bdd7cba6f6b0b63f431612e75d169fda13576249..5ed63e8742923fa6a053904be7eeedfb1c1951c1 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -273,7 +273,7 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev, * Available averaging rates for ina226. The indices correspond with * the bit values expected by the chip (according to the ina226 datasheet, * table 3 AVG bit settings, found at - * http://www.ti.com/lit/ds/symlink/ina226.pdf. + * https://www.ti.com/lit/ds/symlink/ina226.pdf. */ static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 }; @@ -1015,8 +1015,6 @@ static int ina2xx_probe(struct i2c_client *client, } indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; if (id->driver_data == ina226) { indio_dev->channels = ina226_channels; indio_dev->num_channels = ARRAY_SIZE(ina226_channels); diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c index 39c0a609fc948029952a5e1ef45fc041abfba047..92b25083e23f10633be5d62c4432dcba078be895 100644 --- a/drivers/iio/adc/ingenic-adc.c +++ b/drivers/iio/adc/ingenic-adc.c @@ -8,11 +8,14 @@ #include #include +#include #include +#include #include #include #include #include +#include #include #include @@ -20,19 +23,46 @@ #define JZ_ADC_REG_CFG 0x04 #define JZ_ADC_REG_CTRL 0x08 #define JZ_ADC_REG_STATUS 0x0c +#define JZ_ADC_REG_ADSAME 0x10 +#define JZ_ADC_REG_ADWAIT 0x14 #define JZ_ADC_REG_ADTCH 0x18 #define JZ_ADC_REG_ADBDAT 0x1c #define JZ_ADC_REG_ADSDAT 0x20 +#define JZ_ADC_REG_ADCMD 0x24 #define JZ_ADC_REG_ADCLK 0x28 #define JZ_ADC_REG_ENABLE_PD BIT(7) #define JZ_ADC_REG_CFG_AUX_MD (BIT(0) | BIT(1)) #define JZ_ADC_REG_CFG_BAT_MD BIT(4) +#define JZ_ADC_REG_CFG_SAMPLE_NUM(n) ((n) << 10) +#define JZ_ADC_REG_CFG_PULL_UP(n) ((n) << 16) +#define JZ_ADC_REG_CFG_CMD_SEL BIT(22) +#define JZ_ADC_REG_CFG_TOUCH_OPS_MASK (BIT(31) | GENMASK(23, 10)) #define JZ_ADC_REG_ADCLK_CLKDIV_LSB 0 #define JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB 16 #define JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB 8 #define JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB 16 +#define JZ_ADC_REG_ADCMD_YNADC BIT(7) +#define JZ_ADC_REG_ADCMD_YPADC BIT(8) +#define JZ_ADC_REG_ADCMD_XNADC BIT(9) +#define JZ_ADC_REG_ADCMD_XPADC BIT(10) +#define JZ_ADC_REG_ADCMD_VREFPYP BIT(11) +#define JZ_ADC_REG_ADCMD_VREFPXP BIT(12) +#define JZ_ADC_REG_ADCMD_VREFPXN BIT(13) +#define JZ_ADC_REG_ADCMD_VREFPAUX BIT(14) +#define JZ_ADC_REG_ADCMD_VREFPVDD33 BIT(15) +#define JZ_ADC_REG_ADCMD_VREFNYN BIT(16) +#define JZ_ADC_REG_ADCMD_VREFNXP BIT(17) +#define JZ_ADC_REG_ADCMD_VREFNXN BIT(18) +#define JZ_ADC_REG_ADCMD_VREFAUX BIT(19) +#define JZ_ADC_REG_ADCMD_YNGRU BIT(20) +#define JZ_ADC_REG_ADCMD_XNGRU BIT(21) +#define JZ_ADC_REG_ADCMD_XPGRU BIT(22) +#define JZ_ADC_REG_ADCMD_YPSUP BIT(23) +#define JZ_ADC_REG_ADCMD_XNSUP BIT(24) +#define JZ_ADC_REG_ADCMD_XPSUP BIT(25) + #define JZ_ADC_AUX_VREF 3300 #define JZ_ADC_AUX_VREF_BITS 12 #define JZ_ADC_BATTERY_LOW_VREF 2500 @@ -44,6 +74,14 @@ #define JZ4770_ADC_BATTERY_VREF 6600 #define JZ4770_ADC_BATTERY_VREF_BITS 12 +#define JZ_ADC_IRQ_AUX BIT(0) +#define JZ_ADC_IRQ_BATTERY BIT(1) +#define JZ_ADC_IRQ_TOUCH BIT(2) +#define JZ_ADC_IRQ_PEN_DOWN BIT(3) +#define JZ_ADC_IRQ_PEN_UP BIT(4) +#define JZ_ADC_IRQ_PEN_DOWN_SLEEP BIT(5) +#define JZ_ADC_IRQ_SLEEP BIT(7) + struct ingenic_adc; struct ingenic_adc_soc_data { @@ -55,6 +93,8 @@ struct ingenic_adc_soc_data { size_t battery_scale_avail_size; unsigned int battery_vref_mode: 1; unsigned int has_aux2: 1; + const struct iio_chan_spec *channels; + unsigned int num_channels; int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc); }; @@ -67,13 +107,67 @@ struct ingenic_adc { bool low_vref_mode; }; +static void ingenic_adc_set_adcmd(struct iio_dev *iio_dev, unsigned long mask) +{ + struct ingenic_adc *adc = iio_priv(iio_dev); + + mutex_lock(&adc->lock); + + /* Init ADCMD */ + readl(adc->base + JZ_ADC_REG_ADCMD); + + if (mask & 0x3) { + /* Second channel (INGENIC_ADC_TOUCH_YP): sample YP vs. GND */ + writel(JZ_ADC_REG_ADCMD_XNGRU + | JZ_ADC_REG_ADCMD_VREFNXN | JZ_ADC_REG_ADCMD_VREFPVDD33 + | JZ_ADC_REG_ADCMD_YPADC, + adc->base + JZ_ADC_REG_ADCMD); + + /* First channel (INGENIC_ADC_TOUCH_XP): sample XP vs. GND */ + writel(JZ_ADC_REG_ADCMD_YNGRU + | JZ_ADC_REG_ADCMD_VREFNYN | JZ_ADC_REG_ADCMD_VREFPVDD33 + | JZ_ADC_REG_ADCMD_XPADC, + adc->base + JZ_ADC_REG_ADCMD); + } + + if (mask & 0xc) { + /* Fourth channel (INGENIC_ADC_TOUCH_YN): sample YN vs. GND */ + writel(JZ_ADC_REG_ADCMD_XNGRU + | JZ_ADC_REG_ADCMD_VREFNXN | JZ_ADC_REG_ADCMD_VREFPVDD33 + | JZ_ADC_REG_ADCMD_YNADC, + adc->base + JZ_ADC_REG_ADCMD); + + /* Third channel (INGENIC_ADC_TOUCH_XN): sample XN vs. GND */ + writel(JZ_ADC_REG_ADCMD_YNGRU + | JZ_ADC_REG_ADCMD_VREFNYN | JZ_ADC_REG_ADCMD_VREFPVDD33 + | JZ_ADC_REG_ADCMD_XNADC, + adc->base + JZ_ADC_REG_ADCMD); + } + + if (mask & 0x30) { + /* Sixth channel (INGENIC_ADC_TOUCH_YD): sample YP vs. YN */ + writel(JZ_ADC_REG_ADCMD_VREFNYN | JZ_ADC_REG_ADCMD_VREFPVDD33 + | JZ_ADC_REG_ADCMD_YPADC, + adc->base + JZ_ADC_REG_ADCMD); + + /* Fifth channel (INGENIC_ADC_TOUCH_XD): sample XP vs. XN */ + writel(JZ_ADC_REG_ADCMD_VREFNXN | JZ_ADC_REG_ADCMD_VREFPVDD33 + | JZ_ADC_REG_ADCMD_XPADC, + adc->base + JZ_ADC_REG_ADCMD); + } + + /* We're done */ + writel(0, adc->base + JZ_ADC_REG_ADCMD); + + mutex_unlock(&adc->lock); +} + static void ingenic_adc_set_config(struct ingenic_adc *adc, uint32_t mask, uint32_t val) { uint32_t cfg; - clk_enable(adc->clk); mutex_lock(&adc->lock); cfg = readl(adc->base + JZ_ADC_REG_CFG) & ~mask; @@ -81,7 +175,6 @@ static void ingenic_adc_set_config(struct ingenic_adc *adc, writel(cfg, adc->base + JZ_ADC_REG_CFG); mutex_unlock(&adc->lock); - clk_disable(adc->clk); } static void ingenic_adc_enable(struct ingenic_adc *adc, @@ -124,6 +217,8 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev, long m) { struct ingenic_adc *adc = iio_priv(iio_dev); + struct device *dev = iio_dev->dev.parent; + int ret; switch (m) { case IIO_CHAN_INFO_SCALE: @@ -131,6 +226,14 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev, case INGENIC_ADC_BATTERY: if (!adc->soc_data->battery_vref_mode) return -EINVAL; + + ret = clk_enable(adc->clk); + if (ret) { + dev_err(dev, "Failed to enable clock: %d\n", + ret); + return ret; + } + if (val > JZ_ADC_BATTERY_LOW_VREF) { ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_BAT_MD, @@ -142,6 +245,9 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev, JZ_ADC_REG_CFG_BAT_MD); adc->low_vref_mode = true; } + + clk_disable(adc->clk); + return 0; default: return -EINVAL; @@ -251,6 +357,127 @@ static int jz4770_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc) return 0; } +static const struct iio_chan_spec jz4740_channels[] = { + { + .extend_name = "aux", + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .indexed = 1, + .channel = INGENIC_ADC_AUX, + .scan_index = -1, + }, + { + .extend_name = "battery", + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .indexed = 1, + .channel = INGENIC_ADC_BATTERY, + .scan_index = -1, + }, +}; + +static const struct iio_chan_spec jz4770_channels[] = { + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = INGENIC_ADC_TOUCH_XP, + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 12, + .storagebits = 16, + }, + }, + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = INGENIC_ADC_TOUCH_YP, + .scan_index = 1, + .scan_type = { + .sign = 'u', + .realbits = 12, + .storagebits = 16, + }, + }, + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = INGENIC_ADC_TOUCH_XN, + .scan_index = 2, + .scan_type = { + .sign = 'u', + .realbits = 12, + .storagebits = 16, + }, + }, + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = INGENIC_ADC_TOUCH_YN, + .scan_index = 3, + .scan_type = { + .sign = 'u', + .realbits = 12, + .storagebits = 16, + }, + }, + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = INGENIC_ADC_TOUCH_XD, + .scan_index = 4, + .scan_type = { + .sign = 'u', + .realbits = 12, + .storagebits = 16, + }, + }, + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = INGENIC_ADC_TOUCH_YD, + .scan_index = 5, + .scan_type = { + .sign = 'u', + .realbits = 12, + .storagebits = 16, + }, + }, + { + .extend_name = "aux", + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .indexed = 1, + .channel = INGENIC_ADC_AUX, + .scan_index = -1, + }, + { + .extend_name = "battery", + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .indexed = 1, + .channel = INGENIC_ADC_BATTERY, + .scan_index = -1, + }, + { + .extend_name = "aux2", + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .indexed = 1, + .channel = INGENIC_ADC_AUX2, + .scan_index = -1, + }, +}; + static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = { .battery_high_vref = JZ4725B_ADC_BATTERY_HIGH_VREF, .battery_high_vref_bits = JZ4725B_ADC_BATTERY_HIGH_VREF_BITS, @@ -260,6 +487,8 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = { .battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail), .battery_vref_mode = true, .has_aux2 = false, + .channels = jz4740_channels, + .num_channels = ARRAY_SIZE(jz4740_channels), .init_clk_div = jz4725b_adc_init_clk_div, }; @@ -272,6 +501,8 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = { .battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail), .battery_vref_mode = true, .has_aux2 = false, + .channels = jz4740_channels, + .num_channels = ARRAY_SIZE(jz4740_channels), .init_clk_div = NULL, /* no ADCLK register on JZ4740 */ }; @@ -284,6 +515,8 @@ static const struct ingenic_adc_soc_data jz4770_adc_soc_data = { .battery_scale_avail_size = ARRAY_SIZE(jz4770_adc_battery_scale_avail), .battery_vref_mode = false, .has_aux2 = true, + .channels = jz4770_channels, + .num_channels = ARRAY_SIZE(jz4770_channels), .init_clk_div = jz4770_adc_init_clk_div, }; @@ -312,11 +545,19 @@ static int ingenic_adc_read_avail(struct iio_dev *iio_dev, }; } -static int ingenic_adc_read_chan_info_raw(struct ingenic_adc *adc, +static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *chan, int *val) { int bit, ret, engine = (chan->channel == INGENIC_ADC_BATTERY); + struct ingenic_adc *adc = iio_priv(iio_dev); + + ret = clk_enable(adc->clk); + if (ret) { + dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n", + ret); + return ret; + } /* We cannot sample AUX/AUX2 in parallel. */ mutex_lock(&adc->aux_lock); @@ -325,7 +566,6 @@ static int ingenic_adc_read_chan_info_raw(struct ingenic_adc *adc, ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_AUX_MD, bit); } - clk_enable(adc->clk); ret = ingenic_adc_capture(adc, engine); if (ret) goto out; @@ -342,8 +582,8 @@ static int ingenic_adc_read_chan_info_raw(struct ingenic_adc *adc, ret = IIO_VAL_INT; out: - clk_disable(adc->clk); mutex_unlock(&adc->aux_lock); + clk_disable(adc->clk); return ret; } @@ -358,7 +598,7 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - return ingenic_adc_read_chan_info_raw(adc, chan, val); + return ingenic_adc_read_chan_info_raw(iio_dev, chan, val); case IIO_CHAN_INFO_SCALE: switch (chan->channel) { case INGENIC_ADC_AUX: @@ -383,6 +623,21 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev, } } +static int ingenic_adc_of_xlate(struct iio_dev *iio_dev, + const struct of_phandle_args *iiospec) +{ + int i; + + if (!iiospec->args_count) + return -EINVAL; + + for (i = 0; i < iio_dev->num_channels; ++i) + if (iio_dev->channels[i].channel == iiospec->args[0]) + return i; + + return -EINVAL; +} + static void ingenic_adc_clk_cleanup(void *data) { clk_unprepare(data); @@ -392,44 +647,92 @@ static const struct iio_info ingenic_adc_info = { .write_raw = ingenic_adc_write_raw, .read_raw = ingenic_adc_read_raw, .read_avail = ingenic_adc_read_avail, + .of_xlate = ingenic_adc_of_xlate, }; -static const struct iio_chan_spec ingenic_channels[] = { - { - .extend_name = "aux", - .type = IIO_VOLTAGE, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_SCALE), - .indexed = 1, - .channel = INGENIC_ADC_AUX, - }, - { - .extend_name = "battery", - .type = IIO_VOLTAGE, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_SCALE), - .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_SCALE), - .indexed = 1, - .channel = INGENIC_ADC_BATTERY, - }, - { /* Must always be last in the array. */ - .extend_name = "aux2", - .type = IIO_VOLTAGE, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_SCALE), - .indexed = 1, - .channel = INGENIC_ADC_AUX2, - }, +static int ingenic_adc_buffer_enable(struct iio_dev *iio_dev) +{ + struct ingenic_adc *adc = iio_priv(iio_dev); + int ret; + + ret = clk_enable(adc->clk); + if (ret) { + dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n", + ret); + return ret; + } + + /* It takes significant time for the touchscreen hw to stabilize. */ + msleep(50); + ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_TOUCH_OPS_MASK, + JZ_ADC_REG_CFG_SAMPLE_NUM(4) | + JZ_ADC_REG_CFG_PULL_UP(4)); + + writew(80, adc->base + JZ_ADC_REG_ADWAIT); + writew(2, adc->base + JZ_ADC_REG_ADSAME); + writeb((u8)~JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_CTRL); + writel(0, adc->base + JZ_ADC_REG_ADTCH); + + ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_CMD_SEL, + JZ_ADC_REG_CFG_CMD_SEL); + ingenic_adc_set_adcmd(iio_dev, iio_dev->active_scan_mask[0]); + + ingenic_adc_enable(adc, 2, true); + + return 0; +} + +static int ingenic_adc_buffer_disable(struct iio_dev *iio_dev) +{ + struct ingenic_adc *adc = iio_priv(iio_dev); + + ingenic_adc_enable(adc, 2, false); + + ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_CMD_SEL, 0); + + writeb(0xff, adc->base + JZ_ADC_REG_CTRL); + writeb(0xff, adc->base + JZ_ADC_REG_STATUS); + ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_TOUCH_OPS_MASK, 0); + writew(0, adc->base + JZ_ADC_REG_ADSAME); + writew(0, adc->base + JZ_ADC_REG_ADWAIT); + clk_disable(adc->clk); + + return 0; +} + +static const struct iio_buffer_setup_ops ingenic_buffer_setup_ops = { + .postenable = &ingenic_adc_buffer_enable, + .predisable = &ingenic_adc_buffer_disable }; +static irqreturn_t ingenic_adc_irq(int irq, void *data) +{ + struct iio_dev *iio_dev = data; + struct ingenic_adc *adc = iio_priv(iio_dev); + unsigned long mask = iio_dev->active_scan_mask[0]; + unsigned int i; + u32 tdat[3]; + + for (i = 0; i < ARRAY_SIZE(tdat); mask >>= 2, i++) { + if (mask & 0x3) + tdat[i] = readl(adc->base + JZ_ADC_REG_ADTCH); + else + tdat[i] = 0; + } + + iio_push_to_buffers(iio_dev, tdat); + writeb(JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_STATUS); + + return IRQ_HANDLED; +} + static int ingenic_adc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct iio_dev *iio_dev; struct ingenic_adc *adc; const struct ingenic_adc_soc_data *soc_data; - int ret; + int irq, ret; soc_data = device_get_match_data(dev); if (!soc_data) @@ -444,6 +747,17 @@ static int ingenic_adc_probe(struct platform_device *pdev) mutex_init(&adc->aux_lock); adc->soc_data = soc_data; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + ret = devm_request_irq(dev, irq, ingenic_adc_irq, 0, + dev_name(dev), iio_dev); + if (ret < 0) { + dev_err(dev, "Failed to request irq: %d\n", ret); + return ret; + } + adc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(adc->base)) return PTR_ERR(adc->base); @@ -481,14 +795,11 @@ static int ingenic_adc_probe(struct platform_device *pdev) return ret; } - iio_dev->dev.parent = dev; iio_dev->name = "jz-adc"; - iio_dev->modes = INDIO_DIRECT_MODE; - iio_dev->channels = ingenic_channels; - iio_dev->num_channels = ARRAY_SIZE(ingenic_channels); - /* Remove AUX2 from the list of supported channels. */ - if (!adc->soc_data->has_aux2) - iio_dev->num_channels -= 1; + iio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; + iio_dev->setup_ops = &ingenic_buffer_setup_ops; + iio_dev->channels = soc_data->channels; + iio_dev->num_channels = soc_data->num_channels; iio_dev->info = &ingenic_adc_info; ret = devm_iio_device_register(dev, iio_dev); @@ -498,7 +809,6 @@ static int ingenic_adc_probe(struct platform_device *pdev) return ret; } -#ifdef CONFIG_OF static const struct of_device_id ingenic_adc_of_match[] = { { .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, }, { .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, }, @@ -506,12 +816,11 @@ static const struct of_device_id ingenic_adc_of_match[] = { { }, }; MODULE_DEVICE_TABLE(of, ingenic_adc_of_match); -#endif static struct platform_driver ingenic_adc_driver = { .driver = { .name = "ingenic-adc", - .of_match_table = of_match_ptr(ingenic_adc_of_match), + .of_match_table = ingenic_adc_of_match, }, .probe = ingenic_adc_probe, }; diff --git a/drivers/iio/adc/intel_mrfld_adc.c b/drivers/iio/adc/intel_mrfld_adc.c index a6d2e1f27e76b085cf221d95348ae29230347dcb..75394350eb4ce5fa0bd6a5e186876e8074dbe18e 100644 --- a/drivers/iio/adc/intel_mrfld_adc.c +++ b/drivers/iio/adc/intel_mrfld_adc.c @@ -207,7 +207,6 @@ static int mrfld_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); - indio_dev->dev.parent = dev; indio_dev->name = pdev->name; indio_dev->channels = mrfld_adc_channels; diff --git a/drivers/iio/adc/lp8788_adc.c b/drivers/iio/adc/lp8788_adc.c index c1fc1b678e0f3257ec743d09c96d3ce61003b1ec..8fb57e375529e3f1d62d7ddf9a4b5cf2b3704cda 100644 --- a/drivers/iio/adc/lp8788_adc.c +++ b/drivers/iio/adc/lp8788_adc.c @@ -198,14 +198,12 @@ static int lp8788_adc_probe(struct platform_device *pdev) adc->lp = lp; platform_set_drvdata(pdev, indio_dev); - indio_dev->dev.of_node = pdev->dev.of_node; ret = lp8788_iio_map_register(indio_dev, lp->pdata, adc); if (ret) return ret; mutex_init(&adc->lock); - indio_dev->dev.parent = &pdev->dev; indio_dev->name = pdev->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &lp8788_adc_info; diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c index 4c6ac6644dc0dd3c4238d96aa5db5ef3e3e85c47..3566990ae87db27b35527c66c8b6eca11e5995a0 100644 --- a/drivers/iio/adc/lpc18xx_adc.c +++ b/drivers/iio/adc/lpc18xx_adc.c @@ -152,7 +152,6 @@ static int lpc18xx_adc_probe(struct platform_device *pdev) } indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &lpc18xx_adc_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = lpc18xx_adc_iio_channels; diff --git a/drivers/iio/adc/lpc32xx_adc.c b/drivers/iio/adc/lpc32xx_adc.c index b896f7ff4572eb539a94f44b11ac57be25d66d8a..b56ce15255cfb5c92f3f6e2f34c0f8b2ef41f593 100644 --- a/drivers/iio/adc/lpc32xx_adc.c +++ b/drivers/iio/adc/lpc32xx_adc.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -196,7 +197,6 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) init_completion(&st->completion); iodev->name = LPC32XXAD_NAME; - iodev->dev.parent = &pdev->dev; iodev->info = &lpc32xx_adc_iio_info; iodev->modes = INDIO_DIRECT_MODE; iodev->num_channels = ARRAY_SIZE(lpc32xx_adc_iio_channels); @@ -210,19 +210,17 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF static const struct of_device_id lpc32xx_adc_match[] = { { .compatible = "nxp,lpc3220-adc" }, {}, }; MODULE_DEVICE_TABLE(of, lpc32xx_adc_match); -#endif static struct platform_driver lpc32xx_adc_driver = { .probe = lpc32xx_adc_probe, .driver = { .name = LPC32XXAD_NAME, - .of_match_table = of_match_ptr(lpc32xx_adc_match), + .of_match_table = lpc32xx_adc_match, }, }; diff --git a/drivers/iio/adc/ltc2471.c b/drivers/iio/adc/ltc2471.c index 55fab612843ae632058fadc0bc7f766ac901f7a3..0e0fe881a8e69cff0a665e9f33e28a97d8e3e852 100644 --- a/drivers/iio/adc/ltc2471.c +++ b/drivers/iio/adc/ltc2471.c @@ -116,7 +116,6 @@ static int ltc2471_i2c_probe(struct i2c_client *client, data = iio_priv(indio_dev); data->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; indio_dev->info = <c2471_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ltc2485.c b/drivers/iio/adc/ltc2485.c index c418466d51fde0904f96803743c9249cd58b42fe..37c762f8218c98fdbbaa988d50089195467fbb0f 100644 --- a/drivers/iio/adc/ltc2485.c +++ b/drivers/iio/adc/ltc2485.c @@ -108,7 +108,6 @@ static int ltc2485_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; indio_dev->info = <c2485_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ltc2496.c b/drivers/iio/adc/ltc2496.c index 88a30156a849bcc867607d7ceedb7e2df6d61389..dd956a7c216e133a76d9aa9ce1215bca1b5c4301 100644 --- a/drivers/iio/adc/ltc2496.c +++ b/drivers/iio/adc/ltc2496.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "ltc2497.h" @@ -96,7 +96,7 @@ MODULE_DEVICE_TABLE(of, ltc2496_of_match); static struct spi_driver ltc2496_driver = { .driver = { .name = "ltc2496", - .of_match_table = of_match_ptr(ltc2496_of_match), + .of_match_table = ltc2496_of_match, }, .probe = ltc2496_probe, .remove = ltc2496_remove, diff --git a/drivers/iio/adc/ltc2497-core.c b/drivers/iio/adc/ltc2497-core.c index f5f7039caacc595d8ff3df1ff5665083781f296e..9b8fd9c323643a4b2e2377e43ee95aebcb7a0f25 100644 --- a/drivers/iio/adc/ltc2497-core.c +++ b/drivers/iio/adc/ltc2497-core.c @@ -169,7 +169,6 @@ int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev) struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); int ret; - indio_dev->dev.parent = dev; indio_dev->name = dev_name(dev); indio_dev->info = <c2497core_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c index 5db63d7c6bc572455d50a2346bee2079b83b189b..1adddf5a88a94b0a2ae4284e1cf4033ce11fdc2c 100644 --- a/drivers/iio/adc/ltc2497.c +++ b/drivers/iio/adc/ltc2497.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include "ltc2497.h" @@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(of, ltc2497_of_match); static struct i2c_driver ltc2497_driver = { .driver = { .name = "ltc2497", - .of_match_table = of_match_ptr(ltc2497_of_match), + .of_match_table = ltc2497_of_match, }, .probe = ltc2497_probe, .remove = ltc2497_remove, diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index 02834ca3e1cede38c527e4c11dc64d0740c29ad6..ca1dff3924ff9c8d93802297f299c280a38d922c 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -79,7 +80,6 @@ static const struct spi_device_id max1027_id[] = { }; MODULE_DEVICE_TABLE(spi, max1027_id); -#ifdef CONFIG_OF static const struct of_device_id max1027_adc_dt_ids[] = { { .compatible = "maxim,max1027" }, { .compatible = "maxim,max1029" }, @@ -90,7 +90,6 @@ static const struct of_device_id max1027_adc_dt_ids[] = { {}, }; MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids); -#endif #define MAX1027_V_CHAN(index, depth) \ { \ @@ -440,8 +439,6 @@ static int max1027_probe(struct spi_device *spi) mutex_init(&st->lock); indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->info = &max1027_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->info->channels; @@ -520,7 +517,7 @@ static int max1027_probe(struct spi_device *spi) static struct spi_driver max1027_driver = { .driver = { .name = "max1027", - .of_match_table = of_match_ptr(max1027_adc_dt_ids), + .of_match_table = max1027_adc_dt_ids, }, .probe = max1027_probe, .id_table = max1027_id, diff --git a/drivers/iio/adc/max11100.c b/drivers/iio/adc/max11100.c index 3440539cfdba7323952bed1ba89dace2ff7b2d18..6cf21758ca66cc13865b34995d7821c3fe2c99a5 100644 --- a/drivers/iio/adc/max11100.c +++ b/drivers/iio/adc/max11100.c @@ -8,6 +8,7 @@ */ #include #include +#include #include #include #include @@ -37,7 +38,7 @@ struct max11100_state { u8 buffer[3] ____cacheline_aligned; }; -static struct iio_chan_spec max11100_channels[] = { +static const struct iio_chan_spec max11100_channels[] = { { /* [0] */ .type = IIO_VOLTAGE, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | @@ -115,8 +116,6 @@ static int max11100_probe(struct spi_device *spi) state = iio_priv(indio_dev); state->spi = spi; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = "max11100"; indio_dev->info = &max11100_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -163,7 +162,7 @@ MODULE_DEVICE_TABLE(of, max11100_ids); static struct spi_driver max11100_driver = { .driver = { .name = "max11100", - .of_match_table = of_match_ptr(max11100_ids), + .of_match_table = max11100_ids, }, .probe = max11100_probe, .remove = max11100_remove, diff --git a/drivers/iio/adc/max1118.c b/drivers/iio/adc/max1118.c index 0c5d7aaf68262a59f535e0f6cdb8cd27e141f413..01b20e420ac4563719ab3ab623611f7f33a5aa85 100644 --- a/drivers/iio/adc/max1118.c +++ b/drivers/iio/adc/max1118.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -225,7 +226,6 @@ static int max1118_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; indio_dev->info = &max1118_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = max1118_channels; @@ -281,8 +281,6 @@ static const struct spi_device_id max1118_id[] = { }; MODULE_DEVICE_TABLE(spi, max1118_id); -#ifdef CONFIG_OF - static const struct of_device_id max1118_dt_ids[] = { { .compatible = "maxim,max1117" }, { .compatible = "maxim,max1118" }, @@ -291,12 +289,10 @@ static const struct of_device_id max1118_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, max1118_dt_ids); -#endif - static struct spi_driver max1118_spi_driver = { .driver = { .name = "max1118", - .of_match_table = of_match_ptr(max1118_dt_ids), + .of_match_table = max1118_dt_ids, }, .probe = max1118_probe, .remove = max1118_remove, diff --git a/drivers/iio/adc/max1241.c b/drivers/iio/adc/max1241.c index 541939c7abcaef2f118113b2415ea8bf924c0bcf..0cbbb3c56d08a7de63dbc11fd1023c3f7f617a25 100644 --- a/drivers/iio/adc/max1241.c +++ b/drivers/iio/adc/max1241.c @@ -192,7 +192,6 @@ static int max1241_probe(struct spi_device *spi) dev_dbg(dev, "no shutdown pin passed, low-power mode disabled"); indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = dev; indio_dev->info = &max1241_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = max1241_channels; diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index 9d92017c79b2de93409286bc2479d26e23788eb4..f2b576c69949e0344c8e5d47138ba2ee548eb8dd 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -22,8 +22,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -150,7 +150,7 @@ struct max1363_chip_info { * @current_mode: the scan mode of this chip * @requestedmask: a valid requested set of channels * @reg: supply regulator - * @lock lock to ensure state is consistent + * @lock: lock to ensure state is consistent * @monitor_on: whether monitor mode is enabled * @monitor_speed: parameter corresponding to device monitor speed setting * @mask_high: bitmask for enabled high thresholds @@ -1529,8 +1529,6 @@ done: return IRQ_HANDLED; } -#ifdef CONFIG_OF - #define MAX1363_COMPATIBLE(of_compatible, cfg) { \ .compatible = of_compatible, \ .data = &max1363_chip_info_tbl[cfg], \ @@ -1578,7 +1576,6 @@ static const struct of_device_id max1363_of_match[] = { { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, max1363_of_match); -#endif static int max1363_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -1593,7 +1590,6 @@ static int max1363_probe(struct i2c_client *client, if (!indio_dev) return -ENOMEM; - indio_dev->dev.of_node = client->dev.of_node; ret = iio_map_array_register(indio_dev, client->dev.platform_data); if (ret < 0) return ret; @@ -1614,7 +1610,7 @@ static int max1363_probe(struct i2c_client *client, /* this is only used for device removal purposes */ i2c_set_clientdata(client, indio_dev); - st->chip_info = of_device_get_match_data(&client->dev); + st->chip_info = device_get_match_data(&client->dev); if (!st->chip_info) st->chip_info = &max1363_chip_info_tbl[id->driver_data]; st->client = client; @@ -1652,9 +1648,6 @@ static int max1363_probe(struct i2c_client *client, if (ret) goto error_disable_reg; - /* Establish that the iio_dev is a child of the i2c device */ - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->name = id->name; indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; @@ -1760,7 +1753,7 @@ MODULE_DEVICE_TABLE(i2c, max1363_id); static struct i2c_driver max1363_driver = { .driver = { .name = "max1363", - .of_match_table = of_match_ptr(max1363_of_match), + .of_match_table = max1363_of_match, }, .probe = max1363_probe, .remove = max1363_remove, diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c index 04d5ff7d2c8ecf217b17c06eaa5883285681b0fb..052ab23f10b20939218179716895cda33d5fd3b5 100644 --- a/drivers/iio/adc/max9611.c +++ b/drivers/iio/adc/max9611.c @@ -110,7 +110,7 @@ enum max9611_conf_ids { CONF_TEMP, }; -/** +/* * max9611_mux_conf - associate ADC mux configuration with register address * where data shall be read from */ @@ -133,7 +133,7 @@ enum max9611_csa_gain_params { CSA_GAIN_OFFS_RAW, }; -/** +/* * max9611_csa_gain_conf - associate gain multiplier with LSB and * offset values. * @@ -545,8 +545,6 @@ static int max9611_probe(struct i2c_client *client, if (ret) return ret; - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->name = of_id->data; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &indio_info; diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index 2c0eb5de110cac89e6a0f969f96aaf4ff9b86a59..8d1cff28cae0ad0af17bab32753021b35e51c4e8 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -27,13 +27,13 @@ * MCP3553 * * Datasheet can be found here: - * http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf mcp3001 - * http://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf mcp3002 - * http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf mcp3004/08 + * https://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf mcp3001 + * https://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf mcp3002 + * https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf mcp3004/08 * http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf mcp3201 * http://ww1.microchip.com/downloads/en/DeviceDoc/21034D.pdf mcp3202 * http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf mcp3204/08 - * http://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf mcp3301 + * https://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf mcp3301 * http://ww1.microchip.com/downloads/en/DeviceDoc/21950D.pdf mcp3550/1/3 */ @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -384,8 +385,6 @@ static int mcp320x_probe(struct spi_device *spi) adc = iio_priv(indio_dev); adc->spi = spi; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &mcp320x_info; @@ -471,7 +470,6 @@ static int mcp320x_remove(struct spi_device *spi) return 0; } -#if defined(CONFIG_OF) static const struct of_device_id mcp320x_dt_ids[] = { /* NOTE: The use of compatibles with no vendor prefix is deprecated. */ { .compatible = "mcp3001" }, @@ -499,7 +497,6 @@ static const struct of_device_id mcp320x_dt_ids[] = { { } }; MODULE_DEVICE_TABLE(of, mcp320x_dt_ids); -#endif static const struct spi_device_id mcp320x_id[] = { { "mcp3001", mcp3001 }, @@ -522,7 +519,7 @@ MODULE_DEVICE_TABLE(spi, mcp320x_id); static struct spi_driver mcp320x_driver = { .driver = { .name = "mcp320x", - .of_match_table = of_match_ptr(mcp320x_dt_ids), + .of_match_table = mcp320x_dt_ids, }, .probe = mcp320x_probe, .remove = mcp320x_remove, diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index d86c0b5d80a3d843089d66fce5980307b40e4270..5f1706d1c3c08a66fdc45f6e2d4f73691f6f99c3 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c @@ -6,8 +6,8 @@ * Author: Angelo Compagnucci * * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf - * http://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf - * http://ww1.microchip.com/downloads/en/DeviceDoc/22072b.pdf + * https://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf + * https://ww1.microchip.com/downloads/en/DeviceDoc/22072b.pdf * * This driver exports the value of analog input voltage to sysfs, the * voltage unit is nV. @@ -16,9 +16,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -347,8 +347,6 @@ static int mcp3422_probe(struct i2c_client *client, mutex_init(&adc->lock); - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &mcp3422_info; @@ -404,18 +402,16 @@ static const struct i2c_device_id mcp3422_id[] = { }; MODULE_DEVICE_TABLE(i2c, mcp3422_id); -#ifdef CONFIG_OF static const struct of_device_id mcp3422_of_match[] = { { .compatible = "mcp3422" }, { } }; MODULE_DEVICE_TABLE(of, mcp3422_of_match); -#endif static struct i2c_driver mcp3422_driver = { .driver = { .name = "mcp3422", - .of_match_table = of_match_ptr(mcp3422_of_match), + .of_match_table = mcp3422_of_match, }, .probe = mcp3422_probe, .id_table = mcp3422_id, diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c index dd52f08ec82e2dc14e6febdd2cb1fb03f08f42ec..e573da5397bb35956b19269d6aa4d9c63fe1ff39 100644 --- a/drivers/iio/adc/mcp3911.c +++ b/drivers/iio/adc/mcp3911.c @@ -293,8 +293,6 @@ static int mcp3911_probe(struct spi_device *spi) if (ret) goto clk_disable; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &mcp3911_info; diff --git a/drivers/iio/adc/men_z188_adc.c b/drivers/iio/adc/men_z188_adc.c index 196c8226381e6f1ff22a30691c477b560f74db9e..42ea8bc7e78051c16bc8f1dcd7546393c99153d5 100644 --- a/drivers/iio/adc/men_z188_adc.c +++ b/drivers/iio/adc/men_z188_adc.c @@ -110,7 +110,6 @@ static int men_z188_probe(struct mcb_device *dev, adc = iio_priv(indio_dev); indio_dev->name = "z188-adc"; - indio_dev->dev.parent = &dev->dev; indio_dev->info = &z188_adc_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = z188_adc_iio_channels; diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 22a470db9ef82f59c9b01a74a9461d22628b0deb..93c2252c0b89017f9d39bbd9f4faf6fbb526baf0 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -1208,8 +1208,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev) priv->param = match_data->param; indio_dev->name = match_data->name; - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &meson_sar_adc_iio_info; diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index a4776d924f3a0aa36c363e526289051548cdc46c..ac415cb089cdd080695d77edc5ba1898961e6a89 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -245,7 +245,6 @@ static int mt6577_auxadc_probe(struct platform_device *pdev) return -ENOMEM; adc_dev = iio_priv(indio_dev); - indio_dev->dev.parent = &pdev->dev; indio_dev->name = dev_name(&pdev->dev); indio_dev->info = &mt6577_auxadc_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c index 9d2f74c2489a873ae0a5baf3c44423d7214d9806..30e29f44ebd2ee6bf3ac8bc950a8e043f44ae214 100644 --- a/drivers/iio/adc/mxs-lradc-adc.c +++ b/drivers/iio/adc/mxs-lradc-adc.c @@ -568,8 +568,6 @@ static bool mxs_lradc_adc_validate_scan_mask(struct iio_dev *iio, static const struct iio_buffer_setup_ops mxs_lradc_adc_buffer_ops = { .preenable = &mxs_lradc_adc_buffer_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, .postdisable = &mxs_lradc_adc_buffer_postdisable, .validate_scan_mask = &mxs_lradc_adc_validate_scan_mask, }; @@ -722,7 +720,6 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, iio); iio->name = pdev->name; - iio->dev.parent = dev; iio->dev.of_node = dev->parent->of_node; iio->info = &mxs_lradc_adc_iio_info; iio->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c index 572579139fbaaddba9885ac1c3b92925a1f8dc35..07c85434b56801d20afed2114e652d6f6e7ab6c1 100644 --- a/drivers/iio/adc/nau7802.c +++ b/drivers/iio/adc/nau7802.c @@ -430,8 +430,6 @@ static int nau7802_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &nau7802_info; diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c index 83bad2d5575d4a37bf9df8e85872719818b63101..d9d105920001e9747736a4a85b42f7b1273f7da5 100644 --- a/drivers/iio/adc/npcm_adc.c +++ b/drivers/iio/adc/npcm_adc.c @@ -261,7 +261,6 @@ static int npcm_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &npcm_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = npcm_adc_iio_channels; diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c index 46e595eb889face6f911057a19f30cccb6c8d813..1ca6570be66a12c2cbcf9ff767da53f6400b7817 100644 --- a/drivers/iio/adc/palmas_gpadc.c +++ b/drivers/iio/adc/palmas_gpadc.c @@ -76,7 +76,7 @@ static struct palmas_gpadc_info palmas_gpadc_info[] = { PALMAS_ADC_INFO(IN15, 0, 0, 0, 0, INVALID, INVALID, true), }; -/** +/* * struct palmas_gpadc - the palmas_gpadc structure * @ch0_current: channel 0 current source setting * 0: 0 uA @@ -94,7 +94,6 @@ static struct palmas_gpadc_info palmas_gpadc_info[] = { * This is the palmas_gpadc structure to store run-time information * and pointers for this driver instance. */ - struct palmas_gpadc { struct device *dev; struct palmas *palmas; @@ -593,7 +592,6 @@ static int palmas_gpadc_probe(struct platform_device *pdev) adc->extended_delay = gpadc_pdata->extended_delay; indio_dev->name = MOD_NAME; - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &palmas_gpadc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = palmas_gpadc_iio_channel; diff --git a/drivers/iio/adc/qcom-pm8xxx-xoadc.c b/drivers/iio/adc/qcom-pm8xxx-xoadc.c index c599ffa45a04c3e69915071a01074c68a8b6eea6..7e108da7d255f97b2fb89b87eaa8f3e16e93effc 100644 --- a/drivers/iio/adc/qcom-pm8xxx-xoadc.c +++ b/drivers/iio/adc/qcom-pm8xxx-xoadc.c @@ -120,7 +120,7 @@ #define ADC_ARB_USRP_DATA0 0x19D #define ADC_ARB_USRP_DATA1 0x19C -/** +/* * Physical channels which MUST exist on all PM variants in order to provide * proper reference points for calibration. * @@ -388,6 +388,7 @@ struct pm8xxx_chan_info { * struct pm8xxx_xoadc - state container for the XOADC * @dev: pointer to device * @map: regmap to access registers + * @variant: XOADC variant characteristics * @vref: reference voltage regulator * characteristics of the channels, and sensible default settings * @nchans: number of channels, configured by the device tree @@ -933,8 +934,6 @@ static int pm8xxx_xoadc_probe(struct platform_device *pdev) goto out_disable_vref; } - indio_dev->dev.parent = dev; - indio_dev->dev.of_node = np; indio_dev->name = variant->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &pm8xxx_xoadc_info; diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c index 21fdcde77883f8dd5b4fadf6b7a8e6794c9a9413..b4b73c9920b4043296d56b885afd30d0f3570584 100644 --- a/drivers/iio/adc/qcom-spmi-adc5.c +++ b/drivers/iio/adc/qcom-spmi-adc5.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved. */ #include @@ -23,6 +23,7 @@ #define ADC5_USR_REVISION1 0x0 #define ADC5_USR_STATUS1 0x8 +#define ADC5_USR_STATUS1_CONV_FAULT BIT(7) #define ADC5_USR_STATUS1_REQ_STS BIT(1) #define ADC5_USR_STATUS1_EOC BIT(0) #define ADC5_USR_STATUS1_REQ_STS_EOC_MASK 0x3 @@ -65,6 +66,9 @@ #define ADC5_USR_IBAT_DATA1 0x53 +#define ADC_CHANNEL_OFFSET 0x8 +#define ADC_CHANNEL_MASK GENMASK(7, 0) + /* * Conversion time varies based on the decimation, clock rate, fast average * samples and measurements queued across different VADC peripherals. @@ -79,6 +83,11 @@ #define ADC5_HW_SETTLE_DIFF_MINOR 3 #define ADC5_HW_SETTLE_DIFF_MAJOR 5 +/* For PMIC7 */ +#define ADC_APP_SID 0x40 +#define ADC_APP_SID_MASK GENMASK(3, 0) +#define ADC7_CONV_TIMEOUT msecs_to_jiffies(10) + enum adc5_cal_method { ADC5_NO_CAL = 0, ADC5_RATIOMETRIC_CAL, @@ -96,6 +105,7 @@ enum adc5_cal_val { * @cal_method: calibration method. * @cal_val: calibration value * @decimation: sampling rate supported for the channel. + * @sid: slave id of PMIC owning the channel, for PMIC7. * @prescale: channel scaling performed on the input signal. * @hw_settle_time: the time between AMUX being configured and the * start of conversion. @@ -110,6 +120,7 @@ struct adc5_channel_prop { enum adc5_cal_method cal_method; enum adc5_cal_val cal_val; unsigned int decimation; + unsigned int sid; unsigned int prescale; unsigned int hw_settle_time; unsigned int avg_samples; @@ -165,6 +176,11 @@ static int adc5_write(struct adc5_chip *adc, u16 offset, u8 *data, int len) return regmap_bulk_write(adc->regmap, adc->base + offset, data, len); } +static int adc5_masked_write(struct adc5_chip *adc, u16 offset, u8 mask, u8 val) +{ + return regmap_update_bits(adc->regmap, adc->base + offset, mask, val); +} + static int adc5_prescaling_from_dt(u32 num, u32 den) { unsigned int pre; @@ -230,11 +246,11 @@ static int adc5_read_voltage_data(struct adc5_chip *adc, u16 *data) *data = (rslt_msb << 8) | rslt_lsb; if (*data == ADC5_USR_DATA_CHECK) { - pr_err("Invalid data:0x%x\n", *data); + dev_err(adc->dev, "Invalid data:0x%x\n", *data); return -EINVAL; } - pr_debug("voltage raw code:0x%x\n", *data); + dev_dbg(adc->dev, "voltage raw code:0x%x\n", *data); return 0; } @@ -285,7 +301,7 @@ static int adc5_configure(struct adc5_chip *adc, /* Read registers 0x42 through 0x46 */ ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf)); - if (ret < 0) + if (ret) return ret; /* Digital param selection */ @@ -314,6 +330,47 @@ static int adc5_configure(struct adc5_chip *adc, return adc5_write(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf)); } +static int adc7_configure(struct adc5_chip *adc, + struct adc5_channel_prop *prop) +{ + int ret; + u8 conv_req = 0, buf[4]; + + ret = adc5_masked_write(adc, ADC_APP_SID, ADC_APP_SID_MASK, prop->sid); + if (ret) + return ret; + + ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf)); + if (ret) + return ret; + + /* Digital param selection */ + adc5_update_dig_param(adc, prop, &buf[0]); + + /* Update fast average sample value */ + buf[1] &= ~ADC5_USR_FAST_AVG_CTL_SAMPLES_MASK; + buf[1] |= prop->avg_samples; + + /* Select ADC channel */ + buf[2] = prop->channel; + + /* Select HW settle delay for channel */ + buf[3] &= ~ADC5_USR_HW_SETTLE_DELAY_MASK; + buf[3] |= prop->hw_settle_time; + + /* Select CONV request */ + conv_req = ADC5_USR_CONV_REQ_REQ; + + if (!adc->poll_eoc) + reinit_completion(&adc->complete); + + ret = adc5_write(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf)); + if (ret) + return ret; + + return adc5_write(adc, ADC5_USR_CONV_REQ, &conv_req, 1); +} + static int adc5_do_conversion(struct adc5_chip *adc, struct adc5_channel_prop *prop, struct iio_chan_spec const *chan, @@ -325,24 +382,24 @@ static int adc5_do_conversion(struct adc5_chip *adc, ret = adc5_configure(adc, prop); if (ret) { - pr_err("ADC configure failed with %d\n", ret); + dev_err(adc->dev, "ADC configure failed with %d\n", ret); goto unlock; } if (adc->poll_eoc) { ret = adc5_poll_wait_eoc(adc); - if (ret < 0) { - pr_err("EOC bit not set\n"); + if (ret) { + dev_err(adc->dev, "EOC bit not set\n"); goto unlock; } } else { ret = wait_for_completion_timeout(&adc->complete, ADC5_CONV_TIMEOUT); if (!ret) { - pr_debug("Did not get completion timeout.\n"); + dev_dbg(adc->dev, "Did not get completion timeout.\n"); ret = adc5_poll_wait_eoc(adc); - if (ret < 0) { - pr_err("EOC bit not set\n"); + if (ret) { + dev_err(adc->dev, "EOC bit not set\n"); goto unlock; } } @@ -355,6 +412,48 @@ unlock: return ret; } +static int adc7_do_conversion(struct adc5_chip *adc, + struct adc5_channel_prop *prop, + struct iio_chan_spec const *chan, + u16 *data_volt, u16 *data_cur) +{ + int ret; + u8 status; + + mutex_lock(&adc->lock); + + ret = adc7_configure(adc, prop); + if (ret) { + dev_err(adc->dev, "ADC configure failed with %d\n", ret); + goto unlock; + } + + /* No support for polling mode at present */ + wait_for_completion_timeout(&adc->complete, ADC7_CONV_TIMEOUT); + + ret = adc5_read(adc, ADC5_USR_STATUS1, &status, 1); + if (ret) + goto unlock; + + if (status & ADC5_USR_STATUS1_CONV_FAULT) { + dev_err(adc->dev, "Unexpected conversion fault\n"); + ret = -EIO; + goto unlock; + } + + ret = adc5_read_voltage_data(adc, data_volt); + +unlock: + mutex_unlock(&adc->lock); + + return ret; +} + +typedef int (*adc_do_conversion)(struct adc5_chip *adc, + struct adc5_channel_prop *prop, + struct iio_chan_spec const *chan, + u16 *data_volt, u16 *data_cur); + static irqreturn_t adc5_isr(int irq, void *dev_id) { struct adc5_chip *adc = dev_id; @@ -377,9 +476,25 @@ static int adc5_of_xlate(struct iio_dev *indio_dev, return -EINVAL; } -static int adc5_read_raw(struct iio_dev *indio_dev, +static int adc7_of_xlate(struct iio_dev *indio_dev, + const struct of_phandle_args *iiospec) +{ + struct adc5_chip *adc = iio_priv(indio_dev); + int i, v_channel; + + for (i = 0; i < adc->nchannels; i++) { + v_channel = (adc->chan_props[i].sid << ADC_CHANNEL_OFFSET) | + adc->chan_props[i].channel; + if (v_channel == iiospec->args[0]) + return i; + } + + return -EINVAL; +} + +static int adc_read_raw_common(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, - long mask) + long mask, adc_do_conversion do_conv) { struct adc5_chip *adc = iio_priv(indio_dev); struct adc5_channel_prop *prop; @@ -390,8 +505,8 @@ static int adc5_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_PROCESSED: - ret = adc5_do_conversion(adc, prop, chan, - &adc_code_volt, &adc_code_cur); + ret = do_conv(adc, prop, chan, + &adc_code_volt, &adc_code_cur); if (ret) return ret; @@ -406,8 +521,22 @@ static int adc5_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } +} - return 0; +static int adc5_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, + long mask) +{ + return adc_read_raw_common(indio_dev, chan, val, val2, + mask, adc5_do_conversion); +} + +static int adc7_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, + long mask) +{ + return adc_read_raw_common(indio_dev, chan, val, val2, + mask, adc7_do_conversion); } static const struct iio_info adc5_info = { @@ -415,6 +544,11 @@ static const struct iio_info adc5_info = { .of_xlate = adc5_of_xlate, }; +static const struct iio_info adc7_info = { + .read_raw = adc7_read_raw, + .of_xlate = adc7_of_xlate, +}; + struct adc5_channels { const char *datasheet_name; unsigned int prescale_index; @@ -477,6 +611,39 @@ static const struct adc5_channels adc5_chans_pmic[ADC5_MAX_CHANNEL] = { SCALE_HW_CALIB_PM5_SMB_TEMP) }; +static const struct adc5_channels adc7_chans_pmic[ADC5_MAX_CHANNEL] = { + [ADC7_REF_GND] = ADC5_CHAN_VOLT("ref_gnd", 0, + SCALE_HW_CALIB_DEFAULT) + [ADC7_1P25VREF] = ADC5_CHAN_VOLT("vref_1p25", 0, + SCALE_HW_CALIB_DEFAULT) + [ADC7_VPH_PWR] = ADC5_CHAN_VOLT("vph_pwr", 1, + SCALE_HW_CALIB_DEFAULT) + [ADC7_VBAT_SNS] = ADC5_CHAN_VOLT("vbat_sns", 3, + SCALE_HW_CALIB_DEFAULT) + [ADC7_DIE_TEMP] = ADC5_CHAN_TEMP("die_temp", 0, + SCALE_HW_CALIB_PMIC_THERM_PM7) + [ADC7_AMUX_THM1_100K_PU] = ADC5_CHAN_TEMP("amux_thm1_pu2", 0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC7_AMUX_THM2_100K_PU] = ADC5_CHAN_TEMP("amux_thm2_pu2", 0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC7_AMUX_THM3_100K_PU] = ADC5_CHAN_TEMP("amux_thm3_pu2", 0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC7_AMUX_THM4_100K_PU] = ADC5_CHAN_TEMP("amux_thm4_pu2", 0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC7_AMUX_THM5_100K_PU] = ADC5_CHAN_TEMP("amux_thm5_pu2", 0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC7_AMUX_THM6_100K_PU] = ADC5_CHAN_TEMP("amux_thm6_pu2", 0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC7_GPIO1_100K_PU] = ADC5_CHAN_TEMP("gpio1_pu2", 0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC7_GPIO2_100K_PU] = ADC5_CHAN_TEMP("gpio2_pu2", 0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC7_GPIO3_100K_PU] = ADC5_CHAN_TEMP("gpio3_pu2", 0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC7_GPIO4_100K_PU] = ADC5_CHAN_TEMP("gpio4_pu2", 0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) +}; + static const struct adc5_channels adc5_chans_rev2[ADC5_MAX_CHANNEL] = { [ADC5_REF_GND] = ADC5_CHAN_VOLT("ref_gnd", 0, SCALE_HW_CALIB_DEFAULT) @@ -511,6 +678,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc, { const char *name = node->name, *channel_name; u32 chan, value, varr[2]; + u32 sid = 0; int ret; struct device *dev = adc->dev; @@ -520,6 +688,15 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc, return ret; } + /* Value read from "reg" is virtual channel number */ + + /* virtual channel number = sid << 8 | channel number */ + + if (adc->data->info == &adc7_info) { + sid = chan >> ADC_CHANNEL_OFFSET; + chan = chan & ADC_CHANNEL_MASK; + } + if (chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA || !data->adc_chans[chan].datasheet_name) { dev_err(dev, "%s invalid channel number %d\n", name, chan); @@ -528,11 +705,12 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc, /* the channel has DT description */ prop->channel = chan; + prop->sid = sid; channel_name = of_get_property(node, "label", NULL) ? : node->name; if (!channel_name) { - pr_err("Invalid channel name\n"); + dev_err(dev, "Invalid channel name\n"); return -EINVAL; } prop->datasheet_name = channel_name; @@ -570,16 +748,17 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc, ret = adc5_read(adc, ADC5_USR_REVISION1, dig_version, sizeof(dig_version)); - if (ret < 0) { + if (ret) { dev_err(dev, "Invalid dig version read %d\n", ret); return ret; } - pr_debug("dig_ver:minor:%d, major:%d\n", dig_version[0], + dev_dbg(dev, "dig_ver:minor:%d, major:%d\n", dig_version[0], dig_version[1]); /* Digital controller >= 5.3 have hw_settle_2 option */ - if (dig_version[0] >= ADC5_HW_SETTLE_DIFF_MINOR && - dig_version[1] >= ADC5_HW_SETTLE_DIFF_MAJOR) + if ((dig_version[0] >= ADC5_HW_SETTLE_DIFF_MINOR && + dig_version[1] >= ADC5_HW_SETTLE_DIFF_MAJOR) || + adc->data->info == &adc7_info) ret = adc5_hw_settle_time_from_dt(value, data->hw_settle_2); else @@ -629,6 +808,7 @@ static const struct adc5_data adc5_data_pmic = { .full_scale_code_volt = 0x70e4, .full_scale_code_cur = 0x2710, .adc_chans = adc5_chans_pmic, + .info = &adc5_info, .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX]) {250, 420, 840}, .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX]) @@ -639,10 +819,23 @@ static const struct adc5_data adc5_data_pmic = { 1, 2, 4, 8, 16, 32, 64, 128}, }; +static const struct adc5_data adc7_data_pmic = { + .full_scale_code_volt = 0x70e4, + .adc_chans = adc7_chans_pmic, + .info = &adc7_info, + .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX]) + {85, 340, 1360}, + .hw_settle_2 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX]) + {15, 100, 200, 300, 400, 500, 600, 700, + 1000, 2000, 4000, 8000, 16000, 32000, + 64000, 128000}, +}; + static const struct adc5_data adc5_data_pmic_rev2 = { .full_scale_code_volt = 0x4000, .full_scale_code_cur = 0x1800, .adc_chans = adc5_chans_rev2, + .info = &adc5_info, .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX]) {256, 512, 1024}, .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX]) @@ -658,6 +851,10 @@ static const struct of_device_id adc5_match_table[] = { .compatible = "qcom,spmi-adc5", .data = &adc5_data_pmic, }, + { + .compatible = "qcom,spmi-adc7", + .data = &adc7_data_pmic, + }, { .compatible = "qcom,spmi-adc-rev2", .data = &adc5_data_pmic_rev2, @@ -752,12 +949,13 @@ static int adc5_probe(struct platform_device *pdev) adc->regmap = regmap; adc->dev = dev; adc->base = reg; + init_completion(&adc->complete); mutex_init(&adc->lock); ret = adc5_get_dt_data(adc, node); if (ret) { - pr_err("adc get dt data failed\n"); + dev_err(dev, "adc get dt data failed\n"); return ret; } @@ -773,11 +971,9 @@ static int adc5_probe(struct platform_device *pdev) return ret; } - indio_dev->dev.parent = dev; - indio_dev->dev.of_node = node; indio_dev->name = pdev->name; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->info = &adc5_info; + indio_dev->info = adc->data->info; indio_dev->channels = adc->iio_chans; indio_dev->num_channels = adc->nchannels; diff --git a/drivers/iio/adc/qcom-spmi-iadc.c b/drivers/iio/adc/qcom-spmi-iadc.c index 46858eddf1c35ef49c80fd1d07e180b9d5344455..acbda6636dc58cb7b73501ff639aacfcdace98ce 100644 --- a/drivers/iio/adc/qcom-spmi-iadc.c +++ b/drivers/iio/adc/qcom-spmi-iadc.c @@ -553,8 +553,6 @@ static int iadc_probe(struct platform_device *pdev) return ret; } - indio_dev->dev.parent = dev; - indio_dev->dev.of_node = node; indio_dev->name = pdev->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &iadc_info; diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c index 203ad59da3364c6a818de2c765aaf3853aa0fa86..b0388f8a69f42e842754ab243570bb6d94dc352e 100644 --- a/drivers/iio/adc/qcom-spmi-vadc.c +++ b/drivers/iio/adc/qcom-spmi-vadc.c @@ -907,8 +907,6 @@ static int vadc_probe(struct platform_device *pdev) if (ret) return ret; - indio_dev->dev.parent = dev; - indio_dev->dev.of_node = node; indio_dev->name = pdev->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &vadc_info; diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c index 2bb78d1c4daa63b8d52fd5697d701de1771f2296..5113aaa6ba6713e2855c18c2b0dd6a63cdf2923a 100644 --- a/drivers/iio/adc/qcom-vadc-common.c +++ b/drivers/iio/adc/qcom-vadc-common.c @@ -89,6 +89,195 @@ static const struct vadc_map_pt adcmap_100k_104ef_104fb_1875_vref[] = { { 46, 125000 }, }; +static const struct vadc_map_pt adcmap7_die_temp[] = { + { 433700, 1967}, + { 473100, 1964}, + { 512400, 1957}, + { 551500, 1949}, + { 590500, 1940}, + { 629300, 1930}, + { 667900, 1921}, + { 706400, 1910}, + { 744600, 1896}, + { 782500, 1878}, + { 820100, 1859}, + { 857300, 0}, +}; + +/* + * Resistance to temperature table for 100k pull up for NTCG104EF104. + */ +static const struct vadc_map_pt adcmap7_100k[] = { + { 4250657, -40960 }, + { 3962085, -39936 }, + { 3694875, -38912 }, + { 3447322, -37888 }, + { 3217867, -36864 }, + { 3005082, -35840 }, + { 2807660, -34816 }, + { 2624405, -33792 }, + { 2454218, -32768 }, + { 2296094, -31744 }, + { 2149108, -30720 }, + { 2012414, -29696 }, + { 1885232, -28672 }, + { 1766846, -27648 }, + { 1656598, -26624 }, + { 1553884, -25600 }, + { 1458147, -24576 }, + { 1368873, -23552 }, + { 1285590, -22528 }, + { 1207863, -21504 }, + { 1135290, -20480 }, + { 1067501, -19456 }, + { 1004155, -18432 }, + { 944935, -17408 }, + { 889550, -16384 }, + { 837731, -15360 }, + { 789229, -14336 }, + { 743813, -13312 }, + { 701271, -12288 }, + { 661405, -11264 }, + { 624032, -10240 }, + { 588982, -9216 }, + { 556100, -8192 }, + { 525239, -7168 }, + { 496264, -6144 }, + { 469050, -5120 }, + { 443480, -4096 }, + { 419448, -3072 }, + { 396851, -2048 }, + { 375597, -1024 }, + { 355598, 0 }, + { 336775, 1024 }, + { 319052, 2048 }, + { 302359, 3072 }, + { 286630, 4096 }, + { 271806, 5120 }, + { 257829, 6144 }, + { 244646, 7168 }, + { 232209, 8192 }, + { 220471, 9216 }, + { 209390, 10240 }, + { 198926, 11264 }, + { 189040, 12288 }, + { 179698, 13312 }, + { 170868, 14336 }, + { 162519, 15360 }, + { 154622, 16384 }, + { 147150, 17408 }, + { 140079, 18432 }, + { 133385, 19456 }, + { 127046, 20480 }, + { 121042, 21504 }, + { 115352, 22528 }, + { 109960, 23552 }, + { 104848, 24576 }, + { 100000, 25600 }, + { 95402, 26624 }, + { 91038, 27648 }, + { 86897, 28672 }, + { 82965, 29696 }, + { 79232, 30720 }, + { 75686, 31744 }, + { 72316, 32768 }, + { 69114, 33792 }, + { 66070, 34816 }, + { 63176, 35840 }, + { 60423, 36864 }, + { 57804, 37888 }, + { 55312, 38912 }, + { 52940, 39936 }, + { 50681, 40960 }, + { 48531, 41984 }, + { 46482, 43008 }, + { 44530, 44032 }, + { 42670, 45056 }, + { 40897, 46080 }, + { 39207, 47104 }, + { 37595, 48128 }, + { 36057, 49152 }, + { 34590, 50176 }, + { 33190, 51200 }, + { 31853, 52224 }, + { 30577, 53248 }, + { 29358, 54272 }, + { 28194, 55296 }, + { 27082, 56320 }, + { 26020, 57344 }, + { 25004, 58368 }, + { 24033, 59392 }, + { 23104, 60416 }, + { 22216, 61440 }, + { 21367, 62464 }, + { 20554, 63488 }, + { 19776, 64512 }, + { 19031, 65536 }, + { 18318, 66560 }, + { 17636, 67584 }, + { 16982, 68608 }, + { 16355, 69632 }, + { 15755, 70656 }, + { 15180, 71680 }, + { 14628, 72704 }, + { 14099, 73728 }, + { 13592, 74752 }, + { 13106, 75776 }, + { 12640, 76800 }, + { 12192, 77824 }, + { 11762, 78848 }, + { 11350, 79872 }, + { 10954, 80896 }, + { 10574, 81920 }, + { 10209, 82944 }, + { 9858, 83968 }, + { 9521, 84992 }, + { 9197, 86016 }, + { 8886, 87040 }, + { 8587, 88064 }, + { 8299, 89088 }, + { 8023, 90112 }, + { 7757, 91136 }, + { 7501, 92160 }, + { 7254, 93184 }, + { 7017, 94208 }, + { 6789, 95232 }, + { 6570, 96256 }, + { 6358, 97280 }, + { 6155, 98304 }, + { 5959, 99328 }, + { 5770, 100352 }, + { 5588, 101376 }, + { 5412, 102400 }, + { 5243, 103424 }, + { 5080, 104448 }, + { 4923, 105472 }, + { 4771, 106496 }, + { 4625, 107520 }, + { 4484, 108544 }, + { 4348, 109568 }, + { 4217, 110592 }, + { 4090, 111616 }, + { 3968, 112640 }, + { 3850, 113664 }, + { 3736, 114688 }, + { 3626, 115712 }, + { 3519, 116736 }, + { 3417, 117760 }, + { 3317, 118784 }, + { 3221, 119808 }, + { 3129, 120832 }, + { 3039, 121856 }, + { 2952, 122880 }, + { 2868, 123904 }, + { 2787, 124928 }, + { 2709, 125952 }, + { 2633, 126976 }, + { 2560, 128000 }, + { 2489, 129024 }, + { 2420, 130048 } +}; + static int qcom_vadc_scale_hw_calib_volt( const struct vadc_prescale_ratio *prescale, const struct adc5_data *data, @@ -97,6 +286,10 @@ static int qcom_vadc_scale_hw_calib_therm( const struct vadc_prescale_ratio *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec); +static int qcom_vadc7_scale_hw_calib_therm( + const struct vadc_prescale_ratio *prescale, + const struct adc5_data *data, + u16 adc_code, int *result_mdec); static int qcom_vadc_scale_hw_smb_temp( const struct vadc_prescale_ratio *prescale, const struct adc5_data *data, @@ -109,12 +302,20 @@ static int qcom_vadc_scale_hw_calib_die_temp( const struct vadc_prescale_ratio *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec); +static int qcom_vadc7_scale_hw_calib_die_temp( + const struct vadc_prescale_ratio *prescale, + const struct adc5_data *data, + u16 adc_code, int *result_mdec); static struct qcom_adc5_scale_type scale_adc5_fn[] = { [SCALE_HW_CALIB_DEFAULT] = {qcom_vadc_scale_hw_calib_volt}, [SCALE_HW_CALIB_THERM_100K_PULLUP] = {qcom_vadc_scale_hw_calib_therm}, [SCALE_HW_CALIB_XOTHERM] = {qcom_vadc_scale_hw_calib_therm}, + [SCALE_HW_CALIB_THERM_100K_PU_PM7] = { + qcom_vadc7_scale_hw_calib_therm}, [SCALE_HW_CALIB_PMIC_THERM] = {qcom_vadc_scale_hw_calib_die_temp}, + [SCALE_HW_CALIB_PMIC_THERM_PM7] = { + qcom_vadc7_scale_hw_calib_die_temp}, [SCALE_HW_CALIB_PM5_CHG_TEMP] = {qcom_vadc_scale_hw_chg5_temp}, [SCALE_HW_CALIB_PM5_SMB_TEMP] = {qcom_vadc_scale_hw_smb_temp}, }; @@ -291,6 +492,32 @@ static int qcom_vadc_scale_code_voltage_factor(u16 adc_code, return (int) voltage; } +static int qcom_vadc7_scale_hw_calib_therm( + const struct vadc_prescale_ratio *prescale, + const struct adc5_data *data, + u16 adc_code, int *result_mdec) +{ + s64 resistance = adc_code; + int ret, result; + + if (adc_code >= RATIO_MAX_ADC7) + return -EINVAL; + + /* (ADC code * R_PULLUP (100Kohm)) / (full_scale_code - ADC code)*/ + resistance *= R_PU_100K; + resistance = div64_s64(resistance, RATIO_MAX_ADC7 - adc_code); + + ret = qcom_vadc_map_voltage_temp(adcmap7_100k, + ARRAY_SIZE(adcmap7_100k), + resistance, &result); + if (ret) + return ret; + + *result_mdec = result; + + return 0; +} + static int qcom_vadc_scale_hw_calib_volt( const struct vadc_prescale_ratio *prescale, const struct adc5_data *data, @@ -330,6 +557,41 @@ static int qcom_vadc_scale_hw_calib_die_temp( return 0; } +static int qcom_vadc7_scale_hw_calib_die_temp( + const struct vadc_prescale_ratio *prescale, + const struct adc5_data *data, + u16 adc_code, int *result_mdec) +{ + + int voltage, vtemp0, temp, i; + + voltage = qcom_vadc_scale_code_voltage_factor(adc_code, + prescale, data, 1); + + if (adcmap7_die_temp[0].x > voltage) { + *result_mdec = DIE_TEMP_ADC7_SCALE_1; + return 0; + } + + if (adcmap7_die_temp[ARRAY_SIZE(adcmap7_die_temp) - 1].x <= voltage) { + *result_mdec = DIE_TEMP_ADC7_MAX; + return 0; + } + + for (i = 0; i < ARRAY_SIZE(adcmap7_die_temp); i++) + if (adcmap7_die_temp[i].x > voltage) + break; + + vtemp0 = adcmap7_die_temp[i - 1].x; + voltage = voltage - vtemp0; + temp = div64_s64(voltage * DIE_TEMP_ADC7_SCALE_FACTOR, + adcmap7_die_temp[i - 1].y); + temp += DIE_TEMP_ADC7_SCALE_1 + (DIE_TEMP_ADC7_SCALE_2 * (i - 1)); + *result_mdec = temp; + + return 0; +} + static int qcom_vadc_scale_hw_smb_temp( const struct vadc_prescale_ratio *prescale, const struct adc5_data *data, diff --git a/drivers/iio/adc/qcom-vadc-common.h b/drivers/iio/adc/qcom-vadc-common.h index e074902a24cc872bffff2c4874ca0f88fc4c1d0a..17b2fc4d8bf29a22546431895a1c651c9c52bf37 100644 --- a/drivers/iio/adc/qcom-vadc-common.h +++ b/drivers/iio/adc/qcom-vadc-common.h @@ -49,6 +49,14 @@ #define ADC5_FULL_SCALE_CODE 0x70e4 #define ADC5_USR_DATA_CHECK 0x8000 +#define R_PU_100K 100000 +#define RATIO_MAX_ADC7 BIT(14) + +#define DIE_TEMP_ADC7_SCALE_1 -60000 +#define DIE_TEMP_ADC7_SCALE_2 20000 +#define DIE_TEMP_ADC7_SCALE_FACTOR 1000 +#define DIE_TEMP_ADC7_MAX 160000 + /** * struct vadc_map_pt - Map the graph representation for ADC channel * @x: Represent the ADC digitized code. @@ -110,8 +118,12 @@ struct vadc_prescale_ratio { * lookup table. The hardware applies offset/slope to adc code. * SCALE_HW_CALIB_XOTHERM: Returns XO thermistor voltage in millidegC using * 100k pullup. The hardware applies offset/slope to adc code. + * SCALE_HW_CALIB_THERM_100K_PU_PM7: Returns temperature in millidegC using + * lookup table for PMIC7. The hardware applies offset/slope to adc code. * SCALE_HW_CALIB_PMIC_THERM: Returns result in milli degree's Centigrade. * The hardware applies offset/slope to adc code. + * SCALE_HW_CALIB_PMIC_THERM: Returns result in milli degree's Centigrade. + * The hardware applies offset/slope to adc code. This is for PMIC7. * SCALE_HW_CALIB_PM5_CHG_TEMP: Returns result in millidegrees for PMIC5 * charger temperature. * SCALE_HW_CALIB_PM5_SMB_TEMP: Returns result in millidegrees for PMIC5 @@ -126,7 +138,9 @@ enum vadc_scale_fn_type { SCALE_HW_CALIB_DEFAULT, SCALE_HW_CALIB_THERM_100K_PULLUP, SCALE_HW_CALIB_XOTHERM, + SCALE_HW_CALIB_THERM_100K_PU_PM7, SCALE_HW_CALIB_PMIC_THERM, + SCALE_HW_CALIB_PMIC_THERM_PM7, SCALE_HW_CALIB_PM5_CHG_TEMP, SCALE_HW_CALIB_PM5_SMB_TEMP, SCALE_HW_CALIB_INVALID, @@ -136,6 +150,7 @@ struct adc5_data { const u32 full_scale_code_volt; const u32 full_scale_code_cur; const struct adc5_channels *adc_chans; + const struct iio_info *info; unsigned int *decimation; unsigned int *hw_settle_1; unsigned int *hw_settle_2; diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c index 63ce743ee7af528c1bc98976227534698708c461..d2c1419e72a013c3d54c240899f64423a72294bc 100644 --- a/drivers/iio/adc/rcar-gyroadc.c +++ b/drivers/iio/adc/rcar-gyroadc.c @@ -516,8 +516,6 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); indio_dev->name = DRIVER_NAME; - indio_dev->dev.parent = dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &rcar_gyroadc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/rn5t618-adc.c b/drivers/iio/adc/rn5t618-adc.c index f21027e4e26a54ddf1c7a0c68c7a22e845c257bf..7010c4276947ea583b14d3566f731bf2ce0b3e23 100644 --- a/drivers/iio/adc/rn5t618-adc.c +++ b/drivers/iio/adc/rn5t618-adc.c @@ -218,7 +218,6 @@ static int rn5t618_adc_probe(struct platform_device *pdev) init_completion(&adc->conv_completion); iio_dev->name = dev_name(&pdev->dev); - iio_dev->dev.parent = &pdev->dev; iio_dev->info = &rn5t618_adc_iio_info; iio_dev->modes = INDIO_DIRECT_MODE; iio_dev->channels = rn5t618_adc_iio_channels; diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 582ba047c4a67404a71903cfff94af4e90f01b7b..1f3d7d639d378ee49dfc87bb68c736464ed5936a 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -15,7 +15,10 @@ #include #include #include +#include #include +#include +#include #define SARADC_DATA 0x00 @@ -32,9 +35,9 @@ #define SARADC_DLY_PU_SOC_MASK 0x3f #define SARADC_TIMEOUT msecs_to_jiffies(100) +#define SARADC_MAX_CHANNELS 6 struct rockchip_saradc_data { - int num_bits; const struct iio_chan_spec *channels; int num_channels; unsigned long clk_rate; @@ -49,8 +52,37 @@ struct rockchip_saradc { struct reset_control *reset; const struct rockchip_saradc_data *data; u16 last_val; + const struct iio_chan_spec *last_chan; }; +static void rockchip_saradc_power_down(struct rockchip_saradc *info) +{ + /* Clear irq & power down adc */ + writel_relaxed(0, info->regs + SARADC_CTRL); +} + +static int rockchip_saradc_conversion(struct rockchip_saradc *info, + struct iio_chan_spec const *chan) +{ + reinit_completion(&info->completion); + + /* 8 clock periods as delay between power up and start cmd */ + writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC); + + info->last_chan = chan; + + /* Select the channel to be used and trigger conversion */ + writel(SARADC_CTRL_POWER_CTRL + | (chan->channel & SARADC_CTRL_CHN_MASK) + | SARADC_CTRL_IRQ_ENABLE, + info->regs + SARADC_CTRL); + + if (!wait_for_completion_timeout(&info->completion, SARADC_TIMEOUT)) + return -ETIMEDOUT; + + return 0; +} + static int rockchip_saradc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -62,22 +94,11 @@ static int rockchip_saradc_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_RAW: mutex_lock(&indio_dev->mlock); - reinit_completion(&info->completion); - - /* 8 clock periods as delay between power up and start cmd */ - writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC); - - /* Select the channel to be used and trigger conversion */ - writel(SARADC_CTRL_POWER_CTRL - | (chan->channel & SARADC_CTRL_CHN_MASK) - | SARADC_CTRL_IRQ_ENABLE, - info->regs + SARADC_CTRL); - - if (!wait_for_completion_timeout(&info->completion, - SARADC_TIMEOUT)) { - writel_relaxed(0, info->regs + SARADC_CTRL); + ret = rockchip_saradc_conversion(info, chan); + if (ret) { + rockchip_saradc_power_down(info); mutex_unlock(&indio_dev->mlock); - return -ETIMEDOUT; + return ret; } *val = info->last_val; @@ -91,7 +112,7 @@ static int rockchip_saradc_read_raw(struct iio_dev *indio_dev, } *val = ret / 1000; - *val2 = info->data->num_bits; + *val2 = chan->scan_type.realbits; return IIO_VAL_FRACTIONAL_LOG2; default: return -EINVAL; @@ -104,10 +125,9 @@ static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) /* Read value */ info->last_val = readl_relaxed(info->regs + SARADC_DATA); - info->last_val &= GENMASK(info->data->num_bits - 1, 0); + info->last_val &= GENMASK(info->last_chan->scan_type.realbits - 1, 0); - /* Clear irq & power down adc */ - writel_relaxed(0, info->regs + SARADC_CTRL); + rockchip_saradc_power_down(info); complete(&info->completion); @@ -118,51 +138,55 @@ static const struct iio_info rockchip_saradc_iio_info = { .read_raw = rockchip_saradc_read_raw, }; -#define ADC_CHANNEL(_index, _id) { \ +#define SARADC_CHANNEL(_index, _id, _res) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = _index, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .datasheet_name = _id, \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = _res, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ } static const struct iio_chan_spec rockchip_saradc_iio_channels[] = { - ADC_CHANNEL(0, "adc0"), - ADC_CHANNEL(1, "adc1"), - ADC_CHANNEL(2, "adc2"), + SARADC_CHANNEL(0, "adc0", 10), + SARADC_CHANNEL(1, "adc1", 10), + SARADC_CHANNEL(2, "adc2", 10), }; static const struct rockchip_saradc_data saradc_data = { - .num_bits = 10, .channels = rockchip_saradc_iio_channels, .num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels), .clk_rate = 1000000, }; static const struct iio_chan_spec rockchip_rk3066_tsadc_iio_channels[] = { - ADC_CHANNEL(0, "adc0"), - ADC_CHANNEL(1, "adc1"), + SARADC_CHANNEL(0, "adc0", 12), + SARADC_CHANNEL(1, "adc1", 12), }; static const struct rockchip_saradc_data rk3066_tsadc_data = { - .num_bits = 12, .channels = rockchip_rk3066_tsadc_iio_channels, .num_channels = ARRAY_SIZE(rockchip_rk3066_tsadc_iio_channels), .clk_rate = 50000, }; static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = { - ADC_CHANNEL(0, "adc0"), - ADC_CHANNEL(1, "adc1"), - ADC_CHANNEL(2, "adc2"), - ADC_CHANNEL(3, "adc3"), - ADC_CHANNEL(4, "adc4"), - ADC_CHANNEL(5, "adc5"), + SARADC_CHANNEL(0, "adc0", 10), + SARADC_CHANNEL(1, "adc1", 10), + SARADC_CHANNEL(2, "adc2", 10), + SARADC_CHANNEL(3, "adc3", 10), + SARADC_CHANNEL(4, "adc4", 10), + SARADC_CHANNEL(5, "adc5", 10), }; static const struct rockchip_saradc_data rk3399_saradc_data = { - .num_bits = 10, .channels = rockchip_rk3399_saradc_iio_channels, .num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels), .clk_rate = 1000000, @@ -183,7 +207,7 @@ static const struct of_device_id rockchip_saradc_match[] = { }; MODULE_DEVICE_TABLE(of, rockchip_saradc_match); -/** +/* * Reset SARADC Controller. */ static void rockchip_saradc_reset_controller(struct reset_control *reset) @@ -193,6 +217,67 @@ static void rockchip_saradc_reset_controller(struct reset_control *reset) reset_control_deassert(reset); } +static void rockchip_saradc_clk_disable(void *data) +{ + struct rockchip_saradc *info = data; + + clk_disable_unprepare(info->clk); +} + +static void rockchip_saradc_pclk_disable(void *data) +{ + struct rockchip_saradc *info = data; + + clk_disable_unprepare(info->pclk); +} + +static void rockchip_saradc_regulator_disable(void *data) +{ + struct rockchip_saradc *info = data; + + regulator_disable(info->vref); +} + +static irqreturn_t rockchip_saradc_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *i_dev = pf->indio_dev; + struct rockchip_saradc *info = iio_priv(i_dev); + /* + * @values: each channel takes an u16 value + * @timestamp: will be 8-byte aligned automatically + */ + struct { + u16 values[SARADC_MAX_CHANNELS]; + int64_t timestamp; + } data; + int ret; + int i, j = 0; + + mutex_lock(&i_dev->mlock); + + for_each_set_bit(i, i_dev->active_scan_mask, i_dev->masklength) { + const struct iio_chan_spec *chan = &i_dev->channels[i]; + + ret = rockchip_saradc_conversion(info, chan); + if (ret) { + rockchip_saradc_power_down(info); + goto out; + } + + data.values[j] = info->last_val; + j++; + } + + iio_push_to_buffers_with_timestamp(i_dev, &data, iio_get_time_ns(i_dev)); +out: + mutex_unlock(&i_dev->mlock); + + iio_trigger_notify_done(i_dev->trig); + + return IRQ_HANDLED; +} + static int rockchip_saradc_probe(struct platform_device *pdev) { struct rockchip_saradc *info = NULL; @@ -221,6 +306,12 @@ static int rockchip_saradc_probe(struct platform_device *pdev) info->data = match->data; + /* Sanity check for possible later IP variants with more channels */ + if (info->data->num_channels > SARADC_MAX_CHANNELS) { + dev_err(&pdev->dev, "max channels exceeded"); + return -EINVAL; + } + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); info->regs = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(info->regs)) @@ -291,56 +382,55 @@ static int rockchip_saradc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to enable vref regulator\n"); return ret; } + ret = devm_add_action_or_reset(&pdev->dev, + rockchip_saradc_regulator_disable, info); + if (ret) { + dev_err(&pdev->dev, "failed to register devm action, %d\n", + ret); + return ret; + } ret = clk_prepare_enable(info->pclk); if (ret < 0) { dev_err(&pdev->dev, "failed to enable pclk\n"); - goto err_reg_voltage; + return ret; + } + ret = devm_add_action_or_reset(&pdev->dev, + rockchip_saradc_pclk_disable, info); + if (ret) { + dev_err(&pdev->dev, "failed to register devm action, %d\n", + ret); + return ret; } ret = clk_prepare_enable(info->clk); if (ret < 0) { dev_err(&pdev->dev, "failed to enable converter clock\n"); - goto err_pclk; + return ret; + } + ret = devm_add_action_or_reset(&pdev->dev, + rockchip_saradc_clk_disable, info); + if (ret) { + dev_err(&pdev->dev, "failed to register devm action, %d\n", + ret); + return ret; } platform_set_drvdata(pdev, indio_dev); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &rockchip_saradc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = info->data->channels; indio_dev->num_channels = info->data->num_channels; - - ret = iio_device_register(indio_dev); + ret = devm_iio_triggered_buffer_setup(&indio_dev->dev, indio_dev, NULL, + rockchip_saradc_trigger_handler, + NULL); if (ret) - goto err_clk; - - return 0; - -err_clk: - clk_disable_unprepare(info->clk); -err_pclk: - clk_disable_unprepare(info->pclk); -err_reg_voltage: - regulator_disable(info->vref); - return ret; -} - -static int rockchip_saradc_remove(struct platform_device *pdev) -{ - struct iio_dev *indio_dev = platform_get_drvdata(pdev); - struct rockchip_saradc *info = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - clk_disable_unprepare(info->clk); - clk_disable_unprepare(info->pclk); - regulator_disable(info->vref); + return ret; - return 0; + return devm_iio_device_register(&pdev->dev, indio_dev); } #ifdef CONFIG_PM_SLEEP @@ -383,7 +473,6 @@ static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops, static struct platform_driver rockchip_saradc_driver = { .probe = rockchip_saradc_probe, - .remove = rockchip_saradc_remove, .driver = { .name = "rockchip-saradc", .of_match_table = rockchip_saradc_match, diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c index 66b387f9b36d94a48d699b2e9a940dd9eae5f441..aa32a1f385e22fc064f99e2de372306fe26d8836 100644 --- a/drivers/iio/adc/sc27xx_adc.c +++ b/drivers/iio/adc/sc27xx_adc.c @@ -533,7 +533,6 @@ static int sc27xx_adc_probe(struct platform_device *pdev) return ret; } - indio_dev->dev.parent = dev; indio_dev->name = dev_name(dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &sc27xx_info; diff --git a/drivers/iio/adc/sd_adc_modulator.c b/drivers/iio/adc/sd_adc_modulator.c index 560d8c7d9d8625ecc2dc2108882a866e3032bc13..327cc2097f6c7222e3a9fc61fcae43a27501df4a 100644 --- a/drivers/iio/adc/sd_adc_modulator.c +++ b/drivers/iio/adc/sd_adc_modulator.c @@ -9,7 +9,8 @@ #include #include #include -#include +#include +#include static const struct iio_info iio_sd_mod_iio_info; @@ -32,8 +33,6 @@ static int iio_sd_mod_probe(struct platform_device *pdev) if (!iio) return -ENOMEM; - iio->dev.parent = dev; - iio->dev.of_node = dev->of_node; iio->name = dev_name(dev); iio->info = &iio_sd_mod_iio_info; iio->modes = INDIO_BUFFER_HARDWARE; @@ -56,7 +55,7 @@ MODULE_DEVICE_TABLE(of, sd_adc_of_match); static struct platform_driver iio_sd_mod_adc = { .driver = { .name = "iio_sd_adc_mod", - .of_match_table = of_match_ptr(sd_adc_of_match), + .of_match_table = sd_adc_of_match, }, .probe = iio_sd_mod_probe, }; diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c index 0ad536494e8f2819040ecf6c854c14b511165cec..1bc986a7009d27edc18e05a3ff5e0c0f00a9d423 100644 --- a/drivers/iio/adc/spear_adc.c +++ b/drivers/iio/adc/spear_adc.c @@ -336,7 +336,6 @@ static int spear_adc_probe(struct platform_device *pdev) init_completion(&st->completion); indio_dev->name = SPEAR_ADC_MOD_NAME; - indio_dev->dev.parent = dev; indio_dev->info = &spear_adc_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = spear_adc_iio_channels; diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index dfc3a306c6677fe3540df532d31fc6b52c07730c..3eb9ebe8372fce23911d71c9ba7eafc10665f113 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -162,10 +162,10 @@ struct stm32_adc_cfg { struct stm32_adc_trig_info *trigs; bool clk_required; bool has_vregready; - int (*prepare)(struct stm32_adc *); - void (*start_conv)(struct stm32_adc *, bool dma); - void (*stop_conv)(struct stm32_adc *); - void (*unprepare)(struct stm32_adc *); + int (*prepare)(struct iio_dev *); + void (*start_conv)(struct iio_dev *, bool dma); + void (*stop_conv)(struct iio_dev *); + void (*unprepare)(struct iio_dev *); const unsigned int *smp_cycles; }; @@ -538,10 +538,11 @@ static void stm32_adc_set_res(struct stm32_adc *adc) static int stm32_adc_hw_stop(struct device *dev) { - struct stm32_adc *adc = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct stm32_adc *adc = iio_priv(indio_dev); if (adc->cfg->unprepare) - adc->cfg->unprepare(adc); + adc->cfg->unprepare(indio_dev); if (adc->clk) clk_disable_unprepare(adc->clk); @@ -551,7 +552,8 @@ static int stm32_adc_hw_stop(struct device *dev) static int stm32_adc_hw_start(struct device *dev) { - struct stm32_adc *adc = dev_get_drvdata(dev); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct stm32_adc *adc = iio_priv(indio_dev); int ret; if (adc->clk) { @@ -563,7 +565,7 @@ static int stm32_adc_hw_start(struct device *dev) stm32_adc_set_res(adc); if (adc->cfg->prepare) { - ret = adc->cfg->prepare(adc); + ret = adc->cfg->prepare(indio_dev); if (ret) goto err_clk_dis; } @@ -579,7 +581,7 @@ err_clk_dis: /** * stm32f4_adc_start_conv() - Start conversions for regular channels. - * @adc: stm32 adc instance + * @indio_dev: IIO device instance * @dma: use dma to transfer conversion result * * Start conversions for regular channels. @@ -587,8 +589,10 @@ err_clk_dis: * conversions, in IIO buffer modes. Otherwise, use ADC interrupt with direct * DR read instead (e.g. read_raw, or triggered buffer mode without DMA). */ -static void stm32f4_adc_start_conv(struct stm32_adc *adc, bool dma) +static void stm32f4_adc_start_conv(struct iio_dev *indio_dev, bool dma) { + struct stm32_adc *adc = iio_priv(indio_dev); + stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN); if (dma) @@ -605,8 +609,10 @@ static void stm32f4_adc_start_conv(struct stm32_adc *adc, bool dma) stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_SWSTART); } -static void stm32f4_adc_stop_conv(struct stm32_adc *adc) +static void stm32f4_adc_stop_conv(struct iio_dev *indio_dev) { + struct stm32_adc *adc = iio_priv(indio_dev); + stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK); stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT); @@ -615,8 +621,9 @@ static void stm32f4_adc_stop_conv(struct stm32_adc *adc) STM32F4_ADON | STM32F4_DMA | STM32F4_DDS); } -static void stm32h7_adc_start_conv(struct stm32_adc *adc, bool dma) +static void stm32h7_adc_start_conv(struct iio_dev *indio_dev, bool dma) { + struct stm32_adc *adc = iio_priv(indio_dev); enum stm32h7_adc_dmngt dmngt; unsigned long flags; u32 val; @@ -635,9 +642,9 @@ static void stm32h7_adc_start_conv(struct stm32_adc *adc, bool dma) stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART); } -static void stm32h7_adc_stop_conv(struct stm32_adc *adc) +static void stm32h7_adc_stop_conv(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_adc *adc = iio_priv(indio_dev); int ret; u32 val; @@ -652,9 +659,9 @@ static void stm32h7_adc_stop_conv(struct stm32_adc *adc) stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK); } -static int stm32h7_adc_exit_pwr_down(struct stm32_adc *adc) +static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_adc *adc = iio_priv(indio_dev); int ret; u32 val; @@ -690,9 +697,9 @@ static void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc) stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD); } -static int stm32h7_adc_enable(struct stm32_adc *adc) +static int stm32h7_adc_enable(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_adc *adc = iio_priv(indio_dev); int ret; u32 val; @@ -713,9 +720,9 @@ static int stm32h7_adc_enable(struct stm32_adc *adc) return ret; } -static void stm32h7_adc_disable(struct stm32_adc *adc) +static void stm32h7_adc_disable(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_adc *adc = iio_priv(indio_dev); int ret; u32 val; @@ -730,12 +737,12 @@ static void stm32h7_adc_disable(struct stm32_adc *adc) /** * stm32h7_adc_read_selfcalib() - read calibration shadow regs, save result - * @adc: stm32 adc instance + * @indio_dev: IIO device instance * Note: Must be called once ADC is enabled, so LINCALRDYW[1..6] are writable */ -static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc) +static int stm32h7_adc_read_selfcalib(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_adc *adc = iio_priv(indio_dev); int i, ret; u32 lincalrdyw_mask, val; @@ -774,12 +781,12 @@ static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc) /** * stm32h7_adc_restore_selfcalib() - Restore saved self-calibration result - * @adc: stm32 adc instance + * @indio_dev: IIO device instance * Note: ADC must be enabled, with no on-going conversions. */ -static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc) +static int stm32h7_adc_restore_selfcalib(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_adc *adc = iio_priv(indio_dev); int i, ret; u32 lincalrdyw_mask, val; @@ -847,12 +854,12 @@ static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc) /** * stm32h7_adc_selfcalib() - Procedure to calibrate ADC - * @adc: stm32 adc instance + * @indio_dev: IIO device instance * Note: Must be called once ADC is out of power down. */ -static int stm32h7_adc_selfcalib(struct stm32_adc *adc) +static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_adc *adc = iio_priv(indio_dev); int ret; u32 val; @@ -903,7 +910,7 @@ out: /** * stm32h7_adc_prepare() - Leave power down mode to enable ADC. - * @adc: stm32 adc instance + * @indio_dev: IIO device instance * Leave power down mode. * Configure channels as single ended or differential before enabling ADC. * Enable ADC. @@ -912,30 +919,31 @@ out: * - Only one input is selected for single ended (e.g. 'vinp') * - Two inputs are selected for differential channels (e.g. 'vinp' & 'vinn') */ -static int stm32h7_adc_prepare(struct stm32_adc *adc) +static int stm32h7_adc_prepare(struct iio_dev *indio_dev) { + struct stm32_adc *adc = iio_priv(indio_dev); int calib, ret; - ret = stm32h7_adc_exit_pwr_down(adc); + ret = stm32h7_adc_exit_pwr_down(indio_dev); if (ret) return ret; - ret = stm32h7_adc_selfcalib(adc); + ret = stm32h7_adc_selfcalib(indio_dev); if (ret < 0) goto pwr_dwn; calib = ret; stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel); - ret = stm32h7_adc_enable(adc); + ret = stm32h7_adc_enable(indio_dev); if (ret) goto pwr_dwn; /* Either restore or read calibration result for future reference */ if (calib) - ret = stm32h7_adc_restore_selfcalib(adc); + ret = stm32h7_adc_restore_selfcalib(indio_dev); else - ret = stm32h7_adc_read_selfcalib(adc); + ret = stm32h7_adc_read_selfcalib(indio_dev); if (ret) goto disable; @@ -944,16 +952,18 @@ static int stm32h7_adc_prepare(struct stm32_adc *adc) return 0; disable: - stm32h7_adc_disable(adc); + stm32h7_adc_disable(indio_dev); pwr_dwn: stm32h7_adc_enter_pwr_down(adc); return ret; } -static void stm32h7_adc_unprepare(struct stm32_adc *adc) +static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) { - stm32h7_adc_disable(adc); + struct stm32_adc *adc = iio_priv(indio_dev); + + stm32h7_adc_disable(indio_dev); stm32h7_adc_enter_pwr_down(adc); } @@ -1160,7 +1170,7 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, stm32_adc_conv_irq_enable(adc); - adc->cfg->start_conv(adc, false); + adc->cfg->start_conv(indio_dev, false); timeout = wait_for_completion_interruptible_timeout( &adc->completion, STM32_ADC_TIMEOUT); @@ -1173,7 +1183,7 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, ret = IIO_VAL_INT; } - adc->cfg->stop_conv(adc); + adc->cfg->stop_conv(indio_dev); stm32_adc_conv_irq_disable(adc); @@ -1227,8 +1237,8 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, static irqreturn_t stm32_adc_threaded_isr(int irq, void *data) { - struct stm32_adc *adc = data; - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct iio_dev *indio_dev = data; + struct stm32_adc *adc = iio_priv(indio_dev); const struct stm32_adc_regspec *regs = adc->cfg->regs; u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); @@ -1240,8 +1250,8 @@ static irqreturn_t stm32_adc_threaded_isr(int irq, void *data) static irqreturn_t stm32_adc_isr(int irq, void *data) { - struct stm32_adc *adc = data; - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct iio_dev *indio_dev = data; + struct stm32_adc *adc = iio_priv(indio_dev); const struct stm32_adc_regspec *regs = adc->cfg->regs; u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); @@ -1482,7 +1492,7 @@ static int stm32_adc_dma_start(struct iio_dev *indio_dev) return 0; } -static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev) +static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev) { struct stm32_adc *adc = iio_priv(indio_dev); struct device *dev = indio_dev->dev.parent; @@ -1514,7 +1524,7 @@ static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev) if (!adc->dma_chan) stm32_adc_conv_irq_enable(adc); - adc->cfg->start_conv(adc, !!adc->dma_chan); + adc->cfg->start_conv(indio_dev, !!adc->dma_chan); return 0; @@ -1527,27 +1537,12 @@ err_pm_put: return ret; } -static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev) -{ - int ret; - - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret < 0) - return ret; - - ret = __stm32_adc_buffer_postenable(indio_dev); - if (ret < 0) - iio_triggered_buffer_predisable(indio_dev); - - return ret; -} - -static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev) +static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev) { struct stm32_adc *adc = iio_priv(indio_dev); struct device *dev = indio_dev->dev.parent; - adc->cfg->stop_conv(adc); + adc->cfg->stop_conv(indio_dev); if (!adc->dma_chan) stm32_adc_conv_irq_disable(adc); @@ -1561,19 +1556,8 @@ static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev) pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); -} - -static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev) -{ - int ret; - __stm32_adc_buffer_predisable(indio_dev); - - ret = iio_triggered_buffer_predisable(indio_dev); - if (ret < 0) - dev_err(&indio_dev->dev, "predisable failed\n"); - - return ret; + return 0; } static const struct iio_buffer_setup_ops stm32_adc_buffer_setup_ops = { @@ -1886,12 +1870,11 @@ static int stm32_adc_probe(struct platform_device *pdev) of_match_device(dev->driver->of_match_table, dev)->data; indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &stm32_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE | INDIO_HARDWARE_TRIGGERED; - platform_set_drvdata(pdev, adc); + platform_set_drvdata(pdev, indio_dev); ret = of_property_read_u32(pdev->dev.of_node, "reg", &adc->offset); if (ret != 0) { @@ -1905,7 +1888,7 @@ static int stm32_adc_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(&pdev->dev, adc->irq, stm32_adc_isr, stm32_adc_threaded_isr, - 0, pdev->name, adc); + 0, pdev->name, indio_dev); if (ret) { dev_err(&pdev->dev, "failed to request IRQ\n"); return ret; @@ -1989,8 +1972,8 @@ err_dma_disable: static int stm32_adc_remove(struct platform_device *pdev) { - struct stm32_adc *adc = platform_get_drvdata(pdev); - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct stm32_adc *adc = iio_priv(indio_dev); pm_runtime_get_sync(&pdev->dev); iio_device_unregister(indio_dev); @@ -2012,19 +1995,17 @@ static int stm32_adc_remove(struct platform_device *pdev) #if defined(CONFIG_PM_SLEEP) static int stm32_adc_suspend(struct device *dev) { - struct stm32_adc *adc = dev_get_drvdata(dev); - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct iio_dev *indio_dev = dev_get_drvdata(dev); if (iio_buffer_enabled(indio_dev)) - __stm32_adc_buffer_predisable(indio_dev); + stm32_adc_buffer_predisable(indio_dev); return pm_runtime_force_suspend(dev); } static int stm32_adc_resume(struct device *dev) { - struct stm32_adc *adc = dev_get_drvdata(dev); - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct iio_dev *indio_dev = dev_get_drvdata(dev); int ret; ret = pm_runtime_force_resume(dev); @@ -2039,7 +2020,7 @@ static int stm32_adc_resume(struct device *dev) if (ret < 0) return ret; - return __stm32_adc_buffer_postenable(indio_dev); + return stm32_adc_buffer_postenable(indio_dev); } #endif diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 506bf519f64ca43fb6d2e6b8278945de862051a2..5e10fb4f3704d041dca78288e4a5d0db9c9e987d 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -330,9 +330,9 @@ static int stm32_dfsdm_compute_all_osrs(struct iio_dev *indio_dev, return 0; } -static int stm32_dfsdm_start_channel(struct stm32_dfsdm_adc *adc) +static int stm32_dfsdm_start_channel(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); struct regmap *regmap = adc->dfsdm->regmap; const struct iio_chan_spec *chan; unsigned int bit; @@ -350,9 +350,9 @@ static int stm32_dfsdm_start_channel(struct stm32_dfsdm_adc *adc) return 0; } -static void stm32_dfsdm_stop_channel(struct stm32_dfsdm_adc *adc) +static void stm32_dfsdm_stop_channel(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); struct regmap *regmap = adc->dfsdm->regmap; const struct iio_chan_spec *chan; unsigned int bit; @@ -418,11 +418,11 @@ static void stm32_dfsdm_stop_filter(struct stm32_dfsdm *dfsdm, DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(0)); } -static int stm32_dfsdm_filter_set_trig(struct stm32_dfsdm_adc *adc, +static int stm32_dfsdm_filter_set_trig(struct iio_dev *indio_dev, unsigned int fl_id, struct iio_trigger *trig) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); struct regmap *regmap = adc->dfsdm->regmap; u32 jextsel = 0, jexten = STM32_DFSDM_JEXTEN_DISABLED; int ret; @@ -447,11 +447,11 @@ static int stm32_dfsdm_filter_set_trig(struct stm32_dfsdm_adc *adc, return 0; } -static int stm32_dfsdm_channels_configure(struct stm32_dfsdm_adc *adc, +static int stm32_dfsdm_channels_configure(struct iio_dev *indio_dev, unsigned int fl_id, struct iio_trigger *trig) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); struct regmap *regmap = adc->dfsdm->regmap; struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id]; struct stm32_dfsdm_filter_osr *flo = &fl->flo[0]; @@ -491,11 +491,11 @@ static int stm32_dfsdm_channels_configure(struct stm32_dfsdm_adc *adc, return 0; } -static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, +static int stm32_dfsdm_filter_configure(struct iio_dev *indio_dev, unsigned int fl_id, struct iio_trigger *trig) { - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); struct regmap *regmap = adc->dfsdm->regmap; struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id]; struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast]; @@ -521,7 +521,7 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, if (ret) return ret; - ret = stm32_dfsdm_filter_set_trig(adc, fl_id, trig); + ret = stm32_dfsdm_filter_set_trig(indio_dev, fl_id, trig); if (ret) return ret; @@ -729,21 +729,22 @@ static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev, return len; } -static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, +static int stm32_dfsdm_start_conv(struct iio_dev *indio_dev, struct iio_trigger *trig) { + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); struct regmap *regmap = adc->dfsdm->regmap; int ret; - ret = stm32_dfsdm_channels_configure(adc, adc->fl_id, trig); + ret = stm32_dfsdm_channels_configure(indio_dev, adc->fl_id, trig); if (ret < 0) return ret; - ret = stm32_dfsdm_start_channel(adc); + ret = stm32_dfsdm_start_channel(indio_dev); if (ret < 0) return ret; - ret = stm32_dfsdm_filter_configure(adc, adc->fl_id, trig); + ret = stm32_dfsdm_filter_configure(indio_dev, adc->fl_id, trig); if (ret < 0) goto stop_channels; @@ -757,13 +758,14 @@ filter_unconfigure: regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), DFSDM_CR1_CFG_MASK, 0); stop_channels: - stm32_dfsdm_stop_channel(adc); + stm32_dfsdm_stop_channel(indio_dev); return ret; } -static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc) +static void stm32_dfsdm_stop_conv(struct iio_dev *indio_dev) { + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); struct regmap *regmap = adc->dfsdm->regmap; stm32_dfsdm_stop_filter(adc->dfsdm, adc->fl_id); @@ -771,7 +773,7 @@ static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc) regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), DFSDM_CR1_CFG_MASK, 0); - stm32_dfsdm_stop_channel(adc); + stm32_dfsdm_stop_channel(indio_dev); } static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev, @@ -993,7 +995,7 @@ static int stm32_dfsdm_update_scan_mode(struct iio_dev *indio_dev, return 0; } -static int __stm32_dfsdm_postenable(struct iio_dev *indio_dev) +static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); int ret; @@ -1017,7 +1019,7 @@ static int __stm32_dfsdm_postenable(struct iio_dev *indio_dev) goto stop_dfsdm; } - ret = stm32_dfsdm_start_conv(adc, indio_dev->trig); + ret = stm32_dfsdm_start_conv(indio_dev, indio_dev->trig); if (ret) { dev_err(&indio_dev->dev, "Can't start conversion\n"); goto err_stop_dma; @@ -1036,34 +1038,11 @@ err_stop_hwc: return ret; } -static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) -{ - int ret; - - if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret < 0) - return ret; - } - - ret = __stm32_dfsdm_postenable(indio_dev); - if (ret < 0) - goto err_predisable; - - return 0; - -err_predisable: - if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) - iio_triggered_buffer_predisable(indio_dev); - - return ret; -} - -static void __stm32_dfsdm_predisable(struct iio_dev *indio_dev) +static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); - stm32_dfsdm_stop_conv(adc); + stm32_dfsdm_stop_conv(indio_dev); stm32_dfsdm_adc_dma_stop(indio_dev); @@ -1071,14 +1050,6 @@ static void __stm32_dfsdm_predisable(struct iio_dev *indio_dev) if (adc->hwc) iio_hw_consumer_disable(adc->hwc); -} - -static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) -{ - __stm32_dfsdm_predisable(indio_dev); - - if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) - iio_triggered_buffer_predisable(indio_dev); return 0; } @@ -1159,7 +1130,7 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, adc->nconv = 1; adc->smask = BIT(chan->scan_index); - ret = stm32_dfsdm_start_conv(adc, NULL); + ret = stm32_dfsdm_start_conv(indio_dev, NULL); if (ret < 0) { regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0)); @@ -1180,7 +1151,7 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, else ret = IIO_VAL_INT; - stm32_dfsdm_stop_conv(adc); + stm32_dfsdm_stop_conv(indio_dev); stm32_dfsdm_process_data(adc, res); @@ -1313,8 +1284,8 @@ static const struct iio_info stm32_dfsdm_info_adc = { static irqreturn_t stm32_dfsdm_irq(int irq, void *arg) { - struct stm32_dfsdm_adc *adc = arg; - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct iio_dev *indio_dev = arg; + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); struct regmap *regmap = adc->dfsdm->regmap; unsigned int status, int_en; @@ -1571,11 +1542,10 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev) adc = iio_priv(iio); adc->dfsdm = dev_get_drvdata(dev->parent); - iio->dev.parent = dev; iio->dev.of_node = np; iio->modes = INDIO_DIRECT_MODE; - platform_set_drvdata(pdev, adc); + platform_set_drvdata(pdev, iio); ret = of_property_read_u32(dev->of_node, "reg", &adc->fl_id); if (ret != 0 || adc->fl_id >= adc->dfsdm->num_fls) { @@ -1604,7 +1574,7 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev) return irq; ret = devm_request_irq(dev, irq, stm32_dfsdm_irq, - 0, pdev->name, adc); + 0, pdev->name, iio); if (ret < 0) { dev_err(dev, "Failed to request IRQ\n"); return ret; @@ -1651,8 +1621,8 @@ err_cleanup: static int stm32_dfsdm_adc_remove(struct platform_device *pdev) { - struct stm32_dfsdm_adc *adc = platform_get_drvdata(pdev); - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); if (adc->dev_data->type == DFSDM_AUDIO) of_platform_depopulate(&pdev->dev); @@ -1664,19 +1634,18 @@ static int stm32_dfsdm_adc_remove(struct platform_device *pdev) static int __maybe_unused stm32_dfsdm_adc_suspend(struct device *dev) { - struct stm32_dfsdm_adc *adc = dev_get_drvdata(dev); - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct iio_dev *indio_dev = dev_get_drvdata(dev); if (iio_buffer_enabled(indio_dev)) - __stm32_dfsdm_predisable(indio_dev); + stm32_dfsdm_predisable(indio_dev); return 0; } static int __maybe_unused stm32_dfsdm_adc_resume(struct device *dev) { - struct stm32_dfsdm_adc *adc = dev_get_drvdata(dev); - struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); const struct iio_chan_spec *chan; struct stm32_dfsdm_channel *ch; int i, ret; @@ -1691,7 +1660,7 @@ static int __maybe_unused stm32_dfsdm_adc_resume(struct device *dev) } if (iio_buffer_enabled(indio_dev)) - __stm32_dfsdm_postenable(indio_dev); + stm32_dfsdm_postenable(indio_dev); return 0; } diff --git a/drivers/iio/adc/stmpe-adc.c b/drivers/iio/adc/stmpe-adc.c index 0f88048ea48f5a6ed7444218ba7fe04a3d483d1a..fba659bfdb40a9977e048a08189c02f8f9dc78c4 100644 --- a/drivers/iio/adc/stmpe-adc.c +++ b/drivers/iio/adc/stmpe-adc.c @@ -297,7 +297,6 @@ static int stmpe_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &stmpe_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c index f87bbc711ccc0e780a9efda93fe90e1e88602c32..55bd2dc514e9367a57c441ecc7e8f4bafffc5340 100644 --- a/drivers/iio/adc/stx104.c +++ b/drivers/iio/adc/stx104.c @@ -319,7 +319,6 @@ static int stx104_probe(struct device *dev, unsigned int id) } indio_dev->name = dev_name(dev); - indio_dev->dev.parent = dev; priv = iio_priv(indio_dev); priv->base = base[id]; diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 0f2c1738a90d1dc5649f05b8c1fbe267441616cb..99b43f28e879ae8337e350cf73d965f53d2f1030 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -619,8 +619,6 @@ static int sun4i_gpadc_probe(struct platform_device *pdev) info->indio_dev = indio_dev; init_completion(&info->completion); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &sun4i_gpadc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c index 0235863ff77b020840e4ff854493d4a283c6cb37..9426f70a800598c0f4010708f332e8e5410a6c13 100644 --- a/drivers/iio/adc/ti-adc081c.c +++ b/drivers/iio/adc/ti-adc081c.c @@ -6,9 +6,9 @@ * Copyright (C) 2016 Intel * * Datasheets: - * http://www.ti.com/lit/ds/symlink/adc081c021.pdf - * http://www.ti.com/lit/ds/symlink/adc101c021.pdf - * http://www.ti.com/lit/ds/symlink/adc121c021.pdf + * https://www.ti.com/lit/ds/symlink/adc081c021.pdf + * https://www.ti.com/lit/ds/symlink/adc101c021.pdf + * https://www.ti.com/lit/ds/symlink/adc121c021.pdf * * The devices have a very similar interface and differ mostly in the number of * bits handled. For the 8-bit and 10-bit models the least-significant 4 or 2 @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include @@ -181,8 +181,6 @@ static int adc081c_probe(struct i2c_client *client, if (err < 0) return err; - iio->dev.parent = &client->dev; - iio->dev.of_node = client->dev.of_node; iio->name = dev_name(&client->dev); iio->modes = INDIO_DIRECT_MODE; iio->info = &adc081c_info; @@ -232,7 +230,6 @@ static const struct i2c_device_id adc081c_id[] = { }; MODULE_DEVICE_TABLE(i2c, adc081c_id); -#ifdef CONFIG_OF static const struct of_device_id adc081c_of_match[] = { { .compatible = "ti,adc081c" }, { .compatible = "ti,adc101c" }, @@ -240,7 +237,6 @@ static const struct of_device_id adc081c_of_match[] = { { } }; MODULE_DEVICE_TABLE(of, adc081c_of_match); -#endif #ifdef CONFIG_ACPI static const struct acpi_device_id adc081c_acpi_match[] = { @@ -255,7 +251,7 @@ MODULE_DEVICE_TABLE(acpi, adc081c_acpi_match); static struct i2c_driver adc081c_driver = { .driver = { .name = "adc081c", - .of_match_table = of_match_ptr(adc081c_of_match), + .of_match_table = adc081c_of_match, .acpi_match_table = ACPI_PTR(adc081c_acpi_match), }, .probe = adc081c_probe, diff --git a/drivers/iio/adc/ti-adc0832.c b/drivers/iio/adc/ti-adc0832.c index 6ea39f4bbb370a3e7efc9d5c353b9436cab3cdb0..c7a085dce1f47701b8384d141b71a6408be477e7 100644 --- a/drivers/iio/adc/ti-adc0832.c +++ b/drivers/iio/adc/ti-adc0832.c @@ -4,10 +4,11 @@ * * Copyright (c) 2016 Akinobu Mita * - * Datasheet: http://www.ti.com/lit/ds/symlink/adc0832-n.pdf + * Datasheet: https://www.ti.com/lit/ds/symlink/adc0832-n.pdf */ #include +#include #include #include #include @@ -245,8 +246,6 @@ static int adc0832_probe(struct spi_device *spi) mutex_init(&adc->lock); indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->info = &adc0832_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -315,8 +314,6 @@ static int adc0832_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_OF - static const struct of_device_id adc0832_dt_ids[] = { { .compatible = "ti,adc0831", }, { .compatible = "ti,adc0832", }, @@ -326,8 +323,6 @@ static const struct of_device_id adc0832_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, adc0832_dt_ids); -#endif - static const struct spi_device_id adc0832_id[] = { { "adc0831", adc0831 }, { "adc0832", adc0832 }, @@ -340,7 +335,7 @@ MODULE_DEVICE_TABLE(spi, adc0832_id); static struct spi_driver adc0832_driver = { .driver = { .name = "adc0832", - .of_match_table = of_match_ptr(adc0832_dt_ids), + .of_match_table = adc0832_dt_ids, }, .probe = adc0832_probe, .remove = adc0832_remove, diff --git a/drivers/iio/adc/ti-adc084s021.c b/drivers/iio/adc/ti-adc084s021.c index bdedf456ee05d1f2ad98c25fc26532a4eb3881a6..9017e1e24273b3bb9fae7a2442164546b2e82bae 100644 --- a/drivers/iio/adc/ti-adc084s021.c +++ b/drivers/iio/adc/ti-adc084s021.c @@ -4,12 +4,13 @@ * * Driver for Texas Instruments' ADC084S021 ADC chip. * Datasheets can be found here: - * http://www.ti.com/lit/ds/symlink/adc084s021.pdf + * https://www.ti.com/lit/ds/symlink/adc084s021.pdf */ #include #include #include +#include #include #include #include @@ -187,8 +188,6 @@ static const struct iio_info adc084s021_info = { static const struct iio_buffer_setup_ops adc084s021_buffer_setup_ops = { .preenable = adc084s021_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = adc084s021_buffer_postdisable, }; @@ -211,8 +210,6 @@ static int adc084s021_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); /* Initiate the Industrial I/O device */ - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &adc084s021_info; @@ -258,7 +255,7 @@ MODULE_DEVICE_TABLE(spi, adc084s021_id); static struct spi_driver adc084s021_driver = { .driver = { .name = ADC084S021_DRIVER_NAME, - .of_match_table = of_match_ptr(adc084s021_of_match), + .of_match_table = adc084s021_of_match, }, .probe = adc084s021_probe, .id_table = adc084s021_id, diff --git a/drivers/iio/adc/ti-adc108s102.c b/drivers/iio/adc/ti-adc108s102.c index de9aaebff862201ac0e5fa5df4bd0674dbd7de5e..9b9b27415c93e6be5964fe9921bd368f943ea87d 100644 --- a/drivers/iio/adc/ti-adc108s102.c +++ b/drivers/iio/adc/ti-adc108s102.c @@ -252,7 +252,6 @@ static int adc108s102_probe(struct spi_device *spi) st->spi = spi; indio_dev->name = spi->modalias; - indio_dev->dev.parent = &spi->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = adc108s102_channels; indio_dev->num_channels = ARRAY_SIZE(adc108s102_channels); diff --git a/drivers/iio/adc/ti-adc12138.c b/drivers/iio/adc/ti-adc12138.c index 68a9dcb8faa2f801ca0b3688752e07ca4d08fb3d..e485719cd2c4c25a7fe99e8457c974c782cc4615 100644 --- a/drivers/iio/adc/ti-adc12138.c +++ b/drivers/iio/adc/ti-adc12138.c @@ -407,7 +407,6 @@ static int adc12138_probe(struct spi_device *spi) init_completion(&adc->complete); indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; indio_dev->info = &adc12138_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ti-adc128s052.c b/drivers/iio/adc/ti-adc128s052.c index 1e5a936b5b6ad0d6b75479549f2295cea98bdee2..e86f55ce093ff542bd63fd2edd91acb3bb14ff93 100644 --- a/drivers/iio/adc/ti-adc128s052.c +++ b/drivers/iio/adc/ti-adc128s052.c @@ -4,9 +4,9 @@ * * Driver for Texas Instruments' ADC128S052, ADC122S021 and ADC124S021 ADC chip. * Datasheets can be found here: - * http://www.ti.com/lit/ds/symlink/adc128s052.pdf - * http://www.ti.com/lit/ds/symlink/adc122s021.pdf - * http://www.ti.com/lit/ds/symlink/adc124s021.pdf + * https://www.ti.com/lit/ds/symlink/adc128s052.pdf + * https://www.ti.com/lit/ds/symlink/adc122s021.pdf + * https://www.ti.com/lit/ds/symlink/adc124s021.pdf */ #include @@ -152,8 +152,6 @@ static int adc128_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &adc128_info; diff --git a/drivers/iio/adc/ti-adc161s626.c b/drivers/iio/adc/ti-adc161s626.c index 3bbc9b9ddbfed2160ebfd9f50088bd0e321dad03..607791ffe7f0dcfe6862eb7326384a2f2b0dc6c1 100644 --- a/drivers/iio/adc/ti-adc161s626.c +++ b/drivers/iio/adc/ti-adc161s626.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -179,8 +180,6 @@ static int ti_adc_probe(struct spi_device *spi) return -ENOMEM; indio_dev->info = &ti_adc_info; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = TI_ADC_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; spi_set_drvdata(spi, indio_dev); @@ -259,7 +258,7 @@ MODULE_DEVICE_TABLE(spi, ti_adc_id); static struct spi_driver ti_adc_driver = { .driver = { .name = TI_ADC_DRV_NAME, - .of_match_table = of_match_ptr(ti_adc_dt_ids), + .of_match_table = ti_adc_dt_ids, }, .probe = ti_adc_probe, .remove = ti_adc_remove, diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index 5ea4f45d6badefeee8acda2eae8a17025dcda195..f42ab112986ec0aa04f9ae43a7676aa1f7cd57b1 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -788,8 +788,6 @@ static int ads1015_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = { .preenable = ads1015_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = ads1015_buffer_postdisable, .validate_scan_mask = &iio_validate_scan_mask_onehot, }; @@ -939,8 +937,6 @@ static int ads1015_probe(struct i2c_client *client, mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->name = ADS1015_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ti-ads124s08.c b/drivers/iio/adc/ti-ads124s08.c index f1ee3b1e28273ffc16080797089890418ff3998a..4b4fbe33930ce38c848e8cc9a024c7df7f48ac92 100644 --- a/drivers/iio/adc/ti-ads124s08.c +++ b/drivers/iio/adc/ti-ads124s08.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* TI ADS124S0X chip family driver - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/ */ #include @@ -325,8 +325,6 @@ static int ads124s_probe(struct spi_device *spi) ads124s_priv->spi = spi; indio_dev->name = spi_id->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ads124s_priv->chip_info->channels; indio_dev->num_channels = ads124s_priv->chip_info->num_channels; diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index f9edc1207f753f863c7279cd28893da80b901f61..2383eacada87ddf43609b299fb29e3a0de2ce11b 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -9,7 +9,7 @@ * Copyright 2012 CS Systemes d'Information * * And also on hwmon/ads79xx.c - * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com/ * Nishanth Menon */ @@ -557,7 +557,6 @@ static int ti_ads7950_probe(struct spi_device *spi) info = &ti_ads7950_chip_info[spi_get_device_id(spi)->driver_data]; indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = info->channels; indio_dev->num_channels = info->num_channels; diff --git a/drivers/iio/adc/ti-ads8344.c b/drivers/iio/adc/ti-ads8344.c index 8a8792010c20b3dfe77e4dc79bb333cd9d038d30..a345a30d74fad9827537508ac8b6cb2884150065 100644 --- a/drivers/iio/adc/ti-ads8344.c +++ b/drivers/iio/adc/ti-ads8344.c @@ -4,7 +4,7 @@ * * Author: Gregory CLEMENT * - * Datasheet: http://www.ti.com/lit/ds/symlink/ads8344.pdf + * Datasheet: https://www.ti.com/lit/ds/symlink/ads8344.pdf */ #include @@ -148,8 +148,6 @@ static int ads8344_probe(struct spi_device *spi) mutex_init(&adc->lock); indio_dev->name = dev_name(&spi->dev); - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->info = &ads8344_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ads8344_channels; diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index 14fe7c320b5222cdf681f3320c730a7f8c474b7b..16bcb37eebb721236eefd6f1510267f74093d338 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -449,8 +449,6 @@ static int ads8688_probe(struct spi_device *spi) st->spi = spi; indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; diff --git a/drivers/iio/adc/ti-tlc4541.c b/drivers/iio/adc/ti-tlc4541.c index 77620359b54c1d0f7ad2c6c72c2012161dd52ecd..403b787f9f7ec69b970cd9a317ce80b5f1dbea6b 100644 --- a/drivers/iio/adc/ti-tlc4541.c +++ b/drivers/iio/adc/ti-tlc4541.c @@ -5,8 +5,8 @@ * Copyright (C) 2017 Phil Reid * * Datasheets can be found here: - * http://www.ti.com/lit/gpn/tlc3541 - * http://www.ti.com/lit/gpn/tlc4541 + * https://www.ti.com/lit/gpn/tlc3541 + * https://www.ti.com/lit/gpn/tlc4541 * * The tlc4541 requires 24 clock cycles to start a transfer. * Conversion then takes 2.94us to complete before data is ready @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -177,7 +178,6 @@ static int tlc4541_probe(struct spi_device *spi) info = &tlc4541_chip_info[spi_get_device_id(spi)->driver_data]; indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = info->channels; indio_dev->num_channels = info->num_channels; @@ -236,14 +236,12 @@ static int tlc4541_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_OF static const struct of_device_id tlc4541_dt_ids[] = { { .compatible = "ti,tlc3541", }, { .compatible = "ti,tlc4541", }, {} }; MODULE_DEVICE_TABLE(of, tlc4541_dt_ids); -#endif static const struct spi_device_id tlc4541_id[] = { {"tlc3541", TLC3541}, @@ -255,7 +253,7 @@ MODULE_DEVICE_TABLE(spi, tlc4541_id); static struct spi_driver tlc4541_driver = { .driver = { .name = "tlc4541", - .of_match_table = of_match_ptr(tlc4541_dt_ids), + .of_match_table = tlc4541_dt_ids, }, .probe = tlc4541_probe, .remove = tlc4541_remove, diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 9d984f2a8ba7489e2920e43af6d14a8b141a541d..b11c8c47ba2aaee658e6d68709062910736e0cf4 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -1,7 +1,7 @@ /* * TI ADC MFD driver * - * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -294,7 +294,7 @@ static int tiadc_start_dma(struct iio_dev *indio_dev) static int tiadc_buffer_preenable(struct iio_dev *indio_dev) { struct tiadc_device *adc_dev = iio_priv(indio_dev); - int i, fifo1count, read; + int i, fifo1count; tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | IRQENB_FIFO1OVRRUN | @@ -303,7 +303,7 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev) /* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); for (i = 0; i < fifo1count; i++) - read = tiadc_readl(adc_dev, REG_FIFO1); + tiadc_readl(adc_dev, REG_FIFO1); return 0; } @@ -343,7 +343,7 @@ static int tiadc_buffer_predisable(struct iio_dev *indio_dev) { struct tiadc_device *adc_dev = iio_priv(indio_dev); struct tiadc_dma *dma = &adc_dev->dma; - int fifo1count, i, read; + int fifo1count, i; tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW)); @@ -358,7 +358,7 @@ static int tiadc_buffer_predisable(struct iio_dev *indio_dev) /* Flush FIFO of leftover data in the time it takes to disable adc */ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); for (i = 0; i < fifo1count; i++) - read = tiadc_readl(adc_dev, REG_FIFO1); + tiadc_readl(adc_dev, REG_FIFO1); return 0; } @@ -377,7 +377,8 @@ static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = { .postdisable = &tiadc_buffer_postdisable, }; -static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, +static int tiadc_iio_buffered_hardware_setup(struct device *dev, + struct iio_dev *indio_dev, irqreturn_t (*pollfunc_bh)(int irq, void *p), irqreturn_t (*pollfunc_th)(int irq, void *p), int irq, @@ -387,13 +388,13 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, struct iio_buffer *buffer; int ret; - buffer = iio_kfifo_allocate(); + buffer = devm_iio_kfifo_allocate(dev); if (!buffer) return -ENOMEM; iio_device_attach_buffer(indio_dev, buffer); - ret = request_threaded_irq(irq, pollfunc_th, pollfunc_bh, + ret = devm_request_threaded_irq(dev, irq, pollfunc_th, pollfunc_bh, flags, indio_dev->name, indio_dev); if (ret) goto error_kfifo_free; @@ -408,15 +409,6 @@ error_kfifo_free: return ret; } -static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev) -{ - struct tiadc_device *adc_dev = iio_priv(indio_dev); - - free_irq(adc_dev->mfd_tscadc->irq, indio_dev); - iio_kfifo_free(indio_dev->buffer); -} - - static const char * const chan_name_ain[] = { "AIN0", "AIN1", @@ -428,7 +420,8 @@ static const char * const chan_name_ain[] = { "AIN7", }; -static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) +static int tiadc_channel_init(struct device *dev, struct iio_dev *indio_dev, + int channels) { struct tiadc_device *adc_dev = iio_priv(indio_dev); struct iio_chan_spec *chan_array; @@ -436,7 +429,8 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) int i; indio_dev->num_channels = channels; - chan_array = kcalloc(channels, sizeof(*chan_array), GFP_KERNEL); + chan_array = devm_kcalloc(dev, channels, sizeof(*chan_array), + GFP_KERNEL); if (chan_array == NULL) return -ENOMEM; @@ -459,11 +453,6 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) return 0; } -static void tiadc_channels_remove(struct iio_dev *indio_dev) -{ - kfree(indio_dev->channels); -} - static int tiadc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -626,7 +615,6 @@ static int tiadc_probe(struct platform_device *pdev) adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev); tiadc_parse_dt(pdev, adc_dev); - indio_dev->dev.parent = &pdev->dev; indio_dev->name = dev_name(&pdev->dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &tiadc_info; @@ -635,11 +623,11 @@ static int tiadc_probe(struct platform_device *pdev) tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD); mutex_init(&adc_dev->fifo1_lock); - err = tiadc_channel_init(indio_dev, adc_dev->channels); + err = tiadc_channel_init(&pdev->dev, indio_dev, adc_dev->channels); if (err < 0) return err; - err = tiadc_iio_buffered_hardware_setup(indio_dev, + err = tiadc_iio_buffered_hardware_setup(&pdev->dev, indio_dev, &tiadc_worker_h, &tiadc_irq_h, adc_dev->mfd_tscadc->irq, @@ -664,9 +652,7 @@ static int tiadc_probe(struct platform_device *pdev) err_dma: iio_device_unregister(indio_dev); err_buffer_unregister: - tiadc_iio_buffered_hardware_remove(indio_dev); err_free_channels: - tiadc_channels_remove(indio_dev); return err; } @@ -683,8 +669,6 @@ static int tiadc_remove(struct platform_device *pdev) dma_release_channel(dma->chan); } iio_device_unregister(indio_dev); - tiadc_iio_buffered_hardware_remove(indio_dev); - tiadc_channels_remove(indio_dev); step_en = get_adc_step_mask(adc_dev); am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en); diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c index 472b08f37feae961bfbefac890b8a77939d7f0c6..6ce40cc4568a2d75561177ec079eaccdce2fc8cb 100644 --- a/drivers/iio/adc/twl4030-madc.c +++ b/drivers/iio/adc/twl4030-madc.c @@ -5,7 +5,7 @@ * conversion of analog signals like battery temperature, * battery type, battery level etc. * - * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/ * J Keerthy * * Based on twl4030-madc.c @@ -153,7 +153,7 @@ enum sample_type { * struct twl4030_madc_data - a container for madc info * @dev: Pointer to device structure for madc * @lock: Mutex protecting this data structure - * @regulator: Pointer to bias regulator for madc + * @usb3v1: Pointer to bias regulator for madc * @requests: Array of request struct corresponding to SW1, SW2 and RT * @use_second_irq: IRQ selection (main or co-processor) * @imr: Interrupt mask register of MADC @@ -161,7 +161,7 @@ enum sample_type { */ struct twl4030_madc_data { struct device *dev; - struct mutex lock; /* mutex protecting this data structure */ + struct mutex lock; struct regulator *usb3v1; struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS]; bool use_second_irq; @@ -472,7 +472,7 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) struct twl4030_madc_data *madc = _madc; const struct twl4030_madc_conversion_method *method; u8 isr_val, imr_val; - int i, len, ret; + int i, ret; struct twl4030_madc_request *r; mutex_lock(&madc->lock); @@ -504,8 +504,8 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) continue; method = &twl4030_conversion_methods[r->method]; /* Read results */ - len = twl4030_madc_read_channels(madc, method->rbase, - r->channels, r->rbuf, r->raw); + twl4030_madc_read_channels(madc, method->rbase, + r->channels, r->rbuf, r->raw); /* Free request */ r->result_pending = false; r->active = false; @@ -525,8 +525,8 @@ err_i2c: continue; method = &twl4030_conversion_methods[r->method]; /* Read results */ - len = twl4030_madc_read_channels(madc, method->rbase, - r->channels, r->rbuf, r->raw); + twl4030_madc_read_channels(madc, method->rbase, + r->channels, r->rbuf, r->raw); /* Free request */ r->result_pending = false; r->active = false; @@ -772,8 +772,6 @@ static int twl4030_madc_probe(struct platform_device *pdev) madc->dev = &pdev->dev; iio_dev->name = dev_name(&pdev->dev); - iio_dev->dev.parent = &pdev->dev; - iio_dev->dev.of_node = pdev->dev.of_node; iio_dev->info = &twl4030_madc_iio_info; iio_dev->modes = INDIO_DIRECT_MODE; iio_dev->channels = twl4030_madc_iio_channels; diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index f24148bd15de42cc9f3fafbf1e9876a9af0195a5..c6416ad795ca48ae2a24cd02c8ecd5e8d4fb74e3 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c @@ -94,9 +94,9 @@ struct twl6030_gpadc_data; * struct twl6030_gpadc_platform_data - platform specific data * @nchannels: number of GPADC channels * @iio_channels: iio channels - * @twl6030_ideal: pointer to calibration parameters + * @ideal: pointer to calibration parameters * @start_conversion: pointer to ADC start conversion function - * @channel_to_reg pointer to ADC function to convert channel to + * @channel_to_reg: pointer to ADC function to convert channel to * register address for reading conversion result * @calibrate: pointer to calibration function */ @@ -926,7 +926,6 @@ static int twl6030_gpadc_probe(struct platform_device *pdev) } indio_dev->name = DRIVER_NAME; - indio_dev->dev.parent = dev; indio_dev->info = &twl6030_gpadc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = pdata->iio_channels; diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index cb7380bf07cadf68f8fac036beccaf99f5f1f41f..1d794cf3e3f1395f38556d3a3a1da27ec789252d 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -724,13 +724,8 @@ static int vf610_adc_buffer_postenable(struct iio_dev *indio_dev) { struct vf610_adc *info = iio_priv(indio_dev); unsigned int channel; - int ret; int val; - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret) - return ret; - val = readl(info->regs + VF610_REG_ADC_GC); val |= VF610_ADC_ADCON; writel(val, info->regs + VF610_REG_ADC_GC); @@ -761,7 +756,7 @@ static int vf610_adc_buffer_predisable(struct iio_dev *indio_dev) writel(hc_cfg, info->regs + VF610_REG_ADC_HC0); - return iio_triggered_buffer_predisable(indio_dev); + return 0; } static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { @@ -860,8 +855,6 @@ static int vf610_adc_probe(struct platform_device *pdev) init_completion(&info->completion); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &vf610_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = vf610_adc_iio_channels; diff --git a/drivers/iio/adc/viperboard_adc.c b/drivers/iio/adc/viperboard_adc.c index 1d2aeb04069b438197d63df1218f5a7290c01bf3..1028b101cf568d709bb95f1d4ec8b1f25ed15c15 100644 --- a/drivers/iio/adc/viperboard_adc.c +++ b/drivers/iio/adc/viperboard_adc.c @@ -121,7 +121,6 @@ static int vprbrd_adc_probe(struct platform_device *pdev) adc = iio_priv(indio_dev); adc->vb = vb; indio_dev->name = "viperboard adc"; - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &vprbrd_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = vprbrd_adc_iio_channels; diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index d7fecab9252e4b2d60f17b26ff2d8bcc0dde8d53..d0b7ef296afb45a23d8505326350116364d67d3b 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -839,8 +839,6 @@ err: static const struct iio_buffer_setup_ops xadc_buffer_ops = { .preenable = &xadc_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, .postdisable = &xadc_postdisable, }; @@ -1221,8 +1219,6 @@ static int xadc_probe(struct platform_device *pdev) if (IS_ERR(xadc->base)) return PTR_ERR(xadc->base); - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->name = "xadc"; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &xadc_info; diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c index e9ceee66d1e7c2fcd6d5b79d83cdfcea2dbd5687..69c0f277ada0cac6e9e999a0f93cf1e0f823c660 100644 --- a/drivers/iio/afe/iio-rescale.c +++ b/drivers/iio/afe/iio-rescale.c @@ -314,7 +314,6 @@ static int rescale_probe(struct platform_device *pdev) rescale->source = source; indio_dev->name = dev_name(dev); - indio_dev->dev.parent = dev; indio_dev->info = &rescale_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = &rescale->chan; diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index 62167b87caea83471fd5b214a62393168063d8ab..cfcf18a0bce8517a20c14b95cc11a84ace53fff7 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c @@ -262,8 +262,11 @@ static int ad8366_probe(struct spi_device *spi) case ID_ADA4961: case ID_ADL5240: case ID_HMC1119: - st->reset_gpio = devm_gpiod_get(&spi->dev, "reset", - GPIOD_OUT_HIGH); + st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(st->reset_gpio)) { + ret = PTR_ERR(st->reset_gpio); + goto error_disable_reg; + } indio_dev->channels = ada4961_channels; indio_dev->num_channels = ARRAY_SIZE(ada4961_channels); break; @@ -274,7 +277,6 @@ static int ad8366_probe(struct spi_device *spi) } st->info = &ad8366_infos[st->type]; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad8366_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/amplifiers/hmc425a.c b/drivers/iio/amplifiers/hmc425a.c index d9e6e9678ffc1dd81c9113b582eb2761b6ea4a7a..582708924e4fc67465bb9917b06774f33dde10a3 100644 --- a/drivers/iio/amplifiers/hmc425a.c +++ b/drivers/iio/amplifiers/hmc425a.c @@ -227,7 +227,6 @@ static int hmc425a_probe(struct platform_device *pdev) mutex_init(&st->lock); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &hmc425a_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/buffer/industrialio-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c index e8046c1ecd6b56d77be04faaf2a383432aa75f70..6c20a83f887e53c5d8194285497d94a10f9f21fb 100644 --- a/drivers/iio/buffer/industrialio-triggered-buffer.c +++ b/drivers/iio/buffer/industrialio-triggered-buffer.c @@ -13,11 +13,6 @@ #include #include -static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, -}; - /** * iio_triggered_buffer_setup() - Setup triggered buffer and pollfunc * @indio_dev: IIO device structure @@ -67,10 +62,7 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev, } /* Ring buffer functions - here trigger setup related */ - if (setup_ops) - indio_dev->setup_ops = setup_ops; - else - indio_dev->setup_ops = &iio_triggered_buffer_setup_ops; + indio_dev->setup_ops = setup_ops; /* Flag that polled ring buffering is possible */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index 7f21afd73b1cd2f6c2776e2024f043187a58c543..10bb431bc3ce19a6512e09c366a89e6e0b4ae913 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -85,6 +85,39 @@ config PMS7003 To compile this driver as a module, choose M here: the module will be called pms7003. +config SCD30_CORE + tristate "SCD30 carbon dioxide sensor driver" + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here to build support for the Sensirion SCD30 sensor with carbon + dioxide, relative humidity and temperature sensing capabilities. + + To compile this driver as a module, choose M here: the module will + be called scd30_core. + +config SCD30_I2C + tristate "SCD30 carbon dioxide sensor I2C driver" + depends on SCD30_CORE && I2C + select CRC8 + help + Say Y here to build support for the Sensirion SCD30 I2C interface + driver. + + To compile this driver as a module, choose M here: the module will + be called scd30_i2c. + +config SCD30_SERIAL + tristate "SCD30 carbon dioxide sensor serial driver" + depends on SCD30_CORE && SERIAL_DEV_BUS + select CRC16 + help + Say Y here to build support for the Sensirion SCD30 serial interface + driver. + + To compile this driver as a module, choose M here: the module will + be called scd30_serial. + config SENSIRION_SGP30 tristate "Sensirion SGPxx gas sensors" depends on I2C diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile index aba4167db745a619a609da5a80c2343a275d0098..fef63dd5bf927865bd086d7c45cde3bed23eff62 100644 --- a/drivers/iio/chemical/Makefile +++ b/drivers/iio/chemical/Makefile @@ -12,6 +12,9 @@ obj-$(CONFIG_BME680_SPI) += bme680_spi.o obj-$(CONFIG_CCS811) += ccs811.o obj-$(CONFIG_IAQCORE) += ams-iaq-core.o obj-$(CONFIG_PMS7003) += pms7003.o +obj-$(CONFIG_SCD30_CORE) += scd30_core.o +obj-$(CONFIG_SCD30_I2C) += scd30_i2c.o +obj-$(CONFIG_SCD30_SERIAL) += scd30_serial.o obj-$(CONFIG_SENSIRION_SGP30) += sgp30.o obj-$(CONFIG_SPS30) += sps30.o obj-$(CONFIG_VZ89X) += vz89x.o diff --git a/drivers/iio/chemical/ams-iaq-core.c b/drivers/iio/chemical/ams-iaq-core.c index a0646ba2ad8873f7f3e7beb503727032dacbcc4e..8c1b64fd424a4471676388341af0b12081d29b37 100644 --- a/drivers/iio/chemical/ams-iaq-core.c +++ b/drivers/iio/chemical/ams-iaq-core.c @@ -152,7 +152,6 @@ static int ams_iaqcore_probe(struct i2c_client *client, data->last_update = jiffies - HZ; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &ams_iaqcore_info; indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/chemical/atlas-ezo-sensor.c b/drivers/iio/chemical/atlas-ezo-sensor.c index f5a6d8ec6d4d3a498ca1e457cce992aee42eab27..8b72bb0123631d0248030d486596156611821df6 100644 --- a/drivers/iio/chemical/atlas-ezo-sensor.c +++ b/drivers/iio/chemical/atlas-ezo-sensor.c @@ -69,13 +69,13 @@ static int atlas_ezo_read_raw(struct iio_dev *indio_dev, { struct atlas_ezo_data *data = iio_priv(indio_dev); struct i2c_client *client = data->client; - int ret = 0; if (chan->type != IIO_CONCENTRATION) return -EINVAL; switch (mask) { case IIO_CHAN_INFO_RAW: { + int ret; long tmp; mutex_lock(&data->lock); @@ -110,7 +110,7 @@ static int atlas_ezo_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; } - return ret; + return 0; } static const struct iio_info atlas_info = { @@ -152,7 +152,6 @@ static int atlas_ezo_probe(struct i2c_client *client, indio_dev->channels = chip->channels; indio_dev->num_channels = chip->num_channels; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->dev.parent = &client->dev; data = iio_priv(indio_dev); data->client = client; diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c index 78a27e36bf32cac6fe09f6ae8c2e56cf1f5737bc..43069636fcd5128696464d12bc781038471e37ee 100644 --- a/drivers/iio/chemical/atlas-sensor.c +++ b/drivers/iio/chemical/atlas-sensor.c @@ -410,10 +410,6 @@ static int atlas_buffer_postenable(struct iio_dev *indio_dev) struct atlas_data *data = iio_priv(indio_dev); int ret; - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret) - return ret; - ret = pm_runtime_get_sync(&data->client->dev); if (ret < 0) { pm_runtime_put_noidle(&data->client->dev); @@ -437,7 +433,7 @@ static int atlas_buffer_predisable(struct iio_dev *indio_dev) if (ret) return ret; - return iio_triggered_buffer_predisable(indio_dev); + return 0; } static const struct iio_trigger_ops atlas_interrupt_trigger_ops = { @@ -644,7 +640,6 @@ static int atlas_probe(struct i2c_client *client, indio_dev->channels = chip->channels; indio_dev->num_channels = chip->num_channels; indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; - indio_dev->dev.parent = &client->dev; trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", indio_dev->name, indio_dev->id); diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c index 13773e01699ba084a3731883b24c4f78db06c2cf..6ea99e4cbf924bd3ceea394346e4fd7495035c6f 100644 --- a/drivers/iio/chemical/bme680_core.c +++ b/drivers/iio/chemical/bme680_core.c @@ -923,7 +923,6 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap, data = iio_priv(indio_dev); dev_set_drvdata(dev, indio_dev); data->regmap = regmap; - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->channels = bme680_channels; indio_dev->num_channels = ARRAY_SIZE(bme680_channels); diff --git a/drivers/iio/chemical/ccs811.c b/drivers/iio/chemical/ccs811.c index 3ecd633f9ed3261a2d51233b55d01156e1ab4e0f..2b007e7568b21b72d51a47614e7498269cc14c18 100644 --- a/drivers/iio/chemical/ccs811.c +++ b/drivers/iio/chemical/ccs811.c @@ -464,7 +464,6 @@ static int ccs811_probe(struct i2c_client *client, mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; indio_dev->info = &ccs811_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/chemical/pms7003.c b/drivers/iio/chemical/pms7003.c index 07bb90d724349e97edcf029fc7fabe3c74fe170b..e9d4405654bcee82d85da93525cd431f513ab61b 100644 --- a/drivers/iio/chemical/pms7003.c +++ b/drivers/iio/chemical/pms7003.c @@ -280,7 +280,6 @@ static int pms7003_probe(struct serdev_device *serdev) state = iio_priv(indio_dev); serdev_device_set_drvdata(serdev, indio_dev); state->serdev = serdev; - indio_dev->dev.parent = &serdev->dev; indio_dev->info = &pms7003_info; indio_dev->name = PMS7003_DRIVER_NAME; indio_dev->channels = pms7003_channels, diff --git a/drivers/iio/chemical/scd30.h b/drivers/iio/chemical/scd30.h new file mode 100644 index 0000000000000000000000000000000000000000..f60127bfe0f4fe82a3814a2c2d1088e1898bcfc3 --- /dev/null +++ b/drivers/iio/chemical/scd30.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _SCD30_H +#define _SCD30_H + +#include +#include +#include +#include +#include +#include + +struct scd30_state; + +enum scd30_cmd { + /* start continuous measurement with pressure compensation */ + CMD_START_MEAS, + /* stop continuous measurement */ + CMD_STOP_MEAS, + /* set/get measurement interval */ + CMD_MEAS_INTERVAL, + /* check whether new measurement is ready */ + CMD_MEAS_READY, + /* get measurement */ + CMD_READ_MEAS, + /* turn on/off automatic self calibration */ + CMD_ASC, + /* set/get forced recalibration value */ + CMD_FRC, + /* set/get temperature offset */ + CMD_TEMP_OFFSET, + /* get firmware version */ + CMD_FW_VERSION, + /* reset sensor */ + CMD_RESET, + /* + * Command for altitude compensation was omitted intentionally because + * the same can be achieved by means of CMD_START_MEAS which takes + * pressure above the sea level as an argument. + */ +}; + +#define SCD30_MEAS_COUNT 3 + +typedef int (*scd30_command_t)(struct scd30_state *state, enum scd30_cmd cmd, u16 arg, + void *response, int size); + +struct scd30_state { + /* serialize access to the device */ + struct mutex lock; + struct device *dev; + struct regulator *vdd; + struct completion meas_ready; + /* + * priv pointer is solely for serdev driver private data. We keep it + * here because driver_data inside dev has been already used for iio and + * struct serdev_device doesn't have one. + */ + void *priv; + int irq; + /* + * no way to retrieve current ambient pressure compensation value from + * the sensor so keep one around + */ + u16 pressure_comp; + u16 meas_interval; + int meas[SCD30_MEAS_COUNT]; + + scd30_command_t command; +}; + +int scd30_suspend(struct device *dev); +int scd30_resume(struct device *dev); + +static __maybe_unused SIMPLE_DEV_PM_OPS(scd30_pm_ops, scd30_suspend, scd30_resume); + +int scd30_probe(struct device *dev, int irq, const char *name, void *priv, scd30_command_t command); + +#endif diff --git a/drivers/iio/chemical/scd30_core.c b/drivers/iio/chemical/scd30_core.c new file mode 100644 index 0000000000000000000000000000000000000000..eac76972f83ea0234989d0e474c407a355cb1913 --- /dev/null +++ b/drivers/iio/chemical/scd30_core.c @@ -0,0 +1,771 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sensirion SCD30 carbon dioxide sensor core driver + * + * Copyright (c) 2020 Tomasz Duszynski + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scd30.h" + +#define SCD30_PRESSURE_COMP_MIN_MBAR 700 +#define SCD30_PRESSURE_COMP_MAX_MBAR 1400 +#define SCD30_PRESSURE_COMP_DEFAULT 1013 +#define SCD30_MEAS_INTERVAL_MIN_S 2 +#define SCD30_MEAS_INTERVAL_MAX_S 1800 +#define SCD30_MEAS_INTERVAL_DEFAULT SCD30_MEAS_INTERVAL_MIN_S +#define SCD30_FRC_MIN_PPM 400 +#define SCD30_FRC_MAX_PPM 2000 +#define SCD30_TEMP_OFFSET_MAX 655360 +#define SCD30_EXTRA_TIMEOUT_PER_S 250 + +enum { + SCD30_CONC, + SCD30_TEMP, + SCD30_HR, +}; + +static int scd30_command_write(struct scd30_state *state, enum scd30_cmd cmd, u16 arg) +{ + return state->command(state, cmd, arg, NULL, 0); +} + +static int scd30_command_read(struct scd30_state *state, enum scd30_cmd cmd, u16 *val) +{ + __be16 tmp; + int ret; + + ret = state->command(state, cmd, 0, &tmp, sizeof(tmp)); + *val = be16_to_cpup(&tmp); + + return ret; +} + +static int scd30_reset(struct scd30_state *state) +{ + int ret; + u16 val; + + ret = scd30_command_write(state, CMD_RESET, 0); + if (ret) + return ret; + + /* sensor boots up within 2 secs */ + msleep(2000); + /* + * Power-on-reset causes sensor to produce some glitch on i2c bus and + * some controllers end up in error state. Try to recover by placing + * any data on the bus. + */ + scd30_command_read(state, CMD_MEAS_READY, &val); + + return 0; +} + +/* simplified float to fixed point conversion with a scaling factor of 0.01 */ +static int scd30_float_to_fp(int float32) +{ + int fraction, shift, + mantissa = float32 & GENMASK(22, 0), + sign = (float32 & BIT(31)) ? -1 : 1, + exp = (float32 & ~BIT(31)) >> 23; + + /* special case 0 */ + if (!exp && !mantissa) + return 0; + + exp -= 127; + if (exp < 0) { + exp = -exp; + /* return values ranging from 1 to 99 */ + return sign * ((((BIT(23) + mantissa) * 100) >> 23) >> exp); + } + + /* return values starting at 100 */ + shift = 23 - exp; + float32 = BIT(exp) + (mantissa >> shift); + fraction = mantissa & GENMASK(shift - 1, 0); + + return sign * (float32 * 100 + ((fraction * 100) >> shift)); +} + +static int scd30_read_meas(struct scd30_state *state) +{ + int i, ret; + + ret = state->command(state, CMD_READ_MEAS, 0, state->meas, sizeof(state->meas)); + if (ret) + return ret; + + be32_to_cpu_array(state->meas, (__be32 *)state->meas, ARRAY_SIZE(state->meas)); + + for (i = 0; i < ARRAY_SIZE(state->meas); i++) + state->meas[i] = scd30_float_to_fp(state->meas[i]); + + /* + * co2 is left unprocessed while temperature and humidity are scaled + * to milli deg C and milli percent respectively. + */ + state->meas[SCD30_TEMP] *= 10; + state->meas[SCD30_HR] *= 10; + + return 0; +} + +static int scd30_wait_meas_irq(struct scd30_state *state) +{ + int ret, timeout; + + reinit_completion(&state->meas_ready); + enable_irq(state->irq); + timeout = msecs_to_jiffies(state->meas_interval * (1000 + SCD30_EXTRA_TIMEOUT_PER_S)); + ret = wait_for_completion_interruptible_timeout(&state->meas_ready, timeout); + if (ret > 0) + ret = 0; + else if (!ret) + ret = -ETIMEDOUT; + + disable_irq(state->irq); + + return ret; +} + +static int scd30_wait_meas_poll(struct scd30_state *state) +{ + int timeout = state->meas_interval * SCD30_EXTRA_TIMEOUT_PER_S, tries = 5; + + do { + int ret; + u16 val; + + ret = scd30_command_read(state, CMD_MEAS_READY, &val); + if (ret) + return -EIO; + + /* new measurement available */ + if (val) + break; + + msleep_interruptible(timeout); + } while (--tries); + + return tries ? 0 : -ETIMEDOUT; +} + +static int scd30_read_poll(struct scd30_state *state) +{ + int ret; + + ret = scd30_wait_meas_poll(state); + if (ret) + return ret; + + return scd30_read_meas(state); +} + +static int scd30_read(struct scd30_state *state) +{ + if (state->irq > 0) + return scd30_wait_meas_irq(state); + + return scd30_read_poll(state); +} + +static int scd30_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct scd30_state *state = iio_priv(indio_dev); + int ret = -EINVAL; + u16 tmp; + + mutex_lock(&state->lock); + switch (mask) { + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: + if (chan->output) { + *val = state->pressure_comp; + ret = IIO_VAL_INT; + break; + } + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + break; + + ret = scd30_read(state); + if (ret) { + iio_device_release_direct_mode(indio_dev); + break; + } + + *val = state->meas[chan->address]; + iio_device_release_direct_mode(indio_dev); + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 1; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = scd30_command_read(state, CMD_MEAS_INTERVAL, &tmp); + if (ret) + break; + + *val = 0; + *val2 = 1000000000 / tmp; + ret = IIO_VAL_INT_PLUS_NANO; + break; + case IIO_CHAN_INFO_CALIBBIAS: + ret = scd30_command_read(state, CMD_TEMP_OFFSET, &tmp); + if (ret) + break; + + *val = tmp; + ret = IIO_VAL_INT; + break; + } + mutex_unlock(&state->lock); + + return ret; +} + +static int scd30_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct scd30_state *state = iio_priv(indio_dev); + int ret = -EINVAL; + + mutex_lock(&state->lock); + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val) + break; + + val = 1000000000 / val2; + if (val < SCD30_MEAS_INTERVAL_MIN_S || val > SCD30_MEAS_INTERVAL_MAX_S) + break; + + ret = scd30_command_write(state, CMD_MEAS_INTERVAL, val); + if (ret) + break; + + state->meas_interval = val; + break; + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_PRESSURE: + if (val < SCD30_PRESSURE_COMP_MIN_MBAR || + val > SCD30_PRESSURE_COMP_MAX_MBAR) + break; + + ret = scd30_command_write(state, CMD_START_MEAS, val); + if (ret) + break; + + state->pressure_comp = val; + break; + default: + break; + } + break; + case IIO_CHAN_INFO_CALIBBIAS: + if (val < 0 || val > SCD30_TEMP_OFFSET_MAX) + break; + /* + * Manufacturer does not explicitly specify min/max sensible + * values hence check is omitted for simplicity. + */ + ret = scd30_command_write(state, CMD_TEMP_OFFSET / 10, val); + } + mutex_unlock(&state->lock); + + return ret; +} + +static int scd30_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_CALIBBIAS: + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static const int scd30_pressure_raw_available[] = { + SCD30_PRESSURE_COMP_MIN_MBAR, 1, SCD30_PRESSURE_COMP_MAX_MBAR, +}; + +static const int scd30_temp_calibbias_available[] = { + 0, 10, SCD30_TEMP_OFFSET_MAX, +}; + +static int scd30_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_RAW: + *vals = scd30_pressure_raw_available; + *type = IIO_VAL_INT; + + return IIO_AVAIL_RANGE; + case IIO_CHAN_INFO_CALIBBIAS: + *vals = scd30_temp_calibbias_available; + *type = IIO_VAL_INT; + + return IIO_AVAIL_RANGE; + } + + return -EINVAL; +} + +static ssize_t sampling_frequency_available_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int i = SCD30_MEAS_INTERVAL_MIN_S; + ssize_t len = 0; + + do { + len += scnprintf(buf + len, PAGE_SIZE - len, "0.%09u ", 1000000000 / i); + /* + * Not all values fit PAGE_SIZE buffer hence print every 6th + * (each frequency differs by 6s in time domain from the + * adjacent). Unlisted but valid ones are still accepted. + */ + i += 6; + } while (i <= SCD30_MEAS_INTERVAL_MAX_S); + + buf[len - 1] = '\n'; + + return len; +} + +static ssize_t calibration_auto_enable_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct scd30_state *state = iio_priv(indio_dev); + int ret; + u16 val; + + mutex_lock(&state->lock); + ret = scd30_command_read(state, CMD_ASC, &val); + mutex_unlock(&state->lock); + + return ret ?: sprintf(buf, "%d\n", val); +} + +static ssize_t calibration_auto_enable_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct scd30_state *state = iio_priv(indio_dev); + bool val; + int ret; + + ret = kstrtobool(buf, &val); + if (ret) + return ret; + + mutex_lock(&state->lock); + ret = scd30_command_write(state, CMD_ASC, val); + mutex_unlock(&state->lock); + + return ret ?: len; +} + +static ssize_t calibration_forced_value_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct scd30_state *state = iio_priv(indio_dev); + int ret; + u16 val; + + mutex_lock(&state->lock); + ret = scd30_command_read(state, CMD_FRC, &val); + mutex_unlock(&state->lock); + + return ret ?: sprintf(buf, "%d\n", val); +} + +static ssize_t calibration_forced_value_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct scd30_state *state = iio_priv(indio_dev); + int ret; + u16 val; + + ret = kstrtou16(buf, 0, &val); + if (ret) + return ret; + + if (val < SCD30_FRC_MIN_PPM || val > SCD30_FRC_MAX_PPM) + return -EINVAL; + + mutex_lock(&state->lock); + ret = scd30_command_write(state, CMD_FRC, val); + mutex_unlock(&state->lock); + + return ret ?: len; +} + +static IIO_DEVICE_ATTR_RO(sampling_frequency_available, 0); +static IIO_DEVICE_ATTR_RW(calibration_auto_enable, 0); +static IIO_DEVICE_ATTR_RW(calibration_forced_value, 0); + +static struct attribute *scd30_attrs[] = { + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, + &iio_dev_attr_calibration_auto_enable.dev_attr.attr, + &iio_dev_attr_calibration_forced_value.dev_attr.attr, + NULL +}; + +static const struct attribute_group scd30_attr_group = { + .attrs = scd30_attrs, +}; + +static const struct iio_info scd30_info = { + .attrs = &scd30_attr_group, + .read_raw = scd30_read_raw, + .write_raw = scd30_write_raw, + .write_raw_get_fmt = scd30_write_raw_get_fmt, + .read_avail = scd30_read_avail, +}; + +#define SCD30_CHAN_SCAN_TYPE(_sign, _realbits) .scan_type = { \ + .sign = _sign, \ + .realbits = _realbits, \ + .storagebits = 32, \ + .endianness = IIO_CPU, \ +} + +static const struct iio_chan_spec scd30_channels[] = { + { + /* + * this channel is special in a sense we are pretending that + * sensor is able to change measurement chamber pressure but in + * fact we're just setting pressure compensation value + */ + .type = IIO_PRESSURE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW), + .output = 1, + .scan_index = -1, + }, + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_CO2, + .address = SCD30_CONC, + .scan_index = SCD30_CONC, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .modified = 1, + + SCD30_CHAN_SCAN_TYPE('u', 20), + }, + { + .type = IIO_TEMP, + .address = SCD30_TEMP, + .scan_index = SCD30_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + .info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBBIAS), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + + SCD30_CHAN_SCAN_TYPE('s', 18), + }, + { + .type = IIO_HUMIDITYRELATIVE, + .address = SCD30_HR, + .scan_index = SCD30_HR, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + + SCD30_CHAN_SCAN_TYPE('u', 17), + }, + IIO_CHAN_SOFT_TIMESTAMP(3), +}; + +int __maybe_unused scd30_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct scd30_state *state = iio_priv(indio_dev); + int ret; + + ret = scd30_command_write(state, CMD_STOP_MEAS, 0); + if (ret) + return ret; + + return regulator_disable(state->vdd); +} +EXPORT_SYMBOL(scd30_suspend); + +int __maybe_unused scd30_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct scd30_state *state = iio_priv(indio_dev); + int ret; + + ret = regulator_enable(state->vdd); + if (ret) + return ret; + + return scd30_command_write(state, CMD_START_MEAS, state->pressure_comp); +} +EXPORT_SYMBOL(scd30_resume); + +static void scd30_stop_meas(void *data) +{ + struct scd30_state *state = data; + + scd30_command_write(state, CMD_STOP_MEAS, 0); +} + +static void scd30_disable_regulator(void *data) +{ + struct scd30_state *state = data; + + regulator_disable(state->vdd); +} + +static irqreturn_t scd30_irq_handler(int irq, void *priv) +{ + struct iio_dev *indio_dev = priv; + + if (iio_buffer_enabled(indio_dev)) { + iio_trigger_poll(indio_dev->trig); + + return IRQ_HANDLED; + } + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t scd30_irq_thread_handler(int irq, void *priv) +{ + struct iio_dev *indio_dev = priv; + struct scd30_state *state = iio_priv(indio_dev); + int ret; + + ret = scd30_read_meas(state); + if (ret) + goto out; + + complete_all(&state->meas_ready); +out: + return IRQ_HANDLED; +} + +static irqreturn_t scd30_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct scd30_state *state = iio_priv(indio_dev); + struct { + int data[SCD30_MEAS_COUNT]; + s64 ts __aligned(8); + } scan; + int ret; + + mutex_lock(&state->lock); + if (!iio_trigger_using_own(indio_dev)) + ret = scd30_read_poll(state); + else + ret = scd30_read_meas(state); + memset(&scan, 0, sizeof(scan)); + memcpy(scan.data, state->meas, sizeof(state->meas)); + mutex_unlock(&state->lock); + if (ret) + goto out; + + iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev)); +out: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static int scd30_set_trigger_state(struct iio_trigger *trig, bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct scd30_state *st = iio_priv(indio_dev); + + if (state) + enable_irq(st->irq); + else + disable_irq(st->irq); + + return 0; +} + +static const struct iio_trigger_ops scd30_trigger_ops = { + .set_trigger_state = scd30_set_trigger_state, + .validate_device = iio_trigger_validate_own_device, +}; + +static int scd30_setup_trigger(struct iio_dev *indio_dev) +{ + struct scd30_state *state = iio_priv(indio_dev); + struct device *dev = indio_dev->dev.parent; + struct iio_trigger *trig; + int ret; + + trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, indio_dev->id); + if (!trig) { + dev_err(dev, "failed to allocate trigger\n"); + return -ENOMEM; + } + + trig->dev.parent = dev; + trig->ops = &scd30_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + + ret = devm_iio_trigger_register(dev, trig); + if (ret) + return ret; + + indio_dev->trig = iio_trigger_get(trig); + + ret = devm_request_threaded_irq(dev, state->irq, scd30_irq_handler, + scd30_irq_thread_handler, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + indio_dev->name, indio_dev); + if (ret) + dev_err(dev, "failed to request irq\n"); + + /* + * Interrupt is enabled just before taking a fresh measurement + * and disabled afterwards. This means we need to disable it here + * to keep calls to enable/disable balanced. + */ + disable_irq(state->irq); + + return ret; +} + +int scd30_probe(struct device *dev, int irq, const char *name, void *priv, + scd30_command_t command) +{ + static const unsigned long scd30_scan_masks[] = { 0x07, 0x00 }; + struct scd30_state *state; + struct iio_dev *indio_dev; + int ret; + u16 val; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*state)); + if (!indio_dev) + return -ENOMEM; + + state = iio_priv(indio_dev); + state->dev = dev; + state->priv = priv; + state->irq = irq; + state->pressure_comp = SCD30_PRESSURE_COMP_DEFAULT; + state->meas_interval = SCD30_MEAS_INTERVAL_DEFAULT; + state->command = command; + mutex_init(&state->lock); + init_completion(&state->meas_ready); + + dev_set_drvdata(dev, indio_dev); + + indio_dev->info = &scd30_info; + indio_dev->name = name; + indio_dev->channels = scd30_channels; + indio_dev->num_channels = ARRAY_SIZE(scd30_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->available_scan_masks = scd30_scan_masks; + + state->vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(state->vdd)) { + if (PTR_ERR(state->vdd) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_err(dev, "failed to get regulator\n"); + return PTR_ERR(state->vdd); + } + + ret = regulator_enable(state->vdd); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, scd30_disable_regulator, state); + if (ret) + return ret; + + ret = scd30_reset(state); + if (ret) { + dev_err(dev, "failed to reset device: %d\n", ret); + return ret; + } + + if (state->irq > 0) { + ret = scd30_setup_trigger(indio_dev); + if (ret) { + dev_err(dev, "failed to setup trigger: %d\n", ret); + return ret; + } + } + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, scd30_trigger_handler, NULL); + if (ret) + return ret; + + ret = scd30_command_read(state, CMD_FW_VERSION, &val); + if (ret) { + dev_err(dev, "failed to read firmware version: %d\n", ret); + return ret; + } + dev_info(dev, "firmware version: %d.%d\n", val >> 8, (char)val); + + ret = scd30_command_write(state, CMD_MEAS_INTERVAL, state->meas_interval); + if (ret) { + dev_err(dev, "failed to set measurement interval: %d\n", ret); + return ret; + } + + ret = scd30_command_write(state, CMD_START_MEAS, state->pressure_comp); + if (ret) { + dev_err(dev, "failed to start measurement: %d\n", ret); + return ret; + } + + ret = devm_add_action_or_reset(dev, scd30_stop_meas, state); + if (ret) + return ret; + + return devm_iio_device_register(dev, indio_dev); +} +EXPORT_SYMBOL(scd30_probe); + +MODULE_AUTHOR("Tomasz Duszynski "); +MODULE_DESCRIPTION("Sensirion SCD30 carbon dioxide sensor core driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/chemical/scd30_i2c.c b/drivers/iio/chemical/scd30_i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..875892a070eec78d68a40eacc4ad07ca5b5634f1 --- /dev/null +++ b/drivers/iio/chemical/scd30_i2c.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sensirion SCD30 carbon dioxide sensor i2c driver + * + * Copyright (c) 2020 Tomasz Duszynski + * + * I2C slave address: 0x61 + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scd30.h" + +#define SCD30_I2C_MAX_BUF_SIZE 18 +#define SCD30_I2C_CRC8_POLYNOMIAL 0x31 + +static u16 scd30_i2c_cmd_lookup_tbl[] = { + [CMD_START_MEAS] = 0x0010, + [CMD_STOP_MEAS] = 0x0104, + [CMD_MEAS_INTERVAL] = 0x4600, + [CMD_MEAS_READY] = 0x0202, + [CMD_READ_MEAS] = 0x0300, + [CMD_ASC] = 0x5306, + [CMD_FRC] = 0x5204, + [CMD_TEMP_OFFSET] = 0x5403, + [CMD_FW_VERSION] = 0xd100, + [CMD_RESET] = 0xd304, +}; + +DECLARE_CRC8_TABLE(scd30_i2c_crc8_tbl); + +static int scd30_i2c_xfer(struct scd30_state *state, char *txbuf, int txsize, + char *rxbuf, int rxsize) +{ + struct i2c_client *client = to_i2c_client(state->dev); + int ret; + + /* + * repeated start is not supported hence instead of sending two i2c + * messages in a row we send one by one + */ + ret = i2c_master_send(client, txbuf, txsize); + if (ret < 0) + return ret; + if (ret != txsize) + return -EIO; + + if (!rxbuf) + return 0; + + ret = i2c_master_recv(client, rxbuf, rxsize); + if (ret < 0) + return ret; + if (ret != rxsize) + return -EIO; + + return 0; +} + +static int scd30_i2c_command(struct scd30_state *state, enum scd30_cmd cmd, u16 arg, + void *response, int size) +{ + char buf[SCD30_I2C_MAX_BUF_SIZE]; + char *rsp = response; + int i, ret; + char crc; + + put_unaligned_be16(scd30_i2c_cmd_lookup_tbl[cmd], buf); + i = 2; + + if (rsp) { + /* each two bytes are followed by a crc8 */ + size += size / 2; + } else { + put_unaligned_be16(arg, buf + i); + crc = crc8(scd30_i2c_crc8_tbl, buf + i, 2, CRC8_INIT_VALUE); + i += 2; + buf[i] = crc; + i += 1; + + /* commands below don't take an argument */ + if ((cmd == CMD_STOP_MEAS) || (cmd == CMD_RESET)) + i -= 3; + } + + ret = scd30_i2c_xfer(state, buf, i, buf, size); + if (ret) + return ret; + + /* validate received data and strip off crc bytes */ + for (i = 0; i < size; i += 3) { + crc = crc8(scd30_i2c_crc8_tbl, buf + i, 2, CRC8_INIT_VALUE); + if (crc != buf[i + 2]) { + dev_err(state->dev, "data integrity check failed\n"); + return -EIO; + } + + *rsp++ = buf[i]; + *rsp++ = buf[i + 1]; + } + + return 0; +} + +static int scd30_i2c_probe(struct i2c_client *client) +{ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EOPNOTSUPP; + + crc8_populate_msb(scd30_i2c_crc8_tbl, SCD30_I2C_CRC8_POLYNOMIAL); + + return scd30_probe(&client->dev, client->irq, client->name, NULL, scd30_i2c_command); +} + +static const struct of_device_id scd30_i2c_of_match[] = { + { .compatible = "sensirion,scd30" }, + { } +}; +MODULE_DEVICE_TABLE(of, scd30_i2c_of_match); + +static struct i2c_driver scd30_i2c_driver = { + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = scd30_i2c_of_match, + .pm = &scd30_pm_ops, + }, + .probe_new = scd30_i2c_probe, +}; +module_i2c_driver(scd30_i2c_driver); + +MODULE_AUTHOR("Tomasz Duszynski "); +MODULE_DESCRIPTION("Sensirion SCD30 carbon dioxide sensor i2c driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/chemical/scd30_serial.c b/drivers/iio/chemical/scd30_serial.c new file mode 100644 index 0000000000000000000000000000000000000000..06f85eb1a4dd840c2270bb3057aec8aff53df425 --- /dev/null +++ b/drivers/iio/chemical/scd30_serial.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sensirion SCD30 carbon dioxide sensor serial driver + * + * Copyright (c) 2020 Tomasz Duszynski + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scd30.h" + +#define SCD30_SERDEV_ADDR 0x61 +#define SCD30_SERDEV_WRITE 0x06 +#define SCD30_SERDEV_READ 0x03 +#define SCD30_SERDEV_MAX_BUF_SIZE 17 +#define SCD30_SERDEV_RX_HEADER_SIZE 3 +#define SCD30_SERDEV_CRC_SIZE 2 +#define SCD30_SERDEV_TIMEOUT msecs_to_jiffies(200) + +struct scd30_serdev_priv { + struct completion meas_ready; + char *buf; + int num_expected; + int num; +}; + +static u16 scd30_serdev_cmd_lookup_tbl[] = { + [CMD_START_MEAS] = 0x0036, + [CMD_STOP_MEAS] = 0x0037, + [CMD_MEAS_INTERVAL] = 0x0025, + [CMD_MEAS_READY] = 0x0027, + [CMD_READ_MEAS] = 0x0028, + [CMD_ASC] = 0x003a, + [CMD_FRC] = 0x0039, + [CMD_TEMP_OFFSET] = 0x003b, + [CMD_FW_VERSION] = 0x0020, + [CMD_RESET] = 0x0034, +}; + +static u16 scd30_serdev_calc_crc(const char *buf, int size) +{ + return crc16(0xffff, buf, size); +} + +static int scd30_serdev_xfer(struct scd30_state *state, char *txbuf, int txsize, + char *rxbuf, int rxsize) +{ + struct serdev_device *serdev = to_serdev_device(state->dev); + struct scd30_serdev_priv *priv = state->priv; + int ret; + + priv->buf = rxbuf; + priv->num_expected = rxsize; + priv->num = 0; + + ret = serdev_device_write(serdev, txbuf, txsize, SCD30_SERDEV_TIMEOUT); + if (ret < 0) + return ret; + if (ret != txsize) + return -EIO; + + ret = wait_for_completion_interruptible_timeout(&priv->meas_ready, SCD30_SERDEV_TIMEOUT); + if (ret < 0) + return ret; + if (!ret) + return -ETIMEDOUT; + + return 0; +} + +static int scd30_serdev_command(struct scd30_state *state, enum scd30_cmd cmd, u16 arg, + void *response, int size) +{ + /* + * Communication over serial line is based on modbus protocol (or rather + * its variation called modbus over serial to be precise). Upon + * receiving a request device should reply with response. + * + * Frame below represents a request message. Each field takes + * exactly one byte. + * + * +------+------+-----+-----+-------+-------+-----+-----+ + * | dev | op | reg | reg | byte1 | byte0 | crc | crc | + * | addr | code | msb | lsb | | | lsb | msb | + * +------+------+-----+-----+-------+-------+-----+-----+ + * + * The message device replies with depends on the 'op code' field from + * the request. In case it was set to SCD30_SERDEV_WRITE sensor should + * reply with unchanged request. Otherwise 'op code' was set to + * SCD30_SERDEV_READ and response looks like the one below. As with + * request, each field takes one byte. + * + * +------+------+--------+-------+-----+-------+-----+-----+ + * | dev | op | num of | byte0 | ... | byteN | crc | crc | + * | addr | code | bytes | | | | lsb | msb | + * +------+------+--------+-------+-----+-------+-----+-----+ + */ + char txbuf[SCD30_SERDEV_MAX_BUF_SIZE] = { SCD30_SERDEV_ADDR }, + rxbuf[SCD30_SERDEV_MAX_BUF_SIZE]; + int ret, rxsize, txsize = 2; + char *rsp = response; + u16 crc; + + put_unaligned_be16(scd30_serdev_cmd_lookup_tbl[cmd], txbuf + txsize); + txsize += 2; + + if (rsp) { + txbuf[1] = SCD30_SERDEV_READ; + if (cmd == CMD_READ_MEAS) + /* number of u16 words to read */ + put_unaligned_be16(size / 2, txbuf + txsize); + else + put_unaligned_be16(0x0001, txbuf + txsize); + txsize += 2; + crc = scd30_serdev_calc_crc(txbuf, txsize); + put_unaligned_le16(crc, txbuf + txsize); + txsize += 2; + rxsize = SCD30_SERDEV_RX_HEADER_SIZE + size + SCD30_SERDEV_CRC_SIZE; + } else { + if ((cmd == CMD_STOP_MEAS) || (cmd == CMD_RESET)) + arg = 0x0001; + + txbuf[1] = SCD30_SERDEV_WRITE; + put_unaligned_be16(arg, txbuf + txsize); + txsize += 2; + crc = scd30_serdev_calc_crc(txbuf, txsize); + put_unaligned_le16(crc, txbuf + txsize); + txsize += 2; + rxsize = txsize; + } + + ret = scd30_serdev_xfer(state, txbuf, txsize, rxbuf, rxsize); + if (ret) + return ret; + + switch (txbuf[1]) { + case SCD30_SERDEV_WRITE: + if (memcmp(txbuf, rxbuf, txsize)) { + dev_err(state->dev, "wrong message received\n"); + return -EIO; + } + break; + case SCD30_SERDEV_READ: + if (rxbuf[2] != (rxsize - SCD30_SERDEV_RX_HEADER_SIZE - SCD30_SERDEV_CRC_SIZE)) { + dev_err(state->dev, "received data size does not match header\n"); + return -EIO; + } + + rxsize -= SCD30_SERDEV_CRC_SIZE; + crc = get_unaligned_le16(rxbuf + rxsize); + if (crc != scd30_serdev_calc_crc(rxbuf, rxsize)) { + dev_err(state->dev, "data integrity check failed\n"); + return -EIO; + } + + rxsize -= SCD30_SERDEV_RX_HEADER_SIZE; + memcpy(rsp, rxbuf + SCD30_SERDEV_RX_HEADER_SIZE, rxsize); + break; + default: + dev_err(state->dev, "received unknown op code\n"); + return -EIO; + } + + return 0; +} + +static int scd30_serdev_receive_buf(struct serdev_device *serdev, + const unsigned char *buf, size_t size) +{ + struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev); + struct scd30_serdev_priv *priv; + struct scd30_state *state; + int num; + + if (!indio_dev) + return 0; + + state = iio_priv(indio_dev); + priv = state->priv; + + /* just in case sensor puts some unexpected bytes on the bus */ + if (!priv->buf) + return 0; + + if (priv->num + size >= priv->num_expected) + num = priv->num_expected - priv->num; + else + num = size; + + memcpy(priv->buf + priv->num, buf, num); + priv->num += num; + + if (priv->num == priv->num_expected) { + priv->buf = NULL; + complete(&priv->meas_ready); + } + + return num; +} + +static const struct serdev_device_ops scd30_serdev_ops = { + .receive_buf = scd30_serdev_receive_buf, + .write_wakeup = serdev_device_write_wakeup, +}; + +static int scd30_serdev_probe(struct serdev_device *serdev) +{ + struct device *dev = &serdev->dev; + struct scd30_serdev_priv *priv; + int irq, ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + init_completion(&priv->meas_ready); + serdev_device_set_client_ops(serdev, &scd30_serdev_ops); + + ret = devm_serdev_device_open(dev, serdev); + if (ret) + return ret; + + serdev_device_set_baudrate(serdev, 19200); + serdev_device_set_flow_control(serdev, false); + + ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); + if (ret) + return ret; + + irq = fwnode_irq_get(dev_fwnode(dev), 0); + + return scd30_probe(dev, irq, KBUILD_MODNAME, priv, scd30_serdev_command); +} + +static const struct of_device_id scd30_serdev_of_match[] = { + { .compatible = "sensirion,scd30" }, + { } +}; +MODULE_DEVICE_TABLE(of, scd30_serdev_of_match); + +static struct serdev_device_driver scd30_serdev_driver = { + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = scd30_serdev_of_match, + .pm = &scd30_pm_ops, + }, + .probe = scd30_serdev_probe, +}; +module_serdev_device_driver(scd30_serdev_driver); + +MODULE_AUTHOR("Tomasz Duszynski "); +MODULE_DESCRIPTION("Sensirion SCD30 carbon dioxide sensor serial driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c index 403e8803471a9b7ac84364ab8b426574f0d898f9..2c4086c481362437f4df08a641e5585caa0fc05b 100644 --- a/drivers/iio/chemical/sgp30.c +++ b/drivers/iio/chemical/sgp30.c @@ -533,7 +533,6 @@ static int sgp_probe(struct i2c_client *client, if (ret) return ret; - indio_dev->dev.parent = &client->dev; indio_dev->info = &sgp_info; indio_dev->name = id->name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c index a88c1fb875a04c79b2b6e7f4d21c8200a661f7eb..5a29e32c295fc9c3e60ced52121e02e3463bdf7f 100644 --- a/drivers/iio/chemical/sps30.c +++ b/drivers/iio/chemical/sps30.c @@ -487,7 +487,6 @@ static int sps30_probe(struct i2c_client *client) i2c_set_clientdata(client, indio_dev); state->client = client; state->state = RESET; - indio_dev->dev.parent = &client->dev; indio_dev->info = &sps30_info; indio_dev->name = client->name; indio_dev->channels = sps30_channels; diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c index 415b39339d4ef66ef253be562bd0925f878f3a5c..5586eb8e12cd1e14f9d1d5456251adf7f8132a90 100644 --- a/drivers/iio/chemical/vz89x.c +++ b/drivers/iio/chemical/vz89x.c @@ -382,7 +382,6 @@ static int vz89x_probe(struct i2c_client *client, data->last_update = jiffies - HZ; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &vz89x_info; indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index a66941fdb3855bea5fc1e45a7510d97e746b39d8..130ab8ce0269bf67a375a00b9238a5b0e804b364 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -200,6 +200,10 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, st->core.param.sensor_range.roundup = 1; ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret == 0) { + st->core.range_updated = true; + st->core.curr_range = val; + } break; default: ret = cros_ec_sensors_core_write( @@ -315,6 +319,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids); static struct platform_driver cros_ec_sensors_platform_driver = { .driver = { .name = "cros-ec-sensors", + .pm = &cros_ec_sensors_pm_ops, }, .probe = cros_ec_sensors_probe, .id_table = cros_ec_sensors_ids, diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index c831915ca7e563167fe75770227c8154b86eba5f..ea480c1d4349ec0789044cb8dc398a2883078422 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -281,7 +281,6 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; state->msg->outsize = sizeof(struct ec_params_motion_sense); - indio_dev->dev.parent = &pdev->dev; indio_dev->name = pdev->name; if (physical_device) { @@ -352,7 +351,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, } else { /* * The only way to get samples in buffer is to set a - * software tigger (systrig, hrtimer). + * software trigger (systrig, hrtimer). */ ret = devm_iio_triggered_buffer_setup( dev, indio_dev, NULL, trigger_capture, @@ -824,5 +823,26 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, } EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write); +static int __maybe_unused cros_ec_sensors_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + int ret = 0; + + if (st->range_updated) { + mutex_lock(&st->cmd_lock); + st->param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; + st->param.sensor_range.data = st->curr_range; + st->param.sensor_range.roundup = 1; + ret = cros_ec_motion_send_host_cmd(st, 0); + mutex_unlock(&st->cmd_lock); + } + return ret; +} + +SIMPLE_DEV_PM_OPS(cros_ec_sensors_pm_ops, NULL, cros_ec_sensors_resume); +EXPORT_SYMBOL_GPL(cros_ec_sensors_pm_ops); + MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c index b52cba1b3c8319120545bc0dd48abd735a60d314..b9e2038d05ef4036fcf8868d927192f4cf2660fc 100644 --- a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c +++ b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c @@ -165,7 +165,7 @@ static bool ms_sensors_crc_valid(u32 value) /** * ms_sensors_read_serial() - Serial number read function - * @cli: pointer to i2c client + * @client: pointer to i2c client * @sn: pointer to 64-bits destination value * * Generic i2c serial number read function for Measurement Specialties devices. diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c index b400560bac9390ad6300979c98416f6cc548fb84..b9e59ad32a02ed99adba60831824dd488d2a70f3 100644 --- a/drivers/iio/common/st_sensors/st_sensors_i2c.c +++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c @@ -56,7 +56,6 @@ int st_sensors_i2c_configure(struct iio_dev *indio_dev, i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; indio_dev->name = client->name; sdata->dev = &client->dev; diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c index ee70515bb89f514cb86dd25c95fab9f97648e411..48fc41dc5633f84772aa6fb03895fc345b81e500 100644 --- a/drivers/iio/common/st_sensors/st_sensors_spi.c +++ b/drivers/iio/common/st_sensors/st_sensors_spi.c @@ -108,7 +108,6 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev, spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi->modalias; sdata->dev = &spi->dev; diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index d33642de9720ec689635f54cc68bc7d1a99956c7..fef503f8012d112e9eae00b24ea503171f72a170 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -787,7 +787,7 @@ static const char * const ad5064_vref_names[] = { "vrefD", }; -static const char * const ad5064_vref_name(struct ad5064_state *st, +static const char *ad5064_vref_name(struct ad5064_state *st, unsigned int vref) { return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; @@ -874,7 +874,6 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type, return ret; } - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &ad5064_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c index 3e0c9e84e8dab9d9128f0e5b0c9f8b37f21bbef6..602dd2ba61b552d4eafd5af0fbdd19d3b56aafa7 100644 --- a/drivers/iio/dac/ad5360.c +++ b/drivers/iio/dac/ad5360.c @@ -67,7 +67,7 @@ struct ad5360_chip_info { * @chip_info: chip model specific constants, available modes etc * @vref_reg: vref supply regulators * @ctrl: control register cache - * @lock lock to protect the data buffer during SPI ops + * @lock: lock to protect the data buffer during SPI ops * @data: spi transfer buffers */ @@ -476,7 +476,6 @@ static int ad5360_probe(struct spi_device *spi) st->chip_info = &ad5360_chip_info_tbl[type]; st->spi = spi; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5360_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index b37e5675f7162e4e2b7a88ba8161deb3ee5e1ce9..37ef653564b0a29d62e0f05b1beba1ee0ba3070b 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -51,7 +51,7 @@ struct ad5380_chip_info { * @vref_reg: vref supply regulator * @vref: actual reference voltage used in uA * @pwr_down: whether the chip is currently in power down mode - * @lock lock to protect the data buffer during regmap ops + * @lock: lock to protect the data buffer during regmap ops */ struct ad5380_state { @@ -240,7 +240,7 @@ static const struct iio_info ad5380_info = { .write_raw = ad5380_write_raw, }; -static struct iio_chan_spec_ext_info ad5380_ext_info[] = { +static const struct iio_chan_spec_ext_info ad5380_ext_info[] = { { .name = "powerdown", .read = ad5380_read_dac_powerdown, @@ -386,7 +386,6 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap, st->chip_info = &ad5380_chip_info_tbl[type]; st->regmap = regmap; - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &ad5380_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c index fec27764cea88c44992eae04aa0fd85a61566870..eedf661d32b2d1cc91b958049e0a43acdf51b901 100644 --- a/drivers/iio/dac/ad5421.c +++ b/drivers/iio/dac/ad5421.c @@ -62,7 +62,7 @@ * @current_range: current range which the device is configured for * @data: spi transfer buffers * @fault_mask: software masking of events - * @lock lock to protect the data buffer during SPI ops + * @lock: lock to protect the data buffer during SPI ops */ struct ad5421_state { struct spi_device *spi; @@ -487,7 +487,6 @@ static int ad5421_probe(struct spi_device *spi) st->spi = spi; - indio_dev->dev.parent = &spi->dev; indio_dev->name = "ad5421"; indio_dev->info = &ad5421_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 8f8afc8999bc70783b52b2b94dff4e7b6a1199d5..935a6177569f5b40b639182e5c4c35f4a81d64e6 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c @@ -29,11 +29,14 @@ /** * struct ad5446_state - driver instance specific data - * @spi: spi_device + * @dev: this device * @chip_info: chip model specific constants, available modes etc * @reg: supply regulator * @vref_mv: actual reference voltage used - * @lock lock to protect the data buffer during write ops + * @cached_val: store/retrieve values during power down + * @pwr_down_mode: power down mode (1k, 100k or tristate) + * @pwr_down: true if the device is in power down + * @lock: lock to protect the data buffer during write ops */ struct ad5446_state { @@ -250,8 +253,6 @@ static int ad5446_probe(struct device *dev, const char *name, st->reg = reg; st->dev = dev; - /* Establish that the iio_dev is a child of the device */ - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &ad5446_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -313,7 +314,7 @@ static int ad5660_write(struct ad5446_state *st, unsigned val) return spi_write(spi, data, sizeof(data)); } -/** +/* * ad5446_supported_spi_device_ids: * The AD5620/40/60 parts are available in different fixed internal reference * voltage options. The actual part numbers may look differently @@ -535,7 +536,7 @@ static int ad5622_write(struct ad5446_state *st, unsigned val) return i2c_master_send(client, (char *)&data, sizeof(data)); } -/** +/* * ad5446_supported_i2c_device_ids: * The AD5620/40/60 parts are available in different fixed internal reference * voltage options. The actual part numbers may look differently diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c index d739b10e52362fd491f910cbfe65a041aaf3c861..f5e93c6acc9d016b91181e63984661a47398fb65 100644 --- a/drivers/iio/dac/ad5449.c +++ b/drivers/iio/dac/ad5449.c @@ -56,7 +56,7 @@ struct ad5449_chip_info { * @has_sdo: whether the SDO line is connected * @dac_cache: Cache for the DAC values * @data: spi transfer buffers - * @lock lock to protect the data buffer during SPI ops + * @lock: lock to protect the data buffer during SPI ops */ struct ad5449 { struct spi_device *spi; @@ -297,7 +297,6 @@ static int ad5449_spi_probe(struct spi_device *spi) if (ret) return ret; - indio_dev->dev.parent = &spi->dev; indio_dev->name = id->name; indio_dev->info = &ad5449_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index c64e6898ff20ab043b7437921c9f959ce34d0ffb..28921b62e64203427a79272798ac9cea4f3c93ce 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -43,8 +43,8 @@ * @spi: spi_device * @reg: supply regulator * @vref_mv: actual reference voltage used - * @pwr_down_mask power down mask - * @pwr_down_mode current power down mode + * @pwr_down_mask: power down mask + * @pwr_down_mode: current power down mode * @data: transfer buffer */ struct ad5504_state { @@ -57,10 +57,9 @@ struct ad5504_state { __be16 data[2] ____cacheline_aligned; }; -/** +/* * ad5504_supported_device_ids: */ - enum ad5504_supported_device_ids { ID_AD5504, ID_AD5501, @@ -304,7 +303,6 @@ static int ad5504_probe(struct spi_device *spi) st->reg = reg; st->spi = spi; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(st->spi)->name; indio_dev->info = &ad5504_info; if (spi_get_device_id(st->spi)->driver_data == ID_AD5501) diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c index 410e90e5f75fb95b31244ef9414fb4c0a056e49a..cc4875660a69f4889233eb7ae6346221592913cb 100644 --- a/drivers/iio/dac/ad5592r-base.c +++ b/drivers/iio/dac/ad5592r-base.c @@ -413,7 +413,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, s64 tmp = *val * (3767897513LL / 25LL); *val = div_s64_rem(tmp, 1000000000LL, val2); - ret = IIO_VAL_INT_PLUS_MICRO; + return IIO_VAL_INT_PLUS_MICRO; } else { int mult; @@ -444,7 +444,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, ret = IIO_VAL_INT; break; default: - ret = -EINVAL; + return -EINVAL; } unlock: @@ -484,7 +484,7 @@ static ssize_t ad5592r_show_scale_available(struct iio_dev *iio_dev, st->scale_avail[1][0], st->scale_avail[1][1]); } -static struct iio_chan_spec_ext_info ad5592r_ext_info[] = { +static const struct iio_chan_spec_ext_info ad5592r_ext_info[] = { { .name = "scale_available", .read = ad5592r_show_scale_available, @@ -508,11 +508,11 @@ static void ad5592r_setup_channel(struct iio_dev *iio_dev, chan->ext_info = ad5592r_ext_info; } -static int ad5592r_alloc_channels(struct ad5592r_state *st) +static int ad5592r_alloc_channels(struct iio_dev *iio_dev) { + struct ad5592r_state *st = iio_priv(iio_dev); unsigned i, curr_channel = 0, num_channels = st->num_channels; - struct iio_dev *iio_dev = iio_priv_to_dev(st); struct iio_chan_spec *channels; struct fwnode_handle *child; u32 reg, tmp; @@ -618,7 +618,6 @@ int ad5592r_probe(struct device *dev, const char *name, return ret; } - iio_dev->dev.parent = dev; iio_dev->name = name; iio_dev->info = &ad5592r_info; iio_dev->modes = INDIO_DIRECT_MODE; @@ -636,7 +635,7 @@ int ad5592r_probe(struct device *dev, const char *name, if (ret) goto error_disable_reg; - ret = ad5592r_alloc_channels(st); + ret = ad5592r_alloc_channels(iio_dev); if (ret) goto error_disable_reg; diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index 2015a5df840c3b6a7c800f6c61cfa4f234cd129a..2b2b8edfd258cb311ee2126bd609356496959917 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -253,7 +253,6 @@ static int ad5624r_probe(struct spi_device *spi) st->us = spi; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5624r_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 8dd67da0a7da2fea2dd1ccecf0cef2bedaac4ec2..56cf9344d187d908f409ca111ac09fc509b7ae32 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -461,7 +461,6 @@ int ad5686_probe(struct device *dev, for (i = 0; i < st->chip_info->num_channels; i++) st->pwr_down_mode |= (0x01 << (i * 2)); - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &ad5686_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index 7723bd313fc6ec442905295212b6c2ab7a8c1b85..0df28acf074a858cd3c3f73611eedb7ca449af29 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -82,7 +82,7 @@ struct ad5755_chip_info { * @pwr_down: bitmask which contains hether a channel is powered down or not * @ctrl: software shadow of the channel ctrl registers * @channels: iio channel spec for the device - * @lock lock to protect the data buffer during SPI ops + * @lock: lock to protect the data buffer during SPI ops * @data: spi transfer buffers */ struct ad5755_state { @@ -744,7 +744,6 @@ static int ad5755_probe(struct spi_device *spi) st->spi = spi; st->pwr_down = 0xf; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5755_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5758.c b/drivers/iio/dac/ad5758.c index 475646c82b40e2dd61e5747f2c687c198b52cbcf..bd9ac8359d986c6776f7642014017cd20aec90af 100644 --- a/drivers/iio/dac/ad5758.c +++ b/drivers/iio/dac/ad5758.c @@ -92,24 +92,24 @@ #define AD5758_FULL_SCALE_MICRO 65535000000ULL +struct ad5758_range { + int reg; + int min; + int max; +}; + /** * struct ad5758_state - driver instance specific data * @spi: spi_device * @lock: mutex lock + * @gpio_reset: gpio descriptor for the reset line * @out_range: struct which stores the output range * @dc_dc_mode: variable which stores the mode of operation * @dc_dc_ilim: variable which stores the dc-to-dc converter current limit * @slew_time: variable which stores the target slew time * @pwr_down: variable which contains whether a channel is powered down or not - * @data: spi transfer buffers + * @d32: spi transfer buffers */ - -struct ad5758_range { - int reg; - int min; - int max; -}; - struct ad5758_state { struct spi_device *spi; struct mutex lock; @@ -122,7 +122,7 @@ struct ad5758_state { __be32 d32[3]; }; -/** +/* * Output ranges corresponding to bits [3:0] from DAC_CONFIG register * 0000: 0 V to 5 V voltage range * 0001: 0 V to 10 V voltage range @@ -854,7 +854,6 @@ static int ad5758_probe(struct spi_device *spi) mutex_init(&st->lock); - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5758_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5761.c b/drivers/iio/dac/ad5761.c index 67c4fa75c6f13e0db1ce0b5c36a45f447a1e1b2e..e37e095e94fc2d9d07bfc7ceb63d62402903877f 100644 --- a/drivers/iio/dac/ad5761.c +++ b/drivers/iio/dac/ad5761.c @@ -57,7 +57,7 @@ enum ad5761_supported_device_ids { * @use_intref: true when the internal voltage reference is used * @vref: actual voltage reference in mVolts * @range: output range mode used - * @lock lock to protect the data buffer during SPI ops + * @lock: lock to protect the data buffer during SPI ops * @data: cache aligned spi buffer */ struct ad5761_state { @@ -376,7 +376,6 @@ static int ad5761_probe(struct spi_device *spi) if (ret) goto disable_regulator_err; - iio_dev->dev.parent = &spi->dev; iio_dev->info = &ad5761_info; iio_dev->modes = INDIO_DIRECT_MODE; iio_dev->channels = &chip_info->channel; diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c index 5b0f0fe354f6bda5e5eb4fab3d19f0677edc9660..ae089b9145cb7b5108e0dbfbc8d5bbe1f1f31a50 100644 --- a/drivers/iio/dac/ad5764.c +++ b/drivers/iio/dac/ad5764.c @@ -33,9 +33,8 @@ * struct ad5764_chip_info - chip specific information * @int_vref: Value of the internal reference voltage in uV - 0 if external * reference voltage is used - * @channel channel specification + * @channels: channel specification */ - struct ad5764_chip_info { unsigned long int_vref; const struct iio_chan_spec *channels; @@ -46,7 +45,7 @@ struct ad5764_chip_info { * @spi: spi_device * @chip_info: chip info * @vref_reg: vref supply regulators - * @lock lock to protect the data buffer during SPI ops + * @lock: lock to protect the data buffer during SPI ops * @data: spi transfer buffers */ @@ -290,7 +289,6 @@ static int ad5764_probe(struct spi_device *spi) st->spi = spi; st->chip_info = &ad5764_chip_infos[type]; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5764_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5770r.c b/drivers/iio/dac/ad5770r.c index 2d7623b9b2c0ec8b88e46676a40086660c7d0cb7..84dcf149261f96adbba236cbef6086a290ba7aaa 100644 --- a/drivers/iio/dac/ad5770r.c +++ b/drivers/iio/dac/ad5770r.c @@ -651,7 +651,6 @@ static int ad5770r_probe(struct spi_device *spi) } } - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5770r_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index 1d11f39ed0474b1bf491690a6ce3588b451b4142..e3ffa4b9f84cc29018ba5b6a39323e1f5f8fb764 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -76,9 +76,11 @@ struct ad5791_chip_info { * @chip_info: chip model specific constants * @vref_mv: actual reference voltage used * @vref_neg_mv: voltage of the negative supply - * @pwr_down_mode current power down mode + * @ctrl: control regster cache + * @pwr_down_mode: current power down mode + * @pwr_down: true if device is powered down + * @data: spi transfer buffers */ - struct ad5791_state { struct spi_device *spi; struct regulator *reg_vdd; @@ -96,10 +98,6 @@ struct ad5791_state { } data[3] ____cacheline_aligned; }; -/** - * ad5791_supported_device_ids: - */ - enum ad5791_supported_device_ids { ID_AD5760, ID_AD5780, @@ -409,7 +407,6 @@ static int ad5791_probe(struct spi_device *spi) goto error_disable_reg_neg; spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; indio_dev->info = &ad5791_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c index 15af8a1cce3eb512a728c4b0d9149854b3a48ff1..4460aa57a33f1d153442690a394a140daf4e22a4 100644 --- a/drivers/iio/dac/ad7303.c +++ b/drivers/iio/dac/ad7303.c @@ -238,7 +238,6 @@ static int ad7303_probe(struct spi_device *spi) st->config |= AD7303_CFG_EXTERNAL_VREF; } - indio_dev->dev.parent = &spi->dev; indio_dev->name = id->name; indio_dev->info = &ad7303_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad8801.c b/drivers/iio/dac/ad8801.c index 0789c9100a8f6e0db029185c4c8bc95ba31e5434..6354b7c8f052258749d00379f4304fd966ed74d5 100644 --- a/drivers/iio/dac/ad8801.c +++ b/drivers/iio/dac/ad8801.c @@ -171,7 +171,6 @@ static int ad8801_probe(struct spi_device *spi) } spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; indio_dev->info = &ad8801_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ad8801_channels; diff --git a/drivers/iio/dac/cio-dac.c b/drivers/iio/dac/cio-dac.c index 81677795e57a53179cd4885d23c6d4ddf305437d..95813569f3940cce1c5285e5e4bc277303d1e817 100644 --- a/drivers/iio/dac/cio-dac.c +++ b/drivers/iio/dac/cio-dac.c @@ -110,7 +110,6 @@ static int cio_dac_probe(struct device *dev, unsigned int id) indio_dev->channels = cio_dac_channels; indio_dev->num_channels = CIO_DAC_NUM_CHAN; indio_dev->name = dev_name(dev); - indio_dev->dev.parent = dev; priv = iio_priv(indio_dev); priv->base = base[id]; diff --git a/drivers/iio/dac/dpot-dac.c b/drivers/iio/dac/dpot-dac.c index 4a6111b7e86ca1337adc2e0787436a24730ebbaf..b3835fb6b86266a85a6a5be4736b351369978ba4 100644 --- a/drivers/iio/dac/dpot-dac.c +++ b/drivers/iio/dac/dpot-dac.c @@ -177,7 +177,6 @@ static int dpot_dac_probe(struct platform_device *pdev) dac = iio_priv(indio_dev); indio_dev->name = dev_name(dev); - indio_dev->dev.parent = dev; indio_dev->info = &dpot_dac_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = &dpot_dac_iio_channel; diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c index 26d206681472e63db674b5549a563c1f9377ed67..79527fbc250a137f244d931b5df9c491d666929c 100644 --- a/drivers/iio/dac/ds4424.c +++ b/drivers/iio/dac/ds4424.c @@ -230,8 +230,6 @@ static int ds4424_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; indio_dev->name = id->name; - indio_dev->dev.of_node = client->dev.of_node; - indio_dev->dev.parent = &client->dev; data->vcc_reg = devm_regulator_get(&client->dev, "vcc"); if (IS_ERR(data->vcc_reg)) { diff --git a/drivers/iio/dac/lpc18xx_dac.c b/drivers/iio/dac/lpc18xx_dac.c index 0ab357bd363349bdc8fd973e4101cd9adec03f87..9e38607a189eda2f05ab41e06e362ba90c062d5a 100644 --- a/drivers/iio/dac/lpc18xx_dac.c +++ b/drivers/iio/dac/lpc18xx_dac.c @@ -133,7 +133,6 @@ static int lpc18xx_dac_probe(struct platform_device *pdev) } indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &lpc18xx_dac_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = lpc18xx_dac_iio_channels; diff --git a/drivers/iio/dac/ltc1660.c b/drivers/iio/dac/ltc1660.c index 10866838c72aa56c966f6fd485e7b143f3e637bc..dc10188540cad3dd87f3366ff3e4023c32780396 100644 --- a/drivers/iio/dac/ltc1660.c +++ b/drivers/iio/dac/ltc1660.c @@ -186,7 +186,6 @@ static int ltc1660_probe(struct spi_device *spi) priv->spi = spi; spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; indio_dev->info = <c1660_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ltc1660_channels[id->driver_data]; diff --git a/drivers/iio/dac/ltc2632.c b/drivers/iio/dac/ltc2632.c index f891311f05cfe8b00b9375e4ca223a194e01f7ea..4002ed0868be92ad049ff5b1520ec76edfa1b197 100644 --- a/drivers/iio/dac/ltc2632.c +++ b/drivers/iio/dac/ltc2632.c @@ -38,9 +38,9 @@ struct ltc2632_chip_info { /** * struct ltc2632_state - driver instance specific data * @spi_dev: pointer to the spi_device struct - * @powerdown_cache_mask used to show current channel powerdown state - * @vref_mv used reference voltage (internal or external) - * @vref_reg regulator for the reference voltage + * @powerdown_cache_mask: used to show current channel powerdown state + * @vref_mv: used reference voltage (internal or external) + * @vref_reg: regulator for the reference voltage */ struct ltc2632_state { struct spi_device *spi_dev; @@ -362,7 +362,6 @@ static int ltc2632_probe(struct spi_device *spi) } } - indio_dev->dev.parent = &spi->dev; indio_dev->name = dev_of_node(&spi->dev) ? dev_of_node(&spi->dev)->name : spi_get_device_id(spi)->name; indio_dev->info = <c2632_info; diff --git a/drivers/iio/dac/m62332.c b/drivers/iio/dac/m62332.c index 3205ca98c32d335a0156f3ceb799ee1540f192f8..225b1a374dc130141dac6053add4f4945e21af8e 100644 --- a/drivers/iio/dac/m62332.c +++ b/drivers/iio/dac/m62332.c @@ -204,9 +204,6 @@ static int m62332_probe(struct i2c_client *client, if (IS_ERR(data->vcc)) return PTR_ERR(data->vcc); - /* establish that the iio_dev is a child of the i2c device */ - indio_dev->dev.parent = &client->dev; - indio_dev->num_channels = ARRAY_SIZE(m62332_channels); indio_dev->channels = m62332_channels; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c index 7e01838ef4d0c35fd4e60b3861beef90d05cdb9a..daa60386bf0c221c0302d582b14100e6576e1358 100644 --- a/drivers/iio/dac/max517.c +++ b/drivers/iio/dac/max517.c @@ -156,9 +156,6 @@ static int max517_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; - /* establish that the iio_dev is a child of the i2c device */ - indio_dev->dev.parent = &client->dev; - switch (id->driver_data) { case ID_MAX521: indio_dev->num_channels = 8; diff --git a/drivers/iio/dac/max5821.c b/drivers/iio/dac/max5821.c index 2da086e372af8ae93163cb047f68053cf5fb56c1..d6bb24db49c4132a362cecc87db8c669fc28b8fd 100644 --- a/drivers/iio/dac/max5821.c +++ b/drivers/iio/dac/max5821.c @@ -341,7 +341,6 @@ static int max5821_probe(struct i2c_client *client, data->vref_mv = ret / 1000; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->num_channels = ARRAY_SIZE(max5821_channels); indio_dev->channels = max5821_channels; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index ed455e801e80c2279ce51499166845b64e26e3de..ee174d224110b333c8569ed36ea69fbdc1c80bb5 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -453,7 +453,6 @@ static int mcp4725_probe(struct i2c_client *client, goto err_disable_vdd_reg; } - indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; indio_dev->info = &mcp4725_info; indio_dev->channels = &mcp472x_channel[id->driver_data]; diff --git a/drivers/iio/dac/mcp4922.c b/drivers/iio/dac/mcp4922.c index f9194b3ddc9c3992ac029ba7078920a0def63b9e..c4e430b4050e1fa0215dc32dcf9ee227e1d66060 100644 --- a/drivers/iio/dac/mcp4922.c +++ b/drivers/iio/dac/mcp4922.c @@ -152,7 +152,6 @@ static int mcp4922_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); id = spi_get_device_id(spi); - indio_dev->dev.parent = &spi->dev; indio_dev->info = &mcp4922_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mcp4922_channels[id->driver_data]; diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c index f22c1d9129b282d10c2169c4b10012c364e72472..092c796fa3d93bc4ae870175bf4d9ed917ccfe2c 100644 --- a/drivers/iio/dac/stm32-dac.c +++ b/drivers/iio/dac/stm32-dac.c @@ -323,7 +323,6 @@ static int stm32_dac_probe(struct platform_device *pdev) dac = iio_priv(indio_dev); dac->common = dev_get_drvdata(pdev->dev.parent); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &stm32_dac_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ti-dac082s085.c b/drivers/iio/dac/ti-dac082s085.c index 57b498d2a2a53d807d5813e96bb72ddd442bcde7..86bfb1c3f9b95a00a60f43b662ee3221b49c2d3d 100644 --- a/drivers/iio/dac/ti-dac082s085.c +++ b/drivers/iio/dac/ti-dac082s085.c @@ -4,12 +4,12 @@ * * Copyright (C) 2017 KUNBUS GmbH * - * http://www.ti.com/lit/ds/symlink/dac082s085.pdf - * http://www.ti.com/lit/ds/symlink/dac102s085.pdf - * http://www.ti.com/lit/ds/symlink/dac122s085.pdf - * http://www.ti.com/lit/ds/symlink/dac084s085.pdf - * http://www.ti.com/lit/ds/symlink/dac104s085.pdf - * http://www.ti.com/lit/ds/symlink/dac124s085.pdf + * https://www.ti.com/lit/ds/symlink/dac082s085.pdf + * https://www.ti.com/lit/ds/symlink/dac102s085.pdf + * https://www.ti.com/lit/ds/symlink/dac122s085.pdf + * https://www.ti.com/lit/ds/symlink/dac084s085.pdf + * https://www.ti.com/lit/ds/symlink/dac104s085.pdf + * https://www.ti.com/lit/ds/symlink/dac124s085.pdf */ #include @@ -268,7 +268,6 @@ static int ti_dac_probe(struct spi_device *spi) if (!indio_dev) return -ENOMEM; - indio_dev->dev.parent = dev; indio_dev->info = &ti_dac_info; indio_dev->name = spi->modalias; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c index 3a2bb0efe50de0f80607cf7b8dbaa72dbd5140c6..00fc7db8eb656696cfd9c158a899f32455345552 100644 --- a/drivers/iio/dac/ti-dac5571.c +++ b/drivers/iio/dac/ti-dac5571.c @@ -4,15 +4,15 @@ * * Copyright (C) 2018 Prevas A/S * - * http://www.ti.com/lit/ds/symlink/dac5571.pdf - * http://www.ti.com/lit/ds/symlink/dac6571.pdf - * http://www.ti.com/lit/ds/symlink/dac7571.pdf - * http://www.ti.com/lit/ds/symlink/dac5574.pdf - * http://www.ti.com/lit/ds/symlink/dac6574.pdf - * http://www.ti.com/lit/ds/symlink/dac7574.pdf - * http://www.ti.com/lit/ds/symlink/dac5573.pdf - * http://www.ti.com/lit/ds/symlink/dac6573.pdf - * http://www.ti.com/lit/ds/symlink/dac7573.pdf + * https://www.ti.com/lit/ds/symlink/dac5571.pdf + * https://www.ti.com/lit/ds/symlink/dac6571.pdf + * https://www.ti.com/lit/ds/symlink/dac7571.pdf + * https://www.ti.com/lit/ds/symlink/dac5574.pdf + * https://www.ti.com/lit/ds/symlink/dac6574.pdf + * https://www.ti.com/lit/ds/symlink/dac7574.pdf + * https://www.ti.com/lit/ds/symlink/dac5573.pdf + * https://www.ti.com/lit/ds/symlink/dac6573.pdf + * https://www.ti.com/lit/ds/symlink/dac7573.pdf */ #include @@ -321,8 +321,6 @@ static int dac5571_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; - indio_dev->dev.parent = dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->info = &dac5571_info; indio_dev->name = id->name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ti-dac7311.c b/drivers/iio/dac/ti-dac7311.c index 6f5df1a30a1c77f88445b427d49009949d3a7817..63171e42f987a4417786f3c8fba132b6766fa74e 100644 --- a/drivers/iio/dac/ti-dac7311.c +++ b/drivers/iio/dac/ti-dac7311.c @@ -3,7 +3,7 @@ * * Copyright (C) 2018 CMC NV * - * http://www.ti.com/lit/ds/symlink/dac7311.pdf + * https://www.ti.com/lit/ds/symlink/dac7311.pdf */ #include @@ -251,8 +251,6 @@ static int ti_dac_probe(struct spi_device *spi) spi->bits_per_word = 16; spi_setup(spi); - indio_dev->dev.parent = dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->info = &ti_dac_info; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ti-dac7612.c b/drivers/iio/dac/ti-dac7612.c index de0c6573cd9790d8c57ef383ee68ea6af9f3bc65..07c9f39d54f13b9921e135ae2d4601384980b4f2 100644 --- a/drivers/iio/dac/ti-dac7612.c +++ b/drivers/iio/dac/ti-dac7612.c @@ -139,7 +139,6 @@ static int dac7612_probe(struct spi_device *spi) return PTR_ERR(priv->loaddacs); priv->spi = spi; spi_set_drvdata(spi, iio_dev); - iio_dev->dev.parent = &spi->dev; iio_dev->info = &dac7612_info; iio_dev->modes = INDIO_DIRECT_MODE; iio_dev->channels = dac7612_channels; diff --git a/drivers/iio/dac/vf610_dac.c b/drivers/iio/dac/vf610_dac.c index 9417a4a3e22a17ce15cd2bb7a4215aa86bbe9986..636b4009f76341970f94de4babaee358643e963c 100644 --- a/drivers/iio/dac/vf610_dac.c +++ b/drivers/iio/dac/vf610_dac.c @@ -199,8 +199,6 @@ static int vf610_dac_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &vf610_dac_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = vf610_dac_iio_channels; diff --git a/drivers/iio/dummy/iio_simple_dummy.c b/drivers/iio/dummy/iio_simple_dummy.c index 6cb02299a2152274b44a655026ad1633e8aca9b8..c0b7ef90073548e569b413112f7f73eddb5b33de 100644 --- a/drivers/iio/dummy/iio_simple_dummy.c +++ b/drivers/iio/dummy/iio_simple_dummy.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * Copyright (c) 2011 Jonathan Cameron * * A reference industrial I/O driver to illustrate the functionality available. @@ -553,7 +553,7 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev) /** * iio_dummy_probe() - device instance probe - * @index: an id number for this instance. + * @name: name of this instance. * * Arguments are bus type specific. * I2C: iio_dummy_probe(struct i2c_client *client, @@ -566,6 +566,13 @@ static struct iio_sw_device *iio_dummy_probe(const char *name) struct iio_dev *indio_dev; struct iio_dummy_state *st; struct iio_sw_device *swd; + struct device *parent = NULL; + + /* + * With hardware: Set the parent device. + * parent = &spi->dev; + * parent = &client->dev; + */ swd = kzalloc(sizeof(*swd), GFP_KERNEL); if (!swd) { @@ -580,7 +587,7 @@ static struct iio_sw_device *iio_dummy_probe(const char *name) * It also has a region (accessed by iio_priv() * for chip specific state information. */ - indio_dev = iio_device_alloc(sizeof(*st)); + indio_dev = iio_device_alloc(parent, sizeof(*st)); if (!indio_dev) { ret = -ENOMEM; goto error_ret; @@ -590,11 +597,6 @@ static struct iio_sw_device *iio_dummy_probe(const char *name) mutex_init(&st->lock); iio_dummy_init_device(indio_dev); - /* - * With hardware: Set the parent device. - * indio_dev->dev.parent = &spi->dev; - * indio_dev->dev.parent = &client->dev; - */ /* * Make the iio_dev struct available to remove function. @@ -687,7 +689,8 @@ static int iio_dummy_remove(struct iio_sw_device *swd) return 0; } -/** + +/* * module_iio_sw_device_driver() - device driver registration * * Varies depending on bus type of the device. As there is no device diff --git a/drivers/iio/dummy/iio_simple_dummy_buffer.c b/drivers/iio/dummy/iio_simple_dummy_buffer.c index 17606eca42b43989808da6011df2b14b1da771d2..5512d5edc70737ad5cf174c2bf9e753128afdaae 100644 --- a/drivers/iio/dummy/iio_simple_dummy_buffer.c +++ b/drivers/iio/dummy/iio_simple_dummy_buffer.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * Copyright (c) 2011 Jonathan Cameron * * Buffer handling elements of industrial I/O reference driver. @@ -99,20 +99,6 @@ done: } static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = { - /* - * iio_triggered_buffer_postenable: - * Generic function that simply attaches the pollfunc to the trigger. - * Replace this to mess with hardware state before we attach the - * trigger. - */ - .postenable = &iio_triggered_buffer_postenable, - /* - * iio_triggered_buffer_predisable: - * Generic function that simple detaches the pollfunc from the trigger. - * Replace this to put hardware state back again after the trigger is - * detached but before userspace knows we have disabled the ring. - */ - .predisable = &iio_triggered_buffer_predisable, }; int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) @@ -179,7 +165,7 @@ error_ret: /** * iio_simple_dummy_unconfigure_buffer() - release buffer resources - * @indo_dev: device instance state + * @indio_dev: device instance state */ void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) { diff --git a/drivers/iio/dummy/iio_simple_dummy_events.c b/drivers/iio/dummy/iio_simple_dummy_events.c index b3abaaca6f5ef410b6d2599da2cb2cfe518381c8..63a2b844be50834e232f653bbb893dee29171c4c 100644 --- a/drivers/iio/dummy/iio_simple_dummy_events.c +++ b/drivers/iio/dummy/iio_simple_dummy_events.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * Copyright (c) 2011 Jonathan Cameron * * Event handling elements of industrial I/O reference driver. @@ -107,6 +107,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, * @dir: direction of the vent whose value is being read * @info: info type of the event whose value is being read * @val: value for the event code. + * @val2: unused * * Many devices provide a large set of events of which only a subset may * be enabled at a time, with value registers whose meaning changes depending @@ -136,6 +137,7 @@ int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev, * @dir: direction of the vent whose value is being set * @info: info type of the event whose value is being set * @val: the value to be set. + * @val2: unused */ int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index a7322184cbdd0680cea8352efc40ac8311402c50..334e1d779d6db9a6fd5155a63ee57714e7afacbb 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -1026,7 +1026,6 @@ static int ad9523_probe(struct spi_device *spi) st->spi = spi; st->pdata = pdata; - indio_dev->dev.parent = &spi->dev; indio_dev->name = (pdata->name[0] != 0) ? pdata->name : spi_get_device_id(spi)->name; indio_dev->info = &ad9523_info; diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 1c2dc9b00f319ee2f2e49c8b39117ee42232dd96..409c9c47161ed4938eacaedc378a802e5f1969dd 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -531,7 +531,6 @@ static int adf4350_probe(struct spi_device *spi) st->spi = spi; st->pdata = pdata; - indio_dev->dev.parent = &spi->dev; indio_dev->name = (pdata->name[0] != 0) ? pdata->name : spi_get_device_id(spi)->name; diff --git a/drivers/iio/frequency/adf4371.c b/drivers/iio/frequency/adf4371.c index ff82863cbf42d4d1f7b59edbe8c1e3052135cf71..ecd5e18995adc6c62e44d319730aebec3c2f640e 100644 --- a/drivers/iio/frequency/adf4371.c +++ b/drivers/iio/frequency/adf4371.c @@ -573,7 +573,6 @@ static int adf4371_probe(struct spi_device *spi) mutex_init(&st->lock); st->chip_info = &adf4371_chip_info[id->driver_data]; - indio_dev->dev.parent = &spi->dev; indio_dev->name = id->name; indio_dev->info = &adf4371_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/gyro/adis16080.c b/drivers/iio/gyro/adis16080.c index 1b84b8e112fe1df59e928a8f8ff40e2fc9bb4ffd..6e5e2d98943c267c6776fd7a99ea489bb1abddc7 100644 --- a/drivers/iio/gyro/adis16080.c +++ b/drivers/iio/gyro/adis16080.c @@ -207,7 +207,6 @@ static int adis16080_probe(struct spi_device *spi) indio_dev->name = spi->dev.driver->name; indio_dev->channels = adis16080_channels; indio_dev->num_channels = ARRAY_SIZE(adis16080_channels); - indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16080_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/gyro/adis16130.c b/drivers/iio/gyro/adis16130.c index 2a9ec08ec5614b95af733c18428ddcc4848a2af5..b9c952e65b55330f0e404fd924b6e2e2c9c10ea3 100644 --- a/drivers/iio/gyro/adis16130.c +++ b/drivers/iio/gyro/adis16130.c @@ -155,7 +155,6 @@ static int adis16130_probe(struct spi_device *spi) indio_dev->name = spi->dev.driver->name; indio_dev->channels = adis16130_channels; indio_dev->num_channels = ARRAY_SIZE(adis16130_channels); - indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16130_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c index afdc57af475d24fb3d54ddcd651fe0b2699282bf..d8a96f6bbae25897828fbcb5b76221b01d973211 100644 --- a/drivers/iio/gyro/adis16136.c +++ b/drivers/iio/gyro/adis16136.c @@ -540,7 +540,6 @@ static int adis16136_probe(struct spi_device *spi) adis16136 = iio_priv(indio_dev); adis16136->chip_info = &adis16136_chip_info[id->driver_data]; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = adis16136_channels; indio_dev->num_channels = ARRAY_SIZE(adis16136_channels); diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c index 9823573e811a58797a012dc7d96ed626d6bb25f2..e638d56e1574dc61180a4f37fe8e85ca25a0da98 100644 --- a/drivers/iio/gyro/adis16260.c +++ b/drivers/iio/gyro/adis16260.c @@ -381,7 +381,6 @@ static int adis16260_probe(struct spi_device *spi) adis16260->info = &adis16260_chip_info_table[id->driver_data]; indio_dev->name = id->name; - indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16260_info; indio_dev->channels = adis16260->info->channels; indio_dev->num_channels = adis16260->info->num_channels; diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c index b00c0eb4424936e4859ac328e17ec2b1fe929768..04f350025215278065ef66fb773d9ad88a9e0e64 100644 --- a/drivers/iio/gyro/adxrs450.c +++ b/drivers/iio/gyro/adxrs450.c @@ -424,7 +424,6 @@ static int adxrs450_probe(struct spi_device *spi) /* This is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; indio_dev->info = &adxrs450_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c index 428ddfc13acb9125c1ffac75ccb40673a4cab3b4..8ddda96455fcb1fffaf44ae715a43cb2507c16df 100644 --- a/drivers/iio/gyro/bmg160_core.c +++ b/drivers/iio/gyro/bmg160_core.c @@ -1051,8 +1051,6 @@ static int bmg160_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = { .preenable = bmg160_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = bmg160_buffer_postdisable, }; @@ -1097,7 +1095,6 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, if (ACPI_HANDLE(dev)) name = bmg160_match_acpi_device(dev); - indio_dev->dev.parent = dev; indio_dev->channels = bmg160_channels; indio_dev->num_channels = ARRAY_SIZE(bmg160_channels); indio_dev->name = name; diff --git a/drivers/iio/gyro/fxas21002c.h b/drivers/iio/gyro/fxas21002c.h index 566d92de267633e6f713fa26f82565e143b75ab4..c81cecee121cbecde7b08f4ea1a861cc8ec3567a 100644 --- a/drivers/iio/gyro/fxas21002c.h +++ b/drivers/iio/gyro/fxas21002c.h @@ -76,72 +76,6 @@ enum fxas21002c_fields { F_MAX_FIELDS, }; -static const struct reg_field fxas21002c_reg_fields[] = { - [F_DR_STATUS] = REG_FIELD(FXAS21002C_REG_STATUS, 0, 7), - [F_OUT_X_MSB] = REG_FIELD(FXAS21002C_REG_OUT_X_MSB, 0, 7), - [F_OUT_X_LSB] = REG_FIELD(FXAS21002C_REG_OUT_X_LSB, 0, 7), - [F_OUT_Y_MSB] = REG_FIELD(FXAS21002C_REG_OUT_Y_MSB, 0, 7), - [F_OUT_Y_LSB] = REG_FIELD(FXAS21002C_REG_OUT_Y_LSB, 0, 7), - [F_OUT_Z_MSB] = REG_FIELD(FXAS21002C_REG_OUT_Z_MSB, 0, 7), - [F_OUT_Z_LSB] = REG_FIELD(FXAS21002C_REG_OUT_Z_LSB, 0, 7), - [F_ZYX_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 7, 7), - [F_Z_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 6, 6), - [F_Y_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 5, 5), - [F_X_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 4, 4), - [F_ZYX_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 3, 3), - [F_Z_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 2, 2), - [F_Y_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 1, 1), - [F_X_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 0, 0), - [F_OVF] = REG_FIELD(FXAS21002C_REG_F_STATUS, 7, 7), - [F_WMKF] = REG_FIELD(FXAS21002C_REG_F_STATUS, 6, 6), - [F_CNT] = REG_FIELD(FXAS21002C_REG_F_STATUS, 0, 5), - [F_MODE] = REG_FIELD(FXAS21002C_REG_F_SETUP, 6, 7), - [F_WMRK] = REG_FIELD(FXAS21002C_REG_F_SETUP, 0, 5), - [F_EVENT] = REG_FIELD(FXAS21002C_REG_F_EVENT, 5, 5), - [FE_TIME] = REG_FIELD(FXAS21002C_REG_F_EVENT, 0, 4), - [F_BOOTEND] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 3, 3), - [F_SRC_FIFO] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 2, 2), - [F_SRC_RT] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 1, 1), - [F_SRC_DRDY] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 0, 0), - [F_WHO_AM_I] = REG_FIELD(FXAS21002C_REG_WHO_AM_I, 0, 7), - [F_BW] = REG_FIELD(FXAS21002C_REG_CTRL0, 6, 7), - [F_SPIW] = REG_FIELD(FXAS21002C_REG_CTRL0, 5, 5), - [F_SEL] = REG_FIELD(FXAS21002C_REG_CTRL0, 3, 4), - [F_HPF_EN] = REG_FIELD(FXAS21002C_REG_CTRL0, 2, 2), - [F_FS] = REG_FIELD(FXAS21002C_REG_CTRL0, 0, 1), - [F_ELE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 3, 3), - [F_ZTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 2, 2), - [F_YTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 1, 1), - [F_XTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 0, 0), - [F_EA] = REG_FIELD(FXAS21002C_REG_RT_SRC, 6, 6), - [F_ZRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 5, 5), - [F_ZRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 4, 4), - [F_YRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 3, 3), - [F_YRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 2, 2), - [F_XRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 1, 1), - [F_XRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 0, 0), - [F_DBCNTM] = REG_FIELD(FXAS21002C_REG_RT_THS, 7, 7), - [F_THS] = REG_FIELD(FXAS21002C_REG_RT_SRC, 0, 6), - [F_RT_COUNT] = REG_FIELD(FXAS21002C_REG_RT_COUNT, 0, 7), - [F_TEMP] = REG_FIELD(FXAS21002C_REG_TEMP, 0, 7), - [F_RST] = REG_FIELD(FXAS21002C_REG_CTRL1, 6, 6), - [F_ST] = REG_FIELD(FXAS21002C_REG_CTRL1, 5, 5), - [F_DR] = REG_FIELD(FXAS21002C_REG_CTRL1, 2, 4), - [F_ACTIVE] = REG_FIELD(FXAS21002C_REG_CTRL1, 1, 1), - [F_READY] = REG_FIELD(FXAS21002C_REG_CTRL1, 0, 0), - [F_INT_CFG_FIFO] = REG_FIELD(FXAS21002C_REG_CTRL2, 7, 7), - [F_INT_EN_FIFO] = REG_FIELD(FXAS21002C_REG_CTRL2, 6, 6), - [F_INT_CFG_RT] = REG_FIELD(FXAS21002C_REG_CTRL2, 5, 5), - [F_INT_EN_RT] = REG_FIELD(FXAS21002C_REG_CTRL2, 4, 4), - [F_INT_CFG_DRDY] = REG_FIELD(FXAS21002C_REG_CTRL2, 3, 3), - [F_INT_EN_DRDY] = REG_FIELD(FXAS21002C_REG_CTRL2, 2, 2), - [F_IPOL] = REG_FIELD(FXAS21002C_REG_CTRL2, 1, 1), - [F_PP_OD] = REG_FIELD(FXAS21002C_REG_CTRL2, 0, 0), - [F_WRAPTOONE] = REG_FIELD(FXAS21002C_REG_CTRL3, 3, 3), - [F_EXTCTRLEN] = REG_FIELD(FXAS21002C_REG_CTRL3, 2, 2), - [F_FS_DOUBLE] = REG_FIELD(FXAS21002C_REG_CTRL3, 0, 0), -}; - extern const struct dev_pm_ops fxas21002c_pm_ops; int fxas21002c_core_probe(struct device *dev, struct regmap *regmap, int irq, diff --git a/drivers/iio/gyro/fxas21002c_core.c b/drivers/iio/gyro/fxas21002c_core.c index 89d2bb2282eac9c442a8904928d7e1f6a0ef3162..129eead8febc0ea1a3a5b161296c822d355c7106 100644 --- a/drivers/iio/gyro/fxas21002c_core.c +++ b/drivers/iio/gyro/fxas21002c_core.c @@ -42,6 +42,72 @@ enum fxas21002c_mode_state { #define FXAS21002C_AXIS_TO_REG(axis) (FXAS21002C_REG_OUT_X_MSB + ((axis) * 2)) +static const struct reg_field fxas21002c_reg_fields[] = { + [F_DR_STATUS] = REG_FIELD(FXAS21002C_REG_STATUS, 0, 7), + [F_OUT_X_MSB] = REG_FIELD(FXAS21002C_REG_OUT_X_MSB, 0, 7), + [F_OUT_X_LSB] = REG_FIELD(FXAS21002C_REG_OUT_X_LSB, 0, 7), + [F_OUT_Y_MSB] = REG_FIELD(FXAS21002C_REG_OUT_Y_MSB, 0, 7), + [F_OUT_Y_LSB] = REG_FIELD(FXAS21002C_REG_OUT_Y_LSB, 0, 7), + [F_OUT_Z_MSB] = REG_FIELD(FXAS21002C_REG_OUT_Z_MSB, 0, 7), + [F_OUT_Z_LSB] = REG_FIELD(FXAS21002C_REG_OUT_Z_LSB, 0, 7), + [F_ZYX_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 7, 7), + [F_Z_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 6, 6), + [F_Y_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 5, 5), + [F_X_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 4, 4), + [F_ZYX_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 3, 3), + [F_Z_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 2, 2), + [F_Y_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 1, 1), + [F_X_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 0, 0), + [F_OVF] = REG_FIELD(FXAS21002C_REG_F_STATUS, 7, 7), + [F_WMKF] = REG_FIELD(FXAS21002C_REG_F_STATUS, 6, 6), + [F_CNT] = REG_FIELD(FXAS21002C_REG_F_STATUS, 0, 5), + [F_MODE] = REG_FIELD(FXAS21002C_REG_F_SETUP, 6, 7), + [F_WMRK] = REG_FIELD(FXAS21002C_REG_F_SETUP, 0, 5), + [F_EVENT] = REG_FIELD(FXAS21002C_REG_F_EVENT, 5, 5), + [FE_TIME] = REG_FIELD(FXAS21002C_REG_F_EVENT, 0, 4), + [F_BOOTEND] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 3, 3), + [F_SRC_FIFO] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 2, 2), + [F_SRC_RT] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 1, 1), + [F_SRC_DRDY] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 0, 0), + [F_WHO_AM_I] = REG_FIELD(FXAS21002C_REG_WHO_AM_I, 0, 7), + [F_BW] = REG_FIELD(FXAS21002C_REG_CTRL0, 6, 7), + [F_SPIW] = REG_FIELD(FXAS21002C_REG_CTRL0, 5, 5), + [F_SEL] = REG_FIELD(FXAS21002C_REG_CTRL0, 3, 4), + [F_HPF_EN] = REG_FIELD(FXAS21002C_REG_CTRL0, 2, 2), + [F_FS] = REG_FIELD(FXAS21002C_REG_CTRL0, 0, 1), + [F_ELE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 3, 3), + [F_ZTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 2, 2), + [F_YTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 1, 1), + [F_XTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 0, 0), + [F_EA] = REG_FIELD(FXAS21002C_REG_RT_SRC, 6, 6), + [F_ZRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 5, 5), + [F_ZRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 4, 4), + [F_YRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 3, 3), + [F_YRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 2, 2), + [F_XRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 1, 1), + [F_XRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 0, 0), + [F_DBCNTM] = REG_FIELD(FXAS21002C_REG_RT_THS, 7, 7), + [F_THS] = REG_FIELD(FXAS21002C_REG_RT_SRC, 0, 6), + [F_RT_COUNT] = REG_FIELD(FXAS21002C_REG_RT_COUNT, 0, 7), + [F_TEMP] = REG_FIELD(FXAS21002C_REG_TEMP, 0, 7), + [F_RST] = REG_FIELD(FXAS21002C_REG_CTRL1, 6, 6), + [F_ST] = REG_FIELD(FXAS21002C_REG_CTRL1, 5, 5), + [F_DR] = REG_FIELD(FXAS21002C_REG_CTRL1, 2, 4), + [F_ACTIVE] = REG_FIELD(FXAS21002C_REG_CTRL1, 1, 1), + [F_READY] = REG_FIELD(FXAS21002C_REG_CTRL1, 0, 0), + [F_INT_CFG_FIFO] = REG_FIELD(FXAS21002C_REG_CTRL2, 7, 7), + [F_INT_EN_FIFO] = REG_FIELD(FXAS21002C_REG_CTRL2, 6, 6), + [F_INT_CFG_RT] = REG_FIELD(FXAS21002C_REG_CTRL2, 5, 5), + [F_INT_EN_RT] = REG_FIELD(FXAS21002C_REG_CTRL2, 4, 4), + [F_INT_CFG_DRDY] = REG_FIELD(FXAS21002C_REG_CTRL2, 3, 3), + [F_INT_EN_DRDY] = REG_FIELD(FXAS21002C_REG_CTRL2, 2, 2), + [F_IPOL] = REG_FIELD(FXAS21002C_REG_CTRL2, 1, 1), + [F_PP_OD] = REG_FIELD(FXAS21002C_REG_CTRL2, 0, 0), + [F_WRAPTOONE] = REG_FIELD(FXAS21002C_REG_CTRL3, 3, 3), + [F_EXTCTRLEN] = REG_FIELD(FXAS21002C_REG_CTRL3, 2, 2), + [F_FS_DOUBLE] = REG_FIELD(FXAS21002C_REG_CTRL3, 0, 0), +}; + static const int fxas21002c_odr_values[] = { 800, 400, 200, 100, 50, 25, 12, 12 }; @@ -905,7 +971,6 @@ int fxas21002c_core_probe(struct device *dev, struct regmap *regmap, int irq, if (ret < 0) return ret; - indio_dev->dev.parent = dev; indio_dev->channels = fxas21002c_channels; indio_dev->num_channels = ARRAY_SIZE(fxas21002c_channels); indio_dev->name = name; diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c index 7f382aae1dfd90e8734dfe8e554d65e7e765b723..6698f5f535f601becb828b0c1db8d06ffaf82f71 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c @@ -319,7 +319,6 @@ static int hid_gyro_3d_probe(struct platform_device *pdev) } indio_dev->num_channels = ARRAY_SIZE(gyro_3d_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &gyro_3d_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c index b3afa556f97342ec04c6c8db00ed94c34d39c5b6..e9804664db7342673eab714da5cce72f714a3dce 100644 --- a/drivers/iio/gyro/itg3200_core.c +++ b/drivers/iio/gyro/itg3200_core.c @@ -316,7 +316,6 @@ static int itg3200_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); st->i2c = client; - indio_dev->dev.parent = &client->dev; indio_dev->name = client->dev.driver->name; indio_dev->channels = itg3200_channels; indio_dev->num_channels = ARRAY_SIZE(itg3200_channels); diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c index 8e908a749f95710df9f80950a96f7208d5b10b63..00e58060968c9da81133711ac6aa7c2c5a157ca1 100644 --- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -662,8 +662,6 @@ static int mpu3050_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops mpu3050_buffer_setup_ops = { .preenable = mpu3050_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = mpu3050_buffer_postdisable, }; @@ -1198,7 +1196,6 @@ int mpu3050_common_probe(struct device *dev, if (ret) goto err_power_down; - indio_dev->dev.parent = dev; indio_dev->channels = mpu3050_channels; indio_dev->num_channels = ARRAY_SIZE(mpu3050_channels); indio_dev->info = &mpu3050_info; diff --git a/drivers/iio/gyro/ssp_gyro_sensor.c b/drivers/iio/gyro/ssp_gyro_sensor.c index 4e4ee41675447f9552c31af437034e6d3c9413dd..ac7c170a20de82dc60d7ade95e7da5c68a944686 100644 --- a/drivers/iio/gyro/ssp_gyro_sensor.c +++ b/drivers/iio/gyro/ssp_gyro_sensor.c @@ -108,7 +108,6 @@ static int ssp_gyro_probe(struct platform_device *pdev) spd->type = SSP_GYROSCOPE_SENSOR; indio_dev->name = ssp_gyro_name; - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &ssp_gyro_iio_info; indio_dev->modes = INDIO_BUFFER_SOFTWARE; indio_dev->channels = ssp_gyro_channels; diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c index 9c92ff7a82bee846dbf7b6bc9963bf418bcc60c8..4feb7ada71953bbaf91d8e646c5cb79b77ce8bc0 100644 --- a/drivers/iio/gyro/st_gyro_buffer.c +++ b/drivers/iio/gyro/st_gyro_buffer.c @@ -33,13 +33,9 @@ static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) { int err; - err = iio_triggered_buffer_postenable(indio_dev); - if (err < 0) - return err; - err = st_sensors_set_axis_enable(indio_dev, indio_dev->active_scan_mask[0]); if (err < 0) - goto st_gyro_buffer_predisable; + return err; err = st_sensors_set_enable(indio_dev, true); if (err < 0) @@ -49,27 +45,18 @@ static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) st_gyro_buffer_enable_all_axis: st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); -st_gyro_buffer_predisable: - iio_triggered_buffer_predisable(indio_dev); return err; } static int st_gyro_buffer_predisable(struct iio_dev *indio_dev) { - int err, err2; + int err; err = st_sensors_set_enable(indio_dev, false); if (err < 0) - goto st_gyro_buffer_predisable; - - err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); - -st_gyro_buffer_predisable: - err2 = iio_triggered_buffer_predisable(indio_dev); - if (!err) - err = err2; + return err; - return err; + return st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); } static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = { diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c index a3507624b30f8eb82fb6920ad31399287d5739ed..38734e4ce360570215f352a69ce0e9a3bf9b6443 100644 --- a/drivers/iio/health/afe4403.c +++ b/drivers/iio/health/afe4403.c @@ -2,7 +2,7 @@ /* * AFE4403 Heart Rate Monitors and Low-Cost Pulse Oximeters * - * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/ * Andrew F. Davis */ @@ -512,7 +512,6 @@ static int afe4403_probe(struct spi_device *spi) } indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->dev.parent = afe->dev; indio_dev->channels = afe4403_channels; indio_dev->num_channels = ARRAY_SIZE(afe4403_channels); indio_dev->name = AFE4403_DRIVER_NAME; diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c index cebb1fd4d0b15b0138cdcf2127d7843d1f97cdb5..61fe4932d81d02269a7b5f776a037da83724b952 100644 --- a/drivers/iio/health/afe4404.c +++ b/drivers/iio/health/afe4404.c @@ -2,7 +2,7 @@ /* * AFE4404 Heart Rate Monitors and Low-Cost Pulse Oximeters * - * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/ * Andrew F. Davis */ @@ -519,7 +519,6 @@ static int afe4404_probe(struct i2c_client *client, } indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->dev.parent = afe->dev; indio_dev->channels = afe4404_channels; indio_dev->num_channels = ARRAY_SIZE(afe4404_channels); indio_dev->name = AFE4404_DRIVER_NAME; diff --git a/drivers/iio/health/afe440x.h b/drivers/iio/health/afe440x.h index 7829c4fcd03b6dad62b96d475f5e9dd76e105ed0..0adea0047eba6e2ae0cf63d7c8d134c80b7f48a3 100644 --- a/drivers/iio/health/afe440x.h +++ b/drivers/iio/health/afe440x.h @@ -2,7 +2,7 @@ /* * AFE440X Heart Rate Monitors and Low-Cost Pulse Oximeters * - * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/ * Andrew F. Davis */ diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c index 546fc37ad75deaad6b6838e3b585015e57422595..38aa2030f3c62d2adcda79c68c0b236183155f8c 100644 --- a/drivers/iio/health/max30100.c +++ b/drivers/iio/health/max30100.c @@ -439,7 +439,6 @@ static int max30100_probe(struct i2c_client *client, indio_dev->available_scan_masks = max30100_scan_masks; indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE); indio_dev->setup_ops = &max30100_buffer_setup_ops; - indio_dev->dev.parent = &client->dev; data = iio_priv(indio_dev); data->indio_dev = indio_dev; diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c index 74fc260b957e763c112a77fb6b00ffa182331646..9b47d9472a4fde84325fabb0b5cc1b22e5fe82f5 100644 --- a/drivers/iio/health/max30102.c +++ b/drivers/iio/health/max30102.c @@ -526,7 +526,6 @@ static int max30102_probe(struct i2c_client *client, indio_dev->info = &max30102_info; indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE); indio_dev->setup_ops = &max30102_buffer_setup_ops; - indio_dev->dev.parent = &client->dev; data = iio_priv(indio_dev); data->indio_dev = indio_dev; diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index 3bac98e731d9cd0b388384e0f73964bf9225e65e..02ad1767c845e8dccc26e6727881d5301cf9d5f2 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c @@ -233,7 +233,6 @@ static int am2315_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &am2315_info; indio_dev->name = AM2315_DRIVER_NAME; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c index d05c6fdb758b815f55a20383e766255117c64cc5..9a7819817488b4a0e3c285b129db385ae6b11065 100644 --- a/drivers/iio/humidity/dht11.c +++ b/drivers/iio/humidity/dht11.c @@ -321,7 +321,6 @@ static int dht11_probe(struct platform_device *pdev) init_completion(&dht11->completion); mutex_init(&dht11->lock); iio->name = pdev->name; - iio->dev.parent = &pdev->dev; iio->info = &dht11_iio_info; iio->modes = INDIO_DIRECT_MODE; iio->channels = dht11_chan_spec; diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index 665eb7e38293bb501e63a5c3083fa18c759d50b4..071cb2b12bb6ac87ab9e18bc6ef2cccf115a95b1 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -6,11 +6,11 @@ * Author: Matt Ranostay * * Datasheets: - * http://www.ti.com/product/HDC1000/datasheet - * http://www.ti.com/product/HDC1008/datasheet - * http://www.ti.com/product/HDC1010/datasheet - * http://www.ti.com/product/HDC1050/datasheet - * http://www.ti.com/product/HDC1080/datasheet + * https://www.ti.com/product/HDC1000/datasheet + * https://www.ti.com/product/HDC1008/datasheet + * https://www.ti.com/product/HDC1010/datasheet + * https://www.ti.com/product/HDC1050/datasheet + * https://www.ti.com/product/HDC1080/datasheet */ #include @@ -283,17 +283,11 @@ static int hdc100x_buffer_postenable(struct iio_dev *indio_dev) struct hdc100x_data *data = iio_priv(indio_dev); int ret; - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret) - return ret; - /* Buffer is enabled. First set ACQ Mode, then attach poll func */ mutex_lock(&data->lock); ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, HDC100X_REG_CONFIG_ACQ_MODE); mutex_unlock(&data->lock); - if (ret) - iio_triggered_buffer_predisable(indio_dev); return ret; } @@ -301,16 +295,12 @@ static int hdc100x_buffer_postenable(struct iio_dev *indio_dev) static int hdc100x_buffer_predisable(struct iio_dev *indio_dev) { struct hdc100x_data *data = iio_priv(indio_dev); - int ret, ret2; + int ret; mutex_lock(&data->lock); ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0); mutex_unlock(&data->lock); - ret2 = iio_triggered_buffer_predisable(indio_dev); - if (ret == 0) - ret = ret2; - return ret; } @@ -378,7 +368,6 @@ static int hdc100x_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &hdc100x_info; diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c index d2318c4aab0ff82222e7a8e63af43dbf82651b47..52f605114ef77e52473eb3d13793aa1c66937ff8 100644 --- a/drivers/iio/humidity/hid-sensor-humidity.c +++ b/drivers/iio/humidity/hid-sensor-humidity.c @@ -226,7 +226,6 @@ static int hid_humidity_probe(struct platform_device *pdev) indio_dev->channels = humid_chans; indio_dev->num_channels = ARRAY_SIZE(humidity_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &humidity_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/humidity/hts221.h b/drivers/iio/humidity/hts221.h index b2eb5abeaccd3f466848e1bbd318563761089a3f..721359e226cb97f7df1c32ad5ddfa20913d82592 100644 --- a/drivers/iio/humidity/hts221.h +++ b/drivers/iio/humidity/hts221.h @@ -49,7 +49,7 @@ extern const struct dev_pm_ops hts221_pm_ops; int hts221_probe(struct device *dev, int irq, const char *name, struct regmap *regmap); int hts221_set_enable(struct hts221_hw *hw, bool enable); -int hts221_allocate_buffers(struct hts221_hw *hw); -int hts221_allocate_trigger(struct hts221_hw *hw); +int hts221_allocate_buffers(struct iio_dev *iio_dev); +int hts221_allocate_trigger(struct iio_dev *iio_dev); #endif /* HTS221_H */ diff --git a/drivers/iio/humidity/hts221_buffer.c b/drivers/iio/humidity/hts221_buffer.c index ba7d413d75ba2bd7173a5e43aaceb12fc4404414..95e56917677faea5ac20410418653962ad329659 100644 --- a/drivers/iio/humidity/hts221_buffer.c +++ b/drivers/iio/humidity/hts221_buffer.c @@ -72,10 +72,10 @@ static irqreturn_t hts221_trigger_handler_thread(int irq, void *private) return IRQ_HANDLED; } -int hts221_allocate_trigger(struct hts221_hw *hw) +int hts221_allocate_trigger(struct iio_dev *iio_dev) { + struct hts221_hw *hw = iio_priv(iio_dev); struct st_sensors_platform_data *pdata = dev_get_platdata(hw->dev); - struct iio_dev *iio_dev = iio_priv_to_dev(hw); bool irq_active_low = false, open_drain = false; unsigned long irq_type; int err; @@ -153,8 +153,6 @@ static int hts221_buffer_postdisable(struct iio_dev *iio_dev) static const struct iio_buffer_setup_ops hts221_buffer_ops = { .preenable = hts221_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = hts221_buffer_postdisable, }; @@ -191,9 +189,10 @@ out: return IRQ_HANDLED; } -int hts221_allocate_buffers(struct hts221_hw *hw) +int hts221_allocate_buffers(struct iio_dev *iio_dev) { - return devm_iio_triggered_buffer_setup(hw->dev, iio_priv_to_dev(hw), + struct hts221_hw *hw = iio_priv(iio_dev); + return devm_iio_triggered_buffer_setup(hw->dev, iio_dev, NULL, hts221_buffer_handler_thread, &hts221_buffer_ops); } diff --git a/drivers/iio/humidity/hts221_core.c b/drivers/iio/humidity/hts221_core.c index 9003671f14fb3ebb5fb4719332c5323fb21ae4cc..16657789dc457552c110aa7427000cb5e4dead76 100644 --- a/drivers/iio/humidity/hts221_core.c +++ b/drivers/iio/humidity/hts221_core.c @@ -572,7 +572,6 @@ int hts221_probe(struct device *dev, int irq, const char *name, return err; iio_dev->modes = INDIO_DIRECT_MODE; - iio_dev->dev.parent = hw->dev; iio_dev->available_scan_masks = hts221_scan_masks; iio_dev->channels = hts221_channels; iio_dev->num_channels = ARRAY_SIZE(hts221_channels); @@ -621,11 +620,11 @@ int hts221_probe(struct device *dev, int irq, const char *name, } if (hw->irq > 0) { - err = hts221_allocate_buffers(hw); + err = hts221_allocate_buffers(iio_dev); if (err < 0) return err; - err = hts221_allocate_trigger(hw); + err = hts221_allocate_trigger(iio_dev); if (err) return err; } diff --git a/drivers/iio/humidity/htu21.c b/drivers/iio/humidity/htu21.c index d4c0589844dd4f89e5a0ce309fd297ab1de0713e..4f5d9d1c05ab984a2040654d5e535192aecbe23a 100644 --- a/drivers/iio/humidity/htu21.c +++ b/drivers/iio/humidity/htu21.c @@ -204,7 +204,6 @@ static int htu21_probe(struct i2c_client *client, indio_dev->info = &htu21_info; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; if (id->driver_data == MS8607) { diff --git a/drivers/iio/humidity/si7005.c b/drivers/iio/humidity/si7005.c index d5aef0bfef01eb7f2a4ffd20c86c2948832b39b4..160b3d92df619c3ece14db020b84d8966b748d8f 100644 --- a/drivers/iio/humidity/si7005.c +++ b/drivers/iio/humidity/si7005.c @@ -142,7 +142,6 @@ static int si7005_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &si7005_info; diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c index b938f07eed64267d0e376a2d5db0d917b123b5d1..a09b5773d377214727663fe32d13ba33d4b13c87 100644 --- a/drivers/iio/humidity/si7020.c +++ b/drivers/iio/humidity/si7020.c @@ -128,7 +128,6 @@ static int si7020_probe(struct i2c_client *client, data = iio_priv(indio_dev); *data = client; - indio_dev->dev.parent = &client->dev; indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &si7020_info; diff --git a/drivers/iio/iio_core_trigger.h b/drivers/iio/iio_core_trigger.h index e59fe2f36bbbb141a0df2d176b727292a0c1d22f..9d1a92cc648042292edbea9497f629b2c07923e3 100644 --- a/drivers/iio/iio_core_trigger.h +++ b/drivers/iio/iio_core_trigger.h @@ -18,6 +18,12 @@ void iio_device_register_trigger_consumer(struct iio_dev *indio_dev); **/ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev); + +int iio_trigger_attach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf); +int iio_trigger_detach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf); + #else /** @@ -37,4 +43,15 @@ static void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) { } +static inline int iio_trigger_attach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) +{ + return 0; +} +static inline int iio_trigger_detach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) +{ + return 0; +} + #endif /* CONFIG_TRIGGER_CONSUMER */ diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index fc4123d518bc66b1bbdb85d09ec144b44335935d..f02883b08480106d6a95fa1b8fd96b0f70d412c5 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -91,6 +91,7 @@ config KMX61 To compile this driver as module, choose M here: the module will be called kmx61. +source "drivers/iio/imu/inv_icm42600/Kconfig" source "drivers/iio/imu/inv_mpu6050/Kconfig" source "drivers/iio/imu/st_lsm6dsx/Kconfig" diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 88b2c4555230d78d1698318c01d7a845af9efa0c..13e9ff442b11f17a56ca00a25434f10b78f3f229 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_FXOS8700) += fxos8700_core.o obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o obj-$(CONFIG_FXOS8700_SPI) += fxos8700_spi.o +obj-y += inv_icm42600/ obj-y += inv_mpu6050/ obj-$(CONFIG_KMX61) += kmx61.o diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 229f2ff98469f51ecdb75f418334e920e6836a15..1ebe3e50d3e69d6189765e468d35a67f5c74f546 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -1181,7 +1181,6 @@ static int adis16400_probe(struct spi_device *spi) /* setup the industrialio driver allocated elements */ st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data]; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = st->variant->channels; indio_dev->num_channels = st->variant->num_channels; diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c index ad20c488a3bae8ac5cdf6a1ff5969b5c5c533f05..b26a5f1bc51a6a26c4614d7924b135040c2173a8 100644 --- a/drivers/iio/imu/adis16460.c +++ b/drivers/iio/imu/adis16460.c @@ -393,7 +393,6 @@ static int adis16460_probe(struct spi_device *spi) st = iio_priv(indio_dev); st->chip_info = &adis16460_chip_info; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c index c6dac4fc67a10c784ed80cdf7f7afd7c7a955b12..35d10ccb66c2a342e9b0d8974f547ff502467408 100644 --- a/drivers/iio/imu/adis16475.c +++ b/drivers/iio/imu/adis16475.c @@ -1289,7 +1289,6 @@ static int adis16475_probe(struct spi_device *spi) if (ret) return ret; - indio_dev->dev.parent = &spi->dev; indio_dev->name = st->info->name; indio_dev->channels = st->info->channels; indio_dev->num_channels = st->info->num_channels; diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index 6a471eee110ee0670e592f2a33438c4da3c44a97..1eb4f98076f15fc2d2f3f6239dc9cf959092db51 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -1102,12 +1102,12 @@ static int adis16480_config_irq_pin(struct device_node *of_node, /* * Get the interrupt line behaviour. The data ready polarity can be * configured as positive or negative, corresponding to - * IRQF_TRIGGER_RISING or IRQF_TRIGGER_FALLING respectively. + * IRQ_TYPE_EDGE_RISING or IRQ_TYPE_EDGE_FALLING respectively. */ irq_type = irqd_get_trigger_type(desc); - if (irq_type == IRQF_TRIGGER_RISING) { /* Default */ + if (irq_type == IRQ_TYPE_EDGE_RISING) { /* Default */ val |= ADIS16480_DRDY_POL(1); - } else if (irq_type == IRQF_TRIGGER_FALLING) { + } else if (irq_type == IRQ_TYPE_EDGE_FALLING) { val |= ADIS16480_DRDY_POL(0); } else { dev_err(&st->adis.spi->dev, @@ -1229,7 +1229,6 @@ static int adis16480_probe(struct spi_device *spi) st = iio_priv(indio_dev); st->chip_info = &adis16480_chip_info[id->driver_data]; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; diff --git a/drivers/iio/imu/bmi160/bmi160.h b/drivers/iio/imu/bmi160/bmi160.h index 621f5309d735aa618e5e4c54b5f443f65606fcef..a82e040bd10983350ec3bdeaf42163dbcd24da89 100644 --- a/drivers/iio/imu/bmi160/bmi160.h +++ b/drivers/iio/imu/bmi160/bmi160.h @@ -3,10 +3,13 @@ #define BMI160_H_ #include +#include struct bmi160_data { struct regmap *regmap; struct iio_trigger *trig; + struct regulator_bulk_data supplies[2]; + struct iio_mount_matrix orientation; }; extern const struct regmap_config bmi160_regmap_config; diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c index 6af65d6f1d280f8f9a60584f086aec808451c683..222ebb26f01320acba7723c0b11b9425d1611dfe 100644 --- a/drivers/iio/imu/bmi160/bmi160_core.c +++ b/drivers/iio/imu/bmi160/bmi160_core.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -109,6 +110,7 @@ .storagebits = 16, \ .endianness = IIO_LE, \ }, \ + .ext_info = bmi160_ext_info, \ } /* scan indexes follow DATA register order */ @@ -264,6 +266,20 @@ static const struct bmi160_odr_item bmi160_odr_table[] = { }, }; +static const struct iio_mount_matrix * +bmi160_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct bmi160_data *data = iio_priv(indio_dev); + + return &data->orientation; +} + +static const struct iio_chan_spec_ext_info bmi160_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bmi160_get_mount_matrix), + { } +}; + static const struct iio_chan_spec bmi160_channels[] = { BMI160_CHANNEL(IIO_ACCEL, X, BMI160_SCAN_ACCEL_X), BMI160_CHANNEL(IIO_ACCEL, Y, BMI160_SCAN_ACCEL_Y), @@ -709,6 +725,12 @@ static int bmi160_chip_init(struct bmi160_data *data, bool use_spi) unsigned int val; struct device *dev = regmap_get_device(data->regmap); + ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies), data->supplies); + if (ret) { + dev_err(dev, "Failed to enable regulators: %d\n", ret); + return ret; + } + ret = regmap_write(data->regmap, BMI160_REG_CMD, BMI160_CMD_SOFTRESET); if (ret) return ret; @@ -793,9 +815,16 @@ int bmi160_probe_trigger(struct iio_dev *indio_dev, int irq, u32 irq_type) static void bmi160_chip_uninit(void *data) { struct bmi160_data *bmi_data = data; + struct device *dev = regmap_get_device(bmi_data->regmap); + int ret; bmi160_set_mode(bmi_data, BMI160_GYRO, false); bmi160_set_mode(bmi_data, BMI160_ACCEL, false); + + ret = regulator_bulk_disable(ARRAY_SIZE(bmi_data->supplies), + bmi_data->supplies); + if (ret) + dev_err(dev, "Failed to disable regulators: %d\n", ret); } int bmi160_core_probe(struct device *dev, struct regmap *regmap, @@ -815,6 +844,21 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap, dev_set_drvdata(dev, indio_dev); data->regmap = regmap; + data->supplies[0].supply = "vdd"; + data->supplies[1].supply = "vddio"; + ret = devm_regulator_bulk_get(dev, + ARRAY_SIZE(data->supplies), + data->supplies); + if (ret) { + dev_err(dev, "Failed to get regulators: %d\n", ret); + return ret; + } + + ret = iio_read_mount_matrix(dev, "mount-matrix", + &data->orientation); + if (ret) + return ret; + ret = bmi160_chip_init(data, use_spi); if (ret) return ret; @@ -826,7 +870,6 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap, if (!name && ACPI_HANDLE(dev)) name = bmi160_match_acpi_device(dev); - indio_dev->dev.parent = dev; indio_dev->channels = bmi160_channels; indio_dev->num_channels = ARRAY_SIZE(bmi160_channels); indio_dev->name = name; @@ -853,6 +896,6 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap, } EXPORT_SYMBOL_GPL(bmi160_core_probe); -MODULE_AUTHOR("Daniel Baluta "); MODULE_DESCRIPTION("Bosch BMI160 driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/imu/fxos8700_core.c b/drivers/iio/imu/fxos8700_core.c index 7b47be44ea5963ae50c10975dbc5a79e91df6647..ab288186f36e4575ac9b68467bf4d59fab606387 100644 --- a/drivers/iio/imu/fxos8700_core.c +++ b/drivers/iio/imu/fxos8700_core.c @@ -633,7 +633,6 @@ int fxos8700_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; - indio_dev->dev.parent = dev; indio_dev->channels = fxos8700_channels; indio_dev->num_channels = ARRAY_SIZE(fxos8700_channels); indio_dev->name = name ? name : "fxos8700"; diff --git a/drivers/iio/imu/inv_icm42600/Kconfig b/drivers/iio/imu/inv_icm42600/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..50cbcfcb6cf18cc91b6dc904942de427800952c2 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/Kconfig @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +config INV_ICM42600 + tristate + select IIO_BUFFER + +config INV_ICM42600_I2C + tristate "InvenSense ICM-426xx I2C driver" + depends on I2C + select INV_ICM42600 + select REGMAP_I2C + help + This driver supports the InvenSense ICM-426xx motion tracking + devices over I2C. + + This driver can be built as a module. The module will be called + inv-icm42600-i2c. + +config INV_ICM42600_SPI + tristate "InvenSense ICM-426xx SPI driver" + depends on SPI_MASTER + select INV_ICM42600 + select REGMAP_SPI + help + This driver supports the InvenSense ICM-426xx motion tracking + devices over SPI. + + This driver can be built as a module. The module will be called + inv-icm42600-spi. diff --git a/drivers/iio/imu/inv_icm42600/Makefile b/drivers/iio/imu/inv_icm42600/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..291714d9aa54f2145c8c2c3c50a3ef9178ab84e4 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +obj-$(CONFIG_INV_ICM42600) += inv-icm42600.o +inv-icm42600-y += inv_icm42600_core.o +inv-icm42600-y += inv_icm42600_gyro.o +inv-icm42600-y += inv_icm42600_accel.o +inv-icm42600-y += inv_icm42600_temp.o +inv-icm42600-y += inv_icm42600_buffer.o +inv-icm42600-y += inv_icm42600_timestamp.o + +obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o +inv-icm42600-i2c-y += inv_icm42600_i2c.o + +obj-$(CONFIG_INV_ICM42600_SPI) += inv-icm42600-spi.o +inv-icm42600-spi-y += inv_icm42600_spi.o diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h new file mode 100644 index 0000000000000000000000000000000000000000..c0f5059b13b3161351a2362a91b3e64fea7c9017 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -0,0 +1,395 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#ifndef INV_ICM42600_H_ +#define INV_ICM42600_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600_buffer.h" + +enum inv_icm42600_chip { + INV_CHIP_ICM42600, + INV_CHIP_ICM42602, + INV_CHIP_ICM42605, + INV_CHIP_ICM42622, + INV_CHIP_NB, +}; + +/* serial bus slew rates */ +enum inv_icm42600_slew_rate { + INV_ICM42600_SLEW_RATE_20_60NS, + INV_ICM42600_SLEW_RATE_12_36NS, + INV_ICM42600_SLEW_RATE_6_18NS, + INV_ICM42600_SLEW_RATE_4_12NS, + INV_ICM42600_SLEW_RATE_2_6NS, + INV_ICM42600_SLEW_RATE_INF_2NS, +}; + +enum inv_icm42600_sensor_mode { + INV_ICM42600_SENSOR_MODE_OFF, + INV_ICM42600_SENSOR_MODE_STANDBY, + INV_ICM42600_SENSOR_MODE_LOW_POWER, + INV_ICM42600_SENSOR_MODE_LOW_NOISE, + INV_ICM42600_SENSOR_MODE_NB, +}; + +/* gyroscope fullscale values */ +enum inv_icm42600_gyro_fs { + INV_ICM42600_GYRO_FS_2000DPS, + INV_ICM42600_GYRO_FS_1000DPS, + INV_ICM42600_GYRO_FS_500DPS, + INV_ICM42600_GYRO_FS_250DPS, + INV_ICM42600_GYRO_FS_125DPS, + INV_ICM42600_GYRO_FS_62_5DPS, + INV_ICM42600_GYRO_FS_31_25DPS, + INV_ICM42600_GYRO_FS_15_625DPS, + INV_ICM42600_GYRO_FS_NB, +}; + +/* accelerometer fullscale values */ +enum inv_icm42600_accel_fs { + INV_ICM42600_ACCEL_FS_16G, + INV_ICM42600_ACCEL_FS_8G, + INV_ICM42600_ACCEL_FS_4G, + INV_ICM42600_ACCEL_FS_2G, + INV_ICM42600_ACCEL_FS_NB, +}; + +/* ODR suffixed by LN or LP are Low-Noise or Low-Power mode only */ +enum inv_icm42600_odr { + INV_ICM42600_ODR_8KHZ_LN = 3, + INV_ICM42600_ODR_4KHZ_LN, + INV_ICM42600_ODR_2KHZ_LN, + INV_ICM42600_ODR_1KHZ_LN, + INV_ICM42600_ODR_200HZ, + INV_ICM42600_ODR_100HZ, + INV_ICM42600_ODR_50HZ, + INV_ICM42600_ODR_25HZ, + INV_ICM42600_ODR_12_5HZ, + INV_ICM42600_ODR_6_25HZ_LP, + INV_ICM42600_ODR_3_125HZ_LP, + INV_ICM42600_ODR_1_5625HZ_LP, + INV_ICM42600_ODR_500HZ, + INV_ICM42600_ODR_NB, +}; + +enum inv_icm42600_filter { + /* Low-Noise mode sensor data filter (3rd order filter by default) */ + INV_ICM42600_FILTER_BW_ODR_DIV_2, + + /* Low-Power mode sensor data filter (averaging) */ + INV_ICM42600_FILTER_AVG_1X = 1, + INV_ICM42600_FILTER_AVG_16X = 6, +}; + +struct inv_icm42600_sensor_conf { + int mode; + int fs; + int odr; + int filter; +}; +#define INV_ICM42600_SENSOR_CONF_INIT {-1, -1, -1, -1} + +struct inv_icm42600_conf { + struct inv_icm42600_sensor_conf gyro; + struct inv_icm42600_sensor_conf accel; + bool temp_en; +}; + +struct inv_icm42600_suspended { + enum inv_icm42600_sensor_mode gyro; + enum inv_icm42600_sensor_mode accel; + bool temp; +}; + +/** + * struct inv_icm42600_state - driver state variables + * @lock: lock for serializing multiple registers access. + * @chip: chip identifier. + * @name: chip name. + * @map: regmap pointer. + * @vdd_supply: VDD voltage regulator for the chip. + * @vddio_supply: I/O voltage regulator for the chip. + * @orientation: sensor chip orientation relative to main hardware. + * @conf: chip sensors configurations. + * @suspended: suspended sensors configuration. + * @indio_gyro: gyroscope IIO device. + * @indio_accel: accelerometer IIO device. + * @buffer: data transfer buffer aligned for DMA. + * @fifo: FIFO management structure. + * @timestamp: interrupt timestamps. + */ +struct inv_icm42600_state { + struct mutex lock; + enum inv_icm42600_chip chip; + const char *name; + struct regmap *map; + struct regulator *vdd_supply; + struct regulator *vddio_supply; + struct iio_mount_matrix orientation; + struct inv_icm42600_conf conf; + struct inv_icm42600_suspended suspended; + struct iio_dev *indio_gyro; + struct iio_dev *indio_accel; + uint8_t buffer[2] ____cacheline_aligned; + struct inv_icm42600_fifo fifo; + struct { + int64_t gyro; + int64_t accel; + } timestamp; +}; + +/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */ + +/* Bank selection register, available in all banks */ +#define INV_ICM42600_REG_BANK_SEL 0x76 +#define INV_ICM42600_BANK_SEL_MASK GENMASK(2, 0) + +/* User bank 0 (MSB 0x00) */ +#define INV_ICM42600_REG_DEVICE_CONFIG 0x0011 +#define INV_ICM42600_DEVICE_CONFIG_SOFT_RESET BIT(0) + +#define INV_ICM42600_REG_DRIVE_CONFIG 0x0013 +#define INV_ICM42600_DRIVE_CONFIG_I2C_MASK GENMASK(5, 3) +#define INV_ICM42600_DRIVE_CONFIG_I2C(_rate) \ + FIELD_PREP(INV_ICM42600_DRIVE_CONFIG_I2C_MASK, (_rate)) +#define INV_ICM42600_DRIVE_CONFIG_SPI_MASK GENMASK(2, 0) +#define INV_ICM42600_DRIVE_CONFIG_SPI(_rate) \ + FIELD_PREP(INV_ICM42600_DRIVE_CONFIG_SPI_MASK, (_rate)) + +#define INV_ICM42600_REG_INT_CONFIG 0x0014 +#define INV_ICM42600_INT_CONFIG_INT2_LATCHED BIT(5) +#define INV_ICM42600_INT_CONFIG_INT2_PUSH_PULL BIT(4) +#define INV_ICM42600_INT_CONFIG_INT2_ACTIVE_HIGH BIT(3) +#define INV_ICM42600_INT_CONFIG_INT2_ACTIVE_LOW 0x00 +#define INV_ICM42600_INT_CONFIG_INT1_LATCHED BIT(2) +#define INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL BIT(1) +#define INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH BIT(0) +#define INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW 0x00 + +#define INV_ICM42600_REG_FIFO_CONFIG 0x0016 +#define INV_ICM42600_FIFO_CONFIG_MASK GENMASK(7, 6) +#define INV_ICM42600_FIFO_CONFIG_BYPASS \ + FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 0) +#define INV_ICM42600_FIFO_CONFIG_STREAM \ + FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 1) +#define INV_ICM42600_FIFO_CONFIG_STOP_ON_FULL \ + FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 2) + +/* all sensor data are 16 bits (2 registers wide) in big-endian */ +#define INV_ICM42600_REG_TEMP_DATA 0x001D +#define INV_ICM42600_REG_ACCEL_DATA_X 0x001F +#define INV_ICM42600_REG_ACCEL_DATA_Y 0x0021 +#define INV_ICM42600_REG_ACCEL_DATA_Z 0x0023 +#define INV_ICM42600_REG_GYRO_DATA_X 0x0025 +#define INV_ICM42600_REG_GYRO_DATA_Y 0x0027 +#define INV_ICM42600_REG_GYRO_DATA_Z 0x0029 +#define INV_ICM42600_DATA_INVALID -32768 + +#define INV_ICM42600_REG_INT_STATUS 0x002D +#define INV_ICM42600_INT_STATUS_UI_FSYNC BIT(6) +#define INV_ICM42600_INT_STATUS_PLL_RDY BIT(5) +#define INV_ICM42600_INT_STATUS_RESET_DONE BIT(4) +#define INV_ICM42600_INT_STATUS_DATA_RDY BIT(3) +#define INV_ICM42600_INT_STATUS_FIFO_THS BIT(2) +#define INV_ICM42600_INT_STATUS_FIFO_FULL BIT(1) +#define INV_ICM42600_INT_STATUS_AGC_RDY BIT(0) + +/* + * FIFO access registers + * FIFO count is 16 bits (2 registers) big-endian + * FIFO data is a continuous read register to read FIFO content + */ +#define INV_ICM42600_REG_FIFO_COUNT 0x002E +#define INV_ICM42600_REG_FIFO_DATA 0x0030 + +#define INV_ICM42600_REG_SIGNAL_PATH_RESET 0x004B +#define INV_ICM42600_SIGNAL_PATH_RESET_DMP_INIT_EN BIT(6) +#define INV_ICM42600_SIGNAL_PATH_RESET_DMP_MEM_RESET BIT(5) +#define INV_ICM42600_SIGNAL_PATH_RESET_RESET BIT(3) +#define INV_ICM42600_SIGNAL_PATH_RESET_TMST_STROBE BIT(2) +#define INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH BIT(1) + +/* default configuration: all data big-endian and fifo count in bytes */ +#define INV_ICM42600_REG_INTF_CONFIG0 0x004C +#define INV_ICM42600_INTF_CONFIG0_FIFO_HOLD_LAST_DATA BIT(7) +#define INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_REC BIT(6) +#define INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_ENDIAN BIT(5) +#define INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN BIT(4) +#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK GENMASK(1, 0) +#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS \ + FIELD_PREP(INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, 2) +#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS \ + FIELD_PREP(INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, 3) + +#define INV_ICM42600_REG_INTF_CONFIG1 0x004D +#define INV_ICM42600_INTF_CONFIG1_ACCEL_LP_CLK_RC BIT(3) + +#define INV_ICM42600_REG_PWR_MGMT0 0x004E +#define INV_ICM42600_PWR_MGMT0_TEMP_DIS BIT(5) +#define INV_ICM42600_PWR_MGMT0_IDLE BIT(4) +#define INV_ICM42600_PWR_MGMT0_GYRO(_mode) \ + FIELD_PREP(GENMASK(3, 2), (_mode)) +#define INV_ICM42600_PWR_MGMT0_ACCEL(_mode) \ + FIELD_PREP(GENMASK(1, 0), (_mode)) + +#define INV_ICM42600_REG_GYRO_CONFIG0 0x004F +#define INV_ICM42600_GYRO_CONFIG0_FS(_fs) \ + FIELD_PREP(GENMASK(7, 5), (_fs)) +#define INV_ICM42600_GYRO_CONFIG0_ODR(_odr) \ + FIELD_PREP(GENMASK(3, 0), (_odr)) + +#define INV_ICM42600_REG_ACCEL_CONFIG0 0x0050 +#define INV_ICM42600_ACCEL_CONFIG0_FS(_fs) \ + FIELD_PREP(GENMASK(7, 5), (_fs)) +#define INV_ICM42600_ACCEL_CONFIG0_ODR(_odr) \ + FIELD_PREP(GENMASK(3, 0), (_odr)) + +#define INV_ICM42600_REG_GYRO_ACCEL_CONFIG0 0x0052 +#define INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(_f) \ + FIELD_PREP(GENMASK(7, 4), (_f)) +#define INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(_f) \ + FIELD_PREP(GENMASK(3, 0), (_f)) + +#define INV_ICM42600_REG_TMST_CONFIG 0x0054 +#define INV_ICM42600_TMST_CONFIG_MASK GENMASK(4, 0) +#define INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN BIT(4) +#define INV_ICM42600_TMST_CONFIG_TMST_RES_16US BIT(3) +#define INV_ICM42600_TMST_CONFIG_TMST_DELTA_EN BIT(2) +#define INV_ICM42600_TMST_CONFIG_TMST_FSYNC_EN BIT(1) +#define INV_ICM42600_TMST_CONFIG_TMST_EN BIT(0) + +#define INV_ICM42600_REG_FIFO_CONFIG1 0x005F +#define INV_ICM42600_FIFO_CONFIG1_RESUME_PARTIAL_RD BIT(6) +#define INV_ICM42600_FIFO_CONFIG1_WM_GT_TH BIT(5) +#define INV_ICM42600_FIFO_CONFIG1_TMST_FSYNC_EN BIT(3) +#define INV_ICM42600_FIFO_CONFIG1_TEMP_EN BIT(2) +#define INV_ICM42600_FIFO_CONFIG1_GYRO_EN BIT(1) +#define INV_ICM42600_FIFO_CONFIG1_ACCEL_EN BIT(0) + +/* FIFO watermark is 16 bits (2 registers wide) in little-endian */ +#define INV_ICM42600_REG_FIFO_WATERMARK 0x0060 +#define INV_ICM42600_FIFO_WATERMARK_VAL(_wm) \ + cpu_to_le16((_wm) & GENMASK(11, 0)) +/* FIFO is 2048 bytes, let 12 samples for reading latency */ +#define INV_ICM42600_FIFO_WATERMARK_MAX (2048 - 12 * 16) + +#define INV_ICM42600_REG_INT_CONFIG1 0x0064 +#define INV_ICM42600_INT_CONFIG1_TPULSE_DURATION BIT(6) +#define INV_ICM42600_INT_CONFIG1_TDEASSERT_DISABLE BIT(5) +#define INV_ICM42600_INT_CONFIG1_ASYNC_RESET BIT(4) + +#define INV_ICM42600_REG_INT_SOURCE0 0x0065 +#define INV_ICM42600_INT_SOURCE0_UI_FSYNC_INT1_EN BIT(6) +#define INV_ICM42600_INT_SOURCE0_PLL_RDY_INT1_EN BIT(5) +#define INV_ICM42600_INT_SOURCE0_RESET_DONE_INT1_EN BIT(4) +#define INV_ICM42600_INT_SOURCE0_UI_DRDY_INT1_EN BIT(3) +#define INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN BIT(2) +#define INV_ICM42600_INT_SOURCE0_FIFO_FULL_INT1_EN BIT(1) +#define INV_ICM42600_INT_SOURCE0_UI_AGC_RDY_INT1_EN BIT(0) + +#define INV_ICM42600_REG_WHOAMI 0x0075 +#define INV_ICM42600_WHOAMI_ICM42600 0x40 +#define INV_ICM42600_WHOAMI_ICM42602 0x41 +#define INV_ICM42600_WHOAMI_ICM42605 0x42 +#define INV_ICM42600_WHOAMI_ICM42622 0x46 + +/* User bank 1 (MSB 0x10) */ +#define INV_ICM42600_REG_SENSOR_CONFIG0 0x1003 +#define INV_ICM42600_SENSOR_CONFIG0_ZG_DISABLE BIT(5) +#define INV_ICM42600_SENSOR_CONFIG0_YG_DISABLE BIT(4) +#define INV_ICM42600_SENSOR_CONFIG0_XG_DISABLE BIT(3) +#define INV_ICM42600_SENSOR_CONFIG0_ZA_DISABLE BIT(2) +#define INV_ICM42600_SENSOR_CONFIG0_YA_DISABLE BIT(1) +#define INV_ICM42600_SENSOR_CONFIG0_XA_DISABLE BIT(0) + +/* Timestamp value is 20 bits (3 registers) in little-endian */ +#define INV_ICM42600_REG_TMSTVAL 0x1062 +#define INV_ICM42600_TMSTVAL_MASK GENMASK(19, 0) + +#define INV_ICM42600_REG_INTF_CONFIG4 0x107A +#define INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY BIT(6) +#define INV_ICM42600_INTF_CONFIG4_SPI_AP_4WIRE BIT(1) + +#define INV_ICM42600_REG_INTF_CONFIG6 0x107C +#define INV_ICM42600_INTF_CONFIG6_MASK GENMASK(4, 0) +#define INV_ICM42600_INTF_CONFIG6_I3C_EN BIT(4) +#define INV_ICM42600_INTF_CONFIG6_I3C_IBI_BYTE_EN BIT(3) +#define INV_ICM42600_INTF_CONFIG6_I3C_IBI_EN BIT(2) +#define INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN BIT(1) +#define INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN BIT(0) + +/* User bank 4 (MSB 0x40) */ +#define INV_ICM42600_REG_INT_SOURCE8 0x404F +#define INV_ICM42600_INT_SOURCE8_FSYNC_IBI_EN BIT(5) +#define INV_ICM42600_INT_SOURCE8_PLL_RDY_IBI_EN BIT(4) +#define INV_ICM42600_INT_SOURCE8_UI_DRDY_IBI_EN BIT(3) +#define INV_ICM42600_INT_SOURCE8_FIFO_THS_IBI_EN BIT(2) +#define INV_ICM42600_INT_SOURCE8_FIFO_FULL_IBI_EN BIT(1) +#define INV_ICM42600_INT_SOURCE8_AGC_RDY_IBI_EN BIT(0) + +#define INV_ICM42600_REG_OFFSET_USER0 0x4077 +#define INV_ICM42600_REG_OFFSET_USER1 0x4078 +#define INV_ICM42600_REG_OFFSET_USER2 0x4079 +#define INV_ICM42600_REG_OFFSET_USER3 0x407A +#define INV_ICM42600_REG_OFFSET_USER4 0x407B +#define INV_ICM42600_REG_OFFSET_USER5 0x407C +#define INV_ICM42600_REG_OFFSET_USER6 0x407D +#define INV_ICM42600_REG_OFFSET_USER7 0x407E +#define INV_ICM42600_REG_OFFSET_USER8 0x407F + +/* Sleep times required by the driver */ +#define INV_ICM42600_POWER_UP_TIME_MS 100 +#define INV_ICM42600_RESET_TIME_MS 1 +#define INV_ICM42600_ACCEL_STARTUP_TIME_MS 20 +#define INV_ICM42600_GYRO_STARTUP_TIME_MS 60 +#define INV_ICM42600_GYRO_STOP_TIME_MS 150 +#define INV_ICM42600_TEMP_STARTUP_TIME_MS 14 +#define INV_ICM42600_SUSPEND_DELAY_MS 2000 + +typedef int (*inv_icm42600_bus_setup)(struct inv_icm42600_state *); + +extern const struct regmap_config inv_icm42600_regmap_config; +extern const struct dev_pm_ops inv_icm42600_pm_ops; + +const struct iio_mount_matrix * +inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan); + +uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr); + +int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st, + struct inv_icm42600_sensor_conf *conf, + unsigned int *sleep_ms); + +int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st, + struct inv_icm42600_sensor_conf *conf, + unsigned int *sleep_ms); + +int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, + unsigned int *sleep_ms); + +int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval); + +int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, + inv_icm42600_bus_setup bus_setup); + +struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st); + +int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev); + +struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st); + +int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev); + +#endif diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c new file mode 100644 index 0000000000000000000000000000000000000000..3441b0d61c5d53b29222be147597af2ccb9ba931 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -0,0 +1,787 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" +#include "inv_icm42600_temp.h" +#include "inv_icm42600_buffer.h" +#include "inv_icm42600_timestamp.h" + +#define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info) \ + { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = _modifier, \ + .info_mask_separate = \ + BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .info_mask_shared_by_type = \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .info_mask_shared_by_all = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + .ext_info = _ext_info, \ + } + +enum inv_icm42600_accel_scan { + INV_ICM42600_ACCEL_SCAN_X, + INV_ICM42600_ACCEL_SCAN_Y, + INV_ICM42600_ACCEL_SCAN_Z, + INV_ICM42600_ACCEL_SCAN_TEMP, + INV_ICM42600_ACCEL_SCAN_TIMESTAMP, +}; + +static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix), + {}, +}; + +static const struct iio_chan_spec inv_icm42600_accel_channels[] = { + INV_ICM42600_ACCEL_CHAN(IIO_MOD_X, INV_ICM42600_ACCEL_SCAN_X, + inv_icm42600_accel_ext_infos), + INV_ICM42600_ACCEL_CHAN(IIO_MOD_Y, INV_ICM42600_ACCEL_SCAN_Y, + inv_icm42600_accel_ext_infos), + INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z, + inv_icm42600_accel_ext_infos), + INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP), + IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP), +}; + +/* + * IIO buffer data: size must be a power of 2 and timestamp aligned + * 16 bytes: 6 bytes acceleration, 2 bytes temperature, 8 bytes timestamp + */ +struct inv_icm42600_accel_buffer { + struct inv_icm42600_fifo_sensor_data accel; + int16_t temp; + int64_t timestamp __aligned(8); +}; + +#define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS \ + (BIT(INV_ICM42600_ACCEL_SCAN_X) | \ + BIT(INV_ICM42600_ACCEL_SCAN_Y) | \ + BIT(INV_ICM42600_ACCEL_SCAN_Z)) + +#define INV_ICM42600_SCAN_MASK_TEMP BIT(INV_ICM42600_ACCEL_SCAN_TEMP) + +static const unsigned long inv_icm42600_accel_scan_masks[] = { + /* 3-axis accel + temperature */ + INV_ICM42600_SCAN_MASK_ACCEL_3AXIS | INV_ICM42600_SCAN_MASK_TEMP, + 0, +}; + +/* enable accelerometer sensor and FIFO write */ +static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + unsigned int fifo_en = 0; + unsigned int sleep_temp = 0; + unsigned int sleep_accel = 0; + unsigned int sleep; + int ret; + + mutex_lock(&st->lock); + + if (*scan_mask & INV_ICM42600_SCAN_MASK_TEMP) { + /* enable temp sensor */ + ret = inv_icm42600_set_temp_conf(st, true, &sleep_temp); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42600_SENSOR_TEMP; + } + + if (*scan_mask & INV_ICM42600_SCAN_MASK_ACCEL_3AXIS) { + /* enable accel sensor */ + conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; + ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_accel); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42600_SENSOR_ACCEL; + } + + /* update data FIFO write */ + inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0); + ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); + if (ret) + goto out_unlock; + + ret = inv_icm42600_buffer_update_watermark(st); + +out_unlock: + mutex_unlock(&st->lock); + /* sleep maximum required time */ + if (sleep_accel > sleep_temp) + sleep = sleep_accel; + else + sleep = sleep_temp; + if (sleep) + msleep(sleep); + return ret; +} + +static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int16_t *val) +{ + struct device *dev = regmap_get_device(st->map); + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + unsigned int reg; + __be16 *data; + int ret; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_ACCEL_DATA_X; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_ACCEL_DATA_Y; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_ACCEL_DATA_Z; + break; + default: + return -EINVAL; + } + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + /* enable accel sensor */ + conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; + ret = inv_icm42600_set_accel_conf(st, &conf, NULL); + if (ret) + goto exit; + + /* read accel register data */ + data = (__be16 *)&st->buffer[0]; + ret = regmap_bulk_read(st->map, reg, data, sizeof(*data)); + if (ret) + goto exit; + + *val = (int16_t)be16_to_cpup(data); + if (*val == INV_ICM42600_DATA_INVALID) + ret = -EINVAL; +exit: + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return ret; +} + +/* IIO format int + nano */ +static const int inv_icm42600_accel_scale[] = { + /* +/- 16G => 0.004788403 m/s-2 */ + [2 * INV_ICM42600_ACCEL_FS_16G] = 0, + [2 * INV_ICM42600_ACCEL_FS_16G + 1] = 4788403, + /* +/- 8G => 0.002394202 m/s-2 */ + [2 * INV_ICM42600_ACCEL_FS_8G] = 0, + [2 * INV_ICM42600_ACCEL_FS_8G + 1] = 2394202, + /* +/- 4G => 0.001197101 m/s-2 */ + [2 * INV_ICM42600_ACCEL_FS_4G] = 0, + [2 * INV_ICM42600_ACCEL_FS_4G + 1] = 1197101, + /* +/- 2G => 0.000598550 m/s-2 */ + [2 * INV_ICM42600_ACCEL_FS_2G] = 0, + [2 * INV_ICM42600_ACCEL_FS_2G + 1] = 598550, +}; + +static int inv_icm42600_accel_read_scale(struct inv_icm42600_state *st, + int *val, int *val2) +{ + unsigned int idx; + + idx = st->conf.accel.fs; + + *val = inv_icm42600_accel_scale[2 * idx]; + *val2 = inv_icm42600_accel_scale[2 * idx + 1]; + return IIO_VAL_INT_PLUS_NANO; +} + +static int inv_icm42600_accel_write_scale(struct inv_icm42600_state *st, + int val, int val2) +{ + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + int ret; + + for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_accel_scale); idx += 2) { + if (val == inv_icm42600_accel_scale[idx] && + val2 == inv_icm42600_accel_scale[idx + 1]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42600_accel_scale)) + return -EINVAL; + + conf.fs = idx / 2; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_icm42600_set_accel_conf(st, &conf, NULL); + + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +/* IIO format int + micro */ +static const int inv_icm42600_accel_odr[] = { + /* 12.5Hz */ + 12, 500000, + /* 25Hz */ + 25, 0, + /* 50Hz */ + 50, 0, + /* 100Hz */ + 100, 0, + /* 200Hz */ + 200, 0, + /* 1kHz */ + 1000, 0, + /* 2kHz */ + 2000, 0, + /* 4kHz */ + 4000, 0, +}; + +static const int inv_icm42600_accel_odr_conv[] = { + INV_ICM42600_ODR_12_5HZ, + INV_ICM42600_ODR_25HZ, + INV_ICM42600_ODR_50HZ, + INV_ICM42600_ODR_100HZ, + INV_ICM42600_ODR_200HZ, + INV_ICM42600_ODR_1KHZ_LN, + INV_ICM42600_ODR_2KHZ_LN, + INV_ICM42600_ODR_4KHZ_LN, +}; + +static int inv_icm42600_accel_read_odr(struct inv_icm42600_state *st, + int *val, int *val2) +{ + unsigned int odr; + unsigned int i; + + odr = st->conf.accel.odr; + + for (i = 0; i < ARRAY_SIZE(inv_icm42600_accel_odr_conv); ++i) { + if (inv_icm42600_accel_odr_conv[i] == odr) + break; + } + if (i >= ARRAY_SIZE(inv_icm42600_accel_odr_conv)) + return -EINVAL; + + *val = inv_icm42600_accel_odr[2 * i]; + *val2 = inv_icm42600_accel_odr[2 * i + 1]; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int inv_icm42600_accel_write_odr(struct iio_dev *indio_dev, + int val, int val2) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + int ret; + + for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_accel_odr); idx += 2) { + if (val == inv_icm42600_accel_odr[idx] && + val2 == inv_icm42600_accel_odr[idx + 1]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42600_accel_odr)) + return -EINVAL; + + conf.odr = inv_icm42600_accel_odr_conv[idx / 2]; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_icm42600_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr), + iio_buffer_enabled(indio_dev)); + if (ret) + goto out_unlock; + + ret = inv_icm42600_set_accel_conf(st, &conf, NULL); + if (ret) + goto out_unlock; + inv_icm42600_buffer_update_fifo_period(st); + inv_icm42600_buffer_update_watermark(st); + +out_unlock: + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +/* + * Calibration bias values, IIO range format int + micro. + * Value is limited to +/-1g coded on 12 bits signed. Step is 0.5mg. + */ +static int inv_icm42600_accel_calibbias[] = { + -10, 42010, /* min: -10.042010 m/s² */ + 0, 4903, /* step: 0.004903 m/s² */ + 10, 37106, /* max: 10.037106 m/s² */ +}; + +static int inv_icm42600_accel_read_offset(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int *val, int *val2) +{ + struct device *dev = regmap_get_device(st->map); + int64_t val64; + int32_t bias; + unsigned int reg; + int16_t offset; + uint8_t data[2]; + int ret; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_OFFSET_USER4; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_OFFSET_USER6; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_OFFSET_USER7; + break; + default: + return -EINVAL; + } + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = regmap_bulk_read(st->map, reg, st->buffer, sizeof(data)); + memcpy(data, st->buffer, sizeof(data)); + + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + if (ret) + return ret; + + /* 12 bits signed value */ + switch (chan->channel2) { + case IIO_MOD_X: + offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11); + break; + case IIO_MOD_Y: + offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11); + break; + case IIO_MOD_Z: + offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11); + break; + default: + return -EINVAL; + } + + /* + * convert raw offset to g then to m/s² + * 12 bits signed raw step 0.5mg to g: 5 / 10000 + * g to m/s²: 9.806650 + * result in micro (1000000) + * (offset * 5 * 9.806650 * 1000000) / 10000 + */ + val64 = (int64_t)offset * 5LL * 9806650LL; + /* for rounding, add + or - divisor (10000) divided by 2 */ + if (val64 >= 0) + val64 += 10000LL / 2LL; + else + val64 -= 10000LL / 2LL; + bias = div_s64(val64, 10000L); + *val = bias / 1000000L; + *val2 = bias % 1000000L; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int inv_icm42600_accel_write_offset(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int val, int val2) +{ + struct device *dev = regmap_get_device(st->map); + int64_t val64; + int32_t min, max; + unsigned int reg, regval; + int16_t offset; + int ret; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_OFFSET_USER4; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_OFFSET_USER6; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_OFFSET_USER7; + break; + default: + return -EINVAL; + } + + /* inv_icm42600_accel_calibbias: min - step - max in micro */ + min = inv_icm42600_accel_calibbias[0] * 1000000L + + inv_icm42600_accel_calibbias[1]; + max = inv_icm42600_accel_calibbias[4] * 1000000L + + inv_icm42600_accel_calibbias[5]; + val64 = (int64_t)val * 1000000LL + (int64_t)val2; + if (val64 < min || val64 > max) + return -EINVAL; + + /* + * convert m/s² to g then to raw value + * m/s² to g: 1 / 9.806650 + * g to raw 12 bits signed, step 0.5mg: 10000 / 5 + * val in micro (1000000) + * val * 10000 / (9.806650 * 1000000 * 5) + */ + val64 = val64 * 10000LL; + /* for rounding, add + or - divisor (9806650 * 5) divided by 2 */ + if (val64 >= 0) + val64 += 9806650 * 5 / 2; + else + val64 -= 9806650 * 5 / 2; + offset = div_s64(val64, 9806650 * 5); + + /* clamp value limited to 12 bits signed */ + if (offset < -2048) + offset = -2048; + else if (offset > 2047) + offset = 2047; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + switch (chan->channel2) { + case IIO_MOD_X: + /* OFFSET_USER4 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER4, + ®val); + if (ret) + goto out_unlock; + st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F); + st->buffer[1] = offset & 0xFF; + break; + case IIO_MOD_Y: + /* OFFSET_USER7 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER7, + ®val); + if (ret) + goto out_unlock; + st->buffer[0] = offset & 0xFF; + st->buffer[1] = ((offset & 0xF00) >> 8) | (regval & 0xF0); + break; + case IIO_MOD_Z: + /* OFFSET_USER7 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER7, + ®val); + if (ret) + goto out_unlock; + st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F); + st->buffer[1] = offset & 0xFF; + break; + default: + ret = -EINVAL; + goto out_unlock; + } + + ret = regmap_bulk_write(st->map, reg, st->buffer, 2); + +out_unlock: + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return ret; +} + +static int inv_icm42600_accel_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int16_t data; + int ret; + + switch (chan->type) { + case IIO_ACCEL: + break; + case IIO_TEMP: + return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, mask); + default: + return -EINVAL; + } + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_accel_read_sensor(st, chan, &data); + iio_device_release_direct_mode(indio_dev); + if (ret) + return ret; + *val = data; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + return inv_icm42600_accel_read_scale(st, val, val2); + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42600_accel_read_odr(st, val, val2); + case IIO_CHAN_INFO_CALIBBIAS: + return inv_icm42600_accel_read_offset(st, chan, val, val2); + default: + return -EINVAL; + } +} + +static int inv_icm42600_accel_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, + int *type, int *length, long mask) +{ + if (chan->type != IIO_ACCEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + *vals = inv_icm42600_accel_scale; + *type = IIO_VAL_INT_PLUS_NANO; + *length = ARRAY_SIZE(inv_icm42600_accel_scale); + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = inv_icm42600_accel_odr; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = ARRAY_SIZE(inv_icm42600_accel_odr); + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_CALIBBIAS: + *vals = inv_icm42600_accel_calibbias; + *type = IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_RANGE; + default: + return -EINVAL; + } +} + +static int inv_icm42600_accel_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_accel_write_scale(st, val, val2); + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42600_accel_write_odr(indio_dev, val, val2); + case IIO_CHAN_INFO_CALIBBIAS: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_accel_write_offset(st, chan, val, val2); + iio_device_release_direct_mode(indio_dev); + return ret; + default: + return -EINVAL; + } +} + +static int inv_icm42600_accel_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + if (chan->type != IIO_ACCEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_CALIBBIAS: + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int inv_icm42600_accel_hwfifo_set_watermark(struct iio_dev *indio_dev, + unsigned int val) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + mutex_lock(&st->lock); + + st->fifo.watermark.accel = val; + ret = inv_icm42600_buffer_update_watermark(st); + + mutex_unlock(&st->lock); + + return ret; +} + +static int inv_icm42600_accel_hwfifo_flush(struct iio_dev *indio_dev, + unsigned int count) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + if (count == 0) + return 0; + + mutex_lock(&st->lock); + + ret = inv_icm42600_buffer_hwfifo_flush(st, count); + if (!ret) + ret = st->fifo.nb.accel; + + mutex_unlock(&st->lock); + + return ret; +} + +static const struct iio_info inv_icm42600_accel_info = { + .read_raw = inv_icm42600_accel_read_raw, + .read_avail = inv_icm42600_accel_read_avail, + .write_raw = inv_icm42600_accel_write_raw, + .write_raw_get_fmt = inv_icm42600_accel_write_raw_get_fmt, + .debugfs_reg_access = inv_icm42600_debugfs_reg, + .update_scan_mode = inv_icm42600_accel_update_scan_mode, + .hwfifo_set_watermark = inv_icm42600_accel_hwfifo_set_watermark, + .hwfifo_flush_to_buffer = inv_icm42600_accel_hwfifo_flush, +}; + +struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st) +{ + struct device *dev = regmap_get_device(st->map); + const char *name; + struct inv_icm42600_timestamp *ts; + struct iio_dev *indio_dev; + struct iio_buffer *buffer; + int ret; + + name = devm_kasprintf(dev, GFP_KERNEL, "%s-accel", st->name); + if (!name) + return ERR_PTR(-ENOMEM); + + indio_dev = devm_iio_device_alloc(dev, sizeof(*ts)); + if (!indio_dev) + return ERR_PTR(-ENOMEM); + + buffer = devm_iio_kfifo_allocate(dev); + if (!buffer) + return ERR_PTR(-ENOMEM); + + ts = iio_priv(indio_dev); + inv_icm42600_timestamp_init(ts, inv_icm42600_odr_to_period(st->conf.accel.odr)); + + iio_device_set_drvdata(indio_dev, st); + indio_dev->name = name; + indio_dev->info = &inv_icm42600_accel_info; + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; + indio_dev->channels = inv_icm42600_accel_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_accel_channels); + indio_dev->available_scan_masks = inv_icm42600_accel_scan_masks; + indio_dev->setup_ops = &inv_icm42600_buffer_ops; + + iio_device_attach_buffer(indio_dev, buffer); + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return ERR_PTR(ret); + + return indio_dev; +} + +int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); + ssize_t i, size; + unsigned int no; + const void *accel, *gyro, *timestamp; + const int8_t *temp; + unsigned int odr; + int64_t ts_val; + struct inv_icm42600_accel_buffer buffer; + + /* parse all fifo packets */ + for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) { + size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i], + &accel, &gyro, &temp, ×tamp, &odr); + /* quit if error or FIFO is empty */ + if (size <= 0) + return size; + + /* skip packet if no accel data or data is invalid */ + if (accel == NULL || !inv_icm42600_fifo_is_data_valid(accel)) + continue; + + /* update odr */ + if (odr & INV_ICM42600_SENSOR_ACCEL) + inv_icm42600_timestamp_apply_odr(ts, st->fifo.period, + st->fifo.nb.total, no); + + /* buffer is copied to userspace, zeroing it to avoid any data leak */ + memset(&buffer, 0, sizeof(buffer)); + memcpy(&buffer.accel, accel, sizeof(buffer.accel)); + /* convert 8 bits FIFO temperature in high resolution format */ + buffer.temp = temp ? (*temp * 64) : 0; + ts_val = inv_icm42600_timestamp_pop(ts); + iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val); + } + + return 0; +} diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c new file mode 100644 index 0000000000000000000000000000000000000000..99576b2c171f4d3d47f18de4704511ec69d1842e --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c @@ -0,0 +1,601 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" +#include "inv_icm42600_timestamp.h" +#include "inv_icm42600_buffer.h" + +/* FIFO header: 1 byte */ +#define INV_ICM42600_FIFO_HEADER_MSG BIT(7) +#define INV_ICM42600_FIFO_HEADER_ACCEL BIT(6) +#define INV_ICM42600_FIFO_HEADER_GYRO BIT(5) +#define INV_ICM42600_FIFO_HEADER_TMST_FSYNC GENMASK(3, 2) +#define INV_ICM42600_FIFO_HEADER_ODR_ACCEL BIT(1) +#define INV_ICM42600_FIFO_HEADER_ODR_GYRO BIT(0) + +struct inv_icm42600_fifo_1sensor_packet { + uint8_t header; + struct inv_icm42600_fifo_sensor_data data; + int8_t temp; +} __packed; +#define INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE 8 + +struct inv_icm42600_fifo_2sensors_packet { + uint8_t header; + struct inv_icm42600_fifo_sensor_data accel; + struct inv_icm42600_fifo_sensor_data gyro; + int8_t temp; + __be16 timestamp; +} __packed; +#define INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE 16 + +ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel, + const void **gyro, const int8_t **temp, + const void **timestamp, unsigned int *odr) +{ + const struct inv_icm42600_fifo_1sensor_packet *pack1 = packet; + const struct inv_icm42600_fifo_2sensors_packet *pack2 = packet; + uint8_t header = *((const uint8_t *)packet); + + /* FIFO empty */ + if (header & INV_ICM42600_FIFO_HEADER_MSG) { + *accel = NULL; + *gyro = NULL; + *temp = NULL; + *timestamp = NULL; + *odr = 0; + return 0; + } + + /* handle odr flags */ + *odr = 0; + if (header & INV_ICM42600_FIFO_HEADER_ODR_GYRO) + *odr |= INV_ICM42600_SENSOR_GYRO; + if (header & INV_ICM42600_FIFO_HEADER_ODR_ACCEL) + *odr |= INV_ICM42600_SENSOR_ACCEL; + + /* accel + gyro */ + if ((header & INV_ICM42600_FIFO_HEADER_ACCEL) && + (header & INV_ICM42600_FIFO_HEADER_GYRO)) { + *accel = &pack2->accel; + *gyro = &pack2->gyro; + *temp = &pack2->temp; + *timestamp = &pack2->timestamp; + return INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE; + } + + /* accel only */ + if (header & INV_ICM42600_FIFO_HEADER_ACCEL) { + *accel = &pack1->data; + *gyro = NULL; + *temp = &pack1->temp; + *timestamp = NULL; + return INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE; + } + + /* gyro only */ + if (header & INV_ICM42600_FIFO_HEADER_GYRO) { + *accel = NULL; + *gyro = &pack1->data; + *temp = &pack1->temp; + *timestamp = NULL; + return INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE; + } + + /* invalid packet if here */ + return -EINVAL; +} + +void inv_icm42600_buffer_update_fifo_period(struct inv_icm42600_state *st) +{ + uint32_t period_gyro, period_accel, period; + + if (st->fifo.en & INV_ICM42600_SENSOR_GYRO) + period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr); + else + period_gyro = U32_MAX; + + if (st->fifo.en & INV_ICM42600_SENSOR_ACCEL) + period_accel = inv_icm42600_odr_to_period(st->conf.accel.odr); + else + period_accel = U32_MAX; + + if (period_gyro <= period_accel) + period = period_gyro; + else + period = period_accel; + + st->fifo.period = period; +} + +int inv_icm42600_buffer_set_fifo_en(struct inv_icm42600_state *st, + unsigned int fifo_en) +{ + unsigned int mask, val; + int ret; + + /* update only FIFO EN bits */ + mask = INV_ICM42600_FIFO_CONFIG1_TMST_FSYNC_EN | + INV_ICM42600_FIFO_CONFIG1_TEMP_EN | + INV_ICM42600_FIFO_CONFIG1_GYRO_EN | + INV_ICM42600_FIFO_CONFIG1_ACCEL_EN; + + val = 0; + if (fifo_en & INV_ICM42600_SENSOR_GYRO) + val |= INV_ICM42600_FIFO_CONFIG1_GYRO_EN; + if (fifo_en & INV_ICM42600_SENSOR_ACCEL) + val |= INV_ICM42600_FIFO_CONFIG1_ACCEL_EN; + if (fifo_en & INV_ICM42600_SENSOR_TEMP) + val |= INV_ICM42600_FIFO_CONFIG1_TEMP_EN; + + ret = regmap_update_bits(st->map, INV_ICM42600_REG_FIFO_CONFIG1, mask, val); + if (ret) + return ret; + + st->fifo.en = fifo_en; + inv_icm42600_buffer_update_fifo_period(st); + + return 0; +} + +static size_t inv_icm42600_get_packet_size(unsigned int fifo_en) +{ + size_t packet_size; + + if ((fifo_en & INV_ICM42600_SENSOR_GYRO) && + (fifo_en & INV_ICM42600_SENSOR_ACCEL)) + packet_size = INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE; + else + packet_size = INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE; + + return packet_size; +} + +static unsigned int inv_icm42600_wm_truncate(unsigned int watermark, + size_t packet_size) +{ + size_t wm_size; + unsigned int wm; + + wm_size = watermark * packet_size; + if (wm_size > INV_ICM42600_FIFO_WATERMARK_MAX) + wm_size = INV_ICM42600_FIFO_WATERMARK_MAX; + + wm = wm_size / packet_size; + + return wm; +} + +/** + * inv_icm42600_buffer_update_watermark - update watermark FIFO threshold + * @st: driver internal state + * + * Returns 0 on success, a negative error code otherwise. + * + * FIFO watermark threshold is computed based on the required watermark values + * set for gyro and accel sensors. Since watermark is all about acceptable data + * latency, use the smallest setting between the 2. It means choosing the + * smallest latency but this is not as simple as choosing the smallest watermark + * value. Latency depends on watermark and ODR. It requires several steps: + * 1) compute gyro and accel latencies and choose the smallest value. + * 2) adapt the choosen latency so that it is a multiple of both gyro and accel + * ones. Otherwise it is possible that you don't meet a requirement. (for + * example with gyro @100Hz wm 4 and accel @100Hz with wm 6, choosing the + * value of 4 will not meet accel latency requirement because 6 is not a + * multiple of 4. You need to use the value 2.) + * 3) Since all periods are multiple of each others, watermark is computed by + * dividing this computed latency by the smallest period, which corresponds + * to the FIFO frequency. Beware that this is only true because we are not + * using 500Hz frequency which is not a multiple of the others. + */ +int inv_icm42600_buffer_update_watermark(struct inv_icm42600_state *st) +{ + size_t packet_size, wm_size; + unsigned int wm_gyro, wm_accel, watermark; + uint32_t period_gyro, period_accel, period; + uint32_t latency_gyro, latency_accel, latency; + bool restore; + __le16 raw_wm; + int ret; + + packet_size = inv_icm42600_get_packet_size(st->fifo.en); + + /* compute sensors latency, depending on sensor watermark and odr */ + wm_gyro = inv_icm42600_wm_truncate(st->fifo.watermark.gyro, packet_size); + wm_accel = inv_icm42600_wm_truncate(st->fifo.watermark.accel, packet_size); + /* use us for odr to avoid overflow using 32 bits values */ + period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr) / 1000UL; + period_accel = inv_icm42600_odr_to_period(st->conf.accel.odr) / 1000UL; + latency_gyro = period_gyro * wm_gyro; + latency_accel = period_accel * wm_accel; + + /* 0 value for watermark means that the sensor is turned off */ + if (latency_gyro == 0) { + watermark = wm_accel; + } else if (latency_accel == 0) { + watermark = wm_gyro; + } else { + /* compute the smallest latency that is a multiple of both */ + if (latency_gyro <= latency_accel) + latency = latency_gyro - (latency_accel % latency_gyro); + else + latency = latency_accel - (latency_gyro % latency_accel); + /* use the shortest period */ + if (period_gyro <= period_accel) + period = period_gyro; + else + period = period_accel; + /* all this works because periods are multiple of each others */ + watermark = latency / period; + if (watermark < 1) + watermark = 1; + } + + /* compute watermark value in bytes */ + wm_size = watermark * packet_size; + + /* changing FIFO watermark requires to turn off watermark interrupt */ + ret = regmap_update_bits_check(st->map, INV_ICM42600_REG_INT_SOURCE0, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, + 0, &restore); + if (ret) + return ret; + + raw_wm = INV_ICM42600_FIFO_WATERMARK_VAL(wm_size); + memcpy(st->buffer, &raw_wm, sizeof(raw_wm)); + ret = regmap_bulk_write(st->map, INV_ICM42600_REG_FIFO_WATERMARK, + st->buffer, sizeof(raw_wm)); + if (ret) + return ret; + + /* restore watermark interrupt */ + if (restore) { + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN); + if (ret) + return ret; + } + + return 0; +} + +static int inv_icm42600_buffer_preenable(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct device *dev = regmap_get_device(st->map); + + pm_runtime_get_sync(dev); + + return 0; +} + +/* + * update_scan_mode callback is turning sensors on and setting data FIFO enable + * bits. + */ +static int inv_icm42600_buffer_postenable(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + mutex_lock(&st->lock); + + /* exit if FIFO is already on */ + if (st->fifo.on) { + ret = 0; + goto out_on; + } + + /* set FIFO threshold interrupt */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN); + if (ret) + goto out_unlock; + + /* flush FIFO data */ + ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET, + INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH); + if (ret) + goto out_unlock; + + /* set FIFO in streaming mode */ + ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, + INV_ICM42600_FIFO_CONFIG_STREAM); + if (ret) + goto out_unlock; + + /* workaround: first read of FIFO count after reset is always 0 */ + ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT, st->buffer, 2); + if (ret) + goto out_unlock; + +out_on: + /* increase FIFO on counter */ + st->fifo.on++; +out_unlock: + mutex_unlock(&st->lock); + return ret; +} + +static int inv_icm42600_buffer_predisable(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + mutex_lock(&st->lock); + + /* exit if there are several sensors using the FIFO */ + if (st->fifo.on > 1) { + ret = 0; + goto out_off; + } + + /* set FIFO in bypass mode */ + ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, + INV_ICM42600_FIFO_CONFIG_BYPASS); + if (ret) + goto out_unlock; + + /* flush FIFO data */ + ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET, + INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH); + if (ret) + goto out_unlock; + + /* disable FIFO threshold interrupt */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, 0); + if (ret) + goto out_unlock; + +out_off: + /* decrease FIFO on counter */ + st->fifo.on--; +out_unlock: + mutex_unlock(&st->lock); + return ret; +} + +static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct device *dev = regmap_get_device(st->map); + unsigned int sensor; + unsigned int *watermark; + struct inv_icm42600_timestamp *ts; + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + unsigned int sleep_temp = 0; + unsigned int sleep_sensor = 0; + unsigned int sleep; + int ret; + + if (indio_dev == st->indio_gyro) { + sensor = INV_ICM42600_SENSOR_GYRO; + watermark = &st->fifo.watermark.gyro; + ts = iio_priv(st->indio_gyro); + } else if (indio_dev == st->indio_accel) { + sensor = INV_ICM42600_SENSOR_ACCEL; + watermark = &st->fifo.watermark.accel; + ts = iio_priv(st->indio_accel); + } else { + return -EINVAL; + } + + mutex_lock(&st->lock); + + ret = inv_icm42600_buffer_set_fifo_en(st, st->fifo.en & ~sensor); + if (ret) + goto out_unlock; + + *watermark = 0; + ret = inv_icm42600_buffer_update_watermark(st); + if (ret) + goto out_unlock; + + conf.mode = INV_ICM42600_SENSOR_MODE_OFF; + if (sensor == INV_ICM42600_SENSOR_GYRO) + ret = inv_icm42600_set_gyro_conf(st, &conf, &sleep_sensor); + else + ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_sensor); + if (ret) + goto out_unlock; + + /* if FIFO is off, turn temperature off */ + if (!st->fifo.on) + ret = inv_icm42600_set_temp_conf(st, false, &sleep_temp); + + inv_icm42600_timestamp_reset(ts); + +out_unlock: + mutex_unlock(&st->lock); + + /* sleep maximum required time */ + if (sleep_sensor > sleep_temp) + sleep = sleep_sensor; + else + sleep = sleep_temp; + if (sleep) + msleep(sleep); + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +const struct iio_buffer_setup_ops inv_icm42600_buffer_ops = { + .preenable = inv_icm42600_buffer_preenable, + .postenable = inv_icm42600_buffer_postenable, + .predisable = inv_icm42600_buffer_predisable, + .postdisable = inv_icm42600_buffer_postdisable, +}; + +int inv_icm42600_buffer_fifo_read(struct inv_icm42600_state *st, + unsigned int max) +{ + size_t max_count; + __be16 *raw_fifo_count; + ssize_t i, size; + const void *accel, *gyro, *timestamp; + const int8_t *temp; + unsigned int odr; + int ret; + + /* reset all samples counters */ + st->fifo.count = 0; + st->fifo.nb.gyro = 0; + st->fifo.nb.accel = 0; + st->fifo.nb.total = 0; + + /* compute maximum FIFO read size */ + if (max == 0) + max_count = sizeof(st->fifo.data); + else + max_count = max * inv_icm42600_get_packet_size(st->fifo.en); + + /* read FIFO count value */ + raw_fifo_count = (__be16 *)st->buffer; + ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT, + raw_fifo_count, sizeof(*raw_fifo_count)); + if (ret) + return ret; + st->fifo.count = be16_to_cpup(raw_fifo_count); + + /* check and clamp FIFO count value */ + if (st->fifo.count == 0) + return 0; + if (st->fifo.count > max_count) + st->fifo.count = max_count; + + /* read all FIFO data in internal buffer */ + ret = regmap_noinc_read(st->map, INV_ICM42600_REG_FIFO_DATA, + st->fifo.data, st->fifo.count); + if (ret) + return ret; + + /* compute number of samples for each sensor */ + for (i = 0; i < st->fifo.count; i += size) { + size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i], + &accel, &gyro, &temp, ×tamp, &odr); + if (size <= 0) + break; + if (gyro != NULL && inv_icm42600_fifo_is_data_valid(gyro)) + st->fifo.nb.gyro++; + if (accel != NULL && inv_icm42600_fifo_is_data_valid(accel)) + st->fifo.nb.accel++; + st->fifo.nb.total++; + } + + return 0; +} + +int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st) +{ + struct inv_icm42600_timestamp *ts; + int ret; + + if (st->fifo.nb.total == 0) + return 0; + + /* handle gyroscope timestamp and FIFO data parsing */ + ts = iio_priv(st->indio_gyro); + inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, + st->fifo.nb.gyro, st->timestamp.gyro); + if (st->fifo.nb.gyro > 0) { + ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); + if (ret) + return ret; + } + + /* handle accelerometer timestamp and FIFO data parsing */ + ts = iio_priv(st->indio_accel); + inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, + st->fifo.nb.accel, st->timestamp.accel); + if (st->fifo.nb.accel > 0) { + ret = inv_icm42600_accel_parse_fifo(st->indio_accel); + if (ret) + return ret; + } + + return 0; +} + +int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st, + unsigned int count) +{ + struct inv_icm42600_timestamp *ts; + int64_t gyro_ts, accel_ts; + int ret; + + gyro_ts = iio_get_time_ns(st->indio_gyro); + accel_ts = iio_get_time_ns(st->indio_accel); + + ret = inv_icm42600_buffer_fifo_read(st, count); + if (ret) + return ret; + + if (st->fifo.nb.total == 0) + return 0; + + if (st->fifo.nb.gyro > 0) { + ts = iio_priv(st->indio_gyro); + inv_icm42600_timestamp_interrupt(ts, st->fifo.period, + st->fifo.nb.total, st->fifo.nb.gyro, + gyro_ts); + ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); + if (ret) + return ret; + } + + if (st->fifo.nb.accel > 0) { + ts = iio_priv(st->indio_accel); + inv_icm42600_timestamp_interrupt(ts, st->fifo.period, + st->fifo.nb.total, st->fifo.nb.accel, + accel_ts); + ret = inv_icm42600_accel_parse_fifo(st->indio_accel); + if (ret) + return ret; + } + + return 0; +} + +int inv_icm42600_buffer_init(struct inv_icm42600_state *st) +{ + unsigned int val; + int ret; + + /* + * Default FIFO configuration (bits 7 to 5) + * - use invalid value + * - FIFO count in bytes + * - FIFO count in big endian + */ + val = INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_ENDIAN; + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, + GENMASK(7, 5), val); + if (ret) + return ret; + + /* + * Enable FIFO partial read and continuous watermark interrupt. + * Disable all FIFO EN bits. + */ + val = INV_ICM42600_FIFO_CONFIG1_RESUME_PARTIAL_RD | + INV_ICM42600_FIFO_CONFIG1_WM_GT_TH; + return regmap_update_bits(st->map, INV_ICM42600_REG_FIFO_CONFIG1, + GENMASK(6, 5) | GENMASK(3, 0), val); +} diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h new file mode 100644 index 0000000000000000000000000000000000000000..de2a3949dcc7d6f82041f383b1f7659f5564f67e --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#ifndef INV_ICM42600_BUFFER_H_ +#define INV_ICM42600_BUFFER_H_ + +#include +#include + +struct inv_icm42600_state; + +#define INV_ICM42600_SENSOR_GYRO BIT(0) +#define INV_ICM42600_SENSOR_ACCEL BIT(1) +#define INV_ICM42600_SENSOR_TEMP BIT(2) + +/** + * struct inv_icm42600_fifo - FIFO state variables + * @on: reference counter for FIFO on. + * @en: bits field of INV_ICM42600_SENSOR_* for FIFO EN bits. + * @period: FIFO internal period. + * @watermark: watermark configuration values for accel and gyro. + * @count: number of bytes in the FIFO data buffer. + * @nb: gyro, accel and total samples in the FIFO data buffer. + * @data: FIFO data buffer aligned for DMA (2kB + 32 bytes of read cache). + */ +struct inv_icm42600_fifo { + unsigned int on; + unsigned int en; + uint32_t period; + struct { + unsigned int gyro; + unsigned int accel; + } watermark; + size_t count; + struct { + size_t gyro; + size_t accel; + size_t total; + } nb; + uint8_t data[2080] ____cacheline_aligned; +}; + +/* FIFO data packet */ +struct inv_icm42600_fifo_sensor_data { + __be16 x; + __be16 y; + __be16 z; +} __packed; +#define INV_ICM42600_FIFO_DATA_INVALID -32768 + +static inline int16_t inv_icm42600_fifo_get_sensor_data(__be16 d) +{ + return be16_to_cpu(d); +} + +static inline bool +inv_icm42600_fifo_is_data_valid(const struct inv_icm42600_fifo_sensor_data *s) +{ + int16_t x, y, z; + + x = inv_icm42600_fifo_get_sensor_data(s->x); + y = inv_icm42600_fifo_get_sensor_data(s->y); + z = inv_icm42600_fifo_get_sensor_data(s->z); + + if (x == INV_ICM42600_FIFO_DATA_INVALID && + y == INV_ICM42600_FIFO_DATA_INVALID && + z == INV_ICM42600_FIFO_DATA_INVALID) + return false; + + return true; +} + +ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel, + const void **gyro, const int8_t **temp, + const void **timestamp, unsigned int *odr); + +extern const struct iio_buffer_setup_ops inv_icm42600_buffer_ops; + +int inv_icm42600_buffer_init(struct inv_icm42600_state *st); + +void inv_icm42600_buffer_update_fifo_period(struct inv_icm42600_state *st); + +int inv_icm42600_buffer_set_fifo_en(struct inv_icm42600_state *st, + unsigned int fifo_en); + +int inv_icm42600_buffer_update_watermark(struct inv_icm42600_state *st); + +int inv_icm42600_buffer_fifo_read(struct inv_icm42600_state *st, + unsigned int max); + +int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st); + +int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st, + unsigned int count); + +#endif diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c new file mode 100644 index 0000000000000000000000000000000000000000..8bd77185ccb716ede55980429224c5f74f91f38d --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -0,0 +1,786 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" +#include "inv_icm42600_buffer.h" +#include "inv_icm42600_timestamp.h" + +static const struct regmap_range_cfg inv_icm42600_regmap_ranges[] = { + { + .name = "user banks", + .range_min = 0x0000, + .range_max = 0x4FFF, + .selector_reg = INV_ICM42600_REG_BANK_SEL, + .selector_mask = INV_ICM42600_BANK_SEL_MASK, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x1000, + }, +}; + +const struct regmap_config inv_icm42600_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x4FFF, + .ranges = inv_icm42600_regmap_ranges, + .num_ranges = ARRAY_SIZE(inv_icm42600_regmap_ranges), +}; +EXPORT_SYMBOL_GPL(inv_icm42600_regmap_config); + +struct inv_icm42600_hw { + uint8_t whoami; + const char *name; + const struct inv_icm42600_conf *conf; +}; + +/* chip initial default configuration */ +static const struct inv_icm42600_conf inv_icm42600_default_conf = { + .gyro = { + .mode = INV_ICM42600_SENSOR_MODE_OFF, + .fs = INV_ICM42600_GYRO_FS_2000DPS, + .odr = INV_ICM42600_ODR_50HZ, + .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2, + }, + .accel = { + .mode = INV_ICM42600_SENSOR_MODE_OFF, + .fs = INV_ICM42600_ACCEL_FS_16G, + .odr = INV_ICM42600_ODR_50HZ, + .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2, + }, + .temp_en = false, +}; + +static const struct inv_icm42600_hw inv_icm42600_hw[INV_CHIP_NB] = { + [INV_CHIP_ICM42600] = { + .whoami = INV_ICM42600_WHOAMI_ICM42600, + .name = "icm42600", + .conf = &inv_icm42600_default_conf, + }, + [INV_CHIP_ICM42602] = { + .whoami = INV_ICM42600_WHOAMI_ICM42602, + .name = "icm42602", + .conf = &inv_icm42600_default_conf, + }, + [INV_CHIP_ICM42605] = { + .whoami = INV_ICM42600_WHOAMI_ICM42605, + .name = "icm42605", + .conf = &inv_icm42600_default_conf, + }, + [INV_CHIP_ICM42622] = { + .whoami = INV_ICM42600_WHOAMI_ICM42622, + .name = "icm42622", + .conf = &inv_icm42600_default_conf, + }, +}; + +const struct iio_mount_matrix * +inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + const struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + + return &st->orientation; +} + +uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr) +{ + static uint32_t odr_periods[INV_ICM42600_ODR_NB] = { + /* reserved values */ + 0, 0, 0, + /* 8kHz */ + 125000, + /* 4kHz */ + 250000, + /* 2kHz */ + 500000, + /* 1kHz */ + 1000000, + /* 200Hz */ + 5000000, + /* 100Hz */ + 10000000, + /* 50Hz */ + 20000000, + /* 25Hz */ + 40000000, + /* 12.5Hz */ + 80000000, + /* 6.25Hz */ + 160000000, + /* 3.125Hz */ + 320000000, + /* 1.5625Hz */ + 640000000, + /* 500Hz */ + 2000000, + }; + + return odr_periods[odr]; +} + +static int inv_icm42600_set_pwr_mgmt0(struct inv_icm42600_state *st, + enum inv_icm42600_sensor_mode gyro, + enum inv_icm42600_sensor_mode accel, + bool temp, unsigned int *sleep_ms) +{ + enum inv_icm42600_sensor_mode oldgyro = st->conf.gyro.mode; + enum inv_icm42600_sensor_mode oldaccel = st->conf.accel.mode; + bool oldtemp = st->conf.temp_en; + unsigned int sleepval; + unsigned int val; + int ret; + + /* if nothing changed, exit */ + if (gyro == oldgyro && accel == oldaccel && temp == oldtemp) + return 0; + + val = INV_ICM42600_PWR_MGMT0_GYRO(gyro) | + INV_ICM42600_PWR_MGMT0_ACCEL(accel); + if (!temp) + val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS; + ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val); + if (ret) + return ret; + + st->conf.gyro.mode = gyro; + st->conf.accel.mode = accel; + st->conf.temp_en = temp; + + /* compute required wait time for sensors to stabilize */ + sleepval = 0; + /* temperature stabilization time */ + if (temp && !oldtemp) { + if (sleepval < INV_ICM42600_TEMP_STARTUP_TIME_MS) + sleepval = INV_ICM42600_TEMP_STARTUP_TIME_MS; + } + /* accel startup time */ + if (accel != oldaccel && oldaccel == INV_ICM42600_SENSOR_MODE_OFF) { + /* block any register write for at least 200 µs */ + usleep_range(200, 300); + if (sleepval < INV_ICM42600_ACCEL_STARTUP_TIME_MS) + sleepval = INV_ICM42600_ACCEL_STARTUP_TIME_MS; + } + if (gyro != oldgyro) { + /* gyro startup time */ + if (oldgyro == INV_ICM42600_SENSOR_MODE_OFF) { + /* block any register write for at least 200 µs */ + usleep_range(200, 300); + if (sleepval < INV_ICM42600_GYRO_STARTUP_TIME_MS) + sleepval = INV_ICM42600_GYRO_STARTUP_TIME_MS; + /* gyro stop time */ + } else if (gyro == INV_ICM42600_SENSOR_MODE_OFF) { + if (sleepval < INV_ICM42600_GYRO_STOP_TIME_MS) + sleepval = INV_ICM42600_GYRO_STOP_TIME_MS; + } + } + + /* deferred sleep value if sleep pointer is provided or direct sleep */ + if (sleep_ms) + *sleep_ms = sleepval; + else if (sleepval) + msleep(sleepval); + + return 0; +} + +int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st, + struct inv_icm42600_sensor_conf *conf, + unsigned int *sleep_ms) +{ + struct inv_icm42600_sensor_conf *oldconf = &st->conf.accel; + unsigned int val; + int ret; + + /* Sanitize missing values with current values */ + if (conf->mode < 0) + conf->mode = oldconf->mode; + if (conf->fs < 0) + conf->fs = oldconf->fs; + if (conf->odr < 0) + conf->odr = oldconf->odr; + if (conf->filter < 0) + conf->filter = oldconf->filter; + + /* set ACCEL_CONFIG0 register (accel fullscale & odr) */ + if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) { + val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->fs) | + INV_ICM42600_ACCEL_CONFIG0_ODR(conf->odr); + ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val); + if (ret) + return ret; + oldconf->fs = conf->fs; + oldconf->odr = conf->odr; + } + + /* set GYRO_ACCEL_CONFIG0 register (accel filter) */ + if (conf->filter != oldconf->filter) { + val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->filter) | + INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(st->conf.gyro.filter); + ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val); + if (ret) + return ret; + oldconf->filter = conf->filter; + } + + /* set PWR_MGMT0 register (accel sensor mode) */ + return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode, conf->mode, + st->conf.temp_en, sleep_ms); +} + +int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st, + struct inv_icm42600_sensor_conf *conf, + unsigned int *sleep_ms) +{ + struct inv_icm42600_sensor_conf *oldconf = &st->conf.gyro; + unsigned int val; + int ret; + + /* sanitize missing values with current values */ + if (conf->mode < 0) + conf->mode = oldconf->mode; + if (conf->fs < 0) + conf->fs = oldconf->fs; + if (conf->odr < 0) + conf->odr = oldconf->odr; + if (conf->filter < 0) + conf->filter = oldconf->filter; + + /* set GYRO_CONFIG0 register (gyro fullscale & odr) */ + if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) { + val = INV_ICM42600_GYRO_CONFIG0_FS(conf->fs) | + INV_ICM42600_GYRO_CONFIG0_ODR(conf->odr); + ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val); + if (ret) + return ret; + oldconf->fs = conf->fs; + oldconf->odr = conf->odr; + } + + /* set GYRO_ACCEL_CONFIG0 register (gyro filter) */ + if (conf->filter != oldconf->filter) { + val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(st->conf.accel.filter) | + INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->filter); + ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val); + if (ret) + return ret; + oldconf->filter = conf->filter; + } + + /* set PWR_MGMT0 register (gyro sensor mode) */ + return inv_icm42600_set_pwr_mgmt0(st, conf->mode, st->conf.accel.mode, + st->conf.temp_en, sleep_ms); + + return 0; +} + +int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, + unsigned int *sleep_ms) +{ + return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode, + st->conf.accel.mode, enable, + sleep_ms); +} + +int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + mutex_lock(&st->lock); + + if (readval) + ret = regmap_read(st->map, reg, readval); + else + ret = regmap_write(st->map, reg, writeval); + + mutex_unlock(&st->lock); + + return ret; +} + +static int inv_icm42600_set_conf(struct inv_icm42600_state *st, + const struct inv_icm42600_conf *conf) +{ + unsigned int val; + int ret; + + /* set PWR_MGMT0 register (gyro & accel sensor mode, temp enabled) */ + val = INV_ICM42600_PWR_MGMT0_GYRO(conf->gyro.mode) | + INV_ICM42600_PWR_MGMT0_ACCEL(conf->accel.mode); + if (!conf->temp_en) + val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS; + ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val); + if (ret) + return ret; + + /* set GYRO_CONFIG0 register (gyro fullscale & odr) */ + val = INV_ICM42600_GYRO_CONFIG0_FS(conf->gyro.fs) | + INV_ICM42600_GYRO_CONFIG0_ODR(conf->gyro.odr); + ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val); + if (ret) + return ret; + + /* set ACCEL_CONFIG0 register (accel fullscale & odr) */ + val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->accel.fs) | + INV_ICM42600_ACCEL_CONFIG0_ODR(conf->accel.odr); + ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val); + if (ret) + return ret; + + /* set GYRO_ACCEL_CONFIG0 register (gyro & accel filters) */ + val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->accel.filter) | + INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->gyro.filter); + ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val); + if (ret) + return ret; + + /* update internal conf */ + st->conf = *conf; + + return 0; +} + +/** + * inv_icm42600_setup() - check and setup chip + * @st: driver internal state + * @bus_setup: callback for setting up bus specific registers + * + * Returns 0 on success, a negative error code otherwise. + */ +static int inv_icm42600_setup(struct inv_icm42600_state *st, + inv_icm42600_bus_setup bus_setup) +{ + const struct inv_icm42600_hw *hw = &inv_icm42600_hw[st->chip]; + const struct device *dev = regmap_get_device(st->map); + unsigned int val; + int ret; + + /* check chip self-identification value */ + ret = regmap_read(st->map, INV_ICM42600_REG_WHOAMI, &val); + if (ret) + return ret; + if (val != hw->whoami) { + dev_err(dev, "invalid whoami %#02x expected %#02x (%s)\n", + val, hw->whoami, hw->name); + return -ENODEV; + } + st->name = hw->name; + + /* reset to make sure previous state are not there */ + ret = regmap_write(st->map, INV_ICM42600_REG_DEVICE_CONFIG, + INV_ICM42600_DEVICE_CONFIG_SOFT_RESET); + if (ret) + return ret; + msleep(INV_ICM42600_RESET_TIME_MS); + + ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &val); + if (ret) + return ret; + if (!(val & INV_ICM42600_INT_STATUS_RESET_DONE)) { + dev_err(dev, "reset error, reset done bit not set\n"); + return -ENODEV; + } + + /* set chip bus configuration */ + ret = bus_setup(st); + if (ret) + return ret; + + /* sensor data in big-endian (default) */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, + INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN, + INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN); + if (ret) + return ret; + + return inv_icm42600_set_conf(st, hw->conf); +} + +static irqreturn_t inv_icm42600_irq_timestamp(int irq, void *_data) +{ + struct inv_icm42600_state *st = _data; + + st->timestamp.gyro = iio_get_time_ns(st->indio_gyro); + st->timestamp.accel = iio_get_time_ns(st->indio_accel); + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data) +{ + struct inv_icm42600_state *st = _data; + struct device *dev = regmap_get_device(st->map); + unsigned int status; + int ret; + + mutex_lock(&st->lock); + + ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &status); + if (ret) + goto out_unlock; + + /* FIFO full */ + if (status & INV_ICM42600_INT_STATUS_FIFO_FULL) + dev_warn(dev, "FIFO full data lost!\n"); + + /* FIFO threshold reached */ + if (status & INV_ICM42600_INT_STATUS_FIFO_THS) { + ret = inv_icm42600_buffer_fifo_read(st, 0); + if (ret) { + dev_err(dev, "FIFO read error %d\n", ret); + goto out_unlock; + } + ret = inv_icm42600_buffer_fifo_parse(st); + if (ret) + dev_err(dev, "FIFO parsing error %d\n", ret); + } + +out_unlock: + mutex_unlock(&st->lock); + return IRQ_HANDLED; +} + +/** + * inv_icm42600_irq_init() - initialize int pin and interrupt handler + * @st: driver internal state + * @irq: irq number + * @irq_type: irq trigger type + * @open_drain: true if irq is open drain, false for push-pull + * + * Returns 0 on success, a negative error code otherwise. + */ +static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq, + int irq_type, bool open_drain) +{ + struct device *dev = regmap_get_device(st->map); + unsigned int val; + int ret; + + /* configure INT1 interrupt: default is active low on edge */ + switch (irq_type) { + case IRQF_TRIGGER_RISING: + case IRQF_TRIGGER_HIGH: + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH; + break; + default: + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW; + break; + } + + switch (irq_type) { + case IRQF_TRIGGER_LOW: + case IRQF_TRIGGER_HIGH: + val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED; + break; + default: + break; + } + + if (!open_drain) + val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL; + + ret = regmap_write(st->map, INV_ICM42600_REG_INT_CONFIG, val); + if (ret) + return ret; + + /* Deassert async reset for proper INT pin operation (cf datasheet) */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_CONFIG1, + INV_ICM42600_INT_CONFIG1_ASYNC_RESET, 0); + if (ret) + return ret; + + return devm_request_threaded_irq(dev, irq, inv_icm42600_irq_timestamp, + inv_icm42600_irq_handler, irq_type, + "inv_icm42600", st); +} + +static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st) +{ + int ret; + + ret = regulator_enable(st->vddio_supply); + if (ret) + return ret; + + /* wait a little for supply ramp */ + usleep_range(3000, 4000); + + return 0; +} + +static void inv_icm42600_disable_vdd_reg(void *_data) +{ + struct inv_icm42600_state *st = _data; + const struct device *dev = regmap_get_device(st->map); + int ret; + + ret = regulator_disable(st->vdd_supply); + if (ret) + dev_err(dev, "failed to disable vdd error %d\n", ret); +} + +static void inv_icm42600_disable_vddio_reg(void *_data) +{ + struct inv_icm42600_state *st = _data; + const struct device *dev = regmap_get_device(st->map); + int ret; + + ret = regulator_disable(st->vddio_supply); + if (ret) + dev_err(dev, "failed to disable vddio error %d\n", ret); +} + +static void inv_icm42600_disable_pm(void *_data) +{ + struct device *dev = _data; + + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +} + +int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, + inv_icm42600_bus_setup bus_setup) +{ + struct device *dev = regmap_get_device(regmap); + struct inv_icm42600_state *st; + struct irq_data *irq_desc; + int irq_type; + bool open_drain; + int ret; + + if (chip < 0 || chip >= INV_CHIP_NB) { + dev_err(dev, "invalid chip = %d\n", chip); + return -ENODEV; + } + + /* get irq properties, set trigger falling by default */ + irq_desc = irq_get_irq_data(irq); + if (!irq_desc) { + dev_err(dev, "could not find IRQ %d\n", irq); + return -EINVAL; + } + + irq_type = irqd_get_trigger_type(irq_desc); + if (!irq_type) + irq_type = IRQF_TRIGGER_FALLING; + + open_drain = device_property_read_bool(dev, "drive-open-drain"); + + st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + + dev_set_drvdata(dev, st); + mutex_init(&st->lock); + st->chip = chip; + st->map = regmap; + + ret = iio_read_mount_matrix(dev, "mount-matrix", &st->orientation); + if (ret) { + dev_err(dev, "failed to retrieve mounting matrix %d\n", ret); + return ret; + } + + st->vdd_supply = devm_regulator_get(dev, "vdd"); + if (IS_ERR(st->vdd_supply)) + return PTR_ERR(st->vdd_supply); + + st->vddio_supply = devm_regulator_get(dev, "vddio"); + if (IS_ERR(st->vddio_supply)) + return PTR_ERR(st->vddio_supply); + + ret = regulator_enable(st->vdd_supply); + if (ret) + return ret; + msleep(INV_ICM42600_POWER_UP_TIME_MS); + + ret = devm_add_action_or_reset(dev, inv_icm42600_disable_vdd_reg, st); + if (ret) + return ret; + + ret = inv_icm42600_enable_regulator_vddio(st); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, inv_icm42600_disable_vddio_reg, st); + if (ret) + return ret; + + /* setup chip registers */ + ret = inv_icm42600_setup(st, bus_setup); + if (ret) + return ret; + + ret = inv_icm42600_timestamp_setup(st); + if (ret) + return ret; + + ret = inv_icm42600_buffer_init(st); + if (ret) + return ret; + + st->indio_gyro = inv_icm42600_gyro_init(st); + if (IS_ERR(st->indio_gyro)) + return PTR_ERR(st->indio_gyro); + + st->indio_accel = inv_icm42600_accel_init(st); + if (IS_ERR(st->indio_accel)) + return PTR_ERR(st->indio_accel); + + ret = inv_icm42600_irq_init(st, irq, irq_type, open_drain); + if (ret) + return ret; + + /* setup runtime power management */ + ret = pm_runtime_set_active(dev); + if (ret) + return ret; + pm_runtime_get_noresume(dev); + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, INV_ICM42600_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(dev); + pm_runtime_put(dev); + + return devm_add_action_or_reset(dev, inv_icm42600_disable_pm, dev); +} +EXPORT_SYMBOL_GPL(inv_icm42600_core_probe); + +/* + * Suspend saves sensors state and turns everything off. + * Check first if runtime suspend has not already done the job. + */ +static int __maybe_unused inv_icm42600_suspend(struct device *dev) +{ + struct inv_icm42600_state *st = dev_get_drvdata(dev); + int ret; + + mutex_lock(&st->lock); + + st->suspended.gyro = st->conf.gyro.mode; + st->suspended.accel = st->conf.accel.mode; + st->suspended.temp = st->conf.temp_en; + if (pm_runtime_suspended(dev)) { + ret = 0; + goto out_unlock; + } + + /* disable FIFO data streaming */ + if (st->fifo.on) { + ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, + INV_ICM42600_FIFO_CONFIG_BYPASS); + if (ret) + goto out_unlock; + } + + ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF, + INV_ICM42600_SENSOR_MODE_OFF, false, + NULL); + if (ret) + goto out_unlock; + + regulator_disable(st->vddio_supply); + +out_unlock: + mutex_unlock(&st->lock); + return ret; +} + +/* + * System resume gets the system back on and restores the sensors state. + * Manually put runtime power management in system active state. + */ +static int __maybe_unused inv_icm42600_resume(struct device *dev) +{ + struct inv_icm42600_state *st = dev_get_drvdata(dev); + int ret; + + mutex_lock(&st->lock); + + ret = inv_icm42600_enable_regulator_vddio(st); + if (ret) + goto out_unlock; + + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + /* restore sensors state */ + ret = inv_icm42600_set_pwr_mgmt0(st, st->suspended.gyro, + st->suspended.accel, + st->suspended.temp, NULL); + if (ret) + goto out_unlock; + + /* restore FIFO data streaming */ + if (st->fifo.on) + ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, + INV_ICM42600_FIFO_CONFIG_STREAM); + +out_unlock: + mutex_unlock(&st->lock); + return ret; +} + +/* Runtime suspend will turn off sensors that are enabled by iio devices. */ +static int __maybe_unused inv_icm42600_runtime_suspend(struct device *dev) +{ + struct inv_icm42600_state *st = dev_get_drvdata(dev); + int ret; + + mutex_lock(&st->lock); + + /* disable all sensors */ + ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF, + INV_ICM42600_SENSOR_MODE_OFF, false, + NULL); + if (ret) + goto error_unlock; + + regulator_disable(st->vddio_supply); + +error_unlock: + mutex_unlock(&st->lock); + return ret; +} + +/* Sensors are enabled by iio devices, no need to turn them back on here. */ +static int __maybe_unused inv_icm42600_runtime_resume(struct device *dev) +{ + struct inv_icm42600_state *st = dev_get_drvdata(dev); + int ret; + + mutex_lock(&st->lock); + + ret = inv_icm42600_enable_regulator_vddio(st); + + mutex_unlock(&st->lock); + return ret; +} + +const struct dev_pm_ops inv_icm42600_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(inv_icm42600_suspend, inv_icm42600_resume) + SET_RUNTIME_PM_OPS(inv_icm42600_runtime_suspend, + inv_icm42600_runtime_resume, NULL) +}; +EXPORT_SYMBOL_GPL(inv_icm42600_pm_ops); + +MODULE_AUTHOR("InvenSense, Inc."); +MODULE_DESCRIPTION("InvenSense ICM-426xx device driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c new file mode 100644 index 0000000000000000000000000000000000000000..aee7b9ff4bf4f2aae9994ee18f8149b6da687000 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c @@ -0,0 +1,798 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" +#include "inv_icm42600_temp.h" +#include "inv_icm42600_buffer.h" +#include "inv_icm42600_timestamp.h" + +#define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info) \ + { \ + .type = IIO_ANGL_VEL, \ + .modified = 1, \ + .channel2 = _modifier, \ + .info_mask_separate = \ + BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .info_mask_shared_by_type = \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .info_mask_shared_by_all = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + .ext_info = _ext_info, \ + } + +enum inv_icm42600_gyro_scan { + INV_ICM42600_GYRO_SCAN_X, + INV_ICM42600_GYRO_SCAN_Y, + INV_ICM42600_GYRO_SCAN_Z, + INV_ICM42600_GYRO_SCAN_TEMP, + INV_ICM42600_GYRO_SCAN_TIMESTAMP, +}; + +static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix), + {}, +}; + +static const struct iio_chan_spec inv_icm42600_gyro_channels[] = { + INV_ICM42600_GYRO_CHAN(IIO_MOD_X, INV_ICM42600_GYRO_SCAN_X, + inv_icm42600_gyro_ext_infos), + INV_ICM42600_GYRO_CHAN(IIO_MOD_Y, INV_ICM42600_GYRO_SCAN_Y, + inv_icm42600_gyro_ext_infos), + INV_ICM42600_GYRO_CHAN(IIO_MOD_Z, INV_ICM42600_GYRO_SCAN_Z, + inv_icm42600_gyro_ext_infos), + INV_ICM42600_TEMP_CHAN(INV_ICM42600_GYRO_SCAN_TEMP), + IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_GYRO_SCAN_TIMESTAMP), +}; + +/* + * IIO buffer data: size must be a power of 2 and timestamp aligned + * 16 bytes: 6 bytes angular velocity, 2 bytes temperature, 8 bytes timestamp + */ +struct inv_icm42600_gyro_buffer { + struct inv_icm42600_fifo_sensor_data gyro; + int16_t temp; + int64_t timestamp __aligned(8); +}; + +#define INV_ICM42600_SCAN_MASK_GYRO_3AXIS \ + (BIT(INV_ICM42600_GYRO_SCAN_X) | \ + BIT(INV_ICM42600_GYRO_SCAN_Y) | \ + BIT(INV_ICM42600_GYRO_SCAN_Z)) + +#define INV_ICM42600_SCAN_MASK_TEMP BIT(INV_ICM42600_GYRO_SCAN_TEMP) + +static const unsigned long inv_icm42600_gyro_scan_masks[] = { + /* 3-axis gyro + temperature */ + INV_ICM42600_SCAN_MASK_GYRO_3AXIS | INV_ICM42600_SCAN_MASK_TEMP, + 0, +}; + +/* enable gyroscope sensor and FIFO write */ +static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + unsigned int fifo_en = 0; + unsigned int sleep_gyro = 0; + unsigned int sleep_temp = 0; + unsigned int sleep; + int ret; + + mutex_lock(&st->lock); + + if (*scan_mask & INV_ICM42600_SCAN_MASK_TEMP) { + /* enable temp sensor */ + ret = inv_icm42600_set_temp_conf(st, true, &sleep_temp); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42600_SENSOR_TEMP; + } + + if (*scan_mask & INV_ICM42600_SCAN_MASK_GYRO_3AXIS) { + /* enable gyro sensor */ + conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; + ret = inv_icm42600_set_gyro_conf(st, &conf, &sleep_gyro); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42600_SENSOR_GYRO; + } + + /* update data FIFO write */ + inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0); + ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); + if (ret) + goto out_unlock; + + ret = inv_icm42600_buffer_update_watermark(st); + +out_unlock: + mutex_unlock(&st->lock); + /* sleep maximum required time */ + if (sleep_gyro > sleep_temp) + sleep = sleep_gyro; + else + sleep = sleep_temp; + if (sleep) + msleep(sleep); + return ret; +} + +static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int16_t *val) +{ + struct device *dev = regmap_get_device(st->map); + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + unsigned int reg; + __be16 *data; + int ret; + + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_GYRO_DATA_X; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_GYRO_DATA_Y; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_GYRO_DATA_Z; + break; + default: + return -EINVAL; + } + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + /* enable gyro sensor */ + conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; + ret = inv_icm42600_set_gyro_conf(st, &conf, NULL); + if (ret) + goto exit; + + /* read gyro register data */ + data = (__be16 *)&st->buffer[0]; + ret = regmap_bulk_read(st->map, reg, data, sizeof(*data)); + if (ret) + goto exit; + + *val = (int16_t)be16_to_cpup(data); + if (*val == INV_ICM42600_DATA_INVALID) + ret = -EINVAL; +exit: + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return ret; +} + +/* IIO format int + nano */ +static const int inv_icm42600_gyro_scale[] = { + /* +/- 2000dps => 0.001065264 rad/s */ + [2 * INV_ICM42600_GYRO_FS_2000DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_2000DPS + 1] = 1065264, + /* +/- 1000dps => 0.000532632 rad/s */ + [2 * INV_ICM42600_GYRO_FS_1000DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_1000DPS + 1] = 532632, + /* +/- 500dps => 0.000266316 rad/s */ + [2 * INV_ICM42600_GYRO_FS_500DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_500DPS + 1] = 266316, + /* +/- 250dps => 0.000133158 rad/s */ + [2 * INV_ICM42600_GYRO_FS_250DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_250DPS + 1] = 133158, + /* +/- 125dps => 0.000066579 rad/s */ + [2 * INV_ICM42600_GYRO_FS_125DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_125DPS + 1] = 66579, + /* +/- 62.5dps => 0.000033290 rad/s */ + [2 * INV_ICM42600_GYRO_FS_62_5DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_62_5DPS + 1] = 33290, + /* +/- 31.25dps => 0.000016645 rad/s */ + [2 * INV_ICM42600_GYRO_FS_31_25DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_31_25DPS + 1] = 16645, + /* +/- 15.625dps => 0.000008322 rad/s */ + [2 * INV_ICM42600_GYRO_FS_15_625DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_15_625DPS + 1] = 8322, +}; + +static int inv_icm42600_gyro_read_scale(struct inv_icm42600_state *st, + int *val, int *val2) +{ + unsigned int idx; + + idx = st->conf.gyro.fs; + + *val = inv_icm42600_gyro_scale[2 * idx]; + *val2 = inv_icm42600_gyro_scale[2 * idx + 1]; + return IIO_VAL_INT_PLUS_NANO; +} + +static int inv_icm42600_gyro_write_scale(struct inv_icm42600_state *st, + int val, int val2) +{ + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + int ret; + + for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_gyro_scale); idx += 2) { + if (val == inv_icm42600_gyro_scale[idx] && + val2 == inv_icm42600_gyro_scale[idx + 1]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42600_gyro_scale)) + return -EINVAL; + + conf.fs = idx / 2; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_icm42600_set_gyro_conf(st, &conf, NULL); + + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +/* IIO format int + micro */ +static const int inv_icm42600_gyro_odr[] = { + /* 12.5Hz */ + 12, 500000, + /* 25Hz */ + 25, 0, + /* 50Hz */ + 50, 0, + /* 100Hz */ + 100, 0, + /* 200Hz */ + 200, 0, + /* 1kHz */ + 1000, 0, + /* 2kHz */ + 2000, 0, + /* 4kHz */ + 4000, 0, +}; + +static const int inv_icm42600_gyro_odr_conv[] = { + INV_ICM42600_ODR_12_5HZ, + INV_ICM42600_ODR_25HZ, + INV_ICM42600_ODR_50HZ, + INV_ICM42600_ODR_100HZ, + INV_ICM42600_ODR_200HZ, + INV_ICM42600_ODR_1KHZ_LN, + INV_ICM42600_ODR_2KHZ_LN, + INV_ICM42600_ODR_4KHZ_LN, +}; + +static int inv_icm42600_gyro_read_odr(struct inv_icm42600_state *st, + int *val, int *val2) +{ + unsigned int odr; + unsigned int i; + + odr = st->conf.gyro.odr; + + for (i = 0; i < ARRAY_SIZE(inv_icm42600_gyro_odr_conv); ++i) { + if (inv_icm42600_gyro_odr_conv[i] == odr) + break; + } + if (i >= ARRAY_SIZE(inv_icm42600_gyro_odr_conv)) + return -EINVAL; + + *val = inv_icm42600_gyro_odr[2 * i]; + *val2 = inv_icm42600_gyro_odr[2 * i + 1]; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int inv_icm42600_gyro_write_odr(struct iio_dev *indio_dev, + int val, int val2) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + int ret; + + for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_gyro_odr); idx += 2) { + if (val == inv_icm42600_gyro_odr[idx] && + val2 == inv_icm42600_gyro_odr[idx + 1]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42600_gyro_odr)) + return -EINVAL; + + conf.odr = inv_icm42600_gyro_odr_conv[idx / 2]; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_icm42600_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr), + iio_buffer_enabled(indio_dev)); + if (ret) + goto out_unlock; + + ret = inv_icm42600_set_gyro_conf(st, &conf, NULL); + if (ret) + goto out_unlock; + inv_icm42600_buffer_update_fifo_period(st); + inv_icm42600_buffer_update_watermark(st); + +out_unlock: + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +/* + * Calibration bias values, IIO range format int + nano. + * Value is limited to +/-64dps coded on 12 bits signed. Step is 1/32 dps. + */ +static int inv_icm42600_gyro_calibbias[] = { + -1, 117010721, /* min: -1.117010721 rad/s */ + 0, 545415, /* step: 0.000545415 rad/s */ + 1, 116465306, /* max: 1.116465306 rad/s */ +}; + +static int inv_icm42600_gyro_read_offset(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int *val, int *val2) +{ + struct device *dev = regmap_get_device(st->map); + int64_t val64; + int32_t bias; + unsigned int reg; + int16_t offset; + uint8_t data[2]; + int ret; + + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_OFFSET_USER0; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_OFFSET_USER1; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_OFFSET_USER3; + break; + default: + return -EINVAL; + } + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = regmap_bulk_read(st->map, reg, st->buffer, sizeof(data)); + memcpy(data, st->buffer, sizeof(data)); + + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + if (ret) + return ret; + + /* 12 bits signed value */ + switch (chan->channel2) { + case IIO_MOD_X: + offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11); + break; + case IIO_MOD_Y: + offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11); + break; + case IIO_MOD_Z: + offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11); + break; + default: + return -EINVAL; + } + + /* + * convert raw offset to dps then to rad/s + * 12 bits signed raw max 64 to dps: 64 / 2048 + * dps to rad: Pi / 180 + * result in nano (1000000000) + * (offset * 64 * Pi * 1000000000) / (2048 * 180) + */ + val64 = (int64_t)offset * 64LL * 3141592653LL; + /* for rounding, add + or - divisor (2048 * 180) divided by 2 */ + if (val64 >= 0) + val64 += 2048 * 180 / 2; + else + val64 -= 2048 * 180 / 2; + bias = div_s64(val64, 2048 * 180); + *val = bias / 1000000000L; + *val2 = bias % 1000000000L; + + return IIO_VAL_INT_PLUS_NANO; +} + +static int inv_icm42600_gyro_write_offset(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int val, int val2) +{ + struct device *dev = regmap_get_device(st->map); + int64_t val64, min, max; + unsigned int reg, regval; + int16_t offset; + int ret; + + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_OFFSET_USER0; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_OFFSET_USER1; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_OFFSET_USER3; + break; + default: + return -EINVAL; + } + + /* inv_icm42600_gyro_calibbias: min - step - max in nano */ + min = (int64_t)inv_icm42600_gyro_calibbias[0] * 1000000000LL + + (int64_t)inv_icm42600_gyro_calibbias[1]; + max = (int64_t)inv_icm42600_gyro_calibbias[4] * 1000000000LL + + (int64_t)inv_icm42600_gyro_calibbias[5]; + val64 = (int64_t)val * 1000000000LL + (int64_t)val2; + if (val64 < min || val64 > max) + return -EINVAL; + + /* + * convert rad/s to dps then to raw value + * rad to dps: 180 / Pi + * dps to raw 12 bits signed, max 64: 2048 / 64 + * val in nano (1000000000) + * val * 180 * 2048 / (Pi * 1000000000 * 64) + */ + val64 = val64 * 180LL * 2048LL; + /* for rounding, add + or - divisor (3141592653 * 64) divided by 2 */ + if (val64 >= 0) + val64 += 3141592653LL * 64LL / 2LL; + else + val64 -= 3141592653LL * 64LL / 2LL; + offset = div64_s64(val64, 3141592653LL * 64LL); + + /* clamp value limited to 12 bits signed */ + if (offset < -2048) + offset = -2048; + else if (offset > 2047) + offset = 2047; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + switch (chan->channel2) { + case IIO_MOD_X: + /* OFFSET_USER1 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER1, + ®val); + if (ret) + goto out_unlock; + st->buffer[0] = offset & 0xFF; + st->buffer[1] = (regval & 0xF0) | ((offset & 0xF00) >> 8); + break; + case IIO_MOD_Y: + /* OFFSET_USER1 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER1, + ®val); + if (ret) + goto out_unlock; + st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F); + st->buffer[1] = offset & 0xFF; + break; + case IIO_MOD_Z: + /* OFFSET_USER4 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER4, + ®val); + if (ret) + goto out_unlock; + st->buffer[0] = offset & 0xFF; + st->buffer[1] = (regval & 0xF0) | ((offset & 0xF00) >> 8); + break; + default: + ret = -EINVAL; + goto out_unlock; + } + + ret = regmap_bulk_write(st->map, reg, st->buffer, 2); + +out_unlock: + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return ret; +} + +static int inv_icm42600_gyro_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int16_t data; + int ret; + + switch (chan->type) { + case IIO_ANGL_VEL: + break; + case IIO_TEMP: + return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, mask); + default: + return -EINVAL; + } + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_gyro_read_sensor(st, chan, &data); + iio_device_release_direct_mode(indio_dev); + if (ret) + return ret; + *val = data; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + return inv_icm42600_gyro_read_scale(st, val, val2); + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42600_gyro_read_odr(st, val, val2); + case IIO_CHAN_INFO_CALIBBIAS: + return inv_icm42600_gyro_read_offset(st, chan, val, val2); + default: + return -EINVAL; + } +} + +static int inv_icm42600_gyro_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, + int *type, int *length, long mask) +{ + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + *vals = inv_icm42600_gyro_scale; + *type = IIO_VAL_INT_PLUS_NANO; + *length = ARRAY_SIZE(inv_icm42600_gyro_scale); + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = inv_icm42600_gyro_odr; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = ARRAY_SIZE(inv_icm42600_gyro_odr); + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_CALIBBIAS: + *vals = inv_icm42600_gyro_calibbias; + *type = IIO_VAL_INT_PLUS_NANO; + return IIO_AVAIL_RANGE; + default: + return -EINVAL; + } +} + +static int inv_icm42600_gyro_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_gyro_write_scale(st, val, val2); + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42600_gyro_write_odr(indio_dev, val, val2); + case IIO_CHAN_INFO_CALIBBIAS: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_gyro_write_offset(st, chan, val, val2); + iio_device_release_direct_mode(indio_dev); + return ret; + default: + return -EINVAL; + } +} + +static int inv_icm42600_gyro_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_CALIBBIAS: + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static int inv_icm42600_gyro_hwfifo_set_watermark(struct iio_dev *indio_dev, + unsigned int val) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + mutex_lock(&st->lock); + + st->fifo.watermark.gyro = val; + ret = inv_icm42600_buffer_update_watermark(st); + + mutex_unlock(&st->lock); + + return ret; +} + +static int inv_icm42600_gyro_hwfifo_flush(struct iio_dev *indio_dev, + unsigned int count) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + if (count == 0) + return 0; + + mutex_lock(&st->lock); + + ret = inv_icm42600_buffer_hwfifo_flush(st, count); + if (!ret) + ret = st->fifo.nb.gyro; + + mutex_unlock(&st->lock); + + return ret; +} + +static const struct iio_info inv_icm42600_gyro_info = { + .read_raw = inv_icm42600_gyro_read_raw, + .read_avail = inv_icm42600_gyro_read_avail, + .write_raw = inv_icm42600_gyro_write_raw, + .write_raw_get_fmt = inv_icm42600_gyro_write_raw_get_fmt, + .debugfs_reg_access = inv_icm42600_debugfs_reg, + .update_scan_mode = inv_icm42600_gyro_update_scan_mode, + .hwfifo_set_watermark = inv_icm42600_gyro_hwfifo_set_watermark, + .hwfifo_flush_to_buffer = inv_icm42600_gyro_hwfifo_flush, +}; + +struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st) +{ + struct device *dev = regmap_get_device(st->map); + const char *name; + struct inv_icm42600_timestamp *ts; + struct iio_dev *indio_dev; + struct iio_buffer *buffer; + int ret; + + name = devm_kasprintf(dev, GFP_KERNEL, "%s-gyro", st->name); + if (!name) + return ERR_PTR(-ENOMEM); + + indio_dev = devm_iio_device_alloc(dev, sizeof(*ts)); + if (!indio_dev) + return ERR_PTR(-ENOMEM); + + buffer = devm_iio_kfifo_allocate(dev); + if (!buffer) + return ERR_PTR(-ENOMEM); + + ts = iio_priv(indio_dev); + inv_icm42600_timestamp_init(ts, inv_icm42600_odr_to_period(st->conf.gyro.odr)); + + iio_device_set_drvdata(indio_dev, st); + indio_dev->name = name; + indio_dev->info = &inv_icm42600_gyro_info; + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; + indio_dev->channels = inv_icm42600_gyro_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_gyro_channels); + indio_dev->available_scan_masks = inv_icm42600_gyro_scan_masks; + indio_dev->setup_ops = &inv_icm42600_buffer_ops; + + iio_device_attach_buffer(indio_dev, buffer); + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return ERR_PTR(ret); + + return indio_dev; +} + +int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); + ssize_t i, size; + unsigned int no; + const void *accel, *gyro, *timestamp; + const int8_t *temp; + unsigned int odr; + int64_t ts_val; + struct inv_icm42600_gyro_buffer buffer; + + /* parse all fifo packets */ + for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) { + size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i], + &accel, &gyro, &temp, ×tamp, &odr); + /* quit if error or FIFO is empty */ + if (size <= 0) + return size; + + /* skip packet if no gyro data or data is invalid */ + if (gyro == NULL || !inv_icm42600_fifo_is_data_valid(gyro)) + continue; + + /* update odr */ + if (odr & INV_ICM42600_SENSOR_GYRO) + inv_icm42600_timestamp_apply_odr(ts, st->fifo.period, + st->fifo.nb.total, no); + + /* buffer is copied to userspace, zeroing it to avoid any data leak */ + memset(&buffer, 0, sizeof(buffer)); + memcpy(&buffer.gyro, gyro, sizeof(buffer.gyro)); + /* convert 8 bits FIFO temperature in high resolution format */ + buffer.temp = temp ? (*temp * 64) : 0; + ts_val = inv_icm42600_timestamp_pop(ts); + iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val); + } + + return 0; +} diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..85b1934cec60ebe2110646d18fbba66d398287db --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 InvenSense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" + +static int inv_icm42600_i2c_bus_setup(struct inv_icm42600_state *st) +{ + unsigned int mask, val; + int ret; + + /* setup interface registers */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6, + INV_ICM42600_INTF_CONFIG6_MASK, + INV_ICM42600_INTF_CONFIG6_I3C_EN); + if (ret) + return ret; + + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4, + INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0); + if (ret) + return ret; + + /* set slew rates for I2C and SPI */ + mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK | + INV_ICM42600_DRIVE_CONFIG_SPI_MASK; + val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_12_36NS) | + INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_12_36NS); + ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG, + mask, val); + if (ret) + return ret; + + /* disable SPI bus */ + return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, + INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, + INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS); +} + +static int inv_icm42600_probe(struct i2c_client *client) +{ + const void *match; + enum inv_icm42600_chip chip; + struct regmap *regmap; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) + return -ENOTSUPP; + + match = device_get_match_data(&client->dev); + if (!match) + return -EINVAL; + chip = (enum inv_icm42600_chip)match; + + regmap = devm_regmap_init_i2c(client, &inv_icm42600_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return inv_icm42600_core_probe(regmap, chip, client->irq, + inv_icm42600_i2c_bus_setup); +} + +static const struct of_device_id inv_icm42600_of_matches[] = { + { + .compatible = "invensense,icm42600", + .data = (void *)INV_CHIP_ICM42600, + }, { + .compatible = "invensense,icm42602", + .data = (void *)INV_CHIP_ICM42602, + }, { + .compatible = "invensense,icm42605", + .data = (void *)INV_CHIP_ICM42605, + }, { + .compatible = "invensense,icm42622", + .data = (void *)INV_CHIP_ICM42622, + }, + {} +}; +MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches); + +static struct i2c_driver inv_icm42600_driver = { + .driver = { + .name = "inv-icm42600-i2c", + .of_match_table = inv_icm42600_of_matches, + .pm = &inv_icm42600_pm_ops, + }, + .probe_new = inv_icm42600_probe, +}; +module_i2c_driver(inv_icm42600_driver); + +MODULE_AUTHOR("InvenSense, Inc."); +MODULE_DESCRIPTION("InvenSense ICM-426xx I2C driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c new file mode 100644 index 0000000000000000000000000000000000000000..323789697a084c4ce19eb56acb195126ddb9a10e --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 InvenSense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" + +static int inv_icm42600_spi_bus_setup(struct inv_icm42600_state *st) +{ + unsigned int mask, val; + int ret; + + /* setup interface registers */ + val = INV_ICM42600_INTF_CONFIG6_I3C_EN | + INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN | + INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN; + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6, + INV_ICM42600_INTF_CONFIG6_MASK, val); + if (ret) + return ret; + + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4, + INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0); + if (ret) + return ret; + + /* set slew rates for I2C and SPI */ + mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK | + INV_ICM42600_DRIVE_CONFIG_SPI_MASK; + val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_20_60NS) | + INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_INF_2NS); + ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG, + mask, val); + if (ret) + return ret; + + /* disable i2c bus */ + return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, + INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, + INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS); +} + +static int inv_icm42600_probe(struct spi_device *spi) +{ + const void *match; + enum inv_icm42600_chip chip; + struct regmap *regmap; + + match = device_get_match_data(&spi->dev); + if (!match) + return -EINVAL; + chip = (enum inv_icm42600_chip)match; + + regmap = devm_regmap_init_spi(spi, &inv_icm42600_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return inv_icm42600_core_probe(regmap, chip, spi->irq, + inv_icm42600_spi_bus_setup); +} + +static const struct of_device_id inv_icm42600_of_matches[] = { + { + .compatible = "invensense,icm42600", + .data = (void *)INV_CHIP_ICM42600, + }, { + .compatible = "invensense,icm42602", + .data = (void *)INV_CHIP_ICM42602, + }, { + .compatible = "invensense,icm42605", + .data = (void *)INV_CHIP_ICM42605, + }, { + .compatible = "invensense,icm42622", + .data = (void *)INV_CHIP_ICM42622, + }, + {} +}; +MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches); + +static struct spi_driver inv_icm42600_driver = { + .driver = { + .name = "inv-icm42600-spi", + .of_match_table = inv_icm42600_of_matches, + .pm = &inv_icm42600_pm_ops, + }, + .probe = inv_icm42600_probe, +}; +module_spi_driver(inv_icm42600_driver); + +MODULE_AUTHOR("InvenSense, Inc."); +MODULE_DESCRIPTION("InvenSense ICM-426xx SPI driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c new file mode 100644 index 0000000000000000000000000000000000000000..213cce1c31110e669e7191c8b42c9524c0d3e5db --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" +#include "inv_icm42600_temp.h" + +static int inv_icm42600_temp_read(struct inv_icm42600_state *st, int16_t *temp) +{ + struct device *dev = regmap_get_device(st->map); + __be16 *raw; + int ret; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_icm42600_set_temp_conf(st, true, NULL); + if (ret) + goto exit; + + raw = (__be16 *)&st->buffer[0]; + ret = regmap_bulk_read(st->map, INV_ICM42600_REG_TEMP_DATA, raw, sizeof(*raw)); + if (ret) + goto exit; + + *temp = (int16_t)be16_to_cpup(raw); + if (*temp == INV_ICM42600_DATA_INVALID) + ret = -EINVAL; + +exit: + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int16_t temp; + int ret; + + if (chan->type != IIO_TEMP) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_temp_read(st, &temp); + iio_device_release_direct_mode(indio_dev); + if (ret) + return ret; + *val = temp; + return IIO_VAL_INT; + /* + * T°C = (temp / 132.48) + 25 + * Tm°C = 1000 * ((temp * 100 / 13248) + 25) + * scale: 100000 / 13248 ~= 7.548309 + * offset: 25000 + */ + case IIO_CHAN_INFO_SCALE: + *val = 7; + *val2 = 548309; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OFFSET: + *val = 25000; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h new file mode 100644 index 0000000000000000000000000000000000000000..3941186512fb19755a9c3df28ad039f81848d20d --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#ifndef INV_ICM42600_TEMP_H_ +#define INV_ICM42600_TEMP_H_ + +#include + +#define INV_ICM42600_TEMP_CHAN(_index) \ + { \ + .type = IIO_TEMP, \ + .info_mask_separate = \ + BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + }, \ + } + +int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask); + +#endif diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c new file mode 100644 index 0000000000000000000000000000000000000000..7f2dc41f807bbec946c5ac96bd9a02c5e28d0069 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include + +#include "inv_icm42600.h" +#include "inv_icm42600_timestamp.h" + +/* internal chip period is 32kHz, 31250ns */ +#define INV_ICM42600_TIMESTAMP_PERIOD 31250 +/* allow a jitter of +/- 2% */ +#define INV_ICM42600_TIMESTAMP_JITTER 2 +/* compute min and max periods accepted */ +#define INV_ICM42600_TIMESTAMP_MIN_PERIOD(_p) \ + (((_p) * (100 - INV_ICM42600_TIMESTAMP_JITTER)) / 100) +#define INV_ICM42600_TIMESTAMP_MAX_PERIOD(_p) \ + (((_p) * (100 + INV_ICM42600_TIMESTAMP_JITTER)) / 100) + +/* Add a new value inside an accumulator and update the estimate value */ +static void inv_update_acc(struct inv_icm42600_timestamp_acc *acc, uint32_t val) +{ + uint64_t sum = 0; + size_t i; + + acc->values[acc->idx++] = val; + if (acc->idx >= ARRAY_SIZE(acc->values)) + acc->idx = 0; + + /* compute the mean of all stored values, use 0 as empty slot */ + for (i = 0; i < ARRAY_SIZE(acc->values); ++i) { + if (acc->values[i] == 0) + break; + sum += acc->values[i]; + } + + acc->val = div_u64(sum, i); +} + +void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts, + uint32_t period) +{ + /* initial odr for sensor after reset is 1kHz */ + const uint32_t default_period = 1000000; + + /* current multiplier and period values after reset */ + ts->mult = default_period / INV_ICM42600_TIMESTAMP_PERIOD; + ts->period = default_period; + /* new set multiplier is the one from chip initialization */ + ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD; + + /* use theoretical value for chip period */ + inv_update_acc(&ts->chip_period, INV_ICM42600_TIMESTAMP_PERIOD); +} + +int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st) +{ + unsigned int val; + + /* enable timestamp register */ + val = INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN | + INV_ICM42600_TMST_CONFIG_TMST_EN; + return regmap_update_bits(st->map, INV_ICM42600_REG_TMST_CONFIG, + INV_ICM42600_TMST_CONFIG_MASK, val); +} + +int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, + uint32_t period, bool fifo) +{ + /* when FIFO is on, prevent odr change if one is already pending */ + if (fifo && ts->new_mult != 0) + return -EAGAIN; + + ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD; + + return 0; +} + +static bool inv_validate_period(uint32_t period, uint32_t mult) +{ + const uint32_t chip_period = INV_ICM42600_TIMESTAMP_PERIOD; + uint32_t period_min, period_max; + + /* check that period is acceptable */ + period_min = INV_ICM42600_TIMESTAMP_MIN_PERIOD(chip_period) * mult; + period_max = INV_ICM42600_TIMESTAMP_MAX_PERIOD(chip_period) * mult; + if (period > period_min && period < period_max) + return true; + else + return false; +} + +static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts, + uint32_t mult, uint32_t period) +{ + uint32_t new_chip_period; + + if (!inv_validate_period(period, mult)) + return false; + + /* update chip internal period estimation */ + new_chip_period = period / mult; + inv_update_acc(&ts->chip_period, new_chip_period); + + return true; +} + +void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, + uint32_t fifo_period, size_t fifo_nb, + size_t sensor_nb, int64_t timestamp) +{ + struct inv_icm42600_timestamp_interval *it; + int64_t delta, interval; + const uint32_t fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD; + uint32_t period = ts->period; + int32_t m; + bool valid = false; + + if (fifo_nb == 0) + return; + + /* update interrupt timestamp and compute chip and sensor periods */ + it = &ts->it; + it->lo = it->up; + it->up = timestamp; + delta = it->up - it->lo; + if (it->lo != 0) { + /* compute period: delta time divided by number of samples */ + period = div_s64(delta, fifo_nb); + valid = inv_compute_chip_period(ts, fifo_mult, period); + /* update sensor period if chip internal period is updated */ + if (valid) + ts->period = ts->mult * ts->chip_period.val; + } + + /* no previous data, compute theoritical value from interrupt */ + if (ts->timestamp == 0) { + /* elapsed time: sensor period * sensor samples number */ + interval = (int64_t)ts->period * (int64_t)sensor_nb; + ts->timestamp = it->up - interval; + return; + } + + /* if interrupt interval is valid, sync with interrupt timestamp */ + if (valid) { + /* compute measured fifo_period */ + fifo_period = fifo_mult * ts->chip_period.val; + /* delta time between last sample and last interrupt */ + delta = it->lo - ts->timestamp; + /* if there are multiple samples, go back to first one */ + while (delta >= (fifo_period * 3 / 2)) + delta -= fifo_period; + /* compute maximal adjustment value */ + m = INV_ICM42600_TIMESTAMP_MAX_PERIOD(ts->period) - ts->period; + if (delta > m) + delta = m; + else if (delta < -m) + delta = -m; + ts->timestamp += delta; + } +} + +void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts, + uint32_t fifo_period, size_t fifo_nb, + unsigned int fifo_no) +{ + int64_t interval; + uint32_t fifo_mult; + + if (ts->new_mult == 0) + return; + + /* update to new multiplier and update period */ + ts->mult = ts->new_mult; + ts->new_mult = 0; + ts->period = ts->mult * ts->chip_period.val; + + /* + * After ODR change the time interval with the previous sample is + * undertermined (depends when the change occures). So we compute the + * timestamp from the current interrupt using the new FIFO period, the + * total number of samples and the current sample numero. + */ + if (ts->timestamp != 0) { + /* compute measured fifo period */ + fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD; + fifo_period = fifo_mult * ts->chip_period.val; + /* computes time interval between interrupt and this sample */ + interval = (int64_t)(fifo_nb - fifo_no) * (int64_t)fifo_period; + ts->timestamp = ts->it.up - interval; + } +} diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h new file mode 100644 index 0000000000000000000000000000000000000000..4e4f331d4fe4b899f84ff586192e1019181b4795 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#ifndef INV_ICM42600_TIMESTAMP_H_ +#define INV_ICM42600_TIMESTAMP_H_ + +#include + +struct inv_icm42600_state; + +/** + * struct inv_icm42600_timestamp_interval - timestamps interval + * @lo: interval lower bound + * @up: interval upper bound + */ +struct inv_icm42600_timestamp_interval { + int64_t lo; + int64_t up; +}; + +/** + * struct inv_icm42600_timestamp_acc - accumulator for computing an estimation + * @val: current estimation of the value, the mean of all values + * @idx: current index of the next free place in values table + * @values: table of all measured values, use for computing the mean + */ +struct inv_icm42600_timestamp_acc { + uint32_t val; + size_t idx; + uint32_t values[32]; +}; + +/** + * struct inv_icm42600_timestamp - timestamp management states + * @it: interrupts interval timestamps + * @timestamp: store last timestamp for computing next data timestamp + * @mult: current internal period multiplier + * @new_mult: new set internal period multiplier (not yet effective) + * @period: measured current period of the sensor + * @chip_period: accumulator for computing internal chip period + */ +struct inv_icm42600_timestamp { + struct inv_icm42600_timestamp_interval it; + int64_t timestamp; + uint32_t mult; + uint32_t new_mult; + uint32_t period; + struct inv_icm42600_timestamp_acc chip_period; +}; + +void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts, + uint32_t period); + +int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st); + +int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, + uint32_t period, bool fifo); + +void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, + uint32_t fifo_period, size_t fifo_nb, + size_t sensor_nb, int64_t timestamp); + +static inline int64_t +inv_icm42600_timestamp_pop(struct inv_icm42600_timestamp *ts) +{ + ts->timestamp += ts->period; + return ts->timestamp; +} + +void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts, + uint32_t fifo_period, size_t fifo_nb, + unsigned int fifo_no); + +static inline void +inv_icm42600_timestamp_reset(struct inv_icm42600_timestamp *ts) +{ + const struct inv_icm42600_timestamp_interval interval_init = {0LL, 0LL}; + + ts->it = interval_init; + ts->timestamp = 0; +} + +#endif diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c index c27d06035c8b6947ab0f4c4541038f1c1f022e00..f8f0cf716bc6b233004892dd2891e5be9e88de51 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c @@ -101,8 +101,8 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client, unsigned short *primary_addr, unsigned short *secondary_addr) { + struct acpi_device *adev = ACPI_COMPANION(&client->dev); const struct acpi_device_id *id; - struct acpi_device *adev; u32 i2c_addr = 0; LIST_HEAD(resources); int ret; @@ -112,10 +112,6 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client, if (!id) return -ENODEV; - adev = ACPI_COMPANION(&client->dev); - if (!adev) - return -ENODEV; - ret = acpi_dev_get_resources(adev, &resources, acpi_i2c_check_resource, &i2c_addr); if (ret < 0) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 4d604fe842e5de2ef907a638fecd22783b50ff16..3fee3947f772a3c8f8f1a8b303f94d260a96381b 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -433,7 +433,7 @@ static int inv_mpu6050_set_gyro_fsr(struct inv_mpu6050_state *st, return regmap_write(st->map, st->reg->gyro_config, data); } -/** +/* * inv_mpu6050_set_lpf_regs() - set low pass filter registers, chip dependent * * MPU60xx/MPU9150 use only 1 register for accelerometer + gyroscope @@ -467,7 +467,7 @@ static int inv_mpu6050_set_lpf_regs(struct inv_mpu6050_state *st, return regmap_write(st->map, st->reg->accel_lpf, val); } -/** +/* * inv_mpu6050_init_config() - Initialize hardware, disable FIFO. * * Initial configuration: @@ -847,7 +847,7 @@ error_write_raw_unlock: return result; } -/** +/* * inv_mpu6050_set_lpf() - set low pass filer based on fifo rate. * * Based on the Nyquist principle, the bandwidth of the low @@ -884,7 +884,7 @@ static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate) return 0; } -/** +/* * inv_mpu6050_fifo_rate_store() - Set fifo rate. */ static ssize_t @@ -945,7 +945,7 @@ fifo_rate_fail_unlock: return count; } -/** +/* * inv_fifo_rate_show() - Get the current sampling rate. */ static ssize_t @@ -962,7 +962,7 @@ inv_fifo_rate_show(struct device *dev, struct device_attribute *attr, return scnprintf(buf, PAGE_SIZE, "%u\n", fifo_rate); } -/** +/* * inv_attr_show() - calling this function will show current * parameters. * @@ -1275,7 +1275,7 @@ static const struct iio_info mpu_info = { .debugfs_reg_access = &inv_mpu6050_reg_access, }; -/** +/* * inv_check_and_setup_chip() - check and setup chip. */ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) @@ -1530,7 +1530,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, } dev_set_drvdata(dev, indio_dev); - indio_dev->dev.parent = dev; /* name will be NULL when enumerated via ACPI */ if (name) indio_dev->name = name; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index 9511e4715e2c1680b01fb6970ec96ee71a8346c6..b533fa2dad0abe214a92c692099e82ce0ac9c754 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -111,7 +111,7 @@ reset_fifo_fail: return result; } -/** +/* * inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO. */ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index e67466100aff4dca53110295a6912f2f74e9bdef..61885e99d3fc14db2655e7ac955b1adb4dd7a618 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -312,10 +312,10 @@ static int kmx61_convert_wake_up_odr_to_bit(int val, int val2) /** * kmx61_set_mode() - set KMX61 device operating mode - * @data - kmx61 device private data pointer - * @mode - bitmask, indicating operating mode for @device - * @device - bitmask, indicating device for which @mode needs to be set - * @update - update stby bits stored in device's private @data + * @data: kmx61 device private data pointer + * @mode: bitmask, indicating operating mode for @device + * @device: bitmask, indicating device for which @mode needs to be set + * @update: update stby bits stored in device's private @data * * For each sensor (accelerometer/magnetometer) there are two operating modes * STANDBY and OPERATION. Neither accel nor magn can be disabled independently @@ -718,9 +718,9 @@ static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, /** * kmx61_set_power_state() - set power state for kmx61 @device - * @data - kmx61 device private pointer - * @on - power state to be set for @device - * @device - bitmask indicating device for which @on state needs to be set + * @data: kmx61 device private pointer + * @on: power state to be set for @device + * @device: bitmask indicating device for which @on state needs to be set * * Notice that when ACC power state needs to be set to ON and MAG is in * OPERATION then we know that kmx61_runtime_resume was already called @@ -1248,7 +1248,6 @@ static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data, kmx61_set_data(indio_dev, data); - indio_dev->dev.parent = &data->client->dev; indio_dev->channels = chan; indio_dev->num_channels = num_channels; indio_dev->name = name; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index b56df409ed0fa01f40e374562b9c5b7d70c1b2c8..d80ba2e688ed0551f9677ce4766a40244bf373e5 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -436,8 +436,7 @@ int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark); int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable); int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw); -int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw, - enum st_lsm6dsx_fifo_mode fifo_mode); +int st_lsm6dsx_resume_fifo(struct st_lsm6dsx_hw *hw); int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw); int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw); int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val); @@ -484,7 +483,7 @@ st_lsm6dsx_write_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, return err; } -static const inline struct iio_mount_matrix * +static inline const struct iio_mount_matrix * st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev, const struct iio_chan_spec *chan) { @@ -494,7 +493,8 @@ st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev, return &hw->orientation; } -static const struct iio_chan_spec_ext_info st_lsm6dsx_accel_ext_info[] = { +static const +struct iio_chan_spec_ext_info __maybe_unused st_lsm6dsx_accel_ext_info[] = { IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_lsm6dsx_get_mount_matrix), { } }; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index afd00daeefb2d4ae6fb57659cd3085c83193fefe..7de10bd636ea0eac27b58b00ebfff26cc70d16bb 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -184,8 +184,8 @@ static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw) return err; } -int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw, - enum st_lsm6dsx_fifo_mode fifo_mode) +static int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw, + enum st_lsm6dsx_fifo_mode fifo_mode) { unsigned int data; @@ -302,6 +302,18 @@ static int st_lsm6dsx_reset_hw_ts(struct st_lsm6dsx_hw *hw) return 0; } +int st_lsm6dsx_resume_fifo(struct st_lsm6dsx_hw *hw) +{ + int err; + + /* reset hw ts counter */ + err = st_lsm6dsx_reset_hw_ts(hw); + if (err < 0) + return err; + + return st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT); +} + /* * Set max bulk read to ST_LSM6DSX_MAX_WORD_LEN/ST_LSM6DSX_MAX_TAGGED_WORD_LEN * in order to avoid a kmalloc for each bus access @@ -675,12 +687,7 @@ int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable) goto out; if (fifo_mask) { - /* reset hw ts counter */ - err = st_lsm6dsx_reset_hw_ts(hw); - if (err < 0) - goto out; - - err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT); + err = st_lsm6dsx_resume_fifo(hw); if (err < 0) goto out; } diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 0b776cb91928bd5002f1393689b3739681b46324..346c24281d262ddaf1ed87ff87e3889f014d0f0b 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -2152,7 +2152,6 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, return NULL; iio_dev->modes = INDIO_DIRECT_MODE; - iio_dev->dev.parent = hw->dev; iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks; iio_dev->channels = hw->settings->channels[id].chan; iio_dev->num_channels = hw->settings->channels[id].len; @@ -2458,7 +2457,7 @@ static int __maybe_unused st_lsm6dsx_resume(struct device *dev) } if (hw->fifo_mask) - err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT); + err = st_lsm6dsx_resume_fifo(hw); return err; } diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c index c1f83fe0d8dad608d577f0c787c800c3e4509352..ed83471dc7ddfd2c7748d08e7d94597d31c64399 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -163,7 +163,7 @@ static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw) msleep((2000000U / odr) + 1); } -/** +/* * st_lsm6dsx_shub_read_output - read i2c controller register * * Read st_lsm6dsx i2c controller register @@ -195,7 +195,7 @@ out: return err; } -/** +/* * st_lsm6dsx_shub_write_reg - write i2c controller register * * Write st_lsm6dsx i2c controller register @@ -273,7 +273,7 @@ out: return err; } -/** +/* * st_lsm6dsx_shub_read - read data from slave device register * * Read data from slave device register. SLV0 is used for @@ -323,7 +323,7 @@ st_lsm6dsx_shub_read(struct st_lsm6dsx_sensor *sensor, u8 addr, sizeof(config)); } -/** +/* * st_lsm6dsx_shub_write - write data to slave device register * * Write data from slave device register. SLV0 is used for @@ -735,7 +735,6 @@ st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw, return NULL; iio_dev->modes = INDIO_DIRECT_MODE; - iio_dev->dev.parent = hw->dev; iio_dev->info = &st_lsm6dsx_ext_info; sensor = iio_priv(iio_dev); diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 9fa238c0a7d4f4fc0d9372854ee30c2c1fb4b6d4..a7d7e5143ed25d41c6aedbf07d9042dc64edf5f0 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -19,7 +19,9 @@ #include #include +#include #include "iio_core.h" +#include "iio_core_trigger.h" #include #include #include @@ -598,8 +600,10 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, static void iio_buffer_activate(struct iio_dev *indio_dev, struct iio_buffer *buffer) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + iio_buffer_get(buffer); - list_add(&buffer->buffer_list, &indio_dev->buffer_list); + list_add(&buffer->buffer_list, &iio_dev_opaque->buffer_list); } static void iio_buffer_deactivate(struct iio_buffer *buffer) @@ -611,10 +615,11 @@ static void iio_buffer_deactivate(struct iio_buffer *buffer) static void iio_buffer_deactivate_all(struct iio_dev *indio_dev) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_buffer *buffer, *_buffer; list_for_each_entry_safe(buffer, _buffer, - &indio_dev->buffer_list, buffer_list) + &iio_dev_opaque->buffer_list, buffer_list) iio_buffer_deactivate(buffer); } @@ -687,6 +692,7 @@ static int iio_verify_update(struct iio_dev *indio_dev, struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer, struct iio_device_config *config) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); unsigned long *compound_mask; const unsigned long *scan_mask; bool strict_scanmask = false; @@ -709,12 +715,12 @@ static int iio_verify_update(struct iio_dev *indio_dev, * to verify. */ if (remove_buffer && !insert_buffer && - list_is_singular(&indio_dev->buffer_list)) + list_is_singular(&iio_dev_opaque->buffer_list)) return 0; modes = indio_dev->modes; - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { if (buffer == remove_buffer) continue; modes &= buffer->access->modes; @@ -735,7 +741,7 @@ static int iio_verify_update(struct iio_dev *indio_dev, * Keep things simple for now and only allow a single buffer to * be connected in hardware mode. */ - if (insert_buffer && !list_empty(&indio_dev->buffer_list)) + if (insert_buffer && !list_empty(&iio_dev_opaque->buffer_list)) return -EINVAL; config->mode = INDIO_BUFFER_HARDWARE; strict_scanmask = true; @@ -755,7 +761,7 @@ static int iio_verify_update(struct iio_dev *indio_dev, scan_timestamp = false; - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { if (buffer == remove_buffer) continue; bitmap_or(compound_mask, compound_mask, buffer->scan_mask, @@ -901,10 +907,11 @@ error_clear_mux_table: static int iio_update_demux(struct iio_dev *indio_dev) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_buffer *buffer; int ret; - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { ret = iio_buffer_update_demux(indio_dev, buffer); if (ret < 0) goto error_clear_mux_table; @@ -912,7 +919,7 @@ static int iio_update_demux(struct iio_dev *indio_dev) return 0; error_clear_mux_table: - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) iio_buffer_demux_free(buffer); return ret; @@ -921,6 +928,7 @@ error_clear_mux_table: static int iio_enable_buffers(struct iio_dev *indio_dev, struct iio_device_config *config) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_buffer *buffer; int ret; @@ -957,25 +965,37 @@ static int iio_enable_buffers(struct iio_dev *indio_dev, indio_dev->info->hwfifo_set_watermark(indio_dev, config->watermark); - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { ret = iio_buffer_enable(buffer, indio_dev); if (ret) goto err_disable_buffers; } + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + ret = iio_trigger_attach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + if (ret) + goto err_disable_buffers; + } + if (indio_dev->setup_ops->postenable) { ret = indio_dev->setup_ops->postenable(indio_dev); if (ret) { dev_dbg(&indio_dev->dev, "Buffer not started: postenable failed (%d)\n", ret); - goto err_disable_buffers; + goto err_detach_pollfunc; } } return 0; +err_detach_pollfunc: + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + iio_trigger_detach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } err_disable_buffers: - list_for_each_entry_continue_reverse(buffer, &indio_dev->buffer_list, + list_for_each_entry_continue_reverse(buffer, &iio_dev_opaque->buffer_list, buffer_list) iio_buffer_disable(buffer, indio_dev); err_run_postdisable: @@ -990,12 +1010,13 @@ err_undo_config: static int iio_disable_buffers(struct iio_dev *indio_dev) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_buffer *buffer; int ret = 0; int ret2; /* Wind down existing buffers - iff there are any */ - if (list_empty(&indio_dev->buffer_list)) + if (list_empty(&iio_dev_opaque->buffer_list)) return 0; /* @@ -1011,7 +1032,12 @@ static int iio_disable_buffers(struct iio_dev *indio_dev) ret = ret2; } - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + iio_trigger_detach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } + + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { ret2 = iio_buffer_disable(buffer, indio_dev); if (ret2 && !ret) ret = ret2; @@ -1034,6 +1060,7 @@ static int __iio_update_buffers(struct iio_dev *indio_dev, struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_device_config new_config; int ret; @@ -1058,7 +1085,7 @@ static int __iio_update_buffers(struct iio_dev *indio_dev, iio_buffer_activate(indio_dev, insert_buffer); /* If no buffers in list, we are done */ - if (list_empty(&indio_dev->buffer_list)) + if (list_empty(&iio_dev_opaque->buffer_list)) return 0; ret = iio_enable_buffers(indio_dev, &new_config); @@ -1407,10 +1434,11 @@ static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data) */ int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); int ret; struct iio_buffer *buf; - list_for_each_entry(buf, &indio_dev->buffer_list, buffer_list) { + list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) { ret = iio_push_to_buffer(buf, data); if (ret < 0) return ret; diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 35253334270202b4f93eb283f70e37f02c1b6e0b..606d5e61c5759970689db730f4a240c786458263 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "iio_core.h" #include "iio_core_trigger.h" #include @@ -166,6 +167,19 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_THERMOCOUPLE_TYPE] = "thermocouple_type", }; +#if defined(CONFIG_DEBUG_FS) +/** + * There's also a CONFIG_DEBUG_FS guard in include/linux/iio/iio.h for + * iio_get_debugfs_dentry() to make it inline if CONFIG_DEBUG_FS is undefined + */ +struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) +{ + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + return iio_dev_opaque->debugfs_dentry; +} +EXPORT_SYMBOL_GPL(iio_get_debugfs_dentry); +#endif + /** * iio_find_channel_from_si() - get channel from its scan index * @indio_dev: device @@ -199,7 +213,8 @@ EXPORT_SYMBOL(iio_read_const_attr); int iio_device_set_clock(struct iio_dev *indio_dev, clockid_t clock_id) { int ret; - const struct iio_event_interface *ev_int = indio_dev->event_interface; + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + const struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; ret = mutex_lock_interruptible(&indio_dev->mlock); if (ret) @@ -309,35 +324,37 @@ static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct iio_dev *indio_dev = file->private_data; + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); unsigned val = 0; int ret; if (*ppos > 0) return simple_read_from_buffer(userbuf, count, ppos, - indio_dev->read_buf, - indio_dev->read_buf_len); + iio_dev_opaque->read_buf, + iio_dev_opaque->read_buf_len); ret = indio_dev->info->debugfs_reg_access(indio_dev, - indio_dev->cached_reg_addr, + iio_dev_opaque->cached_reg_addr, 0, &val); if (ret) { dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__); return ret; } - indio_dev->read_buf_len = snprintf(indio_dev->read_buf, - sizeof(indio_dev->read_buf), - "0x%X\n", val); + iio_dev_opaque->read_buf_len = snprintf(iio_dev_opaque->read_buf, + sizeof(iio_dev_opaque->read_buf), + "0x%X\n", val); return simple_read_from_buffer(userbuf, count, ppos, - indio_dev->read_buf, - indio_dev->read_buf_len); + iio_dev_opaque->read_buf, + iio_dev_opaque->read_buf_len); } static ssize_t iio_debugfs_write_reg(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { struct iio_dev *indio_dev = file->private_data; + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); unsigned reg, val; char buf[80]; int ret; @@ -352,10 +369,10 @@ static ssize_t iio_debugfs_write_reg(struct file *file, switch (ret) { case 1: - indio_dev->cached_reg_addr = reg; + iio_dev_opaque->cached_reg_addr = reg; break; case 2: - indio_dev->cached_reg_addr = reg; + iio_dev_opaque->cached_reg_addr = reg; ret = indio_dev->info->debugfs_reg_access(indio_dev, reg, val, NULL); if (ret) { @@ -379,23 +396,28 @@ static const struct file_operations iio_debugfs_reg_fops = { static void iio_device_unregister_debugfs(struct iio_dev *indio_dev) { - debugfs_remove_recursive(indio_dev->debugfs_dentry); + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + debugfs_remove_recursive(iio_dev_opaque->debugfs_dentry); } static void iio_device_register_debugfs(struct iio_dev *indio_dev) { + struct iio_dev_opaque *iio_dev_opaque; + if (indio_dev->info->debugfs_reg_access == NULL) return; if (!iio_debugfs_dentry) return; - indio_dev->debugfs_dentry = + iio_dev_opaque = to_iio_dev_opaque(indio_dev); + + iio_dev_opaque->debugfs_dentry = debugfs_create_dir(dev_name(&indio_dev->dev), iio_debugfs_dentry); debugfs_create_file("direct_reg_access", 0644, - indio_dev->debugfs_dentry, indio_dev, + iio_dev_opaque->debugfs_dentry, indio_dev, &iio_debugfs_reg_fops); } #else @@ -1118,6 +1140,7 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev, enum iio_shared_by shared_by, const long *infomask) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); int i, ret, attrcount = 0; for_each_set_bit(i, infomask, sizeof(*infomask)*8) { @@ -1130,7 +1153,7 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev, i, shared_by, &indio_dev->dev, - &indio_dev->channel_attr_list); + &iio_dev_opaque->channel_attr_list); if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE)) continue; else if (ret < 0) @@ -1146,6 +1169,7 @@ static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev, enum iio_shared_by shared_by, const long *infomask) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); int i, ret, attrcount = 0; char *avail_postfix; @@ -1165,7 +1189,7 @@ static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev, i, shared_by, &indio_dev->dev, - &indio_dev->channel_attr_list); + &iio_dev_opaque->channel_attr_list); kfree(avail_postfix); if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE)) continue; @@ -1180,6 +1204,7 @@ static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev, static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, struct iio_chan_spec const *chan) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); int ret, attrcount = 0; const struct iio_chan_spec_ext_info *ext_info; @@ -1255,7 +1280,7 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, i, ext_info->shared, &indio_dev->dev, - &indio_dev->channel_attr_list); + &iio_dev_opaque->channel_attr_list); i++; if (ret == -EBUSY && ext_info->shared) continue; @@ -1390,6 +1415,7 @@ static DEVICE_ATTR(current_timestamp_clock, S_IRUGO | S_IWUSR, static int iio_device_register_sysfs(struct iio_dev *indio_dev) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); int i, ret = 0, attrcount, attrn, attrcount_orig = 0; struct iio_dev_attr *p; struct attribute **attr, *clk = NULL; @@ -1419,7 +1445,7 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev) attrcount += ret; } - if (indio_dev->event_interface) + if (iio_dev_opaque->event_interface) clk = &dev_attr_current_timestamp_clock.attr; if (indio_dev->name) @@ -1429,52 +1455,56 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev) if (clk) attrcount++; - indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1, - sizeof(indio_dev->chan_attr_group.attrs[0]), - GFP_KERNEL); - if (indio_dev->chan_attr_group.attrs == NULL) { + iio_dev_opaque->chan_attr_group.attrs = + kcalloc(attrcount + 1, + sizeof(iio_dev_opaque->chan_attr_group.attrs[0]), + GFP_KERNEL); + if (iio_dev_opaque->chan_attr_group.attrs == NULL) { ret = -ENOMEM; goto error_clear_attrs; } /* Copy across original attributes */ if (indio_dev->info->attrs) - memcpy(indio_dev->chan_attr_group.attrs, + memcpy(iio_dev_opaque->chan_attr_group.attrs, indio_dev->info->attrs->attrs, - sizeof(indio_dev->chan_attr_group.attrs[0]) + sizeof(iio_dev_opaque->chan_attr_group.attrs[0]) *attrcount_orig); attrn = attrcount_orig; /* Add all elements from the list. */ - list_for_each_entry(p, &indio_dev->channel_attr_list, l) - indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; + list_for_each_entry(p, &iio_dev_opaque->channel_attr_list, l) + iio_dev_opaque->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; if (indio_dev->name) - indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; + iio_dev_opaque->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; if (indio_dev->label) - indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_label.attr; + iio_dev_opaque->chan_attr_group.attrs[attrn++] = &dev_attr_label.attr; if (clk) - indio_dev->chan_attr_group.attrs[attrn++] = clk; + iio_dev_opaque->chan_attr_group.attrs[attrn++] = clk; indio_dev->groups[indio_dev->groupcounter++] = - &indio_dev->chan_attr_group; + &iio_dev_opaque->chan_attr_group; return 0; error_clear_attrs: - iio_free_chan_devattr_list(&indio_dev->channel_attr_list); + iio_free_chan_devattr_list(&iio_dev_opaque->channel_attr_list); return ret; } static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); - iio_free_chan_devattr_list(&indio_dev->channel_attr_list); - kfree(indio_dev->chan_attr_group.attrs); - indio_dev->chan_attr_group.attrs = NULL; + iio_free_chan_devattr_list(&iio_dev_opaque->channel_attr_list); + kfree(iio_dev_opaque->chan_attr_group.attrs); + iio_dev_opaque->chan_attr_group.attrs = NULL; } static void iio_dev_release(struct device *device) { struct iio_dev *indio_dev = dev_to_iio_dev(device); + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES) iio_device_unregister_trigger_consumer(indio_dev); iio_device_unregister_eventset(indio_dev); @@ -1483,7 +1513,7 @@ static void iio_dev_release(struct device *device) iio_buffer_put(indio_dev->buffer); ida_simple_remove(&iio_ida, indio_dev->id); - kfree(indio_dev); + kfree(iio_dev_opaque); } struct device_type iio_device_type = { @@ -1495,23 +1525,27 @@ struct device_type iio_device_type = { * iio_device_alloc() - allocate an iio_dev from a driver * @sizeof_priv: Space to allocate for private structure. **/ -struct iio_dev *iio_device_alloc(int sizeof_priv) +struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) { + struct iio_dev_opaque *iio_dev_opaque; struct iio_dev *dev; size_t alloc_size; - alloc_size = sizeof(struct iio_dev); + alloc_size = sizeof(struct iio_dev_opaque); if (sizeof_priv) { alloc_size = ALIGN(alloc_size, IIO_ALIGN); alloc_size += sizeof_priv; } - /* ensure 32-byte alignment of whole construct ? */ - alloc_size += IIO_ALIGN - 1; - dev = kzalloc(alloc_size, GFP_KERNEL); - if (!dev) + iio_dev_opaque = kzalloc(alloc_size, GFP_KERNEL); + if (!iio_dev_opaque) return NULL; + dev = &iio_dev_opaque->indio_dev; + dev->priv = (char *)iio_dev_opaque + + ALIGN(sizeof(struct iio_dev_opaque), IIO_ALIGN); + + dev->dev.parent = parent; dev->dev.groups = dev->groups; dev->dev.type = &iio_device_type; dev->dev.bus = &iio_bus_type; @@ -1519,17 +1553,17 @@ struct iio_dev *iio_device_alloc(int sizeof_priv) dev_set_drvdata(&dev->dev, (void *)dev); mutex_init(&dev->mlock); mutex_init(&dev->info_exist_lock); - INIT_LIST_HEAD(&dev->channel_attr_list); + INIT_LIST_HEAD(&iio_dev_opaque->channel_attr_list); dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); if (dev->id < 0) { /* cannot use a dev_err as the name isn't available */ pr_err("failed to get device id\n"); - kfree(dev); + kfree(iio_dev_opaque); return NULL; } dev_set_name(&dev->dev, "iio:device%d", dev->id); - INIT_LIST_HEAD(&dev->buffer_list); + INIT_LIST_HEAD(&iio_dev_opaque->buffer_list); return dev; } @@ -1553,7 +1587,7 @@ static void devm_iio_device_release(struct device *dev, void *res) /** * devm_iio_device_alloc - Resource-managed iio_device_alloc() - * @dev: Device to allocate iio_dev for + * @parent: Device to allocate iio_dev for, and parent for this IIO device * @sizeof_priv: Space to allocate for private structure. * * Managed iio_device_alloc. iio_dev allocated with this function is @@ -1562,7 +1596,7 @@ static void devm_iio_device_release(struct device *dev, void *res) * RETURNS: * Pointer to allocated iio_dev on success, NULL on failure. */ -struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv) +struct iio_dev *devm_iio_device_alloc(struct device *parent, int sizeof_priv) { struct iio_dev **ptr, *iio_dev; @@ -1571,10 +1605,10 @@ struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv) if (!ptr) return NULL; - iio_dev = iio_device_alloc(sizeof_priv); + iio_dev = iio_device_alloc(parent, sizeof_priv); if (iio_dev) { *ptr = iio_dev; - devres_add(dev, ptr); + devres_add(parent, ptr); } else { devres_free(ptr); } diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 5b17c92d3b508ac31f27696f6dbe2031c1f02cd1..2ab4d4c444272af1bd8764f258404be7bdbf90d3 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "iio_core.h" #include #include @@ -62,7 +63,8 @@ bool iio_event_enabled(const struct iio_event_interface *ev_int) **/ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) { - struct iio_event_interface *ev_int = indio_dev->event_interface; + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; struct iio_event_data ev; int copied; @@ -96,7 +98,8 @@ static __poll_t iio_event_poll(struct file *filep, struct poll_table_struct *wait) { struct iio_dev *indio_dev = filep->private_data; - struct iio_event_interface *ev_int = indio_dev->event_interface; + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; __poll_t events = 0; if (!indio_dev->info) @@ -116,7 +119,8 @@ static ssize_t iio_event_chrdev_read(struct file *filep, loff_t *f_ps) { struct iio_dev *indio_dev = filep->private_data; - struct iio_event_interface *ev_int = indio_dev->event_interface; + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; unsigned int copied; int ret; @@ -165,7 +169,8 @@ static ssize_t iio_event_chrdev_read(struct file *filep, static int iio_event_chrdev_release(struct inode *inode, struct file *filep) { struct iio_dev *indio_dev = filep->private_data; - struct iio_event_interface *ev_int = indio_dev->event_interface; + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); @@ -184,7 +189,8 @@ static const struct file_operations iio_event_chrdev_fileops = { int iio_event_getfd(struct iio_dev *indio_dev) { - struct iio_event_interface *ev_int = indio_dev->event_interface; + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; int fd; if (ev_int == NULL) @@ -343,6 +349,7 @@ static int iio_device_add_event(struct iio_dev *indio_dev, enum iio_event_type type, enum iio_event_direction dir, enum iio_shared_by shared_by, const unsigned long *mask) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); ssize_t (*show)(struct device *, struct device_attribute *, char *); ssize_t (*store)(struct device *, struct device_attribute *, const char *, size_t); @@ -376,7 +383,7 @@ static int iio_device_add_event(struct iio_dev *indio_dev, ret = __iio_add_chan_devattr(postfix, chan, show, store, (i << 16) | spec_index, shared_by, &indio_dev->dev, - &indio_dev->event_interface->dev_attr_list); + &iio_dev_opaque->event_interface->dev_attr_list); kfree(postfix); if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE)) @@ -469,6 +476,7 @@ static void iio_setup_ev_int(struct iio_event_interface *ev_int) static const char *iio_event_group_name = "events"; int iio_device_register_eventset(struct iio_dev *indio_dev) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_dev_attr *p; int ret = 0, attrcount_orig = 0, attrcount, attrn; struct attribute **attr; @@ -477,14 +485,14 @@ int iio_device_register_eventset(struct iio_dev *indio_dev) iio_check_for_dynamic_events(indio_dev))) return 0; - indio_dev->event_interface = + iio_dev_opaque->event_interface = kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); - if (indio_dev->event_interface == NULL) + if (iio_dev_opaque->event_interface == NULL) return -ENOMEM; - INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); + INIT_LIST_HEAD(&iio_dev_opaque->event_interface->dev_attr_list); - iio_setup_ev_int(indio_dev->event_interface); + iio_setup_ev_int(iio_dev_opaque->event_interface); if (indio_dev->info->event_attrs != NULL) { attr = indio_dev->info->event_attrs->attrs; while (*attr++ != NULL) @@ -498,35 +506,35 @@ int iio_device_register_eventset(struct iio_dev *indio_dev) attrcount += ret; } - indio_dev->event_interface->group.name = iio_event_group_name; - indio_dev->event_interface->group.attrs = kcalloc(attrcount + 1, - sizeof(indio_dev->event_interface->group.attrs[0]), + iio_dev_opaque->event_interface->group.name = iio_event_group_name; + iio_dev_opaque->event_interface->group.attrs = kcalloc(attrcount + 1, + sizeof(iio_dev_opaque->event_interface->group.attrs[0]), GFP_KERNEL); - if (indio_dev->event_interface->group.attrs == NULL) { + if (iio_dev_opaque->event_interface->group.attrs == NULL) { ret = -ENOMEM; goto error_free_setup_event_lines; } if (indio_dev->info->event_attrs) - memcpy(indio_dev->event_interface->group.attrs, + memcpy(iio_dev_opaque->event_interface->group.attrs, indio_dev->info->event_attrs->attrs, - sizeof(indio_dev->event_interface->group.attrs[0]) + sizeof(iio_dev_opaque->event_interface->group.attrs[0]) *attrcount_orig); attrn = attrcount_orig; /* Add all elements from the list. */ list_for_each_entry(p, - &indio_dev->event_interface->dev_attr_list, + &iio_dev_opaque->event_interface->dev_attr_list, l) - indio_dev->event_interface->group.attrs[attrn++] = + iio_dev_opaque->event_interface->group.attrs[attrn++] = &p->dev_attr.attr; indio_dev->groups[indio_dev->groupcounter++] = - &indio_dev->event_interface->group; + &iio_dev_opaque->event_interface->group; return 0; error_free_setup_event_lines: - iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list); - kfree(indio_dev->event_interface); - indio_dev->event_interface = NULL; + iio_free_chan_devattr_list(&iio_dev_opaque->event_interface->dev_attr_list); + kfree(iio_dev_opaque->event_interface); + iio_dev_opaque->event_interface = NULL; return ret; } @@ -539,16 +547,20 @@ error_free_setup_event_lines: */ void iio_device_wakeup_eventset(struct iio_dev *indio_dev) { - if (indio_dev->event_interface == NULL) + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + + if (iio_dev_opaque->event_interface == NULL) return; - wake_up(&indio_dev->event_interface->wait); + wake_up(&iio_dev_opaque->event_interface->wait); } void iio_device_unregister_eventset(struct iio_dev *indio_dev) { - if (indio_dev->event_interface == NULL) + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + + if (iio_dev_opaque->event_interface == NULL) return; - iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list); - kfree(indio_dev->event_interface->group.attrs); - kfree(indio_dev->event_interface); + iio_free_chan_devattr_list(&iio_dev_opaque->event_interface->dev_attr_list); + kfree(iio_dev_opaque->event_interface->group.attrs); + kfree(iio_dev_opaque->event_interface); } diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 53d1931f6be8b20496a61238bbd1c72426f67ca3..6f16357fd732234afe282abc97fd60e62d13500b 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -239,8 +239,8 @@ static void iio_trigger_put_irq(struct iio_trigger *trig, int irq) * the relevant function is in there may be the best option. */ /* Worth protecting against double additions? */ -static int iio_trigger_attach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf) +int iio_trigger_attach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) { int ret = 0; bool notinuse @@ -290,8 +290,8 @@ out_put_module: return ret; } -static int iio_trigger_detach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf) +int iio_trigger_detach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) { int ret = 0; bool no_other_users @@ -705,17 +705,3 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) if (indio_dev->trig) iio_trigger_put(indio_dev->trig); } - -int iio_triggered_buffer_postenable(struct iio_dev *indio_dev) -{ - return iio_trigger_attach_poll_func(indio_dev->trig, - indio_dev->pollfunc); -} -EXPORT_SYMBOL(iio_triggered_buffer_postenable); - -int iio_triggered_buffer_predisable(struct iio_dev *indio_dev) -{ - return iio_trigger_detach_poll_func(indio_dev->trig, - indio_dev->pollfunc); -} -EXPORT_SYMBOL(iio_triggered_buffer_predisable); diff --git a/drivers/iio/light/acpi-als.c b/drivers/iio/light/acpi-als.c index 1eafd0b24e18234bf2a28323fb598d530d90586f..2be7180e2cbfa8a9c0a58efb05cf83c73d82e200 100644 --- a/drivers/iio/light/acpi-als.c +++ b/drivers/iio/light/acpi-als.c @@ -178,7 +178,6 @@ static int acpi_als_add(struct acpi_device *device) mutex_init(&als->lock); indio_dev->name = ACPI_ALS_DEVICE_NAME; - indio_dev->dev.parent = &device->dev; indio_dev->info = &acpi_als_info; indio_dev->modes = INDIO_BUFFER_SOFTWARE; indio_dev->channels = acpi_als_channels; diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c index d3269cd44fb5cf4ec839be60f4549323087f96c0..17dac8d0e11dd06c9d16f3cacf0ee8ca56d3199a 100644 --- a/drivers/iio/light/adjd_s311.c +++ b/drivers/iio/light/adjd_s311.c @@ -259,7 +259,6 @@ static int adjd_s311_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->info = &adjd_s311_info; indio_dev->name = ADJD_S311_DRV_NAME; indio_dev->channels = adjd_s311_channels; diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c index b07797ac10d7da28ef84fb85cad50e02e5b1b9be..9aa28695e6f19cc5246d38591618fb0521b9698e 100644 --- a/drivers/iio/light/adux1020.c +++ b/drivers/iio/light/adux1020.c @@ -785,7 +785,6 @@ static int adux1020_probe(struct i2c_client *client, if (!indio_dev) return -ENOMEM; - indio_dev->dev.parent = &client->dev; indio_dev->info = &adux1020_info; indio_dev->name = ADUX1020_DRV_NAME; indio_dev->channels = adux1020_channels; diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c index b1ed7658cc46ea2e03a7e7c59c4aa9534f2935f1..b4e9924094cd17743402d738d07d4c786a31909a 100644 --- a/drivers/iio/light/al3010.c +++ b/drivers/iio/light/al3010.c @@ -179,7 +179,6 @@ static int al3010_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->info = &al3010_info; indio_dev->name = AL3010_DRV_NAME; indio_dev->channels = al3010_channels; diff --git a/drivers/iio/light/al3320a.c b/drivers/iio/light/al3320a.c index 20ed0a73c39013a7abdb71f60759815960426ff6..cc1407ccc10ad5464e5a124c8d7f6f2b56a9fa8a 100644 --- a/drivers/iio/light/al3320a.c +++ b/drivers/iio/light/al3320a.c @@ -202,7 +202,6 @@ static int al3320a_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->info = &al3320a_info; indio_dev->name = AL3320A_DRV_NAME; indio_dev->channels = al3320a_channels; diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c index 856b6c468dea6891a47af6ae12e063f2019a3668..baaf202dce05659586c7c6712bc4f839163fe2ea 100644 --- a/drivers/iio/light/apds9300.c +++ b/drivers/iio/light/apds9300.c @@ -419,7 +419,6 @@ static int apds9300_probe(struct i2c_client *client, mutex_init(&data->mutex); - indio_dev->dev.parent = &client->dev; indio_dev->channels = apds9300_channels; indio_dev->num_channels = ARRAY_SIZE(apds9300_channels); indio_dev->name = APDS9300_DRV_NAME; diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c index 52f86bc777ddf65435de3dbf1edd8630a6db651e..9afb3fcc74e627edf4a8184a229f163bd05e90dd 100644 --- a/drivers/iio/light/apds9960.c +++ b/drivers/iio/light/apds9960.c @@ -1001,7 +1001,6 @@ static int apds9960_probe(struct i2c_client *client, iio_device_attach_buffer(indio_dev, buffer); - indio_dev->dev.parent = &client->dev; indio_dev->info = &apds9960_info; indio_dev->name = APDS9960_DRV_NAME; indio_dev->channels = apds9960_channels; diff --git a/drivers/iio/light/bh1750.c b/drivers/iio/light/bh1750.c index adb5ab9e343909ba2ae3a1a01c65aa27d3009096..48484b9401b9d82db1e48dec37d8f52e1652856a 100644 --- a/drivers/iio/light/bh1750.c +++ b/drivers/iio/light/bh1750.c @@ -254,7 +254,6 @@ static int bh1750_probe(struct i2c_client *client, return ret; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &bh1750_info; indio_dev->name = id->name; indio_dev->channels = bh1750_channels; diff --git a/drivers/iio/light/bh1780.c b/drivers/iio/light/bh1780.c index 03f2d8d123c4a671bf1dc81800ac3b0d9d921935..abbf2e662e7dbc345c0ed7ccb7a10a0027eb35ef 100644 --- a/drivers/iio/light/bh1780.c +++ b/drivers/iio/light/bh1780.c @@ -185,7 +185,6 @@ static int bh1780_probe(struct i2c_client *client, pm_runtime_use_autosuspend(&client->dev); pm_runtime_put(&client->dev); - indio_dev->dev.parent = &client->dev; indio_dev->info = &bh1780_info; indio_dev->name = "bh1780"; indio_dev->channels = bh1780_channels; diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c index 160eb3f99795ee26a9028ddd83b25aaca2572e44..97649944f1df65651076f83b9db169ad87a5253e 100644 --- a/drivers/iio/light/cm32181.c +++ b/drivers/iio/light/cm32181.c @@ -93,10 +93,10 @@ static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2); #ifdef CONFIG_ACPI /** * cm32181_acpi_get_cpm() - Get CPM object from ACPI - * @client pointer of struct i2c_client. - * @obj_name pointer of ACPI object name. - * @count maximum size of return array. - * @vals pointer of array for return elements. + * @dev: pointer of struct device. + * @obj_name: pointer of ACPI object name. + * @values: pointer of array for return elements. + * @count: maximum size of return array. * * Convert ACPI CPM table to array. * @@ -465,7 +465,6 @@ static int cm32181_probe(struct i2c_client *client) cm32181->dev = dev; mutex_init(&cm32181->lock); - indio_dev->dev.parent = dev; indio_dev->channels = cm32181_channels; indio_dev->num_channels = ARRAY_SIZE(cm32181_channels); indio_dev->info = &cm32181_info; diff --git a/drivers/iio/light/cm3232.c b/drivers/iio/light/cm3232.c index 8672008256860f3b99e3e038271fe4bf07c0ef73..18a410340dc563813583718a3165992df889e91f 100644 --- a/drivers/iio/light/cm3232.c +++ b/drivers/iio/light/cm3232.c @@ -340,7 +340,6 @@ static int cm3232_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); chip->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->channels = cm3232_channels; indio_dev->num_channels = ARRAY_SIZE(cm3232_channels); indio_dev->info = &cm3232_info; diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c index 0443861ba1ec924be6def0bd39075a1e59d14a3d..6d1b0ffd144b69a6442848c85458f5b150143123 100644 --- a/drivers/iio/light/cm3323.c +++ b/drivers/iio/light/cm3323.c @@ -231,7 +231,6 @@ static int cm3323_probe(struct i2c_client *client, mutex_init(&data->mutex); - indio_dev->dev.parent = &client->dev; indio_dev->info = &cm3323_info; indio_dev->name = CM3323_DRV_NAME; indio_dev->channels = cm3323_channels; diff --git a/drivers/iio/light/cm3605.c b/drivers/iio/light/cm3605.c index 964ede49f662dda4f52b6e19a6dcd61d712dd1af..4c83953672bec0507769daf4770a16dd35cb9b27 100644 --- a/drivers/iio/light/cm3605.c +++ b/drivers/iio/light/cm3605.c @@ -239,7 +239,6 @@ static int cm3605_probe(struct platform_device *pdev) led_trigger_register_simple("cm3605", &cm3605->led); led_trigger_event(cm3605->led, LED_FULL); - indio_dev->dev.parent = dev; indio_dev->info = &cm3605_info; indio_dev->name = "cm3605"; indio_dev->channels = cm3605_channels; diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c index 90e38fcc974b05b9dd47e336954e0aa9e20862d5..fd83a19929bc391203572e7384d27d4d423a91df 100644 --- a/drivers/iio/light/cm36651.c +++ b/drivers/iio/light/cm36651.c @@ -662,7 +662,6 @@ static int cm36651_probe(struct i2c_client *client, } mutex_init(&cm36651->lock); - indio_dev->dev.parent = &client->dev; indio_dev->channels = cm36651_channels; indio_dev->num_channels = ARRAY_SIZE(cm36651_channels); indio_dev->info = &cm36651_info; diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index 2198b50909ed0de7159b62c187a0eb054aa199c3..fed79ba27fda5b87cae534b819f60981488241f7 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -145,8 +145,11 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_CALIBSCALE: st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; - st->core.param.sensor_range.data = (val << 16) | (val2 / 100); + st->core.curr_range = (val << 16) | (val2 / 100); + st->core.param.sensor_range.data = st->core.curr_range; ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret == 0) + st->core.range_updated = true; break; default: ret = cros_ec_sensors_core_write(&st->core, chan, val, val2, @@ -256,6 +259,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_light_prox_ids); static struct platform_driver cros_ec_light_prox_platform_driver = { .driver = { .name = "cros-ec-light-prox", + .pm = &cros_ec_sensors_pm_ops, }, .probe = cros_ec_light_prox_probe, .id_table = cros_ec_light_prox_ids, diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c index 7a2679bdc987a5f38b2956c5bd2f379b8610a131..d5e1cd27eb4660d9b062b356d16beeea186f63b3 100644 --- a/drivers/iio/light/gp2ap002.c +++ b/drivers/iio/light/gp2ap002.c @@ -596,7 +596,6 @@ static int gp2ap002_probe(struct i2c_client *client, pm_runtime_use_autosuspend(dev); pm_runtime_put(dev); - indio_dev->dev.parent = dev; indio_dev->info = &gp2ap002_info; indio_dev->name = "gp2ap002"; indio_dev->channels = gp2ap002_channels; diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c index 070d4cd0cf54e5980604ed769c1e1fd950676dd6..e2850c1a735339b4b9582728b06647383ac77a09 100644 --- a/drivers/iio/light/gp2ap020a00f.c +++ b/drivers/iio/light/gp2ap020a00f.c @@ -1390,12 +1390,6 @@ static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev) mutex_lock(&data->lock); - err = iio_triggered_buffer_postenable(indio_dev); - if (err < 0) { - mutex_unlock(&data->lock); - return err; - } - /* * Enable triggers according to the scan_mask. Enabling either * LIGHT_CLEAR or LIGHT_IR scan mode results in enabling ALS @@ -1430,8 +1424,6 @@ static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev) err = -ENOMEM; error_unlock: - if (err < 0) - iio_triggered_buffer_predisable(indio_dev); mutex_unlock(&data->lock); return err; @@ -1465,8 +1457,6 @@ static int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev) if (err == 0) kfree(data->buffer); - iio_triggered_buffer_predisable(indio_dev); - mutex_unlock(&data->lock); return err; @@ -1527,7 +1517,6 @@ static int gp2ap020a00f_probe(struct i2c_client *client, init_waitqueue_head(&data->data_ready_queue); mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->channels = gp2ap020a00f_channels; indio_dev->num_channels = ARRAY_SIZE(gp2ap020a00f_channels); indio_dev->info = &gp2ap020a00f_info; diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index 81fa2a422797f2c29ca244333e2280fcaa5b49f7..a21c827e4953dd217cf6a36364f9f1bcc842714b 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -301,7 +301,6 @@ static int hid_als_probe(struct platform_device *pdev) indio_dev->num_channels = ARRAY_SIZE(als_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &als_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index e9c04df07344a1baec5a97e86726b6e33f2e83df..330cf359e0b81c27802662713239665ca4ebb8bb 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -279,7 +279,6 @@ static int hid_prox_probe(struct platform_device *pdev) } indio_dev->num_channels = ARRAY_SIZE(prox_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &prox_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/light/iqs621-als.c b/drivers/iio/light/iqs621-als.c index b2988a782bd023535737f7bdd1cb9204ff2a68e1..004ea890a4b2ccfef25258e9fa832140fd684829 100644 --- a/drivers/iio/light/iqs621-als.c +++ b/drivers/iio/light/iqs621-als.c @@ -36,6 +36,7 @@ struct iqs621_als_private { struct iqs62x_core *iqs62x; + struct iio_dev *indio_dev; struct notifier_block notifier; struct mutex lock; bool light_en; @@ -103,7 +104,7 @@ static int iqs621_als_notifier(struct notifier_block *notifier, iqs621_als = container_of(notifier, struct iqs621_als_private, notifier); - indio_dev = iio_priv_to_dev(iqs621_als); + indio_dev = iqs621_als->indio_dev; timestamp = iio_get_time_ns(indio_dev); mutex_lock(&iqs621_als->lock); @@ -191,7 +192,7 @@ err_mutex: static void iqs621_als_notifier_unregister(void *context) { struct iqs621_als_private *iqs621_als = context; - struct iio_dev *indio_dev = iio_priv_to_dev(iqs621_als); + struct iio_dev *indio_dev = iqs621_als->indio_dev; int ret; ret = blocking_notifier_chain_unregister(&iqs621_als->iqs62x->nh, @@ -551,6 +552,7 @@ static int iqs621_als_probe(struct platform_device *pdev) iqs621_als = iio_priv(indio_dev); iqs621_als->iqs62x = iqs62x; + iqs621_als->indio_dev = indio_dev; if (iqs62x->dev_desc->prod_num == IQS622_PROD_NUM) { ret = regmap_read(iqs62x->regmap, IQS622_IR_THRESH_TOUCH, @@ -580,7 +582,6 @@ static int iqs621_als_probe(struct platform_device *pdev) } indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->dev.parent = &pdev->dev; indio_dev->name = iqs62x->dev_desc->dev_name; indio_dev->info = &iqs621_als_info; diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c index 805a74f08ad118daaa401301739cebcd398d07ca..ac8ad0f326899d40e8c1401b4daf35d77e4a6be2 100644 --- a/drivers/iio/light/isl29018.c +++ b/drivers/iio/light/isl29018.c @@ -782,7 +782,6 @@ static int isl29018_probe(struct i2c_client *client, indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels; indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels; indio_dev->name = name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; return devm_iio_device_register(&client->dev, indio_dev); diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c index 4d220c835c7589b9bedbf0442704d9b712d9bf09..2f8b494f3e0807d0d730302b4a7359fab826dcfa 100644 --- a/drivers/iio/light/isl29028.c +++ b/drivers/iio/light/isl29028.c @@ -620,7 +620,6 @@ static int isl29028_probe(struct i2c_client *client, indio_dev->channels = isl29028_channels; indio_dev->num_channels = ARRAY_SIZE(isl29028_channels); indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; pm_runtime_enable(&client->dev); diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c index 95611f5eff01a892d7c66d2fef5ebaaa6bca9117..b93b85dbc3a6a15e0d267ddf1634b33a855f50b8 100644 --- a/drivers/iio/light/isl29125.c +++ b/drivers/iio/light/isl29125.c @@ -216,36 +216,20 @@ static const struct iio_info isl29125_info = { static int isl29125_buffer_postenable(struct iio_dev *indio_dev) { struct isl29125_data *data = iio_priv(indio_dev); - int err; - - err = iio_triggered_buffer_postenable(indio_dev); - if (err) - return err; data->conf1 |= ISL29125_MODE_RGB; - err = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, + return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, data->conf1); - if (err) { - iio_triggered_buffer_predisable(indio_dev); - return err; - } - - return 0; } static int isl29125_buffer_predisable(struct iio_dev *indio_dev) { struct isl29125_data *data = iio_priv(indio_dev); - int ret; data->conf1 &= ~ISL29125_MODE_MASK; data->conf1 |= ISL29125_MODE_PD; - ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, + return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, data->conf1); - - iio_triggered_buffer_predisable(indio_dev); - - return ret; } static const struct iio_buffer_setup_ops isl29125_buffer_setup_ops = { @@ -268,7 +252,6 @@ static int isl29125_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->info = &isl29125_info; indio_dev->name = ISL29125_DRV_NAME; indio_dev->channels = isl29125_channels; diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c index 13deeebe37ebbd4a3efa9d166eb6f3576f4cf209..724a0ec9f35cc76b3cc5404ef6a3e1a060d5e756 100644 --- a/drivers/iio/light/jsa1212.c +++ b/drivers/iio/light/jsa1212.c @@ -338,7 +338,6 @@ static int jsa1212_probe(struct i2c_client *client, if (ret < 0) return ret; - indio_dev->dev.parent = &client->dev; indio_dev->channels = jsa1212_channels; indio_dev->num_channels = ARRAY_SIZE(jsa1212_channels); indio_dev->name = JSA1212_DRIVER_NAME; diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c index bc196c21288171a6d89ef5ced4651178369537b4..8a621244dd0126fc5bfa345e347137b69851e4d5 100644 --- a/drivers/iio/light/lm3533-als.c +++ b/drivers/iio/light/lm3533-als.c @@ -852,7 +852,7 @@ static int lm3533_als_probe(struct platform_device *pdev) indio_dev->channels = lm3533_als_channels; indio_dev->num_channels = ARRAY_SIZE(lm3533_als_channels); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = pdev->dev.parent; + iio_device_set_parent(indio_dev, pdev->dev.parent); indio_dev->modes = INDIO_DIRECT_MODE; als = iio_priv(indio_dev); diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 5a3fcb127cd20d3f8a5f09234a100021b7e39250..4bac0646398d569752d869dbe5e342265ad2e39c 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -1480,7 +1480,6 @@ static int ltr501_probe(struct i2c_client *client, if ((partid >> 4) != data->chip_info->partid) return -ENODEV; - indio_dev->dev.parent = &client->dev; indio_dev->info = data->chip_info->info; indio_dev->channels = data->chip_info->channels; indio_dev->num_channels = data->chip_info->no_channels; diff --git a/drivers/iio/light/lv0104cs.c b/drivers/iio/light/lv0104cs.c index 55b8e2855647731388bf1448fc45c2c7770c5173..c2aef88f4e6349f16918a5e3ae64a7f29ac402c5 100644 --- a/drivers/iio/light/lv0104cs.c +++ b/drivers/iio/light/lv0104cs.c @@ -7,7 +7,7 @@ * * 7-bit I2C slave address: 0x13 * - * Link to data sheet: http://www.onsemi.com/pub/Collateral/LV0104CS-D.PDF + * Link to data sheet: https://www.onsemi.com/pub/Collateral/LV0104CS-D.PDF */ #include @@ -502,7 +502,6 @@ static int lv0104cs_probe(struct i2c_client *client, return ret; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->dev.parent = &client->dev; indio_dev->channels = lv0104cs_channels; indio_dev->num_channels = ARRAY_SIZE(lv0104cs_channels); indio_dev->name = client->name; diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c index d6d8007ba430a60f76cb2072d3b52d09092b9f4b..aa8ed1e3e89a5165f50402674148c0e7191699a4 100644 --- a/drivers/iio/light/max44000.c +++ b/drivers/iio/light/max44000.c @@ -538,7 +538,6 @@ static int max44000_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &max44000_info; indio_dev->name = MAX44000_DRV_NAME; indio_dev->channels = max44000_channels; diff --git a/drivers/iio/light/max44009.c b/drivers/iio/light/max44009.c index 00ba15499638d3d2914e9bf6f9e0ea02557dc883..801e5a0ad496be915554d8d9fb8175705ee47d20 100644 --- a/drivers/iio/light/max44009.c +++ b/drivers/iio/light/max44009.c @@ -501,7 +501,6 @@ static int max44009_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->info = &max44009_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = MAX44009_DRV_NAME; diff --git a/drivers/iio/light/noa1305.c b/drivers/iio/light/noa1305.c index 5ebfbc52f541caeb5aa8accb63ab3119ad99d087..a308fbc2fc7bd8affb2dd6e2492fc9eb31fa3b28 100644 --- a/drivers/iio/light/noa1305.c +++ b/drivers/iio/light/noa1305.c @@ -270,7 +270,6 @@ static int noa1305_probe(struct i2c_client *client, return ret; } - indio_dev->dev.parent = &client->dev; indio_dev->info = &noa1305_info; indio_dev->channels = noa1305_channels; indio_dev->num_channels = ARRAY_SIZE(noa1305_channels); diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index 82abfa57b59c51189c1423d3bd5d741bf5f52996..2d48d61909a4de45c1e14c3b6aef2fc2159b560e 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -2,7 +2,7 @@ /** * opt3001.c - Texas Instruments OPT3001 Light Sensor * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com * * Author: Andreas Dannenberg * Based on previous work from: Felipe Balbi @@ -768,7 +768,6 @@ static int opt3001_probe(struct i2c_client *client, iio->name = client->name; iio->channels = opt3001_channels; iio->num_channels = ARRAY_SIZE(opt3001_channels); - iio->dev.parent = dev; iio->modes = INDIO_DIRECT_MODE; iio->info = &opt3001_info; diff --git a/drivers/iio/light/pa12203001.c b/drivers/iio/light/pa12203001.c index 0295783f036ac33f5f0bdf0d2e72fa79ccf26946..bfade6577a38053a76f8531e2b8ec2dacc48ccda 100644 --- a/drivers/iio/light/pa12203001.c +++ b/drivers/iio/light/pa12203001.c @@ -362,7 +362,6 @@ static int pa12203001_probe(struct i2c_client *client, mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &pa12203001_info; indio_dev->name = PA12203001_DRIVER_NAME; indio_dev->channels = pa12203001_channels; diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c index a0a7aeae5a82254d274556601d68d4fa9b2d1e37..aa2972b0483344476ff88563e1d0c603a350bfa1 100644 --- a/drivers/iio/light/rpr0521.c +++ b/drivers/iio/light/rpr0521.c @@ -570,8 +570,6 @@ static int rpr0521_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops rpr0521_buffer_setup_ops = { .preenable = rpr0521_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = rpr0521_buffer_postdisable, }; @@ -948,7 +946,6 @@ static int rpr0521_probe(struct i2c_client *client, mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &rpr0521_info; indio_dev->name = RPR0521_DRV_NAME; indio_dev->channels = rpr0521_channels; diff --git a/drivers/iio/light/si1133.c b/drivers/iio/light/si1133.c index c1adab2a50fd5a0631d561c48080830f4bf34ba5..c280b41950036a57b32db6a75e7acae81fb7eb68 100644 --- a/drivers/iio/light/si1133.c +++ b/drivers/iio/light/si1133.c @@ -1015,7 +1015,6 @@ static int si1133_probe(struct i2c_client *client, i2c_set_clientdata(client, iio_dev); data->client = client; - iio_dev->dev.parent = &client->dev; iio_dev->name = id->name; iio_dev->channels = si1133_channels; iio_dev->num_channels = ARRAY_SIZE(si1133_channels); diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index 0476c2bc813841530b5e3977bfa2012baec51921..155faaea8c72faafb7d8be6659c20c33f7bb242f 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -181,7 +181,7 @@ struct si1145_data { int meas_rate; }; -/** +/* * __si1145_command_reset() - Send CMD_NOP and wait for response 0 * * Does not modify data->rsp_seq @@ -215,7 +215,7 @@ static int __si1145_command_reset(struct si1145_data *data) } } -/** +/* * si1145_command() - Execute a command and poll the response register * * All conversion overflows are reported as -EOVERFLOW @@ -1171,12 +1171,10 @@ static bool si1145_validate_scan_mask(struct iio_dev *indio_dev, static const struct iio_buffer_setup_ops si1145_buffer_setup_ops = { .preenable = si1145_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .validate_scan_mask = si1145_validate_scan_mask, }; -/** +/* * si1145_trigger_set_state() - Set trigger state * * When not using triggers interrupts are disabled and measurement rate is @@ -1307,7 +1305,6 @@ static int si1145_probe(struct i2c_client *client, return -ENODEV; } - indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; indio_dev->channels = data->part_info->channels; indio_dev->num_channels = data->part_info->num_channels; diff --git a/drivers/iio/light/st_uvis25_core.c b/drivers/iio/light/st_uvis25_core.c index d262c254b895aef946df6137ac4a2befa818a5c4..a18a82e6bbf5d6f76876b1c9ca2cbe5a64def8bf 100644 --- a/drivers/iio/light/st_uvis25_core.c +++ b/drivers/iio/light/st_uvis25_core.c @@ -227,8 +227,6 @@ static int st_uvis25_buffer_postdisable(struct iio_dev *iio_dev) static const struct iio_buffer_setup_ops st_uvis25_buffer_ops = { .preenable = st_uvis25_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = st_uvis25_buffer_postdisable, }; @@ -303,7 +301,6 @@ int st_uvis25_probe(struct device *dev, int irq, struct regmap *regmap) return err; iio_dev->modes = INDIO_DIRECT_MODE; - iio_dev->dev.parent = dev; iio_dev->channels = st_uvis25_channels; iio_dev->num_channels = ARRAY_SIZE(st_uvis25_channels); iio_dev->name = ST_UVIS25_DEV_NAME; diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index 185c24a75ae6fa2fadfc8c9736a3c550e865b42a..a2827d03ab0fb4282e4a4bae22aea10be39abd72 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -37,6 +37,7 @@ #define STK3310_CHIP_ID_VAL 0x13 #define STK3311_CHIP_ID_VAL 0x1D +#define STK3311X_CHIP_ID_VAL 0x12 #define STK3335_CHIP_ID_VAL 0x51 #define STK3310_PSINT_EN 0x01 #define STK3310_PS_MAX_VAL 0xFFFF @@ -453,6 +454,7 @@ static int stk3310_init(struct iio_dev *indio_dev) if (chipid != STK3310_CHIP_ID_VAL && chipid != STK3311_CHIP_ID_VAL && + chipid != STK3311X_CHIP_ID_VAL && chipid != STK3335_CHIP_ID_VAL) { dev_err(&client->dev, "invalid chip id: 0x%x\n", chipid); return -ENODEV; @@ -487,7 +489,7 @@ static bool stk3310_is_volatile_reg(struct device *dev, unsigned int reg) } } -static struct regmap_config stk3310_regmap_config = { +static const struct regmap_config stk3310_regmap_config = { .name = STK3310_REGMAP_NAME, .reg_bits = 8, .val_bits = 8, @@ -585,7 +587,6 @@ static int stk3310_probe(struct i2c_client *client, if (ret < 0) return ret; - indio_dev->dev.parent = &client->dev; indio_dev->info = &stk3310_info; indio_dev->name = STK3310_DRIVER_NAME; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c index b542e5619ead85679b63bda47c5d51a1305bc666..6fe5d46f80d40126a07247a42a1c62cd05a87cca 100644 --- a/drivers/iio/light/tcs3414.c +++ b/drivers/iio/light/tcs3414.c @@ -243,35 +243,19 @@ static const struct iio_info tcs3414_info = { static int tcs3414_buffer_postenable(struct iio_dev *indio_dev) { struct tcs3414_data *data = iio_priv(indio_dev); - int ret; - - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret) - return ret; data->control |= TCS3414_CONTROL_ADC_EN; - ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL, + return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL, data->control); - if (ret) - iio_triggered_buffer_predisable(indio_dev); - - return ret; } static int tcs3414_buffer_predisable(struct iio_dev *indio_dev) { struct tcs3414_data *data = iio_priv(indio_dev); - int ret, ret2; data->control &= ~TCS3414_CONTROL_ADC_EN; - ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL, + return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL, data->control); - - ret2 = iio_triggered_buffer_predisable(indio_dev); - if (!ret) - ret = ret2; - - return ret; } static const struct iio_buffer_setup_ops tcs3414_buffer_setup_ops = { @@ -294,7 +278,6 @@ static int tcs3414_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->info = &tcs3414_info; indio_dev->name = TCS3414_DRV_NAME; indio_dev->channels = tcs3414_channels; diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index 12ad344410103c502c86cdb64a709a2c02860d04..a0dc447aeb68b1c3e3d284e11bfce0767ca1938f 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -454,7 +454,6 @@ static int tcs3472_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &tcs3472_info; indio_dev->name = TCS3472_DRV_NAME; indio_dev->channels = tcs3472_channels; diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c index 27a5c28aac7f25ff0d0be7f6bc283471f67be2ee..abc8d7db8dc1dd534bad8168784b2308e35d4446 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -713,7 +713,7 @@ static int tsl2563_probe(struct i2c_client *client, chip = iio_priv(indio_dev); - i2c_set_clientdata(client, chip); + i2c_set_clientdata(client, indio_dev); chip->client = client; err = tsl2563_detect(chip); @@ -750,7 +750,6 @@ static int tsl2563_probe(struct i2c_client *client, indio_dev->name = client->name; indio_dev->channels = tsl2563_channels; indio_dev->num_channels = ARRAY_SIZE(tsl2563_channels); - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; if (client->irq) @@ -797,8 +796,8 @@ fail: static int tsl2563_remove(struct i2c_client *client) { - struct tsl2563_chip *chip = i2c_get_clientdata(client); - struct iio_dev *indio_dev = iio_priv_to_dev(chip); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct tsl2563_chip *chip = iio_priv(indio_dev); iio_device_unregister(indio_dev); if (!chip->int_enabled) @@ -816,7 +815,8 @@ static int tsl2563_remove(struct i2c_client *client) #ifdef CONFIG_PM_SLEEP static int tsl2563_suspend(struct device *dev) { - struct tsl2563_chip *chip = i2c_get_clientdata(to_i2c_client(dev)); + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct tsl2563_chip *chip = iio_priv(indio_dev); int ret; mutex_lock(&chip->lock); @@ -834,7 +834,8 @@ out: static int tsl2563_resume(struct device *dev) { - struct tsl2563_chip *chip = i2c_get_clientdata(to_i2c_client(dev)); + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct tsl2563_chip *chip = iio_priv(indio_dev); int ret; mutex_lock(&chip->lock); diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c index a760d14e146a8f963e78cc46482aae9130723cec..9e5490b7473bdcc40a07f823f41a58634a360866 100644 --- a/drivers/iio/light/tsl2583.c +++ b/drivers/iio/light/tsl2583.c @@ -840,7 +840,6 @@ static int tsl2583_probe(struct i2c_client *clientp, indio_dev->info = &tsl2583_info; indio_dev->channels = tsl2583_channels; indio_dev->num_channels = ARRAY_SIZE(tsl2583_channels); - indio_dev->dev.parent = &clientp->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = chip->client->name; diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index 9fbde9b71b63cdde71b79babdc306da1278ac20c..73539940541719a214e02db3efdc3c01e48b4b41 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -1833,7 +1833,6 @@ static int tsl2772_probe(struct i2c_client *clientp, &tsl2772_chip_info_tbl[device_channel_config[id->driver_data]]; indio_dev->info = chip->chip_info->info; - indio_dev->dev.parent = &clientp->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = chip->client->name; indio_dev->num_channels = chip->chip_info->chan_table_elements; diff --git a/drivers/iio/light/tsl4531.c b/drivers/iio/light/tsl4531.c index 0dfc664205c7ed90a694752db8f9458d77e618f3..70505ba6d8586380cb0286beab15b1e80fa2f232 100644 --- a/drivers/iio/light/tsl4531.c +++ b/drivers/iio/light/tsl4531.c @@ -192,7 +192,6 @@ static int tsl4531_probe(struct i2c_client *client, if (ret < 0) return ret; - indio_dev->dev.parent = &client->dev; indio_dev->info = &tsl4531_info; indio_dev->channels = tsl4531_channels; indio_dev->num_channels = ARRAY_SIZE(tsl4531_channels); diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c index b995f21a3347914e17c96f6fac7da0bac7a6412f..393f27b75c75ec1d82dd2232ed2763a69e26c37f 100644 --- a/drivers/iio/light/us5182d.c +++ b/drivers/iio/light/us5182d.c @@ -446,8 +446,8 @@ static int us5182d_read_raw(struct iio_dev *indio_dev, /** * us5182d_update_dark_th - update Darh_Th registers - * @data us5182d_data structure - * @index index in us5182d_dark_ths array to use for the updated value + * @data: us5182d_data structure + * @index: index in us5182d_dark_ths array to use for the updated value * * Function needs to be called with a lock held because it needs two i2c write * byte operations as these registers (0x27 0x28) don't work in word mode @@ -469,8 +469,8 @@ static int us5182d_update_dark_th(struct us5182d_data *data, int index) /** * us5182d_apply_scale - update the ALS scale - * @data us5182d_data structure - * @index index in us5182d_scales array to use for the updated value + * @data: us5182d_data structure + * @index: index in us5182d_scales array to use for the updated value * * Function needs to be called with a lock held as we're having more than one * i2c operation. @@ -851,7 +851,6 @@ static int us5182d_probe(struct i2c_client *client, mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &us5182d_info; indio_dev->name = US5182D_DRV_NAME; indio_dev->channels = us5182d_channels; diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 2a4b3d331055ea50e8f5de7eee1c06aa9135e79b..fff4b36b8b58dc04cc197b52a846d9737a95648a 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -957,50 +957,29 @@ static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev) int ret; int cmd; - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret) - return ret; - /* Do not enable the buffer if we are already capturing events. */ - if (vcnl4010_is_in_periodic_mode(data)) { - ret = -EBUSY; - goto end; - } + if (vcnl4010_is_in_periodic_mode(data)) + return -EBUSY; ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, VCNL4010_INT_PROX_EN); if (ret < 0) - goto end; + return ret; cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN; - ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd); - if (ret < 0) - goto end; - - return 0; -end: - iio_triggered_buffer_predisable(indio_dev); - - return ret; + return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd); } static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev) { struct vcnl4000_data *data = iio_priv(indio_dev); - int ret, ret_disable; + int ret; ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0); if (ret < 0) - goto end; - - ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0); - -end: - ret_disable = iio_triggered_buffer_predisable(indio_dev); - if (ret == 0) - ret = ret_disable; + return ret; - return ret; + return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0); } static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = { @@ -1058,7 +1037,6 @@ static int vcnl4000_probe(struct i2c_client *client, &data->near_level)) data->near_level = 0; - indio_dev->dev.parent = &client->dev; indio_dev->info = data->chip_spec->info; indio_dev->channels = data->chip_spec->channels; indio_dev->num_channels = data->chip_spec->num_channels; diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c index cca4db312bd3f92d41b59d47f744bcd8542d1da3..765c44adac574f78acbfc6fb56083f76d1055d21 100644 --- a/drivers/iio/light/vcnl4035.c +++ b/drivers/iio/light/vcnl4035.c @@ -564,7 +564,6 @@ static int vcnl4035_probe(struct i2c_client *client, data->client = client; data->regmap = regmap; - indio_dev->dev.parent = &client->dev; indio_dev->info = &vcnl4035_info; indio_dev->name = VCNL4035_DRV_NAME; indio_dev->channels = vcnl4035_channels; diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c index aa25b87fca8f7da3a0a68d2e6fc298ccc4a99e9e..de85c9b30be1e9258f3ae4f768768af8fa07cafc 100644 --- a/drivers/iio/light/veml6030.c +++ b/drivers/iio/light/veml6030.c @@ -814,7 +814,6 @@ static int veml6030_probe(struct i2c_client *client, data->client = client; data->regmap = regmap; - indio_dev->dev.parent = &client->dev; indio_dev->name = "veml6030"; indio_dev->channels = veml6030_channels; indio_dev->num_channels = ARRAY_SIZE(veml6030_channels); diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c index 0be553ad598945cacf1a3acb51aa94312ef47946..1e55e09a8d1658ae25d267674b11a8c683044f32 100644 --- a/drivers/iio/light/veml6070.c +++ b/drivers/iio/light/veml6070.c @@ -151,7 +151,6 @@ static int veml6070_probe(struct i2c_client *client, data->client1 = client; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &veml6070_info; indio_dev->channels = veml6070_channels; indio_dev->num_channels = ARRAY_SIZE(veml6070_channels); diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c index ed7b02765b9746e6f3ab4ce8c927872aa8144c07..4775bd785e5020237c30788b29936b33bdcf7a9e 100644 --- a/drivers/iio/light/vl6180.c +++ b/drivers/iio/light/vl6180.c @@ -509,7 +509,6 @@ static int vl6180_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &vl6180_info; indio_dev->channels = vl6180_channels; indio_dev->num_channels = ARRAY_SIZE(vl6180_channels); diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c index 80ae530720cdb6a29c202849f03d2db0189a1ef2..e0bc9df9c88b00106f36235a2d04f94017c9749c 100644 --- a/drivers/iio/light/zopt2201.c +++ b/drivers/iio/light/zopt2201.c @@ -527,7 +527,6 @@ static int zopt2201_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &zopt2201_info; indio_dev->channels = zopt2201_channels; indio_dev->num_channels = ARRAY_SIZE(zopt2201_channels); diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 91c39352fba26212b3b4b48fd33f94f2cf8ae974..6a8ae145f0c00050c8943bb30d1eea3f8545796d 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -180,6 +180,7 @@ * @drdy_irq: uses the DRDY IRQ line * @drdy_complete: completion for DRDY * @drdy_active_low: the DRDY IRQ is active low + * @scan: timestamps */ struct ak8974 { struct i2c_client *i2c; @@ -893,7 +894,6 @@ static int ak8974_probe(struct i2c_client *i2c, goto disable_pm; } - indio_dev->dev.parent = &i2c->dev; switch (ak8974->variant) { case AK8974_WHOAMI_VALUE_AMI306: case AK8974_WHOAMI_VALUE_AMI305: diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 3c881541ae72f0a2df69320ec9bb82116696511f..03d71f7961772879074b4c6cf355a1f144d77e28 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -358,6 +358,7 @@ struct ak8975_data { u8 asa[3]; long raw_to_gauss[3]; struct gpio_desc *eoc_gpiod; + struct gpio_desc *reset_gpiod; int eoc_irq; wait_queue_head_t data_ready_queue; unsigned long flags; @@ -384,10 +385,13 @@ static int ak8975_power_on(const struct ak8975_data *data) "Failed to enable specified Vid supply\n"); return ret; } + + gpiod_set_value_cansleep(data->reset_gpiod, 0); + /* - * According to the datasheet the power supply rise time i 200us + * According to the datasheet the power supply rise time is 200us * and the minimum wait time before mode setting is 100us, in - * total 300 us. Add some margin and say minimum 500us here. + * total 300us. Add some margin and say minimum 500us here. */ usleep_range(500, 1000); return 0; @@ -396,6 +400,8 @@ static int ak8975_power_on(const struct ak8975_data *data) /* Disable attached power regulator if any. */ static void ak8975_power_off(const struct ak8975_data *data) { + gpiod_set_value_cansleep(data->reset_gpiod, 1); + regulator_disable(data->vid); regulator_disable(data->vdd); } @@ -839,6 +845,7 @@ static int ak8975_probe(struct i2c_client *client, struct ak8975_data *data; struct iio_dev *indio_dev; struct gpio_desc *eoc_gpiod; + struct gpio_desc *reset_gpiod; const void *match; unsigned int i; int err; @@ -856,6 +863,16 @@ static int ak8975_probe(struct i2c_client *client, if (eoc_gpiod) gpiod_set_consumer_name(eoc_gpiod, "ak_8975"); + /* + * According to AK09911 datasheet, if reset GPIO is provided then + * deassert reset on ak8975_power_on() and assert reset on + * ak8975_power_off(). + */ + reset_gpiod = devm_gpiod_get_optional(&client->dev, + "reset", GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpiod)) + return PTR_ERR(reset_gpiod); + /* Register with IIO */ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (indio_dev == NULL) @@ -866,6 +883,7 @@ static int ak8975_probe(struct i2c_client *client, data->client = client; data->eoc_gpiod = eoc_gpiod; + data->reset_gpiod = reset_gpiod; data->eoc_irq = 0; err = iio_read_mount_matrix(&client->dev, "mount-matrix", &data->orientation); @@ -922,7 +940,6 @@ static int ak8975_probe(struct i2c_client *client, } mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->channels = ak8975_channels; indio_dev->num_channels = ARRAY_SIZE(ak8975_channels); indio_dev->info = &ak8975_info; diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index d4de16750b107cddc6231b2211b31122b26f00ea..fc6840f9c1fa6a23f5c680db339d574703a20403 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -836,8 +836,6 @@ static int bmc150_magn_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops bmc150_magn_buffer_setup_ops = { .preenable = bmc150_magn_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = bmc150_magn_buffer_postdisable, }; @@ -883,7 +881,6 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, if (ret < 0) return ret; - indio_dev->dev.parent = dev; indio_dev->channels = bmc150_magn_channels; indio_dev->num_channels = ARRAY_SIZE(bmc150_magn_channels); indio_dev->available_scan_masks = bmc150_magn_scan_masks; diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c index fb45b63c56e4d05f82aeec3b2fb7abb1880f1170..876e96005e33dc9aa42bee47fdd50138d6cd450a 100644 --- a/drivers/iio/magnetometer/bmc150_magn_i2c.c +++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c @@ -58,7 +58,8 @@ MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id); static const struct of_device_id bmc150_magn_of_match[] = { { .compatible = "bosch,bmc150_magn" }, { .compatible = "bosch,bmc156_magn" }, - { .compatible = "bosch,bmm150_magn" }, + { .compatible = "bosch,bmm150_magn" }, /* deprecated compatible */ + { .compatible = "bosch,bmm150" }, { } }; MODULE_DEVICE_TABLE(of, bmc150_magn_of_match); diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index 0c09daf87794a76033761d6d5e8bc8898d70ec78..97642ebd9168dde8bedf2c1a77880237d0b01216 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c @@ -512,7 +512,6 @@ static int hid_magn_3d_probe(struct platform_device *pdev) indio_dev->channels = channels; indio_dev->num_channels = chan_count; - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &magn_3d_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/magnetometer/hmc5843.h b/drivers/iio/magnetometer/hmc5843.h index b0dee87a8b20ec4524da63cf845a656281c7f9cd..3f6c0b6629415fa6794e53ac7dfb3bfa68ea9297 100644 --- a/drivers/iio/magnetometer/hmc5843.h +++ b/drivers/iio/magnetometer/hmc5843.h @@ -52,9 +52,9 @@ int hmc5843_common_suspend(struct device *dev); int hmc5843_common_resume(struct device *dev); #ifdef CONFIG_PM_SLEEP -static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops, - hmc5843_common_suspend, - hmc5843_common_resume); +static __maybe_unused SIMPLE_DEV_PM_OPS(hmc5843_pm_ops, + hmc5843_common_suspend, + hmc5843_common_resume); #define HMC5843_PM_OPS (&hmc5843_pm_ops) #else #define HMC5843_PM_OPS NULL diff --git a/drivers/iio/magnetometer/hmc5843_core.c b/drivers/iio/magnetometer/hmc5843_core.c index c44a4292da92456a0557c5bd5fbcff60c259c754..1474ba63babe61ee0d232414784995c9882a1b8f 100644 --- a/drivers/iio/magnetometer/hmc5843_core.c +++ b/drivers/iio/magnetometer/hmc5843_core.c @@ -642,7 +642,6 @@ int hmc5843_common_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &hmc5843_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index fb16cfdd6fa667552bb4330348335ae2f53f44a7..4d305a21c379a5260a390c2d96638aa623b201bc 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -519,7 +519,6 @@ static int mag3110_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); indio_dev->info = &mag3110_info; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mag3110_channels; indio_dev->num_channels = ARRAY_SIZE(mag3110_channels); diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index 1787d656d009462b0d35588294ce8322d306aa8f..65f3d1ed0d597fb1c16bb1289ebc1dbb185d1d22 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -301,7 +301,7 @@ static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3]) /** * mmc35240_raw_to_mgauss - convert raw readings to milli gauss. Also apply - compensation for output value. + * compensation for output value. * * @data: device private data * @index: axis index for which we want the conversion @@ -459,7 +459,7 @@ static bool mmc35240_is_volatile_reg(struct device *dev, unsigned int reg) } } -static struct reg_default mmc35240_reg_defaults[] = { +static const struct reg_default mmc35240_reg_defaults[] = { { MMC35240_REG_CTRL0, 0x00 }, { MMC35240_REG_CTRL1, 0x00 }, }; @@ -507,7 +507,6 @@ static int mmc35240_probe(struct i2c_client *client, mutex_init(&data->mutex); - indio_dev->dev.parent = &client->dev; indio_dev->info = &mmc35240_info; indio_dev->name = MMC35240_DRV_NAME; indio_dev->channels = mmc35240_channels; diff --git a/drivers/iio/magnetometer/rm3100-core.c b/drivers/iio/magnetometer/rm3100-core.c index 43a2e420c9c40dd735424b919e739a15369e26f5..7242897a05e956ee853ebb30a7c8c862bf72722e 100644 --- a/drivers/iio/magnetometer/rm3100-core.c +++ b/drivers/iio/magnetometer/rm3100-core.c @@ -463,8 +463,6 @@ static int rm3100_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops rm3100_buffer_ops = { .preenable = rm3100_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = rm3100_buffer_postdisable, }; @@ -549,7 +547,6 @@ int rm3100_common_probe(struct device *dev, struct regmap *regmap, int irq) mutex_init(&data->lock); - indio_dev->dev.parent = dev; indio_dev->name = "rm3100"; indio_dev->info = &rm3100_info; indio_dev->channels = rm3100_channels; diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c index bb425c167a9698f1aa931ef160bd8a3178f8142d..4917721fa2e5acf4be639d6caacd6c7b2a2dd8eb 100644 --- a/drivers/iio/magnetometer/st_magn_buffer.c +++ b/drivers/iio/magnetometer/st_magn_buffer.c @@ -31,34 +31,12 @@ int st_magn_trig_set_state(struct iio_trigger *trig, bool state) static int st_magn_buffer_postenable(struct iio_dev *indio_dev) { - int err; - - err = iio_triggered_buffer_postenable(indio_dev); - if (err < 0) - return err; - - err = st_sensors_set_enable(indio_dev, true); - if (err < 0) - goto st_magn_buffer_predisable; - - return 0; - -st_magn_buffer_predisable: - iio_triggered_buffer_predisable(indio_dev); - return err; + return st_sensors_set_enable(indio_dev, true); } static int st_magn_buffer_predisable(struct iio_dev *indio_dev) { - int err, err2; - - err = st_sensors_set_enable(indio_dev, false); - - err2 = iio_triggered_buffer_predisable(indio_dev); - if (!err) - err = err2; - - return err; + return st_sensors_set_enable(indio_dev, false); } static const struct iio_buffer_setup_ops st_magn_buffer_setup_ops = { diff --git a/drivers/iio/multiplexer/iio-mux.c b/drivers/iio/multiplexer/iio-mux.c index 0422ef57914cd0617a1bee41196da466deaff87b..6910218fdb0037b82488b5ed9ada013ff9697ebb 100644 --- a/drivers/iio/multiplexer/iio-mux.c +++ b/drivers/iio/multiplexer/iio-mux.c @@ -395,7 +395,6 @@ static int mux_probe(struct platform_device *pdev) mux->cached_state = -1; indio_dev->name = dev_name(dev); - indio_dev->dev.parent = dev; indio_dev->info = &mux_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mux->chan; diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c index 6aac8bea233add56b00f08e926841fdca1766a77..ae132a93bcae391954547132ba9d0f717e17e1ac 100644 --- a/drivers/iio/orientation/hid-sensor-incl-3d.c +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c @@ -339,7 +339,6 @@ static int hid_incl_3d_probe(struct platform_device *pdev) } indio_dev->num_channels = ARRAY_SIZE(incl_3d_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &incl_3d_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c index b99f41240e3ec5e363a1c13f869d735dff22cef2..23bc61a7f018cf2c03956c675eb3411a71f00ea5 100644 --- a/drivers/iio/orientation/hid-sensor-rotation.c +++ b/drivers/iio/orientation/hid-sensor-rotation.c @@ -281,7 +281,6 @@ static int hid_dev_rot_probe(struct platform_device *pdev) } indio_dev->num_channels = ARRAY_SIZE(dev_rot_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &dev_rot_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/position/iqs624-pos.c b/drivers/iio/position/iqs624-pos.c index 77096c31c2ba566105c1c735e943c6f11479717e..4d7452314209fedd2e41e52764c6d036535cbbb1 100644 --- a/drivers/iio/position/iqs624-pos.c +++ b/drivers/iio/position/iqs624-pos.c @@ -23,6 +23,7 @@ struct iqs624_pos_private { struct iqs62x_core *iqs62x; + struct iio_dev *indio_dev; struct notifier_block notifier; struct mutex lock; bool angle_en; @@ -59,7 +60,7 @@ static int iqs624_pos_notifier(struct notifier_block *notifier, iqs624_pos = container_of(notifier, struct iqs624_pos_private, notifier); - indio_dev = iio_priv_to_dev(iqs624_pos); + indio_dev = iqs624_pos->indio_dev; timestamp = iio_get_time_ns(indio_dev); iqs62x = iqs624_pos->iqs62x; @@ -98,7 +99,7 @@ static int iqs624_pos_notifier(struct notifier_block *notifier, static void iqs624_pos_notifier_unregister(void *context) { struct iqs624_pos_private *iqs624_pos = context; - struct iio_dev *indio_dev = iio_priv_to_dev(iqs624_pos); + struct iio_dev *indio_dev = iqs624_pos->indio_dev; int ret; ret = blocking_notifier_chain_unregister(&iqs624_pos->iqs62x->nh, @@ -243,9 +244,9 @@ static int iqs624_pos_probe(struct platform_device *pdev) iqs624_pos = iio_priv(indio_dev); iqs624_pos->iqs62x = iqs62x; + iqs624_pos->indio_dev = indio_dev; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->dev.parent = &pdev->dev; indio_dev->channels = iqs624_pos_channels; indio_dev->num_channels = ARRAY_SIZE(iqs624_pos_channels); indio_dev->name = iqs62x->dev_desc->dev_name; diff --git a/drivers/iio/potentiometer/ad5272.c b/drivers/iio/potentiometer/ad5272.c index 154f9a5da8bc29f84e7e2a3815b831bca12acc07..933afcf7e9251b2c3a5b7e56a8f03258bc205289 100644 --- a/drivers/iio/potentiometer/ad5272.c +++ b/drivers/iio/potentiometer/ad5272.c @@ -3,7 +3,7 @@ * Analog Devices AD5272 digital potentiometer driver * Copyright (C) 2018 Phil Reid * - * Datasheet: http://www.analog.com/media/en/technical-documentation/data-sheets/AD5272_5274.pdf + * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/AD5272_5274.pdf * * DEVID #Wipers #Positions Resistor Opts (kOhm) i2c address * ad5272 1 1024 20, 50, 100 01011xx @@ -184,7 +184,6 @@ static int ad5272_probe(struct i2c_client *client, if (ret < 0) return -ENODEV; - indio_dev->dev.parent = dev; indio_dev->info = &ad5272_info; indio_dev->channels = &ad5272_channel; indio_dev->num_channels = 1; diff --git a/drivers/iio/potentiometer/ds1803.c b/drivers/iio/potentiometer/ds1803.c index d0de78232a93d97a63671758965b138c73d06dc9..5c061ab8f46c01baa99656bd7776639395504dc9 100644 --- a/drivers/iio/potentiometer/ds1803.c +++ b/drivers/iio/potentiometer/ds1803.c @@ -126,7 +126,6 @@ static int ds1803_probe(struct i2c_client *client, data->client = client; data->cfg = &ds1803_cfg[id->driver_data]; - indio_dev->dev.parent = dev; indio_dev->info = &ds1803_info; indio_dev->channels = ds1803_channels; indio_dev->num_channels = ARRAY_SIZE(ds1803_channels); diff --git a/drivers/iio/potentiometer/max5432.c b/drivers/iio/potentiometer/max5432.c index 641b1821fdf67afa0a5ce392fac40d77f3a39fee..280de9c54471bcc1a68cba4a1a85ef3f3ecea838 100644 --- a/drivers/iio/potentiometer/max5432.c +++ b/drivers/iio/potentiometer/max5432.c @@ -102,7 +102,6 @@ static int max5432_probe(struct i2c_client *client, data->client = client; data->ohm = (unsigned long)of_device_get_match_data(dev); - indio_dev->dev.parent = dev; indio_dev->info = &max5432_info; indio_dev->channels = max5432_channels; indio_dev->num_channels = ARRAY_SIZE(max5432_channels); diff --git a/drivers/iio/potentiometer/max5481.c b/drivers/iio/potentiometer/max5481.c index 732375b6d1313ea2826bbdf4ac98e1ec088c2bb4..5f598818979667fcf3a39b0e0f7ddcfda8ea17b4 100644 --- a/drivers/iio/potentiometer/max5481.c +++ b/drivers/iio/potentiometer/max5481.c @@ -4,7 +4,7 @@ * Copyright 2016 Rockwell Collins * * Datasheet: - * http://datasheets.maximintegrated.com/en/ds/MAX5481-MAX5484.pdf + * https://datasheets.maximintegrated.com/en/ds/MAX5481-MAX5484.pdf */ #include @@ -149,7 +149,6 @@ static int max5481_probe(struct spi_device *spi) data->cfg = &max5481_cfg[id->driver_data]; indio_dev->name = id->name; - indio_dev->dev.parent = &spi->dev; indio_dev->modes = INDIO_DIRECT_MODE; /* variant specific configuration */ diff --git a/drivers/iio/potentiometer/max5487.c b/drivers/iio/potentiometer/max5487.c index 68ff806d46681bdcd9cad6570da758a0f75c2982..7ec51976ec9957c466315955cd327107d0b9b66e 100644 --- a/drivers/iio/potentiometer/max5487.c +++ b/drivers/iio/potentiometer/max5487.c @@ -100,7 +100,6 @@ static int max5487_spi_probe(struct spi_device *spi) indio_dev->info = &max5487_info; indio_dev->name = id->name; - indio_dev->dev.parent = &spi->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = max5487_channels; indio_dev->num_channels = ARRAY_SIZE(max5487_channels); diff --git a/drivers/iio/potentiometer/mcp4018.c b/drivers/iio/potentiometer/mcp4018.c index 62151b2a2b12db798155344995b7e9657fc25c9f..fd0579ad3c836a64d228d00695f59de172b1019d 100644 --- a/drivers/iio/potentiometer/mcp4018.c +++ b/drivers/iio/potentiometer/mcp4018.c @@ -165,7 +165,6 @@ static int mcp4018_probe(struct i2c_client *client) if (!data->cfg) data->cfg = &mcp4018_cfg[i2c_match_id(mcp4018_id, client)->driver_data]; - indio_dev->dev.parent = dev; indio_dev->info = &mcp4018_info; indio_dev->channels = &mcp4018_channel; indio_dev->num_channels = 1; diff --git a/drivers/iio/potentiometer/mcp41010.c b/drivers/iio/potentiometer/mcp41010.c index 2368b39debf5c37735ec73e3368b58cf89585ed1..79ccac6d4be0a4817e5729c3a3706c69f345faa0 100644 --- a/drivers/iio/potentiometer/mcp41010.c +++ b/drivers/iio/potentiometer/mcp41010.c @@ -5,7 +5,7 @@ * Copyright (c) 2018 Chris Coffey * Based on: Slawomir Stepien's code from mcp4131.c * - * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf + * Datasheet: https://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf * * DEVID #Wipers #Positions Resistance (kOhm) * mcp41010 1 256 10 @@ -152,7 +152,6 @@ static int mcp41010_probe(struct spi_device *spi) mutex_init(&data->lock); - indio_dev->dev.parent = dev; indio_dev->info = &mcp41010_info; indio_dev->channels = mcp41010_channels; indio_dev->num_channels = data->cfg->wipers; diff --git a/drivers/iio/potentiometer/mcp4131.c b/drivers/iio/potentiometer/mcp4131.c index 98df91e97f2f843d71ee2da37a561b9e7b1d2f2d..2923ce250fc36f89bce846179e0be1d0bba5aa83 100644 --- a/drivers/iio/potentiometer/mcp4131.c +++ b/drivers/iio/potentiometer/mcp4131.c @@ -5,7 +5,7 @@ * Copyright (c) 2016 Slawomir Stepien * Based on: Peter Rosin's code from mcp4531.c * - * Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf + * Datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf * * DEVID #Wipers #Positions Resistor Opts (kOhm) * mcp4131 1 129 5, 10, 50, 100 @@ -260,7 +260,6 @@ static int mcp4131_probe(struct spi_device *spi) mutex_init(&data->lock); - indio_dev->dev.parent = dev; indio_dev->info = &mcp4131_info; indio_dev->channels = mcp4131_channels; indio_dev->num_channels = data->cfg->wipers; diff --git a/drivers/iio/potentiometer/mcp4531.c b/drivers/iio/potentiometer/mcp4531.c index d71a22d71a308110d4ad178a0571ed0bf1b93331..95efc4b40514ab9153c9504c9056fe018e4a21e1 100644 --- a/drivers/iio/potentiometer/mcp4531.c +++ b/drivers/iio/potentiometer/mcp4531.c @@ -375,7 +375,6 @@ static int mcp4531_probe(struct i2c_client *client) if (!data->cfg) data->cfg = &mcp4531_cfg[i2c_match_id(mcp4531_id, client)->driver_data]; - indio_dev->dev.parent = dev; indio_dev->info = &mcp4531_info; indio_dev->channels = mcp4531_channels; indio_dev->num_channels = data->cfg->wipers; diff --git a/drivers/iio/potentiometer/tpl0102.c b/drivers/iio/potentiometer/tpl0102.c index a0a07e47f13f278b055ffcf8b1a0cc3a2bcf1f88..d996dc367fb77920646cb10ea173c1dfc6b25081 100644 --- a/drivers/iio/potentiometer/tpl0102.c +++ b/drivers/iio/potentiometer/tpl0102.c @@ -140,7 +140,6 @@ static int tpl0102_probe(struct i2c_client *client, return PTR_ERR(data->regmap); } - indio_dev->dev.parent = dev; indio_dev->info = &tpl0102_info; indio_dev->channels = tpl0102_channels; indio_dev->num_channels = data->cfg->wipers; diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c index 2cb11da18e0fda5c5965fcfa49ca4894a2e47b47..67ae635a05f3d29d52cc990d716d27b5ca832c19 100644 --- a/drivers/iio/potentiostat/lmp91000.c +++ b/drivers/iio/potentiostat/lmp91000.c @@ -278,17 +278,8 @@ static const struct iio_trigger_ops lmp91000_trigger_ops = { static int lmp91000_buffer_postenable(struct iio_dev *indio_dev) { struct lmp91000_data *data = iio_priv(indio_dev); - int err; - err = iio_triggered_buffer_postenable(indio_dev); - if (err) - return err; - - err = iio_channel_start_all_cb(data->cb_buffer); - if (err) - iio_triggered_buffer_predisable(indio_dev); - - return err; + return iio_channel_start_all_cb(data->cb_buffer); } static int lmp91000_buffer_predisable(struct iio_dev *indio_dev) @@ -297,7 +288,7 @@ static int lmp91000_buffer_predisable(struct iio_dev *indio_dev) iio_channel_stop_all_cb(data->cb_buffer); - return iio_triggered_buffer_predisable(indio_dev); + return 0; } static const struct iio_buffer_setup_ops lmp91000_buffer_setup_ops = { @@ -321,7 +312,6 @@ static int lmp91000_probe(struct i2c_client *client, indio_dev->channels = lmp91000_channels; indio_dev->num_channels = ARRAY_SIZE(lmp91000_channels); indio_dev->name = LMP91000_DRV_NAME; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; i2c_set_clientdata(client, indio_dev); diff --git a/drivers/iio/pressure/abp060mg.c b/drivers/iio/pressure/abp060mg.c index 267aad8af0a604c038ba2fd5b5318406d3c7290f..e1c3bdb371ee6e31574b13a2bcb6c925516a9377 100644 --- a/drivers/iio/pressure/abp060mg.c +++ b/drivers/iio/pressure/abp060mg.c @@ -194,7 +194,6 @@ static int abp060mg_probe(struct i2c_client *client, abp060mg_init_device(indio_dev, cfg_id); - indio_dev->dev.parent = &client->dev; indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &abp060mg_info; diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index 126a56d31b6e24ce25e4c681f9255d02334cc826..6b7da40f99c828b46102f95114418831e99083c0 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -1004,7 +1004,6 @@ int bmp280_common_probe(struct device *dev, mutex_init(&data->lock); data->dev = dev; - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->channels = bmp280_channels; indio_dev->info = &bmp280_info; diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c index c079b896008241e432cc9e70611a8d949722902b..f0938b6fbba075241dcd091a96b7acaf62f73186 100644 --- a/drivers/iio/pressure/cros_ec_baro.c +++ b/drivers/iio/pressure/cros_ec_baro.c @@ -96,8 +96,11 @@ static int cros_ec_baro_write(struct iio_dev *indio_dev, /* Always roundup, so caller gets at least what it asks for. */ st->core.param.sensor_range.roundup = 1; - if (cros_ec_motion_send_host_cmd(&st->core, 0)) - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret == 0) { + st->core.range_updated = true; + st->core.curr_range = val; + } break; default: ret = cros_ec_sensors_core_write(&st->core, chan, val, val2, @@ -199,6 +202,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_baro_ids); static struct platform_driver cros_ec_baro_platform_driver = { .driver = { .name = "cros-ec-baro", + .pm = &cros_ec_sensors_pm_ops, }, .probe = cros_ec_baro_probe, .id_table = cros_ec_baro_ids, diff --git a/drivers/iio/pressure/dlhl60d.c b/drivers/iio/pressure/dlhl60d.c index b8c99e7bd6cf342a9b4c7ece42b8e6573336b200..ade73267d5eb735506414196cc47ee0c7126f0ce 100644 --- a/drivers/iio/pressure/dlhl60d.c +++ b/drivers/iio/pressure/dlhl60d.c @@ -5,7 +5,7 @@ * Copyright (c) 2019 AVL DiTEST GmbH * Tomislav Denis * - * Datasheet: http://www.allsensors.com/cad/DS-0355_Rev_B.PDF + * Datasheet: https://www.allsensors.com/cad/DS-0355_Rev_B.PDF */ #include @@ -311,8 +311,6 @@ static int dlh_probe(struct i2c_client *client, st->use_interrupt = false; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->info = &dlh_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = dlh_channels; diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c index 2c1943bbc433868d4a07d6cee82a4e195639b31c..0730380ceb692e92d8d109972ff2ccfc097b4adf 100644 --- a/drivers/iio/pressure/dps310.c +++ b/drivers/iio/pressure/dps310.c @@ -732,7 +732,6 @@ static int dps310_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - iio->dev.parent = &client->dev; iio->name = id->name; iio->channels = dps310_channels; iio->num_channels = ARRAY_SIZE(dps310_channels); diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c index 5e6663f757ae7698860c37a0b1c55e062b7bd8a7..5c458788f346e72a47d56df9439b39b39ec7e161 100644 --- a/drivers/iio/pressure/hid-sensor-press.c +++ b/drivers/iio/pressure/hid-sensor-press.c @@ -283,7 +283,6 @@ static int hid_press_probe(struct platform_device *pdev) indio_dev->num_channels = ARRAY_SIZE(press_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &press_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/pressure/hp03.c b/drivers/iio/pressure/hp03.c index 026ba15ef68f3adb91a60a063fbe4d1efac190c8..e40b1d7dc129dc4c831cc7af02d0e67a956848f9 100644 --- a/drivers/iio/pressure/hp03.c +++ b/drivers/iio/pressure/hp03.c @@ -224,7 +224,6 @@ static int hp03_probe(struct i2c_client *client, priv->client = client; mutex_init(&priv->lock); - indio_dev->dev.parent = dev; indio_dev->name = id->name; indio_dev->channels = hp03_channels; indio_dev->num_channels = ARRAY_SIZE(hp03_channels); diff --git a/drivers/iio/pressure/hp206c.c b/drivers/iio/pressure/hp206c.c index 1f931f5b7a65061283dc54b57f7bcdf70de29f6c..986b7a59712e01906d3d22e27be7893fd496299e 100644 --- a/drivers/iio/pressure/hp206c.c +++ b/drivers/iio/pressure/hp206c.c @@ -378,7 +378,6 @@ static int hp206c_probe(struct i2c_client *client, indio_dev->info = &hp206c_info; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = hp206c_channels; indio_dev->num_channels = ARRAY_SIZE(hp206c_channels); diff --git a/drivers/iio/pressure/icp10100.c b/drivers/iio/pressure/icp10100.c index 06cb5b63a189a9d5f8c350e4f91e0ac5c5224d9c..90c0df068bbb5ae2d7eeafc140d0b2f76081d2e5 100644 --- a/drivers/iio/pressure/icp10100.c +++ b/drivers/iio/pressure/icp10100.c @@ -545,7 +545,6 @@ static int icp10100_probe(struct i2c_client *client, return -ENOMEM; i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; indio_dev->name = client->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = icp10100_channels; diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c index ca81a3dc564666c381db5f320a141b5c1b6890f8..81f288312a28ded53b3ee5cca0534854df83fdfc 100644 --- a/drivers/iio/pressure/mpl115.c +++ b/drivers/iio/pressure/mpl115.c @@ -160,7 +160,6 @@ int mpl115_probe(struct device *dev, const char *name, indio_dev->info = &mpl115_info; indio_dev->name = name; - indio_dev->dev.parent = dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mpl115_channels; indio_dev->num_channels = ARRAY_SIZE(mpl115_channels); diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c index d066f3c5a8a6113fc573766ecff185db1e280697..ccdb0b70e48caf70857124d1ca0aad53805da727 100644 --- a/drivers/iio/pressure/mpl3115.c +++ b/drivers/iio/pressure/mpl3115.c @@ -241,7 +241,6 @@ static int mpl3115_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); indio_dev->info = &mpl3115_info; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mpl3115_channels; indio_dev->num_channels = ARRAY_SIZE(mpl3115_channels); diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index f5db9fa086f3a192d5a46520d1db32e5a48fa9ba..214b0d25f59804ba499a679482e69e6ab3c91ce4 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -440,7 +440,6 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, st->pressure_osr = &ms5611_avail_pressure_osr[ARRAY_SIZE(ms5611_avail_pressure_osr) - 1]; - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &ms5611_info; indio_dev->channels = ms5611_channels; diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c index f49c7003c72a22def3c03ae3299febccca4e6d07..05e0ef7260d5dfcbbb4cbd1f18599347769333b0 100644 --- a/drivers/iio/pressure/ms5637.c +++ b/drivers/iio/pressure/ms5637.c @@ -152,7 +152,6 @@ static int ms5637_probe(struct i2c_client *client, indio_dev->info = &ms5637_info; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ms5637_channels; indio_dev->num_channels = ARRAY_SIZE(ms5637_channels); diff --git a/drivers/iio/pressure/st_pressure_buffer.c b/drivers/iio/pressure/st_pressure_buffer.c index 418dbf9e6e1e350b20fa9be1ac4a3170ec56da3f..7cf6f06797e1e7d2a192dd44b5a207f904250f24 100644 --- a/drivers/iio/pressure/st_pressure_buffer.c +++ b/drivers/iio/pressure/st_pressure_buffer.c @@ -31,34 +31,12 @@ int st_press_trig_set_state(struct iio_trigger *trig, bool state) static int st_press_buffer_postenable(struct iio_dev *indio_dev) { - int err; - - err = iio_triggered_buffer_postenable(indio_dev); - if (err < 0) - return err; - - err = st_sensors_set_enable(indio_dev, true); - if (err < 0) - goto st_press_buffer_predisable; - - return 0; - -st_press_buffer_predisable: - iio_triggered_buffer_predisable(indio_dev); - return err; + return st_sensors_set_enable(indio_dev, true); } static int st_press_buffer_predisable(struct iio_dev *indio_dev) { - int err, err2; - - err = st_sensors_set_enable(indio_dev, false); - - err2 = iio_triggered_buffer_predisable(indio_dev); - if (!err) - err = err2; - - return err; + return st_sensors_set_enable(indio_dev, false); } static const struct iio_buffer_setup_ops st_press_buffer_setup_ops = { diff --git a/drivers/iio/pressure/t5403.c b/drivers/iio/pressure/t5403.c index 22abd28071b75a8b206cd50de6a1acbf28b0a7d7..685fcf65334fcdeea0f6c8d6001ab229617c47e9 100644 --- a/drivers/iio/pressure/t5403.c +++ b/drivers/iio/pressure/t5403.c @@ -236,7 +236,6 @@ static int t5403_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); indio_dev->info = &t5403_info; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = t5403_channels; indio_dev->num_channels = ARRAY_SIZE(t5403_channels); diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c index 799a8dc3e248d2f2cb96957ce3c0152992d8ee04..2cecbe0adb3f382be11c90b1f3615824f9f28527 100644 --- a/drivers/iio/pressure/zpa2326.c +++ b/drivers/iio/pressure/zpa2326.c @@ -1244,19 +1244,17 @@ static int zpa2326_postenable_buffer(struct iio_dev *indio_dev) const struct zpa2326_private *priv = iio_priv(indio_dev); int err; - /* Plug our own trigger event handler. */ - err = iio_triggered_buffer_postenable(indio_dev); - if (err) - goto err; - if (!priv->waken) { /* * We were already power supplied. Just clear hardware FIFO to * get rid of samples acquired during previous rounds (if any). */ err = zpa2326_clear_fifo(indio_dev, 0); - if (err) - goto err_buffer_predisable; + if (err) { + zpa2326_err(indio_dev, + "failed to enable buffering (%d)", err); + return err; + } } if (!iio_trigger_using_own(indio_dev) && priv->waken) { @@ -1265,18 +1263,14 @@ static int zpa2326_postenable_buffer(struct iio_dev *indio_dev) * powered up: reconfigure one-shot mode. */ err = zpa2326_config_oneshot(indio_dev, priv->irq); - if (err) - goto err_buffer_predisable; + if (err) { + zpa2326_err(indio_dev, + "failed to enable buffering (%d)", err); + return err; + } } return 0; - -err_buffer_predisable: - iio_triggered_buffer_predisable(indio_dev); -err: - zpa2326_err(indio_dev, "failed to enable buffering (%d)", err); - - return err; } static int zpa2326_postdisable_buffer(struct iio_dev *indio_dev) @@ -1289,7 +1283,6 @@ static int zpa2326_postdisable_buffer(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops zpa2326_buffer_setup_ops = { .preenable = zpa2326_preenable_buffer, .postenable = zpa2326_postenable_buffer, - .predisable = iio_triggered_buffer_predisable, .postdisable = zpa2326_postdisable_buffer }; @@ -1603,7 +1596,6 @@ static struct iio_dev *zpa2326_create_managed_iiodev(struct device *device, /* Setup for userspace synchronous on demand sampling. */ indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->dev.parent = device; indio_dev->channels = zpa2326_channels; indio_dev->num_channels = ARRAY_SIZE(zpa2326_channels); indio_dev->name = name; diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index bac9a433dd19a78002185c3fb70981d75c256253..c339e7339ec896ea23277ba9465a336d86ffa1bb 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -399,7 +399,6 @@ static int as3935_probe(struct spi_device *spi) return -EINVAL; } - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = as3935_channels; indio_dev->num_channels = ARRAY_SIZE(as3935_channels); diff --git a/drivers/iio/proximity/isl29501.c b/drivers/iio/proximity/isl29501.c index 5ae549075b27c50d512cbf5ef75b9630c87ef9c3..90e76451c972a8c7cba0ccd0d369ba15d90f0620 100644 --- a/drivers/iio/proximity/isl29501.c +++ b/drivers/iio/proximity/isl29501.c @@ -972,7 +972,6 @@ static int isl29501_probe(struct i2c_client *client, return ret; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->dev.parent = &client->dev; indio_dev->channels = isl29501_channels; indio_dev->num_channels = ARRAY_SIZE(isl29501_channels); indio_dev->name = client->name; diff --git a/drivers/iio/proximity/mb1232.c b/drivers/iio/proximity/mb1232.c index 166b3e6d7db896fcd7de4e539a2985f57664cc4c..654564c452489cbe62b6f6f1eacac10452896916 100644 --- a/drivers/iio/proximity/mb1232.c +++ b/drivers/iio/proximity/mb1232.c @@ -200,7 +200,6 @@ static int mb1232_probe(struct i2c_client *client, indio_dev->info = &mb1232_info; indio_dev->name = id->name; - indio_dev->dev.parent = dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mb1232_channels; indio_dev->num_channels = ARRAY_SIZE(mb1232_channels); diff --git a/drivers/iio/proximity/ping.c b/drivers/iio/proximity/ping.c index 2e99eeb27f2eb85ed89565d70f8cb18834981d28..1283ac1c2e03c47aef699483636597e6942f54c6 100644 --- a/drivers/iio/proximity/ping.c +++ b/drivers/iio/proximity/ping.c @@ -309,7 +309,6 @@ static int ping_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); indio_dev->name = "ping"; - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &ping_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ping_chan_spec; diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index 5b369645ef49cf7c9964bca567bc4a1966214bce..a8e716dbd24e506ff86da05f860ec8381d6ca243 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -270,7 +270,6 @@ static int lidar_probe(struct i2c_client *client, indio_dev->name = LIDAR_DRV_NAME; indio_dev->channels = lidar_channels; indio_dev->num_channels = ARRAY_SIZE(lidar_channels); - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; i2c_set_clientdata(client, indio_dev); diff --git a/drivers/iio/proximity/rfd77402.c b/drivers/iio/proximity/rfd77402.c index 36480c0100a783c1100624630e5ee7e11045c567..7a0472323f176cb11051b8458e7210e0709ff438 100644 --- a/drivers/iio/proximity/rfd77402.c +++ b/drivers/iio/proximity/rfd77402.c @@ -274,7 +274,6 @@ static int rfd77402_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &rfd77402_info; indio_dev->channels = rfd77402_channels; indio_dev->num_channels = ARRAY_SIZE(rfd77402_channels); diff --git a/drivers/iio/proximity/srf04.c b/drivers/iio/proximity/srf04.c index 568b76e063859a9f892a3b5754f3c419bcc048b7..420c37c72de4b586bd41f26ccf280b90f27aa075 100644 --- a/drivers/iio/proximity/srf04.c +++ b/drivers/iio/proximity/srf04.c @@ -5,7 +5,7 @@ * Copyright (c) 2017 Andreas Klinger * * For details about the device see: - * http://www.robot-electronics.co.uk/htm/srf04tech.htm + * https://www.robot-electronics.co.uk/htm/srf04tech.htm * * the measurement cycle as timing diagram looks like: * @@ -317,7 +317,6 @@ static int srf04_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); indio_dev->name = "srf04"; - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &srf04_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = srf04_chan_spec; diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c index b23ce446b7be6ad899a5bf18abfc272d9a993040..70beac5c9c1dfc72ae8a3c9aacc044cb10f0b7eb 100644 --- a/drivers/iio/proximity/srf08.c +++ b/drivers/iio/proximity/srf08.c @@ -7,9 +7,9 @@ * Copyright (c) 2016, 2017 Andreas Klinger * * For details about the device see: - * http://www.robot-electronics.co.uk/htm/srf08tech.html - * http://www.robot-electronics.co.uk/htm/srf10tech.htm - * http://www.robot-electronics.co.uk/htm/srf02tech.htm + * https://www.robot-electronics.co.uk/htm/srf08tech.html + * https://www.robot-electronics.co.uk/htm/srf10tech.htm + * https://www.robot-electronics.co.uk/htm/srf02tech.htm */ #include @@ -483,7 +483,6 @@ static int srf08_probe(struct i2c_client *client, } indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = srf08_channels; indio_dev->num_channels = ARRAY_SIZE(srf08_channels); diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index d161f3061e353d74e3d1343b78965624a1a8eb4c..dc2e11b43431dea3f6c0fa94a1178b581cef66f2 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -736,8 +736,6 @@ static int sx9310_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops sx9310_buffer_setup_ops = { .preenable = sx9310_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = sx9310_buffer_postdisable, }; @@ -931,7 +929,6 @@ static int sx9310_probe(struct i2c_client *client, return ret; ACPI_COMPANION_SET(&indio_dev->dev, ACPI_COMPANION(&client->dev)); - indio_dev->dev.parent = &client->dev; indio_dev->channels = sx9310_channels; indio_dev->num_channels = ARRAY_SIZE(sx9310_channels); indio_dev->info = &sx9310_info; diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 287d288e40c27b107e838762c4fd17a519c0c7cb..acb821cbad46ffdcee84ccf73249c0b8d81a7b06 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -680,10 +680,6 @@ static int sx9500_buffer_postenable(struct iio_dev *indio_dev) struct sx9500_data *data = iio_priv(indio_dev); int ret = 0, i; - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret) - return ret; - mutex_lock(&data->mutex); for (i = 0; i < SX9500_NUM_CHANNELS; i++) @@ -700,9 +696,6 @@ static int sx9500_buffer_postenable(struct iio_dev *indio_dev) mutex_unlock(&data->mutex); - if (ret) - iio_triggered_buffer_predisable(indio_dev); - return ret; } @@ -727,8 +720,6 @@ static int sx9500_buffer_predisable(struct iio_dev *indio_dev) mutex_unlock(&data->mutex); - iio_triggered_buffer_predisable(indio_dev); - return ret; } @@ -931,7 +922,6 @@ static int sx9500_probe(struct i2c_client *client, if (IS_ERR(data->regmap)) return PTR_ERR(data->regmap); - indio_dev->dev.parent = &client->dev; indio_dev->name = SX9500_DRIVER_NAME; indio_dev->channels = sx9500_channels; indio_dev->num_channels = ARRAY_SIZE(sx9500_channels); diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c index 9ff1a164c2e665cf448bee8c082c69b11df116d5..37264f801ad023cb96b6020d79a93d4ac5023873 100644 --- a/drivers/iio/proximity/vcnl3020.c +++ b/drivers/iio/proximity/vcnl3020.c @@ -226,7 +226,6 @@ static int vcnl3020_probe(struct i2c_client *client) if (rc) return rc; - indio_dev->dev.parent = &client->dev; indio_dev->info = &vcnl3020_info; indio_dev->channels = vcnl3020_channels; indio_dev->num_channels = ARRAY_SIZE(vcnl3020_channels); diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c index b48216cc18589a5a6937d8e544b6683a4d54a4a0..5fbda9475ba90f0a5299127dc50a010cde0803b1 100644 --- a/drivers/iio/proximity/vl53l0x-i2c.c +++ b/drivers/iio/proximity/vl53l0x-i2c.c @@ -134,7 +134,6 @@ static int vl53l0x_probe(struct i2c_client *client) I2C_FUNC_SMBUS_BYTE_DATA)) return -EOPNOTSUPP; - indio_dev->dev.parent = &client->dev; indio_dev->name = "vl53l0x"; indio_dev->info = &vl53l0x_info; indio_dev->channels = vl53l0x_channels; diff --git a/drivers/iio/resolver/ad2s1200.c b/drivers/iio/resolver/ad2s1200.c index a391f46ee06b7fd67f85b17a08702da1e92a69cf..6007abad116bc7844ca75cb680f657640561b677 100644 --- a/drivers/iio/resolver/ad2s1200.c +++ b/drivers/iio/resolver/ad2s1200.c @@ -157,7 +157,6 @@ static int ad2s1200_probe(struct spi_device *spi) return PTR_ERR(st->rdvel); } - indio_dev->dev.parent = &spi->dev; indio_dev->info = &ad2s1200_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ad2s1200_channels; diff --git a/drivers/iio/resolver/ad2s90.c b/drivers/iio/resolver/ad2s90.c index a41f5cb10da5094650223fe6e01afd26da95e6a4..d6a91f137e134b0214b55222f5962e857537d19b 100644 --- a/drivers/iio/resolver/ad2s90.c +++ b/drivers/iio/resolver/ad2s90.c @@ -94,7 +94,6 @@ static int ad2s90_probe(struct spi_device *spi) mutex_init(&st->lock); st->sdev = spi; - indio_dev->dev.parent = &spi->dev; indio_dev->info = &ad2s90_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = &ad2s90_chan; diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c index 8d1f434f109db6b1368691df6ea72c60bf2ae472..81688f1b932f1085c5540dca9f5800e13b7aebc2 100644 --- a/drivers/iio/temperature/hid-sensor-temperature.c +++ b/drivers/iio/temperature/hid-sensor-temperature.c @@ -223,7 +223,6 @@ static int hid_temperature_probe(struct platform_device *pdev) indio_dev->channels = temp_chans; indio_dev->num_channels = ARRAY_SIZE(temperature_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &temperature_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/temperature/iqs620at-temp.c b/drivers/iio/temperature/iqs620at-temp.c index 3fd52b3eb03045bb3f1f582c725da2e9ceb2b0e6..fe126e1fb7833abdd1ccf570723da73650af8525 100644 --- a/drivers/iio/temperature/iqs620at-temp.c +++ b/drivers/iio/temperature/iqs620at-temp.c @@ -74,7 +74,6 @@ static int iqs620_temp_probe(struct platform_device *pdev) iio_device_set_drvdata(indio_dev, iqs62x); indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->dev.parent = &pdev->dev; indio_dev->channels = iqs620_temp_channels; indio_dev->num_channels = ARRAY_SIZE(iqs620_temp_channels); indio_dev->name = iqs62x->dev_desc->dev_name; diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c index 8976e8d598262ce49b6670ce1ed8e1f2c71e1f9c..55ff28a0f1c748f2c0194dfd61d005cc2d549f6c 100644 --- a/drivers/iio/temperature/ltc2983.c +++ b/drivers/iio/temperature/ltc2983.c @@ -1500,7 +1500,6 @@ static int ltc2983_probe(struct spi_device *spi) if (ret) return ret; - indio_dev->dev.parent = &spi->dev; indio_dev->name = name; indio_dev->num_channels = st->iio_channels; indio_dev->channels = st->iio_chan; diff --git a/drivers/iio/temperature/max31856.c b/drivers/iio/temperature/max31856.c index b4c49a5d36853f0f56981795824fa8a7314a5c1b..1954322e43be5540ea39c0972f95fdc656e2ab50 100644 --- a/drivers/iio/temperature/max31856.c +++ b/drivers/iio/temperature/max31856.c @@ -417,8 +417,6 @@ static int max31856_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); indio_dev->info = &max31856_info; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = id->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = max31856_channels; diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c index 8d21116c7a2249118fea818e76cd96b80cb1cf64..0297e215b61a8e2c9cb2efbc4f0247a1bd275685 100644 --- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -244,7 +244,6 @@ static int maxim_thermocouple_probe(struct spi_device *spi) indio_dev->available_scan_masks = chip->scan_masks; indio_dev->num_channels = chip->num_channels; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->dev.parent = &spi->dev; data = iio_priv(indio_dev); data->spi = spi; diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c index b7c56ddf884fdd8043625f2b11545d93063495f4..ef0fec94d2695c4e3910163dcd644c4384397fea 100644 --- a/drivers/iio/temperature/mlx90614.c +++ b/drivers/iio/temperature/mlx90614.c @@ -525,7 +525,6 @@ static int mlx90614_probe(struct i2c_client *client, mlx90614_wakeup(data); - indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &mlx90614_info; diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c index eaca6ba06864695c6d75eedea53d4518d43af154..51b812bcff2eac513a609dcc1b5d00e33c2ab68c 100644 --- a/drivers/iio/temperature/mlx90632.c +++ b/drivers/iio/temperature/mlx90632.c @@ -164,8 +164,8 @@ static s32 mlx90632_pwr_continuous(struct regmap *regmap) } /** - * mlx90632_perform_measurement - Trigger and retrieve current measurement cycle - * @*data: pointer to mlx90632_data object containing regmap information + * mlx90632_perform_measurement() - Trigger and retrieve current measurement cycle + * @data: pointer to mlx90632_data object containing regmap information * * Perform a measurement and return latest measurement cycle position reported * by sensor. This is a blocking function for 500ms, as that is default sensor @@ -645,7 +645,6 @@ static int mlx90632_probe(struct i2c_client *client, mlx90632->regmap = regmap; mutex_init(&mlx90632->lock); - indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &mlx90632_info; diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c index cc45d8345eb94a10fe7f4d0894ee844fde30a168..54976c7dad92e93a8dd365c4fccfe1a1f6edf695 100644 --- a/drivers/iio/temperature/tmp006.c +++ b/drivers/iio/temperature/tmp006.c @@ -216,7 +216,6 @@ static int tmp006_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &tmp006_info; diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c index 7df234d96f9409a3c9cb76caa208053f360f3fae..f90fe9e5617b07795d1a93ca032259b063f86a62 100644 --- a/drivers/iio/temperature/tmp007.c +++ b/drivers/iio/temperature/tmp007.c @@ -463,7 +463,6 @@ static int tmp007_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->name = "tmp007"; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &tmp007_info; diff --git a/drivers/iio/temperature/tsys01.c b/drivers/iio/temperature/tsys01.c index d41f050c2fea0483e3a3975e1c664b1d4a2b2f8c..2c631a1ca33b146b2276a6e5edf0253b220ea8f0 100644 --- a/drivers/iio/temperature/tsys01.c +++ b/drivers/iio/temperature/tsys01.c @@ -160,7 +160,6 @@ static int tsys01_probe(struct iio_dev *indio_dev, struct device *dev) indio_dev->info = &tsys01_info; indio_dev->name = dev->driver->name; - indio_dev->dev.parent = dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = tsys01_channels; indio_dev->num_channels = ARRAY_SIZE(tsys01_channels); diff --git a/drivers/iio/temperature/tsys02d.c b/drivers/iio/temperature/tsys02d.c index 6735af400b2260e94609cb42c2c6fff5db78d8bc..fc96e5f9d3fc51eb7b1162702c0ee21e523f2f3e 100644 --- a/drivers/iio/temperature/tsys02d.c +++ b/drivers/iio/temperature/tsys02d.c @@ -149,7 +149,6 @@ static int tsys02d_probe(struct i2c_client *client, indio_dev->info = &tsys02d_info; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = tsys02d_channels; indio_dev->num_channels = ARRAY_SIZE(tsys02d_channels); diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index 7d8962d6566a1621158e6af37c4a9f2a1cabdfed..3aa9e8bba005fb00732ed65791fc45db49477b23 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -723,12 +723,10 @@ static struct stm32_timer_trigger *stm32_setup_counter_device(struct device *dev return NULL; indio_dev->name = dev_name(dev); - indio_dev->dev.parent = dev; indio_dev->info = &stm32_trigger_info; indio_dev->modes = INDIO_HARDWARE_TRIGGERED; indio_dev->num_channels = 1; indio_dev->channels = &stm32_trigger_channel; - indio_dev->dev.of_node = dev->of_node; ret = devm_iio_device_register(dev, indio_dev); if (ret) diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig index a83f9eb86bfee58f5ced096ebad5db9b9f856554..91b023341b779c06b38c06e6bf86b80733edc304 100644 --- a/drivers/infiniband/Kconfig +++ b/drivers/infiniband/Kconfig @@ -37,14 +37,6 @@ config INFINIBAND_USER_ACCESS libibverbs, libibcm and a hardware driver library from rdma-core . -config INFINIBAND_EXP_LEGACY_VERBS_NEW_UAPI - bool "Allow experimental legacy verbs in new ioctl uAPI (EXPERIMENTAL)" - depends on INFINIBAND_USER_ACCESS - help - IOCTL based uAPI support for Infiniband is enabled by default for - new verbs only. This allows userspace to invoke the IOCTL based uAPI - for current legacy verbs too. - config INFINIBAND_USER_MEM bool depends on INFINIBAND_USER_ACCESS != n diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index a670209bbce6064135b499d567095f64caf47e01..ffad73bb40ff1dba53f65555c5e1fb1f3647a2c1 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -1054,7 +1054,7 @@ int ib_get_cached_pkey(struct ib_device *device, cache = device->port_data[port_num].cache.pkey; - if (index < 0 || index >= cache->table_len) + if (!cache || index < 0 || index >= cache->table_len) ret = -EINVAL; else *pkey = cache->table[index]; @@ -1099,6 +1099,10 @@ int ib_find_cached_pkey(struct ib_device *device, read_lock_irqsave(&device->cache_lock, flags); cache = device->port_data[port_num].cache.pkey; + if (!cache) { + ret = -EINVAL; + goto err; + } *index = -1; @@ -1117,6 +1121,7 @@ int ib_find_cached_pkey(struct ib_device *device, ret = 0; } +err: read_unlock_irqrestore(&device->cache_lock, flags); return ret; @@ -1139,6 +1144,10 @@ int ib_find_exact_cached_pkey(struct ib_device *device, read_lock_irqsave(&device->cache_lock, flags); cache = device->port_data[port_num].cache.pkey; + if (!cache) { + ret = -EINVAL; + goto err; + } *index = -1; @@ -1149,6 +1158,7 @@ int ib_find_exact_cached_pkey(struct ib_device *device, break; } +err: read_unlock_irqrestore(&device->cache_lock, flags); return ret; @@ -1425,23 +1435,26 @@ ib_cache_update(struct ib_device *device, u8 port, bool enforce_security) goto err; } - pkey_cache = kmalloc(struct_size(pkey_cache, table, - tprops->pkey_tbl_len), - GFP_KERNEL); - if (!pkey_cache) { - ret = -ENOMEM; - goto err; - } + if (tprops->pkey_tbl_len) { + pkey_cache = kmalloc(struct_size(pkey_cache, table, + tprops->pkey_tbl_len), + GFP_KERNEL); + if (!pkey_cache) { + ret = -ENOMEM; + goto err; + } - pkey_cache->table_len = tprops->pkey_tbl_len; + pkey_cache->table_len = tprops->pkey_tbl_len; - for (i = 0; i < pkey_cache->table_len; ++i) { - ret = ib_query_pkey(device, port, i, pkey_cache->table + i); - if (ret) { - dev_warn(&device->dev, - "ib_query_pkey failed (%d) for index %d\n", - ret, i); - goto err; + for (i = 0; i < pkey_cache->table_len; ++i) { + ret = ib_query_pkey(device, port, i, + pkey_cache->table + i); + if (ret) { + dev_warn(&device->dev, + "ib_query_pkey failed (%d) for index %d\n", + ret, i); + goto err; + } } } diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index c30cf5307ce3ecef73a6d978018af9ea31cab739..26de0dab60bbba00e7896d1d8261213baa1af843 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -428,19 +428,6 @@ static int cma_comp_exch(struct rdma_id_private *id_priv, return ret; } -static enum rdma_cm_state cma_exch(struct rdma_id_private *id_priv, - enum rdma_cm_state exch) -{ - unsigned long flags; - enum rdma_cm_state old; - - spin_lock_irqsave(&id_priv->lock, flags); - old = id_priv->state; - id_priv->state = exch; - spin_unlock_irqrestore(&id_priv->lock, flags); - return old; -} - static inline u8 cma_get_ip_ver(const struct cma_hdr *hdr) { return hdr->ip_version >> 4; @@ -1829,23 +1816,11 @@ static void cma_leave_mc_groups(struct rdma_id_private *id_priv) } } -void rdma_destroy_id(struct rdma_cm_id *id) +static void _destroy_id(struct rdma_id_private *id_priv, + enum rdma_cm_state state) { - struct rdma_id_private *id_priv; - enum rdma_cm_state state; - - id_priv = container_of(id, struct rdma_id_private, id); - trace_cm_id_destroy(id_priv); - state = cma_exch(id_priv, RDMA_CM_DESTROYING); cma_cancel_operation(id_priv, state); - /* - * Wait for any active callback to finish. New callbacks will find - * the id_priv state set to destroying and abort. - */ - mutex_lock(&id_priv->handler_mutex); - mutex_unlock(&id_priv->handler_mutex); - rdma_restrack_del(&id_priv->res); if (id_priv->cma_dev) { if (rdma_cap_ib_cm(id_priv->id.device, 1)) { @@ -1874,6 +1849,42 @@ void rdma_destroy_id(struct rdma_cm_id *id) put_net(id_priv->id.route.addr.dev_addr.net); kfree(id_priv); } + +/* + * destroy an ID from within the handler_mutex. This ensures that no other + * handlers can start running concurrently. + */ +static void destroy_id_handler_unlock(struct rdma_id_private *id_priv) + __releases(&idprv->handler_mutex) +{ + enum rdma_cm_state state; + unsigned long flags; + + trace_cm_id_destroy(id_priv); + + /* + * Setting the state to destroyed under the handler mutex provides a + * fence against calling handler callbacks. If this is invoked due to + * the failure of a handler callback then it guarentees that no future + * handlers will be called. + */ + lockdep_assert_held(&id_priv->handler_mutex); + spin_lock_irqsave(&id_priv->lock, flags); + state = id_priv->state; + id_priv->state = RDMA_CM_DESTROYING; + spin_unlock_irqrestore(&id_priv->lock, flags); + mutex_unlock(&id_priv->handler_mutex); + _destroy_id(id_priv, state); +} + +void rdma_destroy_id(struct rdma_cm_id *id) +{ + struct rdma_id_private *id_priv = + container_of(id, struct rdma_id_private, id); + + mutex_lock(&id_priv->handler_mutex); + destroy_id_handler_unlock(id_priv); +} EXPORT_SYMBOL(rdma_destroy_id); static int cma_rep_recv(struct rdma_id_private *id_priv) @@ -1925,6 +1936,8 @@ static int cma_cm_event_handler(struct rdma_id_private *id_priv, { int ret; + lockdep_assert_held(&id_priv->handler_mutex); + trace_cm_event_handler(id_priv, event); ret = id_priv->id.event_handler(&id_priv->id, event); trace_cm_event_done(id_priv, event, ret); @@ -1936,7 +1949,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, { struct rdma_id_private *id_priv = cm_id->context; struct rdma_cm_event event = {}; - int ret = 0; + int ret; mutex_lock(&id_priv->handler_mutex); if ((ib_event->event != IB_CM_TIMEWAIT_EXIT && @@ -2005,14 +2018,12 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, if (ret) { /* Destroy the CM ID by returning a non-zero value. */ id_priv->cm_id.ib = NULL; - cma_exch(id_priv, RDMA_CM_DESTROYING); - mutex_unlock(&id_priv->handler_mutex); - rdma_destroy_id(&id_priv->id); + destroy_id_handler_unlock(id_priv); return ret; } out: mutex_unlock(&id_priv->handler_mutex); - return ret; + return 0; } static struct rdma_id_private * @@ -2174,7 +2185,7 @@ static int cma_ib_req_handler(struct ib_cm_id *cm_id, mutex_lock(&listen_id->handler_mutex); if (listen_id->state != RDMA_CM_LISTEN) { ret = -ECONNABORTED; - goto err1; + goto err_unlock; } offset = cma_user_data_offset(listen_id); @@ -2191,55 +2202,38 @@ static int cma_ib_req_handler(struct ib_cm_id *cm_id, } if (!conn_id) { ret = -ENOMEM; - goto err1; + goto err_unlock; } mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING); ret = cma_ib_acquire_dev(conn_id, listen_id, &req); - if (ret) - goto err2; + if (ret) { + destroy_id_handler_unlock(conn_id); + goto err_unlock; + } conn_id->cm_id.ib = cm_id; cm_id->context = conn_id; cm_id->cm_handler = cma_ib_handler; - /* - * Protect against the user destroying conn_id from another thread - * until we're done accessing it. - */ - cma_id_get(conn_id); ret = cma_cm_event_handler(conn_id, &event); - if (ret) - goto err3; - /* - * Acquire mutex to prevent user executing rdma_destroy_id() - * while we're accessing the cm_id. - */ - mutex_lock(&lock); + if (ret) { + /* Destroy the CM ID by returning a non-zero value. */ + conn_id->cm_id.ib = NULL; + mutex_unlock(&listen_id->handler_mutex); + destroy_id_handler_unlock(conn_id); + goto net_dev_put; + } + if (cma_comp(conn_id, RDMA_CM_CONNECT) && (conn_id->id.qp_type != IB_QPT_UD)) { trace_cm_send_mra(cm_id->context); ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0); } - mutex_unlock(&lock); mutex_unlock(&conn_id->handler_mutex); - mutex_unlock(&listen_id->handler_mutex); - cma_id_put(conn_id); - if (net_dev) - dev_put(net_dev); - return 0; -err3: - cma_id_put(conn_id); - /* Destroy the CM ID by returning a non-zero value. */ - conn_id->cm_id.ib = NULL; -err2: - cma_exch(conn_id, RDMA_CM_DESTROYING); - mutex_unlock(&conn_id->handler_mutex); -err1: +err_unlock: mutex_unlock(&listen_id->handler_mutex); - if (conn_id) - rdma_destroy_id(&conn_id->id); net_dev_put: if (net_dev) @@ -2339,9 +2333,7 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) if (ret) { /* Destroy the CM ID by returning a non-zero value. */ id_priv->cm_id.iw = NULL; - cma_exch(id_priv, RDMA_CM_DESTROYING); - mutex_unlock(&id_priv->handler_mutex); - rdma_destroy_id(&id_priv->id); + destroy_id_handler_unlock(id_priv); return ret; } @@ -2388,16 +2380,16 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, ret = rdma_translate_ip(laddr, &conn_id->id.route.addr.dev_addr); if (ret) { - mutex_unlock(&conn_id->handler_mutex); - rdma_destroy_id(new_cm_id); - goto out; + mutex_unlock(&listen_id->handler_mutex); + destroy_id_handler_unlock(conn_id); + return ret; } ret = cma_iw_acquire_dev(conn_id, listen_id); if (ret) { - mutex_unlock(&conn_id->handler_mutex); - rdma_destroy_id(new_cm_id); - goto out; + mutex_unlock(&listen_id->handler_mutex); + destroy_id_handler_unlock(conn_id); + return ret; } conn_id->cm_id.iw = cm_id; @@ -2407,25 +2399,16 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, memcpy(cma_src_addr(conn_id), laddr, rdma_addr_size(laddr)); memcpy(cma_dst_addr(conn_id), raddr, rdma_addr_size(raddr)); - /* - * Protect against the user destroying conn_id from another thread - * until we're done accessing it. - */ - cma_id_get(conn_id); ret = cma_cm_event_handler(conn_id, &event); if (ret) { /* User wants to destroy the CM ID */ conn_id->cm_id.iw = NULL; - cma_exch(conn_id, RDMA_CM_DESTROYING); - mutex_unlock(&conn_id->handler_mutex); mutex_unlock(&listen_id->handler_mutex); - cma_id_put(conn_id); - rdma_destroy_id(&conn_id->id); + destroy_id_handler_unlock(conn_id); return ret; } mutex_unlock(&conn_id->handler_mutex); - cma_id_put(conn_id); out: mutex_unlock(&listen_id->handler_mutex); @@ -2482,6 +2465,10 @@ static int cma_listen_handler(struct rdma_cm_id *id, { struct rdma_id_private *id_priv = id->context; + /* Listening IDs are always destroyed on removal */ + if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL) + return -1; + id->context = id_priv->id.context; id->event_handler = id_priv->id.event_handler; trace_cm_event_handler(id_priv, event); @@ -2657,21 +2644,21 @@ static void cma_work_handler(struct work_struct *_work) { struct cma_work *work = container_of(_work, struct cma_work, work); struct rdma_id_private *id_priv = work->id; - int destroy = 0; mutex_lock(&id_priv->handler_mutex); if (!cma_comp_exch(id_priv, work->old_state, work->new_state)) - goto out; + goto out_unlock; if (cma_cm_event_handler(id_priv, &work->event)) { - cma_exch(id_priv, RDMA_CM_DESTROYING); - destroy = 1; + cma_id_put(id_priv); + destroy_id_handler_unlock(id_priv); + goto out_free; } -out: + +out_unlock: mutex_unlock(&id_priv->handler_mutex); cma_id_put(id_priv); - if (destroy) - rdma_destroy_id(&id_priv->id); +out_free: kfree(work); } @@ -2679,23 +2666,22 @@ static void cma_ndev_work_handler(struct work_struct *_work) { struct cma_ndev_work *work = container_of(_work, struct cma_ndev_work, work); struct rdma_id_private *id_priv = work->id; - int destroy = 0; mutex_lock(&id_priv->handler_mutex); if (id_priv->state == RDMA_CM_DESTROYING || id_priv->state == RDMA_CM_DEVICE_REMOVAL) - goto out; + goto out_unlock; if (cma_cm_event_handler(id_priv, &work->event)) { - cma_exch(id_priv, RDMA_CM_DESTROYING); - destroy = 1; + cma_id_put(id_priv); + destroy_id_handler_unlock(id_priv); + goto out_free; } -out: +out_unlock: mutex_unlock(&id_priv->handler_mutex); cma_id_put(id_priv); - if (destroy) - rdma_destroy_id(&id_priv->id); +out_free: kfree(work); } @@ -3171,9 +3157,7 @@ static void addr_handler(int status, struct sockaddr *src_addr, event.event = RDMA_CM_EVENT_ADDR_RESOLVED; if (cma_cm_event_handler(id_priv, &event)) { - cma_exch(id_priv, RDMA_CM_DESTROYING); - mutex_unlock(&id_priv->handler_mutex); - rdma_destroy_id(&id_priv->id); + destroy_id_handler_unlock(id_priv); return; } out: @@ -3790,7 +3774,7 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, struct rdma_cm_event event = {}; const struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd; - int ret = 0; + int ret; mutex_lock(&id_priv->handler_mutex); if (id_priv->state != RDMA_CM_CONNECT) @@ -3840,14 +3824,12 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, if (ret) { /* Destroy the CM ID by returning a non-zero value. */ id_priv->cm_id.ib = NULL; - cma_exch(id_priv, RDMA_CM_DESTROYING); - mutex_unlock(&id_priv->handler_mutex); - rdma_destroy_id(&id_priv->id); + destroy_id_handler_unlock(id_priv); return ret; } out: mutex_unlock(&id_priv->handler_mutex); - return ret; + return 0; } static int cma_resolve_ib_udp(struct rdma_id_private *id_priv, @@ -4372,9 +4354,7 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast) rdma_destroy_ah_attr(&event.param.ud.ah_attr); if (ret) { - cma_exch(id_priv, RDMA_CM_DESTROYING); - mutex_unlock(&id_priv->handler_mutex); - rdma_destroy_id(&id_priv->id); + destroy_id_handler_unlock(id_priv); return 0; } @@ -4789,50 +4769,59 @@ free_cma_dev: return ret; } -static int cma_remove_id_dev(struct rdma_id_private *id_priv) +static void cma_send_device_removal_put(struct rdma_id_private *id_priv) { - struct rdma_cm_event event = {}; + struct rdma_cm_event event = { .event = RDMA_CM_EVENT_DEVICE_REMOVAL }; enum rdma_cm_state state; - int ret = 0; - - /* Record that we want to remove the device */ - state = cma_exch(id_priv, RDMA_CM_DEVICE_REMOVAL); - if (state == RDMA_CM_DESTROYING) - return 0; + unsigned long flags; - cma_cancel_operation(id_priv, state); mutex_lock(&id_priv->handler_mutex); + /* Record that we want to remove the device */ + spin_lock_irqsave(&id_priv->lock, flags); + state = id_priv->state; + if (state == RDMA_CM_DESTROYING || state == RDMA_CM_DEVICE_REMOVAL) { + spin_unlock_irqrestore(&id_priv->lock, flags); + mutex_unlock(&id_priv->handler_mutex); + cma_id_put(id_priv); + return; + } + id_priv->state = RDMA_CM_DEVICE_REMOVAL; + spin_unlock_irqrestore(&id_priv->lock, flags); - /* Check for destruction from another callback. */ - if (!cma_comp(id_priv, RDMA_CM_DEVICE_REMOVAL)) - goto out; - - event.event = RDMA_CM_EVENT_DEVICE_REMOVAL; - ret = cma_cm_event_handler(id_priv, &event); -out: + if (cma_cm_event_handler(id_priv, &event)) { + /* + * At this point the ULP promises it won't call + * rdma_destroy_id() concurrently + */ + cma_id_put(id_priv); + mutex_unlock(&id_priv->handler_mutex); + trace_cm_id_destroy(id_priv); + _destroy_id(id_priv, state); + return; + } mutex_unlock(&id_priv->handler_mutex); - return ret; + + /* + * If this races with destroy then the thread that first assigns state + * to a destroying does the cancel. + */ + cma_cancel_operation(id_priv, state); + cma_id_put(id_priv); } static void cma_process_remove(struct cma_device *cma_dev) { - struct rdma_id_private *id_priv; - int ret; - mutex_lock(&lock); while (!list_empty(&cma_dev->id_list)) { - id_priv = list_entry(cma_dev->id_list.next, - struct rdma_id_private, list); + struct rdma_id_private *id_priv = list_first_entry( + &cma_dev->id_list, struct rdma_id_private, list); list_del(&id_priv->listen_list); list_del_init(&id_priv->list); cma_id_get(id_priv); mutex_unlock(&lock); - ret = id_priv->internal_id ? 1 : cma_remove_id_dev(id_priv); - cma_id_put(id_priv); - if (ret) - rdma_destroy_id(&id_priv->id); + cma_send_device_removal_put(id_priv); mutex_lock(&lock); } diff --git a/drivers/infiniband/core/counters.c b/drivers/infiniband/core/counters.c index 738d1faf4bba52f61917fbfd2b5a2bd66096316b..63616688044285bda23b1e4e55cd005a326c5c96 100644 --- a/drivers/infiniband/core/counters.c +++ b/drivers/infiniband/core/counters.c @@ -8,7 +8,7 @@ #include "core_priv.h" #include "restrack.h" -#define ALL_AUTO_MODE_MASKS (RDMA_COUNTER_MASK_QP_TYPE) +#define ALL_AUTO_MODE_MASKS (RDMA_COUNTER_MASK_QP_TYPE | RDMA_COUNTER_MASK_PID) static int __counter_set_mode(struct rdma_counter_mode *curr, enum rdma_nl_counter_mode new_mode, @@ -149,23 +149,13 @@ static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter, struct auto_mode_param *param = &counter->mode.param; bool match = true; - /* - * Ensure that counter belongs to the right PID. This operation can - * race with user space which kills the process and leaves QP and - * counters orphans. - * - * It is not a big deal because exitted task will leave both QP and - * counter in the same bucket of zombie process. Just ensure that - * process is still alive before procedding. - * - */ - if (task_pid_nr(counter->res.task) != task_pid_nr(qp->res.task) || - !task_pid_nr(qp->res.task)) - return false; - if (auto_mask & RDMA_COUNTER_MASK_QP_TYPE) match &= (param->qp_type == qp->qp_type); + if (auto_mask & RDMA_COUNTER_MASK_PID) + match &= (task_pid_nr(counter->res.task) == + task_pid_nr(qp->res.task)); + return match; } @@ -288,7 +278,7 @@ int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port) struct rdma_counter *counter; int ret; - if (!qp->res.valid) + if (!qp->res.valid || rdma_is_kernel_res(&qp->res)) return 0; if (!rdma_is_port_valid(dev, port)) @@ -483,7 +473,7 @@ int rdma_counter_bind_qpn(struct ib_device *dev, u8 port, goto err; } - if (counter->res.task != qp->res.task) { + if (rdma_is_kernel_res(&counter->res) != rdma_is_kernel_res(&qp->res)) { ret = -EINVAL; goto err_task; } diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 2927a9d16eaa696d2c5c791d6c3e354a22d4eb23..ef0cd2998671922f064207e9a95335a2eb160177 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -272,7 +272,6 @@ static void ib_device_check_mandatory(struct ib_device *device) } mandatory_table[] = { IB_MANDATORY_FUNC(query_device), IB_MANDATORY_FUNC(query_port), - IB_MANDATORY_FUNC(query_pkey), IB_MANDATORY_FUNC(alloc_pd), IB_MANDATORY_FUNC(dealloc_pd), IB_MANDATORY_FUNC(create_qp), @@ -1343,6 +1342,10 @@ out: return ret; } +static void prevent_dealloc_device(struct ib_device *ib_dev) +{ +} + /** * ib_register_device - Register an IB device with IB core * @device: Device to register @@ -1413,11 +1416,11 @@ int ib_register_device(struct ib_device *device, const char *name) * possibility for a parallel unregistration along with this * error flow. Since we have a refcount here we know any * parallel flow is stopped in disable_device and will see the - * NULL pointers, causing the responsibility to + * special dealloc_driver pointer, causing the responsibility to * ib_dealloc_device() to revert back to this thread. */ dealloc_fn = device->ops.dealloc_driver; - device->ops.dealloc_driver = NULL; + device->ops.dealloc_driver = prevent_dealloc_device; ib_device_put(device); __ib_unregister_device(device); device->ops.dealloc_driver = dealloc_fn; @@ -1466,7 +1469,8 @@ static void __ib_unregister_device(struct ib_device *ib_dev) * Drivers using the new flow may not call ib_dealloc_device except * in error unwind prior to registration success. */ - if (ib_dev->ops.dealloc_driver) { + if (ib_dev->ops.dealloc_driver && + ib_dev->ops.dealloc_driver != prevent_dealloc_device) { WARN_ON(kref_read(&ib_dev->dev.kobj.kref) <= 1); ib_dealloc_device(ib_dev); } @@ -2361,6 +2365,9 @@ int ib_query_pkey(struct ib_device *device, if (!rdma_is_port_valid(device, port_num)) return -EINVAL; + if (!device->ops.query_pkey) + return -EOPNOTSUPP; + return device->ops.query_pkey(device, port_num, index, pkey); } EXPORT_SYMBOL(ib_query_pkey); @@ -2621,8 +2628,14 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops) SET_DEVICE_OP(dev_ops, drain_rq); SET_DEVICE_OP(dev_ops, drain_sq); SET_DEVICE_OP(dev_ops, enable_driver); - SET_DEVICE_OP(dev_ops, fill_res_entry); - SET_DEVICE_OP(dev_ops, fill_stat_entry); + SET_DEVICE_OP(dev_ops, fill_res_cm_id_entry); + SET_DEVICE_OP(dev_ops, fill_res_cq_entry); + SET_DEVICE_OP(dev_ops, fill_res_cq_entry_raw); + SET_DEVICE_OP(dev_ops, fill_res_mr_entry); + SET_DEVICE_OP(dev_ops, fill_res_mr_entry_raw); + SET_DEVICE_OP(dev_ops, fill_res_qp_entry); + SET_DEVICE_OP(dev_ops, fill_res_qp_entry_raw); + SET_DEVICE_OP(dev_ops, fill_stat_mr_entry); SET_DEVICE_OP(dev_ops, get_dev_fw_str); SET_DEVICE_OP(dev_ops, get_dma_mr); SET_DEVICE_OP(dev_ops, get_hw_stats); @@ -2667,6 +2680,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops) SET_DEVICE_OP(dev_ops, query_port); SET_DEVICE_OP(dev_ops, query_qp); SET_DEVICE_OP(dev_ops, query_srq); + SET_DEVICE_OP(dev_ops, query_ucontext); SET_DEVICE_OP(dev_ops, rdma_netdev_get_params); SET_DEVICE_OP(dev_ops, read_counters); SET_DEVICE_OP(dev_ops, reg_dm_mr); @@ -2679,10 +2693,12 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops) SET_DEVICE_OP(dev_ops, set_vf_link_state); SET_OBJ_SIZE(dev_ops, ib_ah); + SET_OBJ_SIZE(dev_ops, ib_counters); SET_OBJ_SIZE(dev_ops, ib_cq); SET_OBJ_SIZE(dev_ops, ib_pd); SET_OBJ_SIZE(dev_ops, ib_srq); SET_OBJ_SIZE(dev_ops, ib_ucontext); + SET_OBJ_SIZE(dev_ops, ib_xrcd); } EXPORT_SYMBOL(ib_set_device_ops); diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index a09f8e3c7f3f3aa1348552452d76a1c09e896ceb..9355e521d9f4d7fdf40108bc9d1b50cd67b6c894 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -402,7 +402,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, INIT_DELAYED_WORK(&mad_agent_priv->timed_work, timeout_sends); INIT_LIST_HEAD(&mad_agent_priv->local_list); INIT_WORK(&mad_agent_priv->local_work, local_completions); - atomic_set(&mad_agent_priv->refcount, 1); + refcount_set(&mad_agent_priv->refcount, 1); init_completion(&mad_agent_priv->comp); ret2 = ib_mad_agent_security_setup(&mad_agent_priv->agent, qp_type); @@ -484,7 +484,7 @@ EXPORT_SYMBOL(ib_register_mad_agent); static inline void deref_mad_agent(struct ib_mad_agent_private *mad_agent_priv) { - if (atomic_dec_and_test(&mad_agent_priv->refcount)) + if (refcount_dec_and_test(&mad_agent_priv->refcount)) complete(&mad_agent_priv->comp); } @@ -718,7 +718,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, * Reference MAD agent until receive * side of local completion handled */ - atomic_inc(&mad_agent_priv->refcount); + refcount_inc(&mad_agent_priv->refcount); } else kfree(mad_priv); break; @@ -758,7 +758,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, local->return_wc_byte_len = mad_size; } /* Reference MAD agent until send side of local completion handled */ - atomic_inc(&mad_agent_priv->refcount); + refcount_inc(&mad_agent_priv->refcount); /* Queue local completion to local list */ spin_lock_irqsave(&mad_agent_priv->lock, flags); list_add_tail(&local->completion_list, &mad_agent_priv->local_list); @@ -916,7 +916,7 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, } mad_send_wr->send_buf.mad_agent = mad_agent; - atomic_inc(&mad_agent_priv->refcount); + refcount_inc(&mad_agent_priv->refcount); return &mad_send_wr->send_buf; } EXPORT_SYMBOL(ib_create_send_mad); @@ -1131,7 +1131,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf, mad_send_wr->status = IB_WC_SUCCESS; /* Reference MAD agent until send completes */ - atomic_inc(&mad_agent_priv->refcount); + refcount_inc(&mad_agent_priv->refcount); spin_lock_irqsave(&mad_agent_priv->lock, flags); list_add_tail(&mad_send_wr->agent_list, &mad_agent_priv->send_list); @@ -1148,7 +1148,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf, spin_lock_irqsave(&mad_agent_priv->lock, flags); list_del(&mad_send_wr->agent_list); spin_unlock_irqrestore(&mad_agent_priv->lock, flags); - atomic_dec(&mad_agent_priv->refcount); + deref_mad_agent(mad_agent_priv); goto error; } } @@ -1554,7 +1554,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv, hi_tid = be64_to_cpu(mad_hdr->tid) >> 32; rcu_read_lock(); mad_agent = xa_load(&ib_mad_clients, hi_tid); - if (mad_agent && !atomic_inc_not_zero(&mad_agent->refcount)) + if (mad_agent && !refcount_inc_not_zero(&mad_agent->refcount)) mad_agent = NULL; rcu_read_unlock(); } else { @@ -1606,7 +1606,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv, } } if (mad_agent) - atomic_inc(&mad_agent->refcount); + refcount_inc(&mad_agent->refcount); out: spin_unlock_irqrestore(&port_priv->reg_lock, flags); } @@ -1831,7 +1831,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, mad_agent_priv->agent.recv_handler( &mad_agent_priv->agent, NULL, mad_recv_wc); - atomic_dec(&mad_agent_priv->refcount); + deref_mad_agent(mad_agent_priv); } else { /* not user rmpp, revert to normal behavior and * drop the mad */ @@ -1848,7 +1848,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, &mad_agent_priv->agent, &mad_send_wr->send_buf, mad_recv_wc); - atomic_dec(&mad_agent_priv->refcount); + deref_mad_agent(mad_agent_priv); mad_send_wc.status = IB_WC_SUCCESS; mad_send_wc.vendor_err = 0; @@ -2438,7 +2438,7 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv) list_del(&mad_send_wr->agent_list); mad_agent_priv->agent.send_handler(&mad_agent_priv->agent, &mad_send_wc); - atomic_dec(&mad_agent_priv->refcount); + deref_mad_agent(mad_agent_priv); } } @@ -2572,7 +2572,7 @@ static void local_completions(struct work_struct *work) &local->mad_send_wr->send_buf, &local->mad_priv->header.recv_wc); spin_lock_irqsave(&recv_mad_agent->lock, flags); - atomic_dec(&recv_mad_agent->refcount); + deref_mad_agent(recv_mad_agent); spin_unlock_irqrestore(&recv_mad_agent->lock, flags); } @@ -2585,7 +2585,7 @@ local_send_completion: &mad_send_wc); spin_lock_irqsave(&mad_agent_priv->lock, flags); - atomic_dec(&mad_agent_priv->refcount); + deref_mad_agent(mad_agent_priv); if (free_mad) kfree(local->mad_priv); kfree(local); @@ -2671,7 +2671,7 @@ static void timeout_sends(struct work_struct *work) mad_agent_priv->agent.send_handler(&mad_agent_priv->agent, &mad_send_wc); - atomic_dec(&mad_agent_priv->refcount); + deref_mad_agent(mad_agent_priv); spin_lock_irqsave(&mad_agent_priv->lock, flags); } spin_unlock_irqrestore(&mad_agent_priv->lock, flags); diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index 403d8673a2f9eab555d339f137a05bddf3b31a06..4aa16b35dad07f513828627fb604e813a3e56b7f 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h @@ -103,7 +103,7 @@ struct ib_mad_agent_private { struct work_struct local_work; struct list_head rmpp_list; - atomic_t refcount; + refcount_t refcount; union { struct completion comp; struct rcu_head rcu; diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index 5ec57abc0849159a9e4adce96bc549e3018f629d..e0573e4d04040875c0a011b8368563d5c64c2c3b 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -40,8 +40,7 @@ enum rmpp_state { RMPP_STATE_ACTIVE, RMPP_STATE_TIMEOUT, - RMPP_STATE_COMPLETE, - RMPP_STATE_CANCELING + RMPP_STATE_COMPLETE }; struct mad_rmpp_recv { @@ -52,7 +51,7 @@ struct mad_rmpp_recv { struct completion comp; enum rmpp_state state; spinlock_t lock; - atomic_t refcount; + refcount_t refcount; struct ib_ah *ah; struct ib_mad_recv_wc *rmpp_wc; @@ -73,7 +72,7 @@ struct mad_rmpp_recv { static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv) { - if (atomic_dec_and_test(&rmpp_recv->refcount)) + if (refcount_dec_and_test(&rmpp_recv->refcount)) complete(&rmpp_recv->comp); } @@ -91,23 +90,19 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent) unsigned long flags; spin_lock_irqsave(&agent->lock, flags); - list_for_each_entry(rmpp_recv, &agent->rmpp_list, list) { - if (rmpp_recv->state != RMPP_STATE_COMPLETE) - ib_free_recv_mad(rmpp_recv->rmpp_wc); - rmpp_recv->state = RMPP_STATE_CANCELING; - } - spin_unlock_irqrestore(&agent->lock, flags); - list_for_each_entry(rmpp_recv, &agent->rmpp_list, list) { cancel_delayed_work(&rmpp_recv->timeout_work); cancel_delayed_work(&rmpp_recv->cleanup_work); } + spin_unlock_irqrestore(&agent->lock, flags); flush_workqueue(agent->qp_info->port_priv->wq); list_for_each_entry_safe(rmpp_recv, temp_rmpp_recv, &agent->rmpp_list, list) { list_del(&rmpp_recv->list); + if (rmpp_recv->state != RMPP_STATE_COMPLETE) + ib_free_recv_mad(rmpp_recv->rmpp_wc); destroy_rmpp_recv(rmpp_recv); } } @@ -272,10 +267,6 @@ static void recv_cleanup_handler(struct work_struct *work) unsigned long flags; spin_lock_irqsave(&rmpp_recv->agent->lock, flags); - if (rmpp_recv->state == RMPP_STATE_CANCELING) { - spin_unlock_irqrestore(&rmpp_recv->agent->lock, flags); - return; - } list_del(&rmpp_recv->list); spin_unlock_irqrestore(&rmpp_recv->agent->lock, flags); destroy_rmpp_recv(rmpp_recv); @@ -305,7 +296,7 @@ create_rmpp_recv(struct ib_mad_agent_private *agent, INIT_DELAYED_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler); spin_lock_init(&rmpp_recv->lock); rmpp_recv->state = RMPP_STATE_ACTIVE; - atomic_set(&rmpp_recv->refcount, 1); + refcount_set(&rmpp_recv->refcount, 1); rmpp_recv->rmpp_wc = mad_recv_wc; rmpp_recv->cur_seg_buf = &mad_recv_wc->recv_buf; @@ -357,7 +348,7 @@ acquire_rmpp_recv(struct ib_mad_agent_private *agent, spin_lock_irqsave(&agent->lock, flags); rmpp_recv = find_rmpp_recv(agent, mad_recv_wc); if (rmpp_recv) - atomic_inc(&rmpp_recv->refcount); + refcount_inc(&rmpp_recv->refcount); spin_unlock_irqrestore(&agent->lock, flags); return rmpp_recv; } @@ -553,7 +544,7 @@ start_rmpp(struct ib_mad_agent_private *agent, destroy_rmpp_recv(rmpp_recv); return continue_rmpp(agent, mad_recv_wc); } - atomic_inc(&rmpp_recv->refcount); + refcount_inc(&rmpp_recv->refcount); if (get_last_flag(&mad_recv_wc->recv_buf)) { rmpp_recv->state = RMPP_STATE_COMPLETE; diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c index e16105be2eb238934655aa186693317e54b1375c..12d29d54a0812da5a778532ef0f1128f4ee10203 100644 --- a/drivers/infiniband/core/nldev.c +++ b/drivers/infiniband/core/nldev.c @@ -114,6 +114,7 @@ static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = { [RDMA_NLDEV_ATTR_RES_PS] = { .type = NLA_U32 }, [RDMA_NLDEV_ATTR_RES_QP] = { .type = NLA_NESTED }, [RDMA_NLDEV_ATTR_RES_QP_ENTRY] = { .type = NLA_NESTED }, + [RDMA_NLDEV_ATTR_RES_RAW] = { .type = NLA_BINARY }, [RDMA_NLDEV_ATTR_RES_RKEY] = { .type = NLA_U32 }, [RDMA_NLDEV_ATTR_RES_RQPN] = { .type = NLA_U32 }, [RDMA_NLDEV_ATTR_RES_RQ_PSN] = { .type = NLA_U32 }, @@ -446,27 +447,11 @@ static int fill_res_name_pid(struct sk_buff *msg, return err ? -EMSGSIZE : 0; } -static bool fill_res_entry(struct ib_device *dev, struct sk_buff *msg, - struct rdma_restrack_entry *res) +static int fill_res_qp_entry_query(struct sk_buff *msg, + struct rdma_restrack_entry *res, + struct ib_device *dev, + struct ib_qp *qp) { - if (!dev->ops.fill_res_entry) - return false; - return dev->ops.fill_res_entry(msg, res); -} - -static bool fill_stat_entry(struct ib_device *dev, struct sk_buff *msg, - struct rdma_restrack_entry *res) -{ - if (!dev->ops.fill_stat_entry) - return false; - return dev->ops.fill_stat_entry(msg, res); -} - -static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin, - struct rdma_restrack_entry *res, uint32_t port) -{ - struct ib_qp *qp = container_of(res, struct ib_qp, res); - struct ib_device *dev = qp->device; struct ib_qp_init_attr qp_init_attr; struct ib_qp_attr qp_attr; int ret; @@ -475,16 +460,6 @@ static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin, if (ret) return ret; - if (port && port != qp_attr.port_num) - return -EAGAIN; - - /* In create_qp() port is not set yet */ - if (qp_attr.port_num && - nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, qp_attr.port_num)) - goto err; - - if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qp->qp_num)) - goto err; if (qp->qp_type == IB_QPT_RC || qp->qp_type == IB_QPT_UC) { if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_RQPN, qp_attr.dest_qp_num)) @@ -508,19 +483,53 @@ static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin, if (nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_STATE, qp_attr.qp_state)) goto err; + if (dev->ops.fill_res_qp_entry) + return dev->ops.fill_res_qp_entry(msg, qp); + return 0; + +err: return -EMSGSIZE; +} + +static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin, + struct rdma_restrack_entry *res, uint32_t port) +{ + struct ib_qp *qp = container_of(res, struct ib_qp, res); + struct ib_device *dev = qp->device; + int ret; + + if (port && port != qp->port) + return -EAGAIN; + + /* In create_qp() port is not set yet */ + if (qp->port && nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, qp->port)) + return -EINVAL; + + ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qp->qp_num); + if (ret) + return -EMSGSIZE; + if (!rdma_is_kernel_res(res) && nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, qp->pd->res.id)) - goto err; + return -EMSGSIZE; - if (fill_res_name_pid(msg, res)) - goto err; + ret = fill_res_name_pid(msg, res); + if (ret) + return -EMSGSIZE; - if (fill_res_entry(dev, msg, res)) - goto err; + return fill_res_qp_entry_query(msg, res, dev, qp); +} - return 0; +static int fill_res_qp_raw_entry(struct sk_buff *msg, bool has_cap_net_admin, + struct rdma_restrack_entry *res, uint32_t port) +{ + struct ib_qp *qp = container_of(res, struct ib_qp, res); + struct ib_device *dev = qp->device; -err: return -EMSGSIZE; + if (port && port != qp->port) + return -EAGAIN; + if (!dev->ops.fill_res_qp_entry_raw) + return -EINVAL; + return dev->ops.fill_res_qp_entry_raw(msg, qp); } static int fill_res_cm_id_entry(struct sk_buff *msg, bool has_cap_net_admin, @@ -568,9 +577,8 @@ static int fill_res_cm_id_entry(struct sk_buff *msg, bool has_cap_net_admin, if (fill_res_name_pid(msg, res)) goto err; - if (fill_res_entry(dev, msg, res)) - goto err; - + if (dev->ops.fill_res_cm_id_entry) + return dev->ops.fill_res_cm_id_entry(msg, cm_id); return 0; err: return -EMSGSIZE; @@ -583,35 +591,42 @@ static int fill_res_cq_entry(struct sk_buff *msg, bool has_cap_net_admin, struct ib_device *dev = cq->device; if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CQE, cq->cqe)) - goto err; + return -EMSGSIZE; if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_USECNT, atomic_read(&cq->usecnt), RDMA_NLDEV_ATTR_PAD)) - goto err; + return -EMSGSIZE; /* Poll context is only valid for kernel CQs */ if (rdma_is_kernel_res(res) && nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_POLL_CTX, cq->poll_ctx)) - goto err; + return -EMSGSIZE; if (nla_put_u8(msg, RDMA_NLDEV_ATTR_DEV_DIM, (cq->dim != NULL))) - goto err; + return -EMSGSIZE; if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CQN, res->id)) - goto err; + return -EMSGSIZE; if (!rdma_is_kernel_res(res) && nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CTXN, cq->uobject->uevent.uobject.context->res.id)) - goto err; + return -EMSGSIZE; if (fill_res_name_pid(msg, res)) - goto err; + return -EMSGSIZE; - if (fill_res_entry(dev, msg, res)) - goto err; + return (dev->ops.fill_res_cq_entry) ? + dev->ops.fill_res_cq_entry(msg, cq) : 0; +} - return 0; +static int fill_res_cq_raw_entry(struct sk_buff *msg, bool has_cap_net_admin, + struct rdma_restrack_entry *res, uint32_t port) +{ + struct ib_cq *cq = container_of(res, struct ib_cq, res); + struct ib_device *dev = cq->device; -err: return -EMSGSIZE; + if (!dev->ops.fill_res_cq_entry_raw) + return -EINVAL; + return dev->ops.fill_res_cq_entry_raw(msg, cq); } static int fill_res_mr_entry(struct sk_buff *msg, bool has_cap_net_admin, @@ -622,38 +637,45 @@ static int fill_res_mr_entry(struct sk_buff *msg, bool has_cap_net_admin, if (has_cap_net_admin) { if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_RKEY, mr->rkey)) - goto err; + return -EMSGSIZE; if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LKEY, mr->lkey)) - goto err; + return -EMSGSIZE; } if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_MRLEN, mr->length, RDMA_NLDEV_ATTR_PAD)) - goto err; + return -EMSGSIZE; if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_MRN, res->id)) - goto err; + return -EMSGSIZE; if (!rdma_is_kernel_res(res) && nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, mr->pd->res.id)) - goto err; + return -EMSGSIZE; if (fill_res_name_pid(msg, res)) - goto err; + return -EMSGSIZE; - if (fill_res_entry(dev, msg, res)) - goto err; + return (dev->ops.fill_res_mr_entry) ? + dev->ops.fill_res_mr_entry(msg, mr) : + 0; +} - return 0; +static int fill_res_mr_raw_entry(struct sk_buff *msg, bool has_cap_net_admin, + struct rdma_restrack_entry *res, uint32_t port) +{ + struct ib_mr *mr = container_of(res, struct ib_mr, res); + struct ib_device *dev = mr->pd->device; -err: return -EMSGSIZE; + if (!dev->ops.fill_res_mr_entry_raw) + return -EINVAL; + return dev->ops.fill_res_mr_entry_raw(msg, mr); } static int fill_res_pd_entry(struct sk_buff *msg, bool has_cap_net_admin, struct rdma_restrack_entry *res, uint32_t port) { struct ib_pd *pd = container_of(res, struct ib_pd, res); - struct ib_device *dev = pd->device; if (has_cap_net_admin) { if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY, @@ -676,13 +698,7 @@ static int fill_res_pd_entry(struct sk_buff *msg, bool has_cap_net_admin, pd->uobject->context->res.id)) goto err; - if (fill_res_name_pid(msg, res)) - goto err; - - if (fill_res_entry(dev, msg, res)) - goto err; - - return 0; + return fill_res_name_pid(msg, res); err: return -EMSGSIZE; } @@ -695,11 +711,16 @@ static int fill_stat_counter_mode(struct sk_buff *msg, if (nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, m->mode)) return -EMSGSIZE; - if (m->mode == RDMA_COUNTER_MODE_AUTO) + if (m->mode == RDMA_COUNTER_MODE_AUTO) { if ((m->mask & RDMA_COUNTER_MASK_QP_TYPE) && nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_TYPE, m->param.qp_type)) return -EMSGSIZE; + if ((m->mask & RDMA_COUNTER_MASK_PID) && + fill_res_name_pid(msg, &counter->res)) + return -EMSGSIZE; + } + return 0; } @@ -738,9 +759,6 @@ static int fill_stat_counter_qps(struct sk_buff *msg, xa_lock(&rt->xa); xa_for_each(&rt->xa, id, res) { qp = container_of(res, struct ib_qp, res); - if (qp->qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW)) - continue; - if (!qp->counter || (qp->counter->id != counter->id)) continue; @@ -793,9 +811,8 @@ static int fill_stat_mr_entry(struct sk_buff *msg, bool has_cap_net_admin, if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_MRN, res->id)) goto err; - if (fill_stat_entry(dev, msg, res)) - goto err; - + if (dev->ops.fill_stat_mr_entry) + return dev->ops.fill_stat_mr_entry(msg, mr); return 0; err: @@ -840,7 +857,6 @@ static int fill_res_counter_entry(struct sk_buff *msg, bool has_cap_net_admin, if (nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, counter->port) || nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, counter->id) || - fill_res_name_pid(msg, &counter->res) || fill_stat_counter_mode(msg, counter) || fill_stat_counter_qps(msg, counter) || fill_stat_counter_hwcounters(msg, counter)) @@ -1177,7 +1193,6 @@ static int nldev_res_get_dumpit(struct sk_buff *skb, struct nldev_fill_res_entry { enum rdma_nldev_attr nldev_attr; - enum rdma_nldev_command nldev_cmd; u8 flags; u32 entry; u32 id; @@ -1189,40 +1204,34 @@ enum nldev_res_flags { static const struct nldev_fill_res_entry fill_entries[RDMA_RESTRACK_MAX] = { [RDMA_RESTRACK_QP] = { - .nldev_cmd = RDMA_NLDEV_CMD_RES_QP_GET, .nldev_attr = RDMA_NLDEV_ATTR_RES_QP, .entry = RDMA_NLDEV_ATTR_RES_QP_ENTRY, .id = RDMA_NLDEV_ATTR_RES_LQPN, }, [RDMA_RESTRACK_CM_ID] = { - .nldev_cmd = RDMA_NLDEV_CMD_RES_CM_ID_GET, .nldev_attr = RDMA_NLDEV_ATTR_RES_CM_ID, .entry = RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY, .id = RDMA_NLDEV_ATTR_RES_CM_IDN, }, [RDMA_RESTRACK_CQ] = { - .nldev_cmd = RDMA_NLDEV_CMD_RES_CQ_GET, .nldev_attr = RDMA_NLDEV_ATTR_RES_CQ, .flags = NLDEV_PER_DEV, .entry = RDMA_NLDEV_ATTR_RES_CQ_ENTRY, .id = RDMA_NLDEV_ATTR_RES_CQN, }, [RDMA_RESTRACK_MR] = { - .nldev_cmd = RDMA_NLDEV_CMD_RES_MR_GET, .nldev_attr = RDMA_NLDEV_ATTR_RES_MR, .flags = NLDEV_PER_DEV, .entry = RDMA_NLDEV_ATTR_RES_MR_ENTRY, .id = RDMA_NLDEV_ATTR_RES_MRN, }, [RDMA_RESTRACK_PD] = { - .nldev_cmd = RDMA_NLDEV_CMD_RES_PD_GET, .nldev_attr = RDMA_NLDEV_ATTR_RES_PD, .flags = NLDEV_PER_DEV, .entry = RDMA_NLDEV_ATTR_RES_PD_ENTRY, .id = RDMA_NLDEV_ATTR_RES_PDN, }, [RDMA_RESTRACK_COUNTER] = { - .nldev_cmd = RDMA_NLDEV_CMD_STAT_GET, .nldev_attr = RDMA_NLDEV_ATTR_STAT_COUNTER, .entry = RDMA_NLDEV_ATTR_STAT_COUNTER_ENTRY, .id = RDMA_NLDEV_ATTR_STAT_COUNTER_ID, @@ -1281,7 +1290,8 @@ static int res_get_common_doit(struct sk_buff *skb, struct nlmsghdr *nlh, } nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, - RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, fe->nldev_cmd), + RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, + RDMA_NL_GET_OP(nlh->nlmsg_type)), 0, 0); if (fill_nldev_handle(msg, device)) { @@ -1359,7 +1369,8 @@ static int res_get_common_dumpit(struct sk_buff *skb, } nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, - RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, fe->nldev_cmd), + RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, + RDMA_NL_GET_OP(cb->nlh->nlmsg_type)), 0, NLM_F_MULTI); if (fill_nldev_handle(skb, device)) { @@ -1441,26 +1452,29 @@ err_index: return ret; } -#define RES_GET_FUNCS(name, type) \ - static int nldev_res_get_##name##_dumpit(struct sk_buff *skb, \ +#define RES_GET_FUNCS(name, type) \ + static int nldev_res_get_##name##_dumpit(struct sk_buff *skb, \ struct netlink_callback *cb) \ - { \ - return res_get_common_dumpit(skb, cb, type, \ - fill_res_##name##_entry); \ - } \ - static int nldev_res_get_##name##_doit(struct sk_buff *skb, \ - struct nlmsghdr *nlh, \ + { \ + return res_get_common_dumpit(skb, cb, type, \ + fill_res_##name##_entry); \ + } \ + static int nldev_res_get_##name##_doit(struct sk_buff *skb, \ + struct nlmsghdr *nlh, \ struct netlink_ext_ack *extack) \ - { \ - return res_get_common_doit(skb, nlh, extack, type, \ - fill_res_##name##_entry); \ + { \ + return res_get_common_doit(skb, nlh, extack, type, \ + fill_res_##name##_entry); \ } RES_GET_FUNCS(qp, RDMA_RESTRACK_QP); +RES_GET_FUNCS(qp_raw, RDMA_RESTRACK_QP); RES_GET_FUNCS(cm_id, RDMA_RESTRACK_CM_ID); RES_GET_FUNCS(cq, RDMA_RESTRACK_CQ); +RES_GET_FUNCS(cq_raw, RDMA_RESTRACK_CQ); RES_GET_FUNCS(pd, RDMA_RESTRACK_PD); RES_GET_FUNCS(mr, RDMA_RESTRACK_MR); +RES_GET_FUNCS(mr_raw, RDMA_RESTRACK_MR); RES_GET_FUNCS(counter, RDMA_RESTRACK_COUNTER); static LIST_HEAD(link_ops); @@ -2145,6 +2159,21 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = { .doit = nldev_stat_del_doit, .flags = RDMA_NL_ADMIN_PERM, }, + [RDMA_NLDEV_CMD_RES_QP_GET_RAW] = { + .doit = nldev_res_get_qp_raw_doit, + .dump = nldev_res_get_qp_raw_dumpit, + .flags = RDMA_NL_ADMIN_PERM, + }, + [RDMA_NLDEV_CMD_RES_CQ_GET_RAW] = { + .doit = nldev_res_get_cq_raw_doit, + .dump = nldev_res_get_cq_raw_dumpit, + .flags = RDMA_NL_ADMIN_PERM, + }, + [RDMA_NLDEV_CMD_RES_MR_GET_RAW] = { + .doit = nldev_res_get_mr_raw_doit, + .dump = nldev_res_get_mr_raw_dumpit, + .flags = RDMA_NL_ADMIN_PERM, + }, }; void __init nldev_init(void) diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index defe9cd4c5eeb97afe40a52497ff0d5467dbbb4c..c11e50510e490c3a9011be7aeed175bf94d1d70c 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -58,7 +58,7 @@ struct ib_port { struct ib_device *ibdev; struct gid_attr_group *gid_attr_group; struct attribute_group gid_group; - struct attribute_group pkey_group; + struct attribute_group *pkey_group; struct attribute_group *pma_table; struct attribute_group *hw_stats_ag; struct rdma_hw_stats *hw_stats; @@ -681,11 +681,16 @@ static void ib_port_release(struct kobject *kobj) kfree(p->gid_group.attrs); } - if (p->pkey_group.attrs) { - for (i = 0; (a = p->pkey_group.attrs[i]); ++i) - kfree(a); + if (p->pkey_group) { + if (p->pkey_group->attrs) { + for (i = 0; (a = p->pkey_group->attrs[i]); ++i) + kfree(a); + + kfree(p->pkey_group->attrs); + } - kfree(p->pkey_group.attrs); + kfree(p->pkey_group); + p->pkey_group = NULL; } kfree(p); @@ -1118,17 +1123,26 @@ static int add_port(struct ib_core_device *coredev, int port_num) if (ret) goto err_free_gid_type; - p->pkey_group.name = "pkeys"; - p->pkey_group.attrs = alloc_group_attrs(show_port_pkey, - attr.pkey_tbl_len); - if (!p->pkey_group.attrs) { - ret = -ENOMEM; - goto err_remove_gid_type; + if (attr.pkey_tbl_len) { + p->pkey_group = kzalloc(sizeof(*p->pkey_group), GFP_KERNEL); + if (!p->pkey_group) { + ret = -ENOMEM; + goto err_remove_gid_type; + } + + p->pkey_group->name = "pkeys"; + p->pkey_group->attrs = alloc_group_attrs(show_port_pkey, + attr.pkey_tbl_len); + if (!p->pkey_group->attrs) { + ret = -ENOMEM; + goto err_free_pkey_group; + } + + ret = sysfs_create_group(&p->kobj, p->pkey_group); + if (ret) + goto err_free_pkey; } - ret = sysfs_create_group(&p->kobj, &p->pkey_group); - if (ret) - goto err_free_pkey; if (device->ops.init_port && is_full_dev) { ret = device->ops.init_port(device, port_num, &p->kobj); @@ -1150,14 +1164,20 @@ static int add_port(struct ib_core_device *coredev, int port_num) return 0; err_remove_pkey: - sysfs_remove_group(&p->kobj, &p->pkey_group); + if (p->pkey_group) + sysfs_remove_group(&p->kobj, p->pkey_group); err_free_pkey: - for (i = 0; i < attr.pkey_tbl_len; ++i) - kfree(p->pkey_group.attrs[i]); + if (p->pkey_group) { + for (i = 0; i < attr.pkey_tbl_len; ++i) + kfree(p->pkey_group->attrs[i]); + + kfree(p->pkey_group->attrs); + p->pkey_group->attrs = NULL; + } - kfree(p->pkey_group.attrs); - p->pkey_group.attrs = NULL; +err_free_pkey_group: + kfree(p->pkey_group); err_remove_gid_type: sysfs_remove_group(&p->gid_attr_group->kobj, @@ -1317,7 +1337,8 @@ void ib_free_port_attrs(struct ib_core_device *coredev) if (port->pma_table) sysfs_remove_group(p, port->pma_table); - sysfs_remove_group(p, &port->pkey_group); + if (port->pkey_group) + sysfs_remove_group(p, port->pkey_group); sysfs_remove_group(p, &port->gid_group); sysfs_remove_group(&port->gid_attr_group->kobj, &port->gid_attr_group->ndev); diff --git a/drivers/infiniband/core/trace.c b/drivers/infiniband/core/trace.c index 6c3514beac4d6616a69451a38dc0968a47e9bb87..31e7860d35bffe1a75bc5cace7e2225c1e050cd1 100644 --- a/drivers/infiniband/core/trace.c +++ b/drivers/infiniband/core/trace.c @@ -9,6 +9,4 @@ #define CREATE_TRACE_POINTS -#include - #include diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index 82455a1392f1d19c96ae956f0bd4e93e3a52d29c..831bff8d52e547834e9e04064127fbb280595126 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -261,6 +261,7 @@ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr, sg = umem->sg_head.sgl; while (npages) { + cond_resched(); ret = pin_user_pages_fast(cur_base, min_t(unsigned long, npages, PAGE_SIZE / diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index ccd28405451cbc6976706a934a967e883cd37fb8..5e32f61a2fe4f8cc260915268060bd2736b1a04c 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -152,6 +152,7 @@ EXPORT_SYMBOL(ib_umem_odp_alloc_implicit); * ib_alloc_implicit_odp_umem() * @addr: The starting userspace VA * @size: The length of the userspace VA + * @ops: MMU interval ops, currently only @invalidate */ struct ib_umem_odp * ib_umem_odp_alloc_child(struct ib_umem_odp *root, unsigned long addr, @@ -213,6 +214,7 @@ EXPORT_SYMBOL(ib_umem_odp_alloc_child); * @addr: userspace virtual address to start at * @size: length of region to pin * @access: IB_ACCESS_xxx flags for memory being pinned + * @ops: MMU interval ops, currently only @invalidate * * The driver should use when the access flags indicate ODP memory. It avoids * pinning, instead, stores the mm for future page fault handling in diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 76e7ec0f07754ce31e76da8de64baeec9d6ad3ac..2fbc583d5bddffac2e44ec8a84eab5ed7034f3a9 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -415,8 +415,8 @@ static int ib_uverbs_query_port(struct uverbs_attr_bundle *attrs) static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs) { + struct ib_uverbs_alloc_pd_resp resp = {}; struct ib_uverbs_alloc_pd cmd; - struct ib_uverbs_alloc_pd_resp resp; struct ib_uobject *uobj; struct ib_pd *pd; int ret; @@ -438,29 +438,20 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs) pd->device = ib_dev; pd->uobject = uobj; - pd->__internal_mr = NULL; atomic_set(&pd->usecnt, 0); pd->res.type = RDMA_RESTRACK_PD; ret = ib_dev->ops.alloc_pd(pd, &attrs->driver_udata); if (ret) goto err_alloc; - - uobj->object = pd; - memset(&resp, 0, sizeof resp); - resp.pd_handle = uobj->id; rdma_restrack_uadd(&pd->res); - ret = uverbs_response(attrs, &resp, sizeof(resp)); - if (ret) - goto err_copy; + uobj->object = pd; + uobj_finalize_uobj_create(uobj, attrs); - rdma_alloc_commit_uobject(uobj, attrs); - return 0; + resp.pd_handle = uobj->id; + return uverbs_response(attrs, &resp, sizeof(resp)); -err_copy: - ib_dealloc_pd_user(pd, uverbs_get_cleared_udata(attrs)); - pd = NULL; err_alloc: kfree(pd); err: @@ -568,15 +559,15 @@ static void xrcd_table_delete(struct ib_uverbs_device *dev, static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_device *ibudev = attrs->ufile->device; + struct ib_uverbs_open_xrcd_resp resp = {}; struct ib_uverbs_open_xrcd cmd; - struct ib_uverbs_open_xrcd_resp resp; struct ib_uxrcd_object *obj; struct ib_xrcd *xrcd = NULL; - struct fd f = {NULL, 0}; struct inode *inode = NULL; - int ret = 0; int new_xrcd = 0; struct ib_device *ib_dev; + struct fd f = {}; + int ret; ret = uverbs_request(attrs, &cmd, sizeof(cmd)); if (ret) @@ -614,24 +605,16 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs) } if (!xrcd) { - xrcd = ib_dev->ops.alloc_xrcd(ib_dev, &attrs->driver_udata); + xrcd = ib_alloc_xrcd_user(ib_dev, inode, &attrs->driver_udata); if (IS_ERR(xrcd)) { ret = PTR_ERR(xrcd); goto err; } - - xrcd->inode = inode; - xrcd->device = ib_dev; - atomic_set(&xrcd->usecnt, 0); - mutex_init(&xrcd->tgt_qp_mutex); - INIT_LIST_HEAD(&xrcd->tgt_qp_list); new_xrcd = 1; } atomic_set(&obj->refcnt, 0); obj->uobject.object = xrcd; - memset(&resp, 0, sizeof resp); - resp.xrcd_handle = obj->uobject.id; if (inode) { if (new_xrcd) { @@ -643,27 +626,17 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs) atomic_inc(&xrcd->usecnt); } - ret = uverbs_response(attrs, &resp, sizeof(resp)); - if (ret) - goto err_copy; - if (f.file) fdput(f); mutex_unlock(&ibudev->xrcd_tree_mutex); + uobj_finalize_uobj_create(&obj->uobject, attrs); - rdma_alloc_commit_uobject(&obj->uobject, attrs); - return 0; - -err_copy: - if (inode) { - if (new_xrcd) - xrcd_table_delete(ibudev, inode); - atomic_dec(&xrcd->usecnt); - } + resp.xrcd_handle = obj->uobject.id; + return uverbs_response(attrs, &resp, sizeof(resp)); err_dealloc_xrcd: - ib_dealloc_xrcd(xrcd, uverbs_get_cleared_udata(attrs)); + ib_dealloc_xrcd_user(xrcd, uverbs_get_cleared_udata(attrs)); err: uobj_alloc_abort(&obj->uobject, attrs); @@ -701,7 +674,7 @@ int ib_uverbs_dealloc_xrcd(struct ib_uobject *uobject, struct ib_xrcd *xrcd, if (inode && !atomic_dec_and_test(&xrcd->usecnt)) return 0; - ret = ib_dealloc_xrcd(xrcd, &attrs->driver_udata); + ret = ib_dealloc_xrcd_user(xrcd, &attrs->driver_udata); if (ib_is_destroy_retryable(ret, why, uobject)) { atomic_inc(&xrcd->usecnt); @@ -716,8 +689,8 @@ int ib_uverbs_dealloc_xrcd(struct ib_uobject *uobject, struct ib_xrcd *xrcd, static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs) { + struct ib_uverbs_reg_mr_resp resp = {}; struct ib_uverbs_reg_mr cmd; - struct ib_uverbs_reg_mr_resp resp; struct ib_uobject *uobj; struct ib_pd *pd; struct ib_mr *mr; @@ -770,30 +743,20 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs) mr->uobject = uobj; atomic_inc(&pd->usecnt); mr->res.type = RDMA_RESTRACK_MR; + mr->iova = cmd.hca_va; rdma_restrack_uadd(&mr->res); uobj->object = mr; - - memset(&resp, 0, sizeof resp); - resp.lkey = mr->lkey; - resp.rkey = mr->rkey; - resp.mr_handle = uobj->id; - - ret = uverbs_response(attrs, &resp, sizeof(resp)); - if (ret) - goto err_copy; - uobj_put_obj_read(pd); + uobj_finalize_uobj_create(uobj, attrs); - rdma_alloc_commit_uobject(uobj, attrs); - return 0; - -err_copy: - ib_dereg_mr_user(mr, uverbs_get_cleared_udata(attrs)); + resp.lkey = mr->lkey; + resp.rkey = mr->rkey; + resp.mr_handle = uobj->id; + return uverbs_response(attrs, &resp, sizeof(resp)); err_put: uobj_put_obj_read(pd); - err_free: uobj_alloc_abort(uobj, attrs); return ret; @@ -861,6 +824,9 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs) atomic_dec(&old_pd->usecnt); } + if (cmd.flags & IB_MR_REREG_TRANS) + mr->iova = cmd.hca_va; + memset(&resp, 0, sizeof(resp)); resp.lkey = mr->lkey; resp.rkey = mr->rkey; @@ -930,21 +896,13 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs) atomic_inc(&pd->usecnt); uobj->object = mw; + uobj_put_obj_read(pd); + uobj_finalize_uobj_create(uobj, attrs); - memset(&resp, 0, sizeof(resp)); - resp.rkey = mw->rkey; + resp.rkey = mw->rkey; resp.mw_handle = uobj->id; + return uverbs_response(attrs, &resp, sizeof(resp)); - ret = uverbs_response(attrs, &resp, sizeof(resp)); - if (ret) - goto err_copy; - - uobj_put_obj_read(pd); - rdma_alloc_commit_uobject(uobj, attrs); - return 0; - -err_copy: - uverbs_dealloc_mw(mw); err_put: uobj_put_obj_read(pd); err_free: @@ -981,40 +939,33 @@ static int ib_uverbs_create_comp_channel(struct uverbs_attr_bundle *attrs) if (IS_ERR(uobj)) return PTR_ERR(uobj); - resp.fd = uobj->id; - ev_file = container_of(uobj, struct ib_uverbs_completion_event_file, uobj); ib_uverbs_init_event_queue(&ev_file->ev_queue); + uobj_finalize_uobj_create(uobj, attrs); - ret = uverbs_response(attrs, &resp, sizeof(resp)); - if (ret) { - uobj_alloc_abort(uobj, attrs); - return ret; - } - - rdma_alloc_commit_uobject(uobj, attrs); - return 0; + resp.fd = uobj->id; + return uverbs_response(attrs, &resp, sizeof(resp)); } -static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, - struct ib_uverbs_ex_create_cq *cmd) +static int create_cq(struct uverbs_attr_bundle *attrs, + struct ib_uverbs_ex_create_cq *cmd) { struct ib_ucq_object *obj; struct ib_uverbs_completion_event_file *ev_file = NULL; struct ib_cq *cq; int ret; - struct ib_uverbs_ex_create_cq_resp resp; + struct ib_uverbs_ex_create_cq_resp resp = {}; struct ib_cq_init_attr attr = {}; struct ib_device *ib_dev; if (cmd->comp_vector >= attrs->ufile->device->num_comp_vectors) - return ERR_PTR(-EINVAL); + return -EINVAL; obj = (struct ib_ucq_object *)uobj_alloc(UVERBS_OBJECT_CQ, attrs, &ib_dev); if (IS_ERR(obj)) - return obj; + return PTR_ERR(obj); if (cmd->comp_channel >= 0) { ev_file = ib_uverbs_lookup_comp_file(cmd->comp_channel, attrs); @@ -1043,53 +994,38 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs, cq->event_handler = ib_uverbs_cq_event_handler; cq->cq_context = ev_file ? &ev_file->ev_queue : NULL; atomic_set(&cq->usecnt, 0); + cq->res.type = RDMA_RESTRACK_CQ; ret = ib_dev->ops.create_cq(cq, &attr, &attrs->driver_udata); if (ret) goto err_free; + rdma_restrack_uadd(&cq->res); obj->uevent.uobject.object = cq; obj->uevent.event_file = READ_ONCE(attrs->ufile->default_async_file); if (obj->uevent.event_file) uverbs_uobject_get(&obj->uevent.event_file->uobj); + uobj_finalize_uobj_create(&obj->uevent.uobject, attrs); - memset(&resp, 0, sizeof resp); resp.base.cq_handle = obj->uevent.uobject.id; - resp.base.cqe = cq->cqe; + resp.base.cqe = cq->cqe; resp.response_length = uverbs_response_length(attrs, sizeof(resp)); + return uverbs_response(attrs, &resp, sizeof(resp)); - cq->res.type = RDMA_RESTRACK_CQ; - rdma_restrack_uadd(&cq->res); - - ret = uverbs_response(attrs, &resp, sizeof(resp)); - if (ret) - goto err_cb; - - rdma_alloc_commit_uobject(&obj->uevent.uobject, attrs); - return obj; - -err_cb: - if (obj->uevent.event_file) - uverbs_uobject_put(&obj->uevent.event_file->uobj); - ib_destroy_cq_user(cq, uverbs_get_cleared_udata(attrs)); - cq = NULL; err_free: kfree(cq); err_file: if (ev_file) ib_uverbs_release_ucq(ev_file, obj); - err: uobj_alloc_abort(&obj->uevent.uobject, attrs); - - return ERR_PTR(ret); + return ret; } static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_create_cq cmd; struct ib_uverbs_ex_create_cq cmd_ex; - struct ib_ucq_object *obj; int ret; ret = uverbs_request(attrs, &cmd, sizeof(cmd)); @@ -1102,14 +1038,12 @@ static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs) cmd_ex.comp_vector = cmd.comp_vector; cmd_ex.comp_channel = cmd.comp_channel; - obj = create_cq(attrs, &cmd_ex); - return PTR_ERR_OR_ZERO(obj); + return create_cq(attrs, &cmd_ex); } static int ib_uverbs_ex_create_cq(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_ex_create_cq cmd; - struct ib_ucq_object *obj; int ret; ret = uverbs_request(attrs, &cmd, sizeof(cmd)); @@ -1122,8 +1056,7 @@ static int ib_uverbs_ex_create_cq(struct uverbs_attr_bundle *attrs) if (cmd.reserved) return -EINVAL; - obj = create_cq(attrs, &cmd); - return PTR_ERR_OR_ZERO(obj); + return create_cq(attrs, &cmd); } static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs) @@ -1131,7 +1064,7 @@ static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs) struct ib_uverbs_resize_cq cmd; struct ib_uverbs_resize_cq_resp resp = {}; struct ib_cq *cq; - int ret = -EINVAL; + int ret; ret = uverbs_request(attrs, &cmd, sizeof(cmd)); if (ret) @@ -1298,7 +1231,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs, struct ib_srq *srq = NULL; struct ib_qp *qp; struct ib_qp_init_attr attr = {}; - struct ib_uverbs_ex_create_qp_resp resp; + struct ib_uverbs_ex_create_qp_resp resp = {}; int ret; struct ib_rwq_ind_table *ind_tbl = NULL; bool has_sq = true; @@ -1468,20 +1401,6 @@ static int create_qp(struct uverbs_attr_bundle *attrs, if (obj->uevent.event_file) uverbs_uobject_get(&obj->uevent.event_file->uobj); - memset(&resp, 0, sizeof resp); - resp.base.qpn = qp->qp_num; - resp.base.qp_handle = obj->uevent.uobject.id; - resp.base.max_recv_sge = attr.cap.max_recv_sge; - resp.base.max_send_sge = attr.cap.max_send_sge; - resp.base.max_recv_wr = attr.cap.max_recv_wr; - resp.base.max_send_wr = attr.cap.max_send_wr; - resp.base.max_inline_data = attr.cap.max_inline_data; - resp.response_length = uverbs_response_length(attrs, sizeof(resp)); - - ret = uverbs_response(attrs, &resp, sizeof(resp)); - if (ret) - goto err_uevent; - if (xrcd) { obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject); @@ -1502,12 +1421,18 @@ static int create_qp(struct uverbs_attr_bundle *attrs, UVERBS_LOOKUP_READ); if (ind_tbl) uobj_put_obj_read(ind_tbl); + uobj_finalize_uobj_create(&obj->uevent.uobject, attrs); + + resp.base.qpn = qp->qp_num; + resp.base.qp_handle = obj->uevent.uobject.id; + resp.base.max_recv_sge = attr.cap.max_recv_sge; + resp.base.max_send_sge = attr.cap.max_send_sge; + resp.base.max_recv_wr = attr.cap.max_recv_wr; + resp.base.max_send_wr = attr.cap.max_send_wr; + resp.base.max_inline_data = attr.cap.max_inline_data; + resp.response_length = uverbs_response_length(attrs, sizeof(resp)); + return uverbs_response(attrs, &resp, sizeof(resp)); - rdma_alloc_commit_uobject(&obj->uevent.uobject, attrs); - return 0; -err_uevent: - if (obj->uevent.event_file) - uverbs_uobject_put(&obj->uevent.event_file->uobj); err_cb: ib_destroy_qp_user(qp, uverbs_get_cleared_udata(attrs)); @@ -1580,14 +1505,14 @@ static int ib_uverbs_ex_create_qp(struct uverbs_attr_bundle *attrs) static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs) { + struct ib_uverbs_create_qp_resp resp = {}; struct ib_uverbs_open_qp cmd; - struct ib_uverbs_create_qp_resp resp; struct ib_uqp_object *obj; struct ib_xrcd *xrcd; - struct ib_uobject *xrcd_uobj; struct ib_qp *qp; struct ib_qp_open_attr attr = {}; int ret; + struct ib_uobject *xrcd_uobj; struct ib_device *ib_dev; ret = uverbs_request(attrs, &cmd, sizeof(cmd)); @@ -1627,24 +1552,16 @@ static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs) obj->uevent.uobject.object = qp; obj->uevent.uobject.user_handle = cmd.user_handle; - memset(&resp, 0, sizeof resp); - resp.qpn = qp->qp_num; - resp.qp_handle = obj->uevent.uobject.id; - - ret = uverbs_response(attrs, &resp, sizeof(resp)); - if (ret) - goto err_destroy; - obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject); atomic_inc(&obj->uxrcd->refcnt); qp->uobject = obj; uobj_put_read(xrcd_uobj); + uobj_finalize_uobj_create(&obj->uevent.uobject, attrs); - rdma_alloc_commit_uobject(&obj->uevent.uobject, attrs); - return 0; + resp.qpn = qp->qp_num; + resp.qp_handle = obj->uevent.uobject.id; + return uverbs_response(attrs, &resp, sizeof(resp)); -err_destroy: - ib_destroy_qp_user(qp, uverbs_get_cleared_udata(attrs)); err_xrcd: uobj_put_read(xrcd_uobj); err_put: @@ -1980,7 +1897,7 @@ static int ib_uverbs_ex_modify_qp(struct uverbs_attr_bundle *attrs) * Last bit is reserved for extending the attr_mask by * using another field. */ - BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1 << 31)); + BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1ULL << 31)); if (cmd.base.attr_mask & ~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1)) @@ -2480,24 +2397,14 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs) ah->uobject = uobj; uobj->user_handle = cmd.user_handle; uobj->object = ah; - - resp.ah_handle = uobj->id; - - ret = uverbs_response(attrs, &resp, sizeof(resp)); - if (ret) - goto err_copy; - uobj_put_obj_read(pd); - rdma_alloc_commit_uobject(uobj, attrs); - return 0; + uobj_finalize_uobj_create(uobj, attrs); -err_copy: - rdma_destroy_ah_user(ah, RDMA_DESTROY_AH_SLEEPABLE, - uverbs_get_cleared_udata(attrs)); + resp.ah_handle = uobj->id; + return uverbs_response(attrs, &resp, sizeof(resp)); err_put: uobj_put_obj_read(pd); - err: uobj_alloc_abort(uobj, attrs); return ret; @@ -2989,26 +2896,18 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs) if (obj->uevent.event_file) uverbs_uobject_get(&obj->uevent.event_file->uobj); - memset(&resp, 0, sizeof(resp)); + uobj_put_obj_read(pd); + rdma_lookup_put_uobject(&cq->uobject->uevent.uobject, + UVERBS_LOOKUP_READ); + uobj_finalize_uobj_create(&obj->uevent.uobject, attrs); + resp.wq_handle = obj->uevent.uobject.id; resp.max_sge = wq_init_attr.max_sge; resp.max_wr = wq_init_attr.max_wr; resp.wqn = wq->wq_num; resp.response_length = uverbs_response_length(attrs, sizeof(resp)); - err = uverbs_response(attrs, &resp, sizeof(resp)); - if (err) - goto err_copy; - - uobj_put_obj_read(pd); - rdma_lookup_put_uobject(&cq->uobject->uevent.uobject, - UVERBS_LOOKUP_READ); - rdma_alloc_commit_uobject(&obj->uevent.uobject, attrs); - return 0; + return uverbs_response(attrs, &resp, sizeof(resp)); -err_copy: - if (obj->uevent.event_file) - uverbs_uobject_put(&obj->uevent.event_file->uobj); - ib_destroy_wq(wq, uverbs_get_cleared_udata(attrs)); err_put_cq: rdma_lookup_put_uobject(&cq->uobject->uevent.uobject, UVERBS_LOOKUP_READ); @@ -3093,7 +2992,7 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs) struct ib_wq **wqs = NULL; u32 *wqs_handles = NULL; struct ib_wq *wq = NULL; - int i, j, num_read_wqs; + int i, num_read_wqs; u32 num_wq_handles; struct uverbs_req_iter iter; struct ib_device *ib_dev; @@ -3139,6 +3038,7 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs) } wqs[num_read_wqs] = wq; + atomic_inc(&wqs[num_read_wqs]->usecnt); } uobj = uobj_alloc(UVERBS_OBJECT_RWQ_IND_TBL, attrs, &ib_dev); @@ -3166,33 +3066,24 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs) atomic_set(&rwq_ind_tbl->usecnt, 0); for (i = 0; i < num_wq_handles; i++) - atomic_inc(&wqs[i]->usecnt); + rdma_lookup_put_uobject(&wqs[i]->uobject->uevent.uobject, + UVERBS_LOOKUP_READ); + kfree(wqs_handles); + uobj_finalize_uobj_create(uobj, attrs); resp.ind_tbl_handle = uobj->id; resp.ind_tbl_num = rwq_ind_tbl->ind_tbl_num; resp.response_length = uverbs_response_length(attrs, sizeof(resp)); + return uverbs_response(attrs, &resp, sizeof(resp)); - err = uverbs_response(attrs, &resp, sizeof(resp)); - if (err) - goto err_copy; - - kfree(wqs_handles); - - for (j = 0; j < num_read_wqs; j++) - rdma_lookup_put_uobject(&wqs[j]->uobject->uevent.uobject, - UVERBS_LOOKUP_READ); - - rdma_alloc_commit_uobject(uobj, attrs); - return 0; - -err_copy: - ib_destroy_rwq_ind_table(rwq_ind_tbl); err_uobj: uobj_alloc_abort(uobj, attrs); put_wqs: - for (j = 0; j < num_read_wqs; j++) - rdma_lookup_put_uobject(&wqs[j]->uobject->uevent.uobject, + for (i = 0; i < num_read_wqs; i++) { + rdma_lookup_put_uobject(&wqs[i]->uobject->uevent.uobject, UVERBS_LOOKUP_READ); + atomic_dec(&wqs[i]->usecnt); + } err_free: kfree(wqs_handles); kfree(wqs); @@ -3218,7 +3109,7 @@ static int ib_uverbs_ex_destroy_rwq_ind_table(struct uverbs_attr_bundle *attrs) static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs) { struct ib_uverbs_create_flow cmd; - struct ib_uverbs_create_flow_resp resp; + struct ib_uverbs_create_flow_resp resp = {}; struct ib_uobject *uobj; struct ib_flow *flow_id; struct ib_uverbs_flow_attr *kern_flow_attr; @@ -3351,23 +3242,17 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs) ib_set_flow(uobj, flow_id, qp, qp->device, uflow_res); - memset(&resp, 0, sizeof(resp)); - resp.flow_handle = uobj->id; - - err = uverbs_response(attrs, &resp, sizeof(resp)); - if (err) - goto err_copy; - rdma_lookup_put_uobject(&qp->uobject->uevent.uobject, UVERBS_LOOKUP_READ); kfree(flow_attr); + if (cmd.flow_attr.num_of_specs) kfree(kern_flow_attr); - rdma_alloc_commit_uobject(uobj, attrs); - return 0; -err_copy: - if (!qp->device->ops.destroy_flow(flow_id)) - atomic_dec(&qp->usecnt); + uobj_finalize_uobj_create(uobj, attrs); + + resp.flow_handle = uobj->id; + return uverbs_response(attrs, &resp, sizeof(resp)); + err_free: ib_uverbs_flow_resources_free(uflow_res); err_free_flow_attr: @@ -3402,13 +3287,13 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, struct ib_uverbs_create_xsrq *cmd, struct ib_udata *udata) { - struct ib_uverbs_create_srq_resp resp; + struct ib_uverbs_create_srq_resp resp = {}; struct ib_usrq_object *obj; struct ib_pd *pd; struct ib_srq *srq; - struct ib_uobject *xrcd_uobj; struct ib_srq_init_attr attr; int ret; + struct ib_uobject *xrcd_uobj; struct ib_device *ib_dev; obj = (struct ib_usrq_object *)uobj_alloc(UVERBS_OBJECT_SRQ, attrs, @@ -3473,17 +3358,9 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, if (obj->uevent.event_file) uverbs_uobject_get(&obj->uevent.event_file->uobj); - memset(&resp, 0, sizeof resp); - resp.srq_handle = obj->uevent.uobject.id; - resp.max_wr = attr.attr.max_wr; - resp.max_sge = attr.attr.max_sge; if (cmd->srq_type == IB_SRQT_XRC) resp.srqn = srq->ext.xrc.srq_num; - ret = uverbs_response(attrs, &resp, sizeof(resp)); - if (ret) - goto err_copy; - if (cmd->srq_type == IB_SRQT_XRC) uobj_put_read(xrcd_uobj); @@ -3492,13 +3369,13 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, UVERBS_LOOKUP_READ); uobj_put_obj_read(pd); - rdma_alloc_commit_uobject(&obj->uevent.uobject, attrs); - return 0; + uobj_finalize_uobj_create(&obj->uevent.uobject, attrs); + + resp.srq_handle = obj->uevent.uobject.id; + resp.max_wr = attr.attr.max_wr; + resp.max_sge = attr.attr.max_sge; + return uverbs_response(attrs, &resp, sizeof(resp)); -err_copy: - if (obj->uevent.event_file) - uverbs_uobject_put(&obj->uevent.event_file->uobj); - ib_destroy_srq_user(srq, uverbs_get_cleared_udata(attrs)); err_put_pd: uobj_put_obj_read(pd); err_put_cq: diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c index 2d882c02387c1d2cd57109642dcd5a8d181f1a8b..ef04a261097fca2a6e2927496b2a728c1d8f6653 100644 --- a/drivers/infiniband/core/uverbs_ioctl.c +++ b/drivers/infiniband/core/uverbs_ioctl.c @@ -790,6 +790,7 @@ int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle, } return uverbs_copy_to(bundle, idx, from, size); } +EXPORT_SYMBOL(uverbs_copy_to_struct_or_zero); /* Once called an abort will call through to the type's destroy_hw() */ void uverbs_finalize_uobj_create(const struct uverbs_attr_bundle *bundle, diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 69e4755cc04ba2f28b2017ef3e872da4a953eb37..37794d88b1f3bbc6f7e2d623d2d663b7bef5abae 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -601,6 +601,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, memset(bundle.attr_present, 0, sizeof(bundle.attr_present)); bundle.ufile = file; bundle.context = NULL; /* only valid if bundle has uobject */ + bundle.uobject = NULL; if (!method_elm->is_ex) { size_t in_len = hdr.in_words * 4 - sizeof(hdr); size_t out_len = hdr.out_words * 4; @@ -664,6 +665,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, } ret = method_elm->handler(&bundle); + if (bundle.uobject) + uverbs_finalize_object(bundle.uobject, UVERBS_ACCESS_NEW, true, + !ret, &bundle); out_unlock: srcu_read_unlock(&file->device->disassociate_srcu, srcu_key); return (ret) ? : count; diff --git a/drivers/infiniband/core/uverbs_std_types_counters.c b/drivers/infiniband/core/uverbs_std_types_counters.c index 9f013304e67786550bb8307caaf4df469758b86b..c7e7438752bc3e5f174c38d6d6e216e4e223a538 100644 --- a/drivers/infiniband/core/uverbs_std_types_counters.c +++ b/drivers/infiniband/core/uverbs_std_types_counters.c @@ -46,7 +46,9 @@ static int uverbs_free_counters(struct ib_uobject *uobject, if (ret) return ret; - return counters->device->ops.destroy_counters(counters); + counters->device->ops.destroy_counters(counters); + kfree(counters); + return 0; } static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)( @@ -66,20 +68,19 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)( if (!ib_dev->ops.create_counters) return -EOPNOTSUPP; - counters = ib_dev->ops.create_counters(ib_dev, attrs); - if (IS_ERR(counters)) { - ret = PTR_ERR(counters); - goto err_create_counters; - } + counters = rdma_zalloc_drv_obj(ib_dev, ib_counters); + if (!counters) + return -ENOMEM; counters->device = ib_dev; counters->uobject = uobj; uobj->object = counters; atomic_set(&counters->usecnt, 0); - return 0; + ret = ib_dev->ops.create_counters(counters, attrs); + if (ret) + kfree(counters); -err_create_counters: return ret; } diff --git a/drivers/infiniband/core/uverbs_std_types_cq.c b/drivers/infiniband/core/uverbs_std_types_cq.c index 5dce2c7cc3239d2e60326ed9f24daa65a24c7d7e..b1c7dacc02de1508481087047312ed0d0b4ebb34 100644 --- a/drivers/infiniband/core/uverbs_std_types_cq.c +++ b/drivers/infiniband/core/uverbs_std_types_cq.c @@ -207,11 +207,8 @@ DECLARE_UVERBS_NAMED_METHOD( DECLARE_UVERBS_NAMED_OBJECT( UVERBS_OBJECT_CQ, UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_ucq_object), uverbs_free_cq), - -#if IS_ENABLED(CONFIG_INFINIBAND_EXP_LEGACY_VERBS_NEW_UAPI) &UVERBS_METHOD(UVERBS_METHOD_CQ_CREATE), &UVERBS_METHOD(UVERBS_METHOD_CQ_DESTROY) -#endif ); const struct uapi_definition uverbs_def_obj_cq[] = { diff --git a/drivers/infiniband/core/uverbs_std_types_device.c b/drivers/infiniband/core/uverbs_std_types_device.c index ae4a59d6f9b14558c8760b1880b53f7cbd1f2ff4..75df2094a0104b40e3cdd173e56f749e469d0578 100644 --- a/drivers/infiniband/core/uverbs_std_types_device.c +++ b/drivers/infiniband/core/uverbs_std_types_device.c @@ -38,7 +38,12 @@ static int UVERBS_HANDLER(UVERBS_METHOD_INVOKE_WRITE)( attrs->ucore.outlen < method_elm->resp_size) return -ENOSPC; - return method_elm->handler(attrs); + attrs->uobject = NULL; + rc = method_elm->handler(attrs); + if (attrs->uobject) + uverbs_finalize_object(attrs->uobject, UVERBS_ACCESS_NEW, true, + !rc, attrs); + return rc; } DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_INVOKE_WRITE, @@ -229,6 +234,37 @@ static int UVERBS_HANDLER(UVERBS_METHOD_GET_CONTEXT)( return 0; } +static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_CONTEXT)( + struct uverbs_attr_bundle *attrs) +{ + u64 core_support = IB_UVERBS_CORE_SUPPORT_OPTIONAL_MR_ACCESS; + struct ib_ucontext *ucontext; + struct ib_device *ib_dev; + u32 num_comp; + int ret; + + ucontext = ib_uverbs_get_ucontext(attrs); + if (IS_ERR(ucontext)) + return PTR_ERR(ucontext); + ib_dev = ucontext->device; + + if (!ib_dev->ops.query_ucontext) + return -EOPNOTSUPP; + + num_comp = attrs->ufile->device->num_comp_vectors; + ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_CONTEXT_NUM_COMP_VECTORS, + &num_comp, sizeof(num_comp)); + if (IS_UVERBS_COPY_ERR(ret)) + return ret; + + ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_CONTEXT_CORE_SUPPORT, + &core_support, sizeof(core_support)); + if (IS_UVERBS_COPY_ERR(ret)) + return ret; + + return ucontext->device->ops.query_ucontext(ucontext, attrs); +} + DECLARE_UVERBS_NAMED_METHOD( UVERBS_METHOD_GET_CONTEXT, UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_GET_CONTEXT_NUM_COMP_VECTORS, @@ -237,6 +273,13 @@ DECLARE_UVERBS_NAMED_METHOD( UVERBS_ATTR_TYPE(u64), UA_OPTIONAL), UVERBS_ATTR_UHW()); +DECLARE_UVERBS_NAMED_METHOD( + UVERBS_METHOD_QUERY_CONTEXT, + UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_CONTEXT_NUM_COMP_VECTORS, + UVERBS_ATTR_TYPE(u32), UA_OPTIONAL), + UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_CONTEXT_CORE_SUPPORT, + UVERBS_ATTR_TYPE(u64), UA_OPTIONAL)); + DECLARE_UVERBS_NAMED_METHOD( UVERBS_METHOD_INFO_HANDLES, /* Also includes any device specific object ids */ @@ -260,7 +303,8 @@ DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE, &UVERBS_METHOD(UVERBS_METHOD_GET_CONTEXT), &UVERBS_METHOD(UVERBS_METHOD_INVOKE_WRITE), &UVERBS_METHOD(UVERBS_METHOD_INFO_HANDLES), - &UVERBS_METHOD(UVERBS_METHOD_QUERY_PORT)); + &UVERBS_METHOD(UVERBS_METHOD_QUERY_PORT), + &UVERBS_METHOD(UVERBS_METHOD_QUERY_CONTEXT)); const struct uapi_definition uverbs_def_obj_device[] = { UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE), diff --git a/drivers/infiniband/core/uverbs_std_types_mr.c b/drivers/infiniband/core/uverbs_std_types_mr.c index a2722ef8496e9a03bf40c574e0f882c62c674d36..9b22bb553e8b32a62b8c383d16db412d51c6606f 100644 --- a/drivers/infiniband/core/uverbs_std_types_mr.c +++ b/drivers/infiniband/core/uverbs_std_types_mr.c @@ -69,7 +69,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_ADVISE_MR)( num_sge = uverbs_attr_ptr_get_array_size( attrs, UVERBS_ATTR_ADVISE_MR_SGE_LIST, sizeof(struct ib_sge)); - if (num_sge < 0) + if (num_sge <= 0) return num_sge; sg_list = uverbs_attr_get_alloced_ptr(attrs, @@ -148,6 +148,36 @@ static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)( return ret; } +static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_MR)( + struct uverbs_attr_bundle *attrs) +{ + struct ib_mr *mr = + uverbs_attr_get_obj(attrs, UVERBS_ATTR_QUERY_MR_HANDLE); + int ret; + + ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_MR_RESP_LKEY, &mr->lkey, + sizeof(mr->lkey)); + if (ret) + return ret; + + ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_MR_RESP_RKEY, + &mr->rkey, sizeof(mr->rkey)); + + if (ret) + return ret; + + ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_MR_RESP_LENGTH, + &mr->length, sizeof(mr->length)); + + if (ret) + return ret; + + ret = uverbs_copy_to(attrs, UVERBS_ATTR_QUERY_MR_RESP_IOVA, + &mr->iova, sizeof(mr->iova)); + + return IS_UVERBS_COPY_ERR(ret) ? ret : 0; +} + DECLARE_UVERBS_NAMED_METHOD( UVERBS_METHOD_ADVISE_MR, UVERBS_ATTR_IDR(UVERBS_ATTR_ADVISE_MR_PD_HANDLE, @@ -165,6 +195,25 @@ DECLARE_UVERBS_NAMED_METHOD( UA_MANDATORY, UA_ALLOC_AND_COPY)); +DECLARE_UVERBS_NAMED_METHOD( + UVERBS_METHOD_QUERY_MR, + UVERBS_ATTR_IDR(UVERBS_ATTR_QUERY_MR_HANDLE, + UVERBS_OBJECT_MR, + UVERBS_ACCESS_READ, + UA_MANDATORY), + UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_MR_RESP_RKEY, + UVERBS_ATTR_TYPE(u32), + UA_MANDATORY), + UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_MR_RESP_LKEY, + UVERBS_ATTR_TYPE(u32), + UA_MANDATORY), + UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_MR_RESP_LENGTH, + UVERBS_ATTR_TYPE(u64), + UA_MANDATORY), + UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_MR_RESP_IOVA, + UVERBS_ATTR_TYPE(u64), + UA_OPTIONAL)); + DECLARE_UVERBS_NAMED_METHOD( UVERBS_METHOD_DM_MR_REG, UVERBS_ATTR_IDR(UVERBS_ATTR_REG_DM_MR_HANDLE, @@ -206,7 +255,8 @@ DECLARE_UVERBS_NAMED_OBJECT( UVERBS_TYPE_ALLOC_IDR(uverbs_free_mr), &UVERBS_METHOD(UVERBS_METHOD_DM_MR_REG), &UVERBS_METHOD(UVERBS_METHOD_MR_DESTROY), - &UVERBS_METHOD(UVERBS_METHOD_ADVISE_MR)); + &UVERBS_METHOD(UVERBS_METHOD_ADVISE_MR), + &UVERBS_METHOD(UVERBS_METHOD_QUERY_MR)); const struct uapi_definition uverbs_def_obj_mr[] = { UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_MR, diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 53d6505c0c7b62c7accfdf4004b0c27cf595c2b5..3096e73797b775f706c4d257fd140024c9031ebe 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -988,8 +988,8 @@ EXPORT_SYMBOL(rdma_destroy_ah_user); * @srq_init_attr: A list of initial attributes required to create the * SRQ. If SRQ creation succeeds, then the attributes are updated to * the actual capabilities of the created SRQ. - * @uobject - uobject pointer if this is not a kernel SRQ - * @udata - udata pointer if this is not a kernel SRQ + * @uobject: uobject pointer if this is not a kernel SRQ + * @udata: udata pointer if this is not a kernel SRQ * * srq_attr->max_wr and srq_attr->max_sge are read the determine the * requested size of the SRQ, and set to the actual values allocated @@ -1090,13 +1090,6 @@ static void __ib_shared_qp_event_handler(struct ib_event *event, void *context) spin_unlock_irqrestore(&qp->device->qp_open_list_lock, flags); } -static void __ib_insert_xrcd_qp(struct ib_xrcd *xrcd, struct ib_qp *qp) -{ - mutex_lock(&xrcd->tgt_qp_mutex); - list_add(&qp->xrcd_list, &xrcd->tgt_qp_list); - mutex_unlock(&xrcd->tgt_qp_mutex); -} - static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp, void (*event_handler)(struct ib_event *, void *), void *qp_context) @@ -1139,16 +1132,15 @@ struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd, if (qp_open_attr->qp_type != IB_QPT_XRC_TGT) return ERR_PTR(-EINVAL); - qp = ERR_PTR(-EINVAL); - mutex_lock(&xrcd->tgt_qp_mutex); - list_for_each_entry(real_qp, &xrcd->tgt_qp_list, xrcd_list) { - if (real_qp->qp_num == qp_open_attr->qp_num) { - qp = __ib_open_qp(real_qp, qp_open_attr->event_handler, - qp_open_attr->qp_context); - break; - } + down_read(&xrcd->tgt_qps_rwsem); + real_qp = xa_load(&xrcd->tgt_qps, qp_open_attr->qp_num); + if (!real_qp) { + up_read(&xrcd->tgt_qps_rwsem); + return ERR_PTR(-EINVAL); } - mutex_unlock(&xrcd->tgt_qp_mutex); + qp = __ib_open_qp(real_qp, qp_open_attr->event_handler, + qp_open_attr->qp_context); + up_read(&xrcd->tgt_qps_rwsem); return qp; } EXPORT_SYMBOL(ib_open_qp); @@ -1157,6 +1149,7 @@ static struct ib_qp *create_xrc_qp_user(struct ib_qp *qp, struct ib_qp_init_attr *qp_init_attr) { struct ib_qp *real_qp = qp; + int err; qp->event_handler = __ib_shared_qp_event_handler; qp->qp_context = qp; @@ -1172,7 +1165,12 @@ static struct ib_qp *create_xrc_qp_user(struct ib_qp *qp, if (IS_ERR(qp)) return qp; - __ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp); + err = xa_err(xa_store(&qp_init_attr->xrcd->tgt_qps, real_qp->qp_num, + real_qp, GFP_KERNEL)); + if (err) { + ib_close_qp(qp); + return ERR_PTR(err); + } return qp; } @@ -1712,7 +1710,7 @@ static int _ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr, if (!(rdma_protocol_ib(qp->device, attr->alt_ah_attr.port_num) && rdma_protocol_ib(qp->device, port))) { - ret = EINVAL; + ret = -EINVAL; goto out; } } @@ -1887,21 +1885,18 @@ static int __ib_destroy_shared_qp(struct ib_qp *qp) real_qp = qp->real_qp; xrcd = real_qp->xrcd; - - mutex_lock(&xrcd->tgt_qp_mutex); + down_write(&xrcd->tgt_qps_rwsem); ib_close_qp(qp); if (atomic_read(&real_qp->usecnt) == 0) - list_del(&real_qp->xrcd_list); + xa_erase(&xrcd->tgt_qps, real_qp->qp_num); else real_qp = NULL; - mutex_unlock(&xrcd->tgt_qp_mutex); + up_write(&xrcd->tgt_qps_rwsem); if (real_qp) { ret = ib_destroy_qp(real_qp); if (!ret) atomic_dec(&xrcd->usecnt); - else - __ib_insert_xrcd_qp(xrcd, real_qp); } return 0; @@ -2077,6 +2072,9 @@ int ib_advise_mr(struct ib_pd *pd, enum ib_uverbs_advise_mr_advice advice, if (!pd->device->ops.advise_mr) return -EOPNOTSUPP; + if (!num_sge) + return 0; + return pd->device->ops.advise_mr(pd, advice, flags, sg_list, num_sge, NULL); } @@ -2104,11 +2102,10 @@ int ib_dereg_mr_user(struct ib_mr *mr, struct ib_udata *udata) EXPORT_SYMBOL(ib_dereg_mr_user); /** - * ib_alloc_mr_user() - Allocates a memory region + * ib_alloc_mr() - Allocates a memory region * @pd: protection domain associated with the region * @mr_type: memory region type * @max_num_sg: maximum sg entries available for registration. - * @udata: user data or null for kernel objects * * Notes: * Memory registeration page/sg lists must not exceed max_num_sg. @@ -2116,8 +2113,8 @@ EXPORT_SYMBOL(ib_dereg_mr_user); * max_num_sg * used_page_size. * */ -struct ib_mr *ib_alloc_mr_user(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata) +struct ib_mr *ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, + u32 max_num_sg) { struct ib_mr *mr; @@ -2132,25 +2129,26 @@ struct ib_mr *ib_alloc_mr_user(struct ib_pd *pd, enum ib_mr_type mr_type, goto out; } - mr = pd->device->ops.alloc_mr(pd, mr_type, max_num_sg, udata); - if (!IS_ERR(mr)) { - mr->device = pd->device; - mr->pd = pd; - mr->dm = NULL; - mr->uobject = NULL; - atomic_inc(&pd->usecnt); - mr->need_inval = false; - mr->res.type = RDMA_RESTRACK_MR; - rdma_restrack_kadd(&mr->res); - mr->type = mr_type; - mr->sig_attrs = NULL; - } + mr = pd->device->ops.alloc_mr(pd, mr_type, max_num_sg); + if (IS_ERR(mr)) + goto out; + + mr->device = pd->device; + mr->pd = pd; + mr->dm = NULL; + mr->uobject = NULL; + atomic_inc(&pd->usecnt); + mr->need_inval = false; + mr->res.type = RDMA_RESTRACK_MR; + rdma_restrack_kadd(&mr->res); + mr->type = mr_type; + mr->sig_attrs = NULL; out: trace_mr_alloc(pd, mr_type, max_num_sg, mr); return mr; } -EXPORT_SYMBOL(ib_alloc_mr_user); +EXPORT_SYMBOL(ib_alloc_mr); /** * ib_alloc_mr_integrity() - Allocates an integrity memory region @@ -2288,45 +2286,57 @@ int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) } EXPORT_SYMBOL(ib_detach_mcast); -struct ib_xrcd *__ib_alloc_xrcd(struct ib_device *device, const char *caller) +/** + * ib_alloc_xrcd_user - Allocates an XRC domain. + * @device: The device on which to allocate the XRC domain. + * @inode: inode to connect XRCD + * @udata: Valid user data or NULL for kernel object + */ +struct ib_xrcd *ib_alloc_xrcd_user(struct ib_device *device, + struct inode *inode, struct ib_udata *udata) { struct ib_xrcd *xrcd; + int ret; if (!device->ops.alloc_xrcd) return ERR_PTR(-EOPNOTSUPP); - xrcd = device->ops.alloc_xrcd(device, NULL); - if (!IS_ERR(xrcd)) { - xrcd->device = device; - xrcd->inode = NULL; - atomic_set(&xrcd->usecnt, 0); - mutex_init(&xrcd->tgt_qp_mutex); - INIT_LIST_HEAD(&xrcd->tgt_qp_list); - } + xrcd = rdma_zalloc_drv_obj(device, ib_xrcd); + if (!xrcd) + return ERR_PTR(-ENOMEM); + xrcd->device = device; + xrcd->inode = inode; + atomic_set(&xrcd->usecnt, 0); + init_rwsem(&xrcd->tgt_qps_rwsem); + xa_init(&xrcd->tgt_qps); + + ret = device->ops.alloc_xrcd(xrcd, udata); + if (ret) + goto err; return xrcd; +err: + kfree(xrcd); + return ERR_PTR(ret); } -EXPORT_SYMBOL(__ib_alloc_xrcd); +EXPORT_SYMBOL(ib_alloc_xrcd_user); -int ib_dealloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata) +/** + * ib_dealloc_xrcd_user - Deallocates an XRC domain. + * @xrcd: The XRC domain to deallocate. + * @udata: Valid user data or NULL for kernel object + */ +int ib_dealloc_xrcd_user(struct ib_xrcd *xrcd, struct ib_udata *udata) { - struct ib_qp *qp; - int ret; - if (atomic_read(&xrcd->usecnt)) return -EBUSY; - while (!list_empty(&xrcd->tgt_qp_list)) { - qp = list_entry(xrcd->tgt_qp_list.next, struct ib_qp, xrcd_list); - ret = ib_destroy_qp(qp); - if (ret) - return ret; - } - mutex_destroy(&xrcd->tgt_qp_mutex); - - return xrcd->device->ops.dealloc_xrcd(xrcd, udata); + WARN_ON(!xa_empty(&xrcd->tgt_qps)); + xrcd->device->ops.dealloc_xrcd(xrcd, udata); + kfree(xrcd); + return 0; } -EXPORT_SYMBOL(ib_dealloc_xrcd); +EXPORT_SYMBOL(ib_dealloc_xrcd_user); /** * ib_create_wq - Creates a WQ associated with the specified protection @@ -2409,45 +2419,6 @@ int ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr, } EXPORT_SYMBOL(ib_modify_wq); -/* - * ib_create_rwq_ind_table - Creates a RQ Indirection Table. - * @device: The device on which to create the rwq indirection table. - * @ib_rwq_ind_table_init_attr: A list of initial attributes required to - * create the Indirection Table. - * - * Note: The life time of ib_rwq_ind_table_init_attr->ind_tbl is not less - * than the created ib_rwq_ind_table object and the caller is responsible - * for its memory allocation/free. - */ -struct ib_rwq_ind_table *ib_create_rwq_ind_table(struct ib_device *device, - struct ib_rwq_ind_table_init_attr *init_attr) -{ - struct ib_rwq_ind_table *rwq_ind_table; - int i; - u32 table_size; - - if (!device->ops.create_rwq_ind_table) - return ERR_PTR(-EOPNOTSUPP); - - table_size = (1 << init_attr->log_ind_tbl_size); - rwq_ind_table = device->ops.create_rwq_ind_table(device, - init_attr, NULL); - if (IS_ERR(rwq_ind_table)) - return rwq_ind_table; - - rwq_ind_table->ind_tbl = init_attr->ind_tbl; - rwq_ind_table->log_ind_tbl_size = init_attr->log_ind_tbl_size; - rwq_ind_table->device = device; - rwq_ind_table->uobject = NULL; - atomic_set(&rwq_ind_table->usecnt, 0); - - for (i = 0; i < table_size; i++) - atomic_inc(&rwq_ind_table->ind_tbl[i]->usecnt); - - return rwq_ind_table; -} -EXPORT_SYMBOL(ib_create_rwq_ind_table); - /* * ib_destroy_rwq_ind_table - Destroys the specified Indirection Table. * @wq_ind_table: The Indirection Table to destroy. diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c index 8b6ad5cddfce99ef5b7fdb9d19187b77865d4274..3f18efc0c29744507d3119bc81438b58f3aa067f 100644 --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c @@ -842,16 +842,79 @@ static u8 __from_ib_qp_type(enum ib_qp_type type) } } +static u16 bnxt_re_setup_rwqe_size(struct bnxt_qplib_qp *qplqp, + int rsge, int max) +{ + if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) + rsge = max; + return bnxt_re_get_rwqe_size(rsge); +} + +static u16 bnxt_re_get_wqe_size(int ilsize, int nsge) +{ + u16 wqe_size, calc_ils; + + wqe_size = bnxt_re_get_swqe_size(nsge); + if (ilsize) { + calc_ils = sizeof(struct sq_send_hdr) + ilsize; + wqe_size = max_t(u16, calc_ils, wqe_size); + wqe_size = ALIGN(wqe_size, sizeof(struct sq_send_hdr)); + } + return wqe_size; +} + +static int bnxt_re_setup_swqe_size(struct bnxt_re_qp *qp, + struct ib_qp_init_attr *init_attr) +{ + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_qplib_qp *qplqp; + struct bnxt_re_dev *rdev; + struct bnxt_qplib_q *sq; + int align, ilsize; + + rdev = qp->rdev; + qplqp = &qp->qplib_qp; + sq = &qplqp->sq; + dev_attr = &rdev->dev_attr; + + align = sizeof(struct sq_send_hdr); + ilsize = ALIGN(init_attr->cap.max_inline_data, align); + + sq->wqe_size = bnxt_re_get_wqe_size(ilsize, sq->max_sge); + if (sq->wqe_size > bnxt_re_get_swqe_size(dev_attr->max_qp_sges)) + return -EINVAL; + /* For gen p4 and gen p5 backward compatibility mode + * wqe size is fixed to 128 bytes + */ + if (sq->wqe_size < bnxt_re_get_swqe_size(dev_attr->max_qp_sges) && + qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) + sq->wqe_size = bnxt_re_get_swqe_size(dev_attr->max_qp_sges); + + if (init_attr->cap.max_inline_data) { + qplqp->max_inline_data = sq->wqe_size - + sizeof(struct sq_send_hdr); + init_attr->cap.max_inline_data = qplqp->max_inline_data; + if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) + sq->max_sge = qplqp->max_inline_data / + sizeof(struct sq_sge); + } + + return 0; +} + static int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, struct bnxt_re_pd *pd, struct bnxt_re_qp *qp, struct ib_udata *udata) { + struct bnxt_qplib_qp *qplib_qp; + struct bnxt_re_ucontext *cntx; struct bnxt_re_qp_req ureq; - struct bnxt_qplib_qp *qplib_qp = &qp->qplib_qp; - struct ib_umem *umem; int bytes = 0, psn_sz; - struct bnxt_re_ucontext *cntx = rdma_udata_to_drv_context( - udata, struct bnxt_re_ucontext, ib_uctx); + struct ib_umem *umem; + int psn_nume; + qplib_qp = &qp->qplib_qp; + cntx = rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, + ib_uctx); if (ib_copy_from_udata(&ureq, udata, sizeof(ureq))) return -EFAULT; @@ -859,10 +922,15 @@ static int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, struct bnxt_re_pd *pd, /* Consider mapping PSN search memory only for RC QPs. */ if (qplib_qp->type == CMDQ_CREATE_QP_TYPE_RC) { psn_sz = bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx) ? - sizeof(struct sq_psn_search_ext) : - sizeof(struct sq_psn_search); - bytes += (qplib_qp->sq.max_wqe * psn_sz); + sizeof(struct sq_psn_search_ext) : + sizeof(struct sq_psn_search); + psn_nume = (qplib_qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? + qplib_qp->sq.max_wqe : + ((qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size) / + sizeof(struct bnxt_qplib_sge)); + bytes += (psn_nume * psn_sz); } + bytes = PAGE_ALIGN(bytes); umem = ib_umem_get(&rdev->ibdev, ureq.qpsva, bytes, IB_ACCESS_LOCAL_WRITE); @@ -975,7 +1043,7 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp qp->qplib_qp.sig_type = true; /* Shadow QP SQ depth should be same as QP1 RQ depth */ - qp->qplib_qp.sq.wqe_size = bnxt_re_get_swqe_size(); + qp->qplib_qp.sq.wqe_size = bnxt_re_get_wqe_size(0, 6); qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe; qp->qplib_qp.sq.max_sge = 2; /* Q full delta can be 1 since it is internal QP */ @@ -986,7 +1054,7 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp qp->qplib_qp.scq = qp1_qp->scq; qp->qplib_qp.rcq = qp1_qp->rcq; - qp->qplib_qp.rq.wqe_size = bnxt_re_get_rwqe_size(); + qp->qplib_qp.rq.wqe_size = bnxt_re_get_rwqe_size(6); qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe; qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge; /* Q full delta can be 1 since it is internal QP */ @@ -1041,19 +1109,21 @@ static int bnxt_re_init_rq_attr(struct bnxt_re_qp *qp, qplqp->srq = &srq->qplib_srq; rq->max_wqe = 0; } else { - rq->wqe_size = bnxt_re_get_rwqe_size(); + rq->max_sge = init_attr->cap.max_recv_sge; + if (rq->max_sge > dev_attr->max_qp_sges) + rq->max_sge = dev_attr->max_qp_sges; + init_attr->cap.max_recv_sge = rq->max_sge; + rq->wqe_size = bnxt_re_setup_rwqe_size(qplqp, rq->max_sge, + dev_attr->max_qp_sges); /* Allocate 1 more than what's provided so posting max doesn't * mean empty. */ entries = roundup_pow_of_two(init_attr->cap.max_recv_wr + 1); rq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + 1); - rq->q_full_delta = rq->max_wqe - init_attr->cap.max_recv_wr; - rq->max_sge = init_attr->cap.max_recv_sge; - if (rq->max_sge > dev_attr->max_qp_sges) - rq->max_sge = dev_attr->max_qp_sges; + rq->q_full_delta = 0; + rq->sg_info.pgsize = PAGE_SIZE; + rq->sg_info.pgshft = PAGE_SHIFT; } - rq->sg_info.pgsize = PAGE_SIZE; - rq->sg_info.pgshft = PAGE_SHIFT; return 0; } @@ -1068,41 +1138,48 @@ static void bnxt_re_adjust_gsi_rq_attr(struct bnxt_re_qp *qp) qplqp = &qp->qplib_qp; dev_attr = &rdev->dev_attr; - qplqp->rq.max_sge = dev_attr->max_qp_sges; - if (qplqp->rq.max_sge > dev_attr->max_qp_sges) + if (!bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx)) { qplqp->rq.max_sge = dev_attr->max_qp_sges; - qplqp->rq.max_sge = 6; + if (qplqp->rq.max_sge > dev_attr->max_qp_sges) + qplqp->rq.max_sge = dev_attr->max_qp_sges; + qplqp->rq.max_sge = 6; + } } -static void bnxt_re_init_sq_attr(struct bnxt_re_qp *qp, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata) +static int bnxt_re_init_sq_attr(struct bnxt_re_qp *qp, + struct ib_qp_init_attr *init_attr, + struct ib_udata *udata) { struct bnxt_qplib_dev_attr *dev_attr; struct bnxt_qplib_qp *qplqp; struct bnxt_re_dev *rdev; struct bnxt_qplib_q *sq; int entries; + int diff; + int rc; rdev = qp->rdev; qplqp = &qp->qplib_qp; sq = &qplqp->sq; dev_attr = &rdev->dev_attr; - sq->wqe_size = bnxt_re_get_swqe_size(); sq->max_sge = init_attr->cap.max_send_sge; - if (sq->max_sge > dev_attr->max_qp_sges) + if (sq->max_sge > dev_attr->max_qp_sges) { sq->max_sge = dev_attr->max_qp_sges; - /* - * Change the SQ depth if user has requested minimum using - * configfs. Only supported for kernel consumers - */ + init_attr->cap.max_send_sge = sq->max_sge; + } + + rc = bnxt_re_setup_swqe_size(qp, init_attr); + if (rc) + return rc; + entries = init_attr->cap.max_send_wr; /* Allocate 128 + 1 more than what's provided */ - entries = roundup_pow_of_two(entries + BNXT_QPLIB_RESERVED_QP_WRS + 1); - sq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + - BNXT_QPLIB_RESERVED_QP_WRS + 1); - sq->q_full_delta = BNXT_QPLIB_RESERVED_QP_WRS + 1; + diff = (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) ? + 0 : BNXT_QPLIB_RESERVED_QP_WRS; + entries = roundup_pow_of_two(entries + diff + 1); + sq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + diff + 1); + sq->q_full_delta = diff + 1; /* * Reserving one slot for Phantom WQE. Application can * post one extra entry in this case. But allowing this to avoid @@ -1111,6 +1188,8 @@ static void bnxt_re_init_sq_attr(struct bnxt_re_qp *qp, qplqp->sq.q_full_delta -= 1; qplqp->sq.sg_info.pgsize = PAGE_SIZE; qplqp->sq.sg_info.pgshft = PAGE_SHIFT; + + return 0; } static void bnxt_re_adjust_gsi_sq_attr(struct bnxt_re_qp *qp, @@ -1125,13 +1204,16 @@ static void bnxt_re_adjust_gsi_sq_attr(struct bnxt_re_qp *qp, qplqp = &qp->qplib_qp; dev_attr = &rdev->dev_attr; - entries = roundup_pow_of_two(init_attr->cap.max_send_wr + 1); - qplqp->sq.max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + 1); - qplqp->sq.q_full_delta = qplqp->sq.max_wqe - - init_attr->cap.max_send_wr; - qplqp->sq.max_sge++; /* Need one extra sge to put UD header */ - if (qplqp->sq.max_sge > dev_attr->max_qp_sges) - qplqp->sq.max_sge = dev_attr->max_qp_sges; + if (!bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx)) { + entries = roundup_pow_of_two(init_attr->cap.max_send_wr + 1); + qplqp->sq.max_wqe = min_t(u32, entries, + dev_attr->max_qp_wqes + 1); + qplqp->sq.q_full_delta = qplqp->sq.max_wqe - + init_attr->cap.max_send_wr; + qplqp->sq.max_sge++; /* Need one extra sge to put UD header */ + if (qplqp->sq.max_sge > dev_attr->max_qp_sges) + qplqp->sq.max_sge = dev_attr->max_qp_sges; + } } static int bnxt_re_init_qp_type(struct bnxt_re_dev *rdev, @@ -1183,6 +1265,7 @@ static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd, goto out; } qplqp->type = (u8)qptype; + qplqp->wqe_mode = rdev->chip_ctx->modes.wqe_mode; if (init_attr->qp_type == IB_QPT_RC) { qplqp->max_rd_atomic = dev_attr->max_qp_rd_atom; @@ -1226,7 +1309,9 @@ static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd, bnxt_re_adjust_gsi_rq_attr(qp); /* Setup SQ */ - bnxt_re_init_sq_attr(qp, init_attr, udata); + rc = bnxt_re_init_sq_attr(qp, init_attr, udata); + if (rc) + goto out; if (init_attr->qp_type == IB_QPT_GSI) bnxt_re_adjust_gsi_sq_attr(qp, init_attr); @@ -1574,8 +1659,9 @@ int bnxt_re_create_srq(struct ib_srq *ib_srq, entries = dev_attr->max_srq_wqes + 1; srq->qplib_srq.max_wqe = entries; - srq->qplib_srq.wqe_size = bnxt_re_get_rwqe_size(); srq->qplib_srq.max_sge = srq_init_attr->attr.max_sge; + srq->qplib_srq.wqe_size = + bnxt_re_get_rwqe_size(srq->qplib_srq.max_sge); srq->qplib_srq.threshold = srq_init_attr->attr.srq_limit; srq->srq_limit = srq_init_attr->attr.srq_limit; srq->qplib_srq.eventq_hw_ring_id = rdev->nq[0].ring_id; @@ -3569,7 +3655,7 @@ int bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents, } struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type type, - u32 max_num_sg, struct ib_udata *udata) + u32 max_num_sg) { struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd); struct bnxt_re_dev *rdev = pd->rdev; diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h index e5fbbeba6d28d3e3d80a7091a71799c6f65ab8f1..1daeb30e06fda31d4bad167d44fbc328b2c5a4f9 100644 --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h @@ -136,14 +136,14 @@ struct bnxt_re_ucontext { spinlock_t sh_lock; /* protect shpg */ }; -static inline u16 bnxt_re_get_swqe_size(void) +static inline u16 bnxt_re_get_swqe_size(int nsge) { - return sizeof(struct sq_send); + return sizeof(struct sq_send_hdr) + nsge * sizeof(struct sq_sge); } -static inline u16 bnxt_re_get_rwqe_size(void) +static inline u16 bnxt_re_get_rwqe_size(int nsge) { - return sizeof(struct rq_wqe); + return sizeof(struct rq_wqe_hdr) + (nsge * sizeof(struct sq_sge)); } int bnxt_re_query_device(struct ib_device *ibdev, @@ -201,7 +201,7 @@ struct ib_mr *bnxt_re_get_dma_mr(struct ib_pd *pd, int mr_access_flags); int bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents, unsigned int *sg_offset); struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata); + u32 max_num_sg); int bnxt_re_dereg_mr(struct ib_mr *mr, struct ib_udata *udata); struct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type, struct ib_udata *udata); diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c index b12fbc857f94253166aabb6aeeddc18d1184cb95..dad0df8a2467993aca1dac4d782bf2045292e62e 100644 --- a/drivers/infiniband/hw/bnxt_re/main.c +++ b/drivers/infiniband/hw/bnxt_re/main.c @@ -82,6 +82,15 @@ static void bnxt_re_remove_device(struct bnxt_re_dev *rdev); static void bnxt_re_dealloc_driver(struct ib_device *ib_dev); static void bnxt_re_stop_irq(void *handle); +static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev, u8 mode) +{ + struct bnxt_qplib_chip_ctx *cctx; + + cctx = rdev->chip_ctx; + cctx->modes.wqe_mode = bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx) ? + mode : BNXT_QPLIB_WQE_MODE_STATIC; +} + static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev) { struct bnxt_qplib_chip_ctx *chip_ctx; @@ -97,7 +106,7 @@ static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev) kfree(chip_ctx); } -static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev) +static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode) { struct bnxt_qplib_chip_ctx *chip_ctx; struct bnxt_en_dev *en_dev; @@ -117,6 +126,7 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev) rdev->qplib_res.cctx = rdev->chip_ctx; rdev->rcfw.res = &rdev->qplib_res; + bnxt_re_set_drv_mode(rdev, wqe_mode); return 0; } @@ -1386,7 +1396,7 @@ static void bnxt_re_worker(struct work_struct *work) schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000)); } -static int bnxt_re_dev_init(struct bnxt_re_dev *rdev) +static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode) { struct bnxt_qplib_creq_ctx *creq; struct bnxt_re_ring_attr rattr; @@ -1406,7 +1416,7 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev) } set_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags); - rc = bnxt_re_setup_chip_ctx(rdev); + rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode); if (rc) { ibdev_err(&rdev->ibdev, "Failed to get chip context\n"); return -EINVAL; @@ -1585,7 +1595,7 @@ static void bnxt_re_remove_device(struct bnxt_re_dev *rdev) } static int bnxt_re_add_device(struct bnxt_re_dev **rdev, - struct net_device *netdev) + struct net_device *netdev, u8 wqe_mode) { int rc; @@ -1599,7 +1609,7 @@ static int bnxt_re_add_device(struct bnxt_re_dev **rdev, } pci_dev_get((*rdev)->en_dev->pdev); - rc = bnxt_re_dev_init(*rdev); + rc = bnxt_re_dev_init(*rdev, wqe_mode); if (rc) { pci_dev_put((*rdev)->en_dev->pdev); bnxt_re_dev_unreg(*rdev); @@ -1711,7 +1721,8 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier, case NETDEV_REGISTER: if (rdev) break; - rc = bnxt_re_add_device(&rdev, real_dev); + rc = bnxt_re_add_device(&rdev, real_dev, + BNXT_QPLIB_WQE_MODE_STATIC); if (!rc) sch_work = true; release = false; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c index c5e29577cd43444152d27f79ea2997be7f4758d4..117b42349a283683c7ea006628a93f71ee42e9dd 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c @@ -178,11 +178,11 @@ static void bnxt_qplib_free_qp_hdr_buf(struct bnxt_qplib_res *res, if (qp->rq_hdr_buf) dma_free_coherent(&res->pdev->dev, - rq->hwq.max_elements * qp->rq_hdr_buf_size, + rq->max_wqe * qp->rq_hdr_buf_size, qp->rq_hdr_buf, qp->rq_hdr_buf_map); if (qp->sq_hdr_buf) dma_free_coherent(&res->pdev->dev, - sq->hwq.max_elements * qp->sq_hdr_buf_size, + sq->max_wqe * qp->sq_hdr_buf_size, qp->sq_hdr_buf, qp->sq_hdr_buf_map); qp->rq_hdr_buf = NULL; qp->sq_hdr_buf = NULL; @@ -199,10 +199,9 @@ static int bnxt_qplib_alloc_qp_hdr_buf(struct bnxt_qplib_res *res, struct bnxt_qplib_q *sq = &qp->sq; int rc = 0; - if (qp->sq_hdr_buf_size && sq->hwq.max_elements) { + if (qp->sq_hdr_buf_size && sq->max_wqe) { qp->sq_hdr_buf = dma_alloc_coherent(&res->pdev->dev, - sq->hwq.max_elements * - qp->sq_hdr_buf_size, + sq->max_wqe * qp->sq_hdr_buf_size, &qp->sq_hdr_buf_map, GFP_KERNEL); if (!qp->sq_hdr_buf) { rc = -ENOMEM; @@ -212,9 +211,9 @@ static int bnxt_qplib_alloc_qp_hdr_buf(struct bnxt_qplib_res *res, } } - if (qp->rq_hdr_buf_size && rq->hwq.max_elements) { + if (qp->rq_hdr_buf_size && rq->max_wqe) { qp->rq_hdr_buf = dma_alloc_coherent(&res->pdev->dev, - rq->hwq.max_elements * + rq->max_wqe * qp->rq_hdr_buf_size, &qp->rq_hdr_buf_map, GFP_KERNEL); @@ -661,6 +660,7 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, srq->dbinfo.hwq = &srq->hwq; srq->dbinfo.xid = srq->id; srq->dbinfo.db = srq->dpi->dbr; + srq->dbinfo.max_slot = 1; srq->dbinfo.priv_db = res->dpi_tbl.dbr_bar_reg_iomem; if (srq->threshold) bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA); @@ -784,6 +784,28 @@ done: } /* QP */ + +static int bnxt_qplib_alloc_init_swq(struct bnxt_qplib_q *que) +{ + int rc = 0; + int indx; + + que->swq = kcalloc(que->max_wqe, sizeof(*que->swq), GFP_KERNEL); + if (!que->swq) { + rc = -ENOMEM; + goto out; + } + + que->swq_start = 0; + que->swq_last = que->max_wqe - 1; + for (indx = 0; indx < que->max_wqe; indx++) + que->swq[indx].next_idx = indx + 1; + que->swq[que->swq_last].next_idx = 0; /* Make it circular */ + que->swq_last = 0; +out: + return rc; +} + int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) { struct bnxt_qplib_hwq_attr hwq_attr = {}; @@ -808,71 +830,63 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) /* SQ */ hwq_attr.res = res; hwq_attr.sginfo = &sq->sg_info; - hwq_attr.depth = sq->max_wqe; - hwq_attr.stride = sq->wqe_size; + hwq_attr.stride = sizeof(struct sq_sge); + hwq_attr.depth = bnxt_qplib_get_depth(sq); hwq_attr.type = HWQ_TYPE_QUEUE; rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr); if (rc) goto exit; - sq->swq = kcalloc(sq->hwq.max_elements, sizeof(*sq->swq), GFP_KERNEL); - if (!sq->swq) { - rc = -ENOMEM; + rc = bnxt_qplib_alloc_init_swq(sq); + if (rc) goto fail_sq; - } + + req.sq_size = cpu_to_le32(bnxt_qplib_set_sq_size(sq, qp->wqe_mode)); pbl = &sq->hwq.pbl[PBL_LVL_0]; req.sq_pbl = cpu_to_le64(pbl->pg_map_arr[0]); pg_sz_lvl = (bnxt_qplib_base_pg_size(&sq->hwq) << CMDQ_CREATE_QP1_SQ_PG_SIZE_SFT); pg_sz_lvl |= (sq->hwq.level & CMDQ_CREATE_QP1_SQ_LVL_MASK); req.sq_pg_size_sq_lvl = pg_sz_lvl; + req.sq_fwo_sq_sge = + cpu_to_le16((sq->max_sge & CMDQ_CREATE_QP1_SQ_SGE_MASK) << + CMDQ_CREATE_QP1_SQ_SGE_SFT); + req.scq_cid = cpu_to_le32(qp->scq->id); - if (qp->scq) - req.scq_cid = cpu_to_le32(qp->scq->id); /* RQ */ if (rq->max_wqe) { hwq_attr.res = res; hwq_attr.sginfo = &rq->sg_info; - hwq_attr.stride = rq->wqe_size; - hwq_attr.depth = qp->rq.max_wqe; + hwq_attr.stride = sizeof(struct sq_sge); + hwq_attr.depth = bnxt_qplib_get_depth(rq); hwq_attr.type = HWQ_TYPE_QUEUE; rc = bnxt_qplib_alloc_init_hwq(&rq->hwq, &hwq_attr); if (rc) - goto fail_sq; - - rq->swq = kcalloc(rq->hwq.max_elements, sizeof(*rq->swq), - GFP_KERNEL); - if (!rq->swq) { - rc = -ENOMEM; + goto sq_swq; + rc = bnxt_qplib_alloc_init_swq(rq); + if (rc) goto fail_rq; - } + req.rq_size = cpu_to_le32(rq->max_wqe); pbl = &rq->hwq.pbl[PBL_LVL_0]; req.rq_pbl = cpu_to_le64(pbl->pg_map_arr[0]); pg_sz_lvl = (bnxt_qplib_base_pg_size(&rq->hwq) << CMDQ_CREATE_QP1_RQ_PG_SIZE_SFT); pg_sz_lvl |= (rq->hwq.level & CMDQ_CREATE_QP1_RQ_LVL_MASK); req.rq_pg_size_rq_lvl = pg_sz_lvl; - if (qp->rcq) - req.rcq_cid = cpu_to_le32(qp->rcq->id); + req.rq_fwo_rq_sge = + cpu_to_le16((rq->max_sge & + CMDQ_CREATE_QP1_RQ_SGE_MASK) << + CMDQ_CREATE_QP1_RQ_SGE_SFT); } + req.rcq_cid = cpu_to_le32(qp->rcq->id); /* Header buffer - allow hdr_buf pass in */ rc = bnxt_qplib_alloc_qp_hdr_buf(res, qp); if (rc) { rc = -ENOMEM; - goto fail; + goto rq_rwq; } qp_flags |= CMDQ_CREATE_QP1_QP_FLAGS_RESERVED_LKEY_ENABLE; req.qp_flags = cpu_to_le32(qp_flags); - req.sq_size = cpu_to_le32(sq->hwq.max_elements); - req.rq_size = cpu_to_le32(rq->hwq.max_elements); - - req.sq_fwo_sq_sge = - cpu_to_le16((sq->max_sge & CMDQ_CREATE_QP1_SQ_SGE_MASK) << - CMDQ_CREATE_QP1_SQ_SGE_SFT); - req.rq_fwo_rq_sge = - cpu_to_le16((rq->max_sge & CMDQ_CREATE_QP1_RQ_SGE_MASK) << - CMDQ_CREATE_QP1_RQ_SGE_SFT); - req.pd_id = cpu_to_le32(qp->pd->id); rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, @@ -886,10 +900,12 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) sq->dbinfo.hwq = &sq->hwq; sq->dbinfo.xid = qp->id; sq->dbinfo.db = qp->dpi->dbr; + sq->dbinfo.max_slot = bnxt_qplib_set_sq_max_slot(qp->wqe_mode); if (rq->max_wqe) { rq->dbinfo.hwq = &rq->hwq; rq->dbinfo.xid = qp->id; rq->dbinfo.db = qp->dpi->dbr; + rq->dbinfo.max_slot = bnxt_qplib_set_rq_max_slot(rq->wqe_size); } rcfw->qp_tbl[qp->id].qp_id = qp->id; rcfw->qp_tbl[qp->id].qp_handle = (void *)qp; @@ -898,12 +914,14 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) fail: bnxt_qplib_free_qp_hdr_buf(res, qp); +rq_rwq: + kfree(rq->swq); fail_rq: bnxt_qplib_free_hwq(res, &rq->hwq); - kfree(rq->swq); +sq_swq: + kfree(sq->swq); fail_sq: bnxt_qplib_free_hwq(res, &sq->hwq); - kfree(sq->swq); exit: return rc; } @@ -912,26 +930,18 @@ static void bnxt_qplib_init_psn_ptr(struct bnxt_qplib_qp *qp, int size) { struct bnxt_qplib_hwq *hwq; struct bnxt_qplib_q *sq; - u64 fpsne, psne, psn_pg; - u16 indx_pad = 0, indx; - u16 pg_num, pg_indx; - u64 *page; + u64 fpsne, psn_pg; + u16 indx_pad = 0; sq = &qp->sq; hwq = &sq->hwq; - - fpsne = (u64)bnxt_qplib_get_qe(hwq, hwq->max_elements, &psn_pg); + fpsne = (u64)bnxt_qplib_get_qe(hwq, hwq->depth, &psn_pg); if (!IS_ALIGNED(fpsne, PAGE_SIZE)) indx_pad = ALIGN(fpsne, PAGE_SIZE) / size; - page = (u64 *)psn_pg; - for (indx = 0; indx < hwq->max_elements; indx++) { - pg_num = (indx + indx_pad) / (PAGE_SIZE / size); - pg_indx = (indx + indx_pad) % (PAGE_SIZE / size); - psne = page[pg_num] + pg_indx * size; - sq->swq[indx].psn_ext = (struct sq_psn_search_ext *)psne; - sq->swq[indx].psn_search = (struct sq_psn_search *)psne; - } + hwq->pad_pgofft = indx_pad; + hwq->pad_pg = (u64 *)psn_pg; + hwq->pad_stride = size; } int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) @@ -944,12 +954,12 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) struct creq_create_qp_resp resp; int rc, req_size, psn_sz = 0; struct bnxt_qplib_hwq *xrrq; - u16 cmd_flags = 0, max_ssge; struct bnxt_qplib_pbl *pbl; struct cmdq_create_qp req; + u16 cmd_flags = 0; u32 qp_flags = 0; u8 pg_sz_lvl; - u16 max_rsge; + u16 nsge; RCFW_CMD_PREP(req, CREATE_QP, cmd_flags); @@ -967,97 +977,78 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) hwq_attr.res = res; hwq_attr.sginfo = &sq->sg_info; - hwq_attr.stride = sq->wqe_size; - hwq_attr.depth = sq->max_wqe; + hwq_attr.stride = sizeof(struct sq_sge); + hwq_attr.depth = bnxt_qplib_get_depth(sq); hwq_attr.aux_stride = psn_sz; - hwq_attr.aux_depth = hwq_attr.depth; + hwq_attr.aux_depth = bnxt_qplib_set_sq_size(sq, qp->wqe_mode); hwq_attr.type = HWQ_TYPE_QUEUE; rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr); if (rc) goto exit; - sq->swq = kcalloc(sq->hwq.max_elements, sizeof(*sq->swq), GFP_KERNEL); - if (!sq->swq) { - rc = -ENOMEM; + rc = bnxt_qplib_alloc_init_swq(sq); + if (rc) goto fail_sq; - } if (psn_sz) bnxt_qplib_init_psn_ptr(qp, psn_sz); + req.sq_size = cpu_to_le32(bnxt_qplib_set_sq_size(sq, qp->wqe_mode)); pbl = &sq->hwq.pbl[PBL_LVL_0]; req.sq_pbl = cpu_to_le64(pbl->pg_map_arr[0]); pg_sz_lvl = (bnxt_qplib_base_pg_size(&sq->hwq) << CMDQ_CREATE_QP_SQ_PG_SIZE_SFT); pg_sz_lvl |= (sq->hwq.level & CMDQ_CREATE_QP_SQ_LVL_MASK); req.sq_pg_size_sq_lvl = pg_sz_lvl; - - if (qp->scq) - req.scq_cid = cpu_to_le32(qp->scq->id); + req.sq_fwo_sq_sge = + cpu_to_le16(((sq->max_sge & CMDQ_CREATE_QP_SQ_SGE_MASK) << + CMDQ_CREATE_QP_SQ_SGE_SFT) | 0); + req.scq_cid = cpu_to_le32(qp->scq->id); /* RQ */ - if (rq->max_wqe) { + if (!qp->srq) { hwq_attr.res = res; hwq_attr.sginfo = &rq->sg_info; - hwq_attr.stride = rq->wqe_size; - hwq_attr.depth = rq->max_wqe; + hwq_attr.stride = sizeof(struct sq_sge); + hwq_attr.depth = bnxt_qplib_get_depth(rq); hwq_attr.aux_stride = 0; hwq_attr.aux_depth = 0; hwq_attr.type = HWQ_TYPE_QUEUE; rc = bnxt_qplib_alloc_init_hwq(&rq->hwq, &hwq_attr); if (rc) - goto fail_sq; - - rq->swq = kcalloc(rq->hwq.max_elements, sizeof(*rq->swq), - GFP_KERNEL); - if (!rq->swq) { - rc = -ENOMEM; + goto sq_swq; + rc = bnxt_qplib_alloc_init_swq(rq); + if (rc) goto fail_rq; - } + + req.rq_size = cpu_to_le32(rq->max_wqe); pbl = &rq->hwq.pbl[PBL_LVL_0]; req.rq_pbl = cpu_to_le64(pbl->pg_map_arr[0]); pg_sz_lvl = (bnxt_qplib_base_pg_size(&rq->hwq) << CMDQ_CREATE_QP_RQ_PG_SIZE_SFT); pg_sz_lvl |= (rq->hwq.level & CMDQ_CREATE_QP_RQ_LVL_MASK); req.rq_pg_size_rq_lvl = pg_sz_lvl; + nsge = (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? + 6 : rq->max_sge; + req.rq_fwo_rq_sge = + cpu_to_le16(((nsge & + CMDQ_CREATE_QP_RQ_SGE_MASK) << + CMDQ_CREATE_QP_RQ_SGE_SFT) | 0); } else { /* SRQ */ - if (qp->srq) { - qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_SRQ_USED; - req.srq_cid = cpu_to_le32(qp->srq->id); - } + qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_SRQ_USED; + req.srq_cid = cpu_to_le32(qp->srq->id); } - - if (qp->rcq) - req.rcq_cid = cpu_to_le32(qp->rcq->id); + req.rcq_cid = cpu_to_le32(qp->rcq->id); qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_RESERVED_LKEY_ENABLE; qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_FR_PMR_ENABLED; if (qp->sig_type) qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_FORCE_COMPLETION; + if (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) + qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_VARIABLE_SIZED_WQE_ENABLED; req.qp_flags = cpu_to_le32(qp_flags); - req.sq_size = cpu_to_le32(sq->hwq.max_elements); - req.rq_size = cpu_to_le32(rq->hwq.max_elements); - qp->sq_hdr_buf = NULL; - qp->rq_hdr_buf = NULL; - - rc = bnxt_qplib_alloc_qp_hdr_buf(res, qp); - if (rc) - goto fail_rq; - - /* CTRL-22434: Irrespective of the requested SGE count on the SQ - * always create the QP with max send sges possible if the requested - * inline size is greater than 0. - */ - max_ssge = qp->max_inline_data ? 6 : sq->max_sge; - req.sq_fwo_sq_sge = cpu_to_le16( - ((max_ssge & CMDQ_CREATE_QP_SQ_SGE_MASK) - << CMDQ_CREATE_QP_SQ_SGE_SFT) | 0); - max_rsge = bnxt_qplib_is_chip_gen_p5(res->cctx) ? 6 : rq->max_sge; - req.rq_fwo_rq_sge = cpu_to_le16( - ((max_rsge & CMDQ_CREATE_QP_RQ_SGE_MASK) - << CMDQ_CREATE_QP_RQ_SGE_SFT) | 0); /* ORRQ and IRRQ */ if (psn_sz) { xrrq = &qp->orrq; @@ -1078,7 +1069,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) hwq_attr.type = HWQ_TYPE_CTX; rc = bnxt_qplib_alloc_init_hwq(xrrq, &hwq_attr); if (rc) - goto fail_buf_free; + goto rq_swq; pbl = &xrrq->pbl[PBL_LVL_0]; req.orrq_addr = cpu_to_le64(pbl->pg_map_arr[0]); @@ -1113,30 +1104,29 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) sq->dbinfo.hwq = &sq->hwq; sq->dbinfo.xid = qp->id; sq->dbinfo.db = qp->dpi->dbr; + sq->dbinfo.max_slot = bnxt_qplib_set_sq_max_slot(qp->wqe_mode); if (rq->max_wqe) { rq->dbinfo.hwq = &rq->hwq; rq->dbinfo.xid = qp->id; rq->dbinfo.db = qp->dpi->dbr; + rq->dbinfo.max_slot = bnxt_qplib_set_rq_max_slot(rq->wqe_size); } rcfw->qp_tbl[qp->id].qp_id = qp->id; rcfw->qp_tbl[qp->id].qp_handle = (void *)qp; return 0; - fail: - if (qp->irrq.max_elements) - bnxt_qplib_free_hwq(res, &qp->irrq); + bnxt_qplib_free_hwq(res, &qp->irrq); fail_orrq: - if (qp->orrq.max_elements) - bnxt_qplib_free_hwq(res, &qp->orrq); -fail_buf_free: - bnxt_qplib_free_qp_hdr_buf(res, qp); + bnxt_qplib_free_hwq(res, &qp->orrq); +rq_swq: + kfree(rq->swq); fail_rq: bnxt_qplib_free_hwq(res, &rq->hwq); - kfree(rq->swq); +sq_swq: + kfree(sq->swq); fail_sq: bnxt_qplib_free_hwq(res, &sq->hwq); - kfree(sq->swq); exit: return rc; } @@ -1512,7 +1502,7 @@ void *bnxt_qplib_get_qp1_sq_buf(struct bnxt_qplib_qp *qp, memset(sge, 0, sizeof(*sge)); if (qp->sq_hdr_buf) { - sw_prod = HWQ_CMP(sq->hwq.prod, &sq->hwq); + sw_prod = sq->swq_start; sge->addr = (dma_addr_t)(qp->sq_hdr_buf_map + sw_prod * qp->sq_hdr_buf_size); sge->lkey = 0xFFFFFFFF; @@ -1526,7 +1516,7 @@ u32 bnxt_qplib_get_rq_prod_index(struct bnxt_qplib_qp *qp) { struct bnxt_qplib_q *rq = &qp->rq; - return HWQ_CMP(rq->hwq.prod, &rq->hwq); + return rq->swq_start; } dma_addr_t bnxt_qplib_get_qp_buf_from_index(struct bnxt_qplib_qp *qp, u32 index) @@ -1543,7 +1533,7 @@ void *bnxt_qplib_get_qp1_rq_buf(struct bnxt_qplib_qp *qp, memset(sge, 0, sizeof(*sge)); if (qp->rq_hdr_buf) { - sw_prod = HWQ_CMP(rq->hwq.prod, &rq->hwq); + sw_prod = rq->swq_start; sge->addr = (dma_addr_t)(qp->rq_hdr_buf_map + sw_prod * qp->rq_hdr_buf_size); sge->lkey = 0xFFFFFFFF; @@ -1562,6 +1552,8 @@ static void bnxt_qplib_fill_psn_search(struct bnxt_qplib_qp *qp, u32 flg_npsn; u32 op_spsn; + if (!swq->psn_search) + return; psns = swq->psn_search; psns_ext = swq->psn_ext; @@ -1575,12 +1567,122 @@ static void bnxt_qplib_fill_psn_search(struct bnxt_qplib_qp *qp, if (bnxt_qplib_is_chip_gen_p5(qp->cctx)) { psns_ext->opcode_start_psn = cpu_to_le32(op_spsn); psns_ext->flags_next_psn = cpu_to_le32(flg_npsn); + psns_ext->start_slot_idx = cpu_to_le16(swq->slot_idx); } else { psns->opcode_start_psn = cpu_to_le32(op_spsn); psns->flags_next_psn = cpu_to_le32(flg_npsn); } } +static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_swqe *wqe, + u16 *idx) +{ + struct bnxt_qplib_hwq *hwq; + int len, t_len, offt; + bool pull_dst = true; + void *il_dst = NULL; + void *il_src = NULL; + int t_cplen, cplen; + int indx; + + hwq = &qp->sq.hwq; + t_len = 0; + for (indx = 0; indx < wqe->num_sge; indx++) { + len = wqe->sg_list[indx].size; + il_src = (void *)wqe->sg_list[indx].addr; + t_len += len; + if (t_len > qp->max_inline_data) + goto bad; + while (len) { + if (pull_dst) { + pull_dst = false; + il_dst = bnxt_qplib_get_prod_qe(hwq, *idx); + (*idx)++; + t_cplen = 0; + offt = 0; + } + cplen = min_t(int, len, sizeof(struct sq_sge)); + cplen = min_t(int, cplen, + (sizeof(struct sq_sge) - offt)); + memcpy(il_dst, il_src, cplen); + t_cplen += cplen; + il_src += cplen; + il_dst += cplen; + offt += cplen; + len -= cplen; + if (t_cplen == sizeof(struct sq_sge)) + pull_dst = true; + } + } + + return t_len; +bad: + return -ENOMEM; +} + +static u32 bnxt_qplib_put_sges(struct bnxt_qplib_hwq *hwq, + struct bnxt_qplib_sge *ssge, + u16 nsge, u16 *idx) +{ + struct sq_sge *dsge; + int indx, len = 0; + + for (indx = 0; indx < nsge; indx++, (*idx)++) { + dsge = bnxt_qplib_get_prod_qe(hwq, *idx); + dsge->va_or_pa = cpu_to_le64(ssge[indx].addr); + dsge->l_key = cpu_to_le32(ssge[indx].lkey); + dsge->size = cpu_to_le32(ssge[indx].size); + len += ssge[indx].size; + } + + return len; +} + +static u16 bnxt_qplib_required_slots(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_swqe *wqe, + u16 *wqe_sz, u16 *qdf, u8 mode) +{ + u32 ilsize, bytes; + u16 nsge; + u16 slot; + + nsge = wqe->num_sge; + /* Adding sq_send_hdr is a misnomer, for rq also hdr size is same. */ + bytes = sizeof(struct sq_send_hdr) + nsge * sizeof(struct sq_sge); + if (wqe->flags & BNXT_QPLIB_SWQE_FLAGS_INLINE) { + ilsize = bnxt_qplib_calc_ilsize(wqe, qp->max_inline_data); + bytes = ALIGN(ilsize, sizeof(struct sq_sge)); + bytes += sizeof(struct sq_send_hdr); + } + + *qdf = __xlate_qfd(qp->sq.q_full_delta, bytes); + slot = bytes >> 4; + *wqe_sz = slot; + if (mode == BNXT_QPLIB_WQE_MODE_STATIC) + slot = 8; + return slot; +} + +static void bnxt_qplib_pull_psn_buff(struct bnxt_qplib_q *sq, + struct bnxt_qplib_swq *swq) +{ + struct bnxt_qplib_hwq *hwq; + u32 pg_num, pg_indx; + void *buff; + u32 tail; + + hwq = &sq->hwq; + if (!hwq->pad_pg) + return; + tail = swq->slot_idx / sq->dbinfo.max_slot; + pg_num = (tail + hwq->pad_pgofft) / (PAGE_SIZE / hwq->pad_stride); + pg_indx = (tail + hwq->pad_pgofft) % (PAGE_SIZE / hwq->pad_stride); + buff = (void *)(hwq->pad_pg[pg_num] + pg_indx * hwq->pad_stride); + swq->psn_ext = buff; + swq->psn_search = buff; +} + void bnxt_qplib_post_send_db(struct bnxt_qplib_qp *qp) { struct bnxt_qplib_q *sq = &qp->sq; @@ -1594,88 +1696,84 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, struct bnxt_qplib_nq_work *nq_work = NULL; int i, rc = 0, data_len = 0, pkt_num = 0; struct bnxt_qplib_q *sq = &qp->sq; - struct sq_send *hw_sq_send_hdr; + struct bnxt_qplib_hwq *hwq; struct bnxt_qplib_swq *swq; bool sch_handler = false; - struct sq_sge *hw_sge; - u8 wqe_size16; + u16 wqe_sz, qdf = 0; + void *base_hdr; + void *ext_hdr; __le32 temp32; - u32 sw_prod; + u32 wqe_idx; + u32 slots; + u16 idx; - if (qp->state != CMDQ_MODIFY_QP_NEW_STATE_RTS) { - if (qp->state == CMDQ_MODIFY_QP_NEW_STATE_ERR) { - sch_handler = true; - dev_dbg(&sq->hwq.pdev->dev, - "%s Error QP. Scheduling for poll_cq\n", - __func__); - goto queue_err; - } + hwq = &sq->hwq; + if (qp->state != CMDQ_MODIFY_QP_NEW_STATE_RTS && + qp->state != CMDQ_MODIFY_QP_NEW_STATE_ERR) { + dev_err(&hwq->pdev->dev, + "QPLIB: FP: QP (0x%x) is in the 0x%x state", + qp->id, qp->state); + rc = -EINVAL; + goto done; } - if (bnxt_qplib_queue_full(sq)) { - dev_err(&sq->hwq.pdev->dev, + slots = bnxt_qplib_required_slots(qp, wqe, &wqe_sz, &qdf, qp->wqe_mode); + if (bnxt_qplib_queue_full(sq, slots + qdf)) { + dev_err(&hwq->pdev->dev, "prod = %#x cons = %#x qdepth = %#x delta = %#x\n", - sq->hwq.prod, sq->hwq.cons, sq->hwq.max_elements, - sq->q_full_delta); + hwq->prod, hwq->cons, hwq->depth, sq->q_full_delta); rc = -ENOMEM; goto done; } - sw_prod = HWQ_CMP(sq->hwq.prod, &sq->hwq); - swq = &sq->swq[sw_prod]; + + swq = bnxt_qplib_get_swqe(sq, &wqe_idx); + bnxt_qplib_pull_psn_buff(sq, swq); + + idx = 0; + swq->slot_idx = hwq->prod; + swq->slots = slots; swq->wr_id = wqe->wr_id; swq->type = wqe->type; swq->flags = wqe->flags; + swq->start_psn = sq->psn & BTH_PSN_MASK; if (qp->sig_type) swq->flags |= SQ_SEND_FLAGS_SIGNAL_COMP; - swq->start_psn = sq->psn & BTH_PSN_MASK; - - hw_sq_send_hdr = bnxt_qplib_get_qe(&sq->hwq, sw_prod, NULL); - memset(hw_sq_send_hdr, 0, sq->wqe_size); - if (wqe->flags & BNXT_QPLIB_SWQE_FLAGS_INLINE) { - /* Copy the inline data */ - if (wqe->inline_len > BNXT_QPLIB_SWQE_MAX_INLINE_LENGTH) { - dev_warn(&sq->hwq.pdev->dev, - "Inline data length > 96 detected\n"); - data_len = BNXT_QPLIB_SWQE_MAX_INLINE_LENGTH; - } else { - data_len = wqe->inline_len; - } - memcpy(hw_sq_send_hdr->data, wqe->inline_data, data_len); - wqe_size16 = (data_len + 15) >> 4; - } else { - for (i = 0, hw_sge = (struct sq_sge *)hw_sq_send_hdr->data; - i < wqe->num_sge; i++, hw_sge++) { - hw_sge->va_or_pa = cpu_to_le64(wqe->sg_list[i].addr); - hw_sge->l_key = cpu_to_le32(wqe->sg_list[i].lkey); - hw_sge->size = cpu_to_le32(wqe->sg_list[i].size); - data_len += wqe->sg_list[i].size; - } - /* Each SGE entry = 1 WQE size16 */ - wqe_size16 = wqe->num_sge; - /* HW requires wqe size has room for atleast one SGE even if - * none was supplied by ULP - */ - if (!wqe->num_sge) - wqe_size16++; + if (qp->state == CMDQ_MODIFY_QP_NEW_STATE_ERR) { + sch_handler = true; + dev_dbg(&hwq->pdev->dev, + "%s Error QP. Scheduling for poll_cq\n", __func__); + goto queue_err; } + base_hdr = bnxt_qplib_get_prod_qe(hwq, idx++); + ext_hdr = bnxt_qplib_get_prod_qe(hwq, idx++); + memset(base_hdr, 0, sizeof(struct sq_sge)); + memset(ext_hdr, 0, sizeof(struct sq_sge)); + + if (wqe->flags & BNXT_QPLIB_SWQE_FLAGS_INLINE) + /* Copy the inline data */ + data_len = bnxt_qplib_put_inline(qp, wqe, &idx); + else + data_len = bnxt_qplib_put_sges(hwq, wqe->sg_list, wqe->num_sge, + &idx); + if (data_len < 0) + goto queue_err; /* Specifics */ switch (wqe->type) { case BNXT_QPLIB_SWQE_TYPE_SEND: if (qp->type == CMDQ_CREATE_QP1_TYPE_GSI) { + struct sq_send_raweth_qp1_hdr *sqe = base_hdr; + struct sq_raw_ext_hdr *ext_sqe = ext_hdr; /* Assemble info for Raw Ethertype QPs */ - struct sq_send_raweth_qp1 *sqe = - (struct sq_send_raweth_qp1 *)hw_sq_send_hdr; sqe->wqe_type = wqe->type; sqe->flags = wqe->flags; - sqe->wqe_size = wqe_size16 + - ((offsetof(typeof(*sqe), data) + 15) >> 4); + sqe->wqe_size = wqe_sz; sqe->cfa_action = cpu_to_le16(wqe->rawqp1.cfa_action); sqe->lflags = cpu_to_le16(wqe->rawqp1.lflags); sqe->length = cpu_to_le32(data_len); - sqe->cfa_meta = cpu_to_le32((wqe->rawqp1.cfa_meta & + ext_sqe->cfa_meta = cpu_to_le32((wqe->rawqp1.cfa_meta & SQ_SEND_RAWETH_QP1_CFA_META_VLAN_VID_MASK) << SQ_SEND_RAWETH_QP1_CFA_META_VLAN_VID_SFT); @@ -1685,27 +1783,24 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM: case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV: { - struct sq_send *sqe = (struct sq_send *)hw_sq_send_hdr; + struct sq_ud_ext_hdr *ext_sqe = ext_hdr; + struct sq_send_hdr *sqe = base_hdr; sqe->wqe_type = wqe->type; sqe->flags = wqe->flags; - sqe->wqe_size = wqe_size16 + - ((offsetof(typeof(*sqe), data) + 15) >> 4); - sqe->inv_key_or_imm_data = cpu_to_le32( - wqe->send.inv_key); + sqe->wqe_size = wqe_sz; + sqe->inv_key_or_imm_data = cpu_to_le32(wqe->send.inv_key); if (qp->type == CMDQ_CREATE_QP_TYPE_UD || qp->type == CMDQ_CREATE_QP_TYPE_GSI) { sqe->q_key = cpu_to_le32(wqe->send.q_key); - sqe->dst_qp = cpu_to_le32( - wqe->send.dst_qp & SQ_SEND_DST_QP_MASK); sqe->length = cpu_to_le32(data_len); - sqe->avid = cpu_to_le32(wqe->send.avid & - SQ_SEND_AVID_MASK); sq->psn = (sq->psn + 1) & BTH_PSN_MASK; + ext_sqe->dst_qp = cpu_to_le32(wqe->send.dst_qp & + SQ_SEND_DST_QP_MASK); + ext_sqe->avid = cpu_to_le32(wqe->send.avid & + SQ_SEND_AVID_MASK); } else { sqe->length = cpu_to_le32(data_len); - sqe->dst_qp = 0; - sqe->avid = 0; if (qp->mtu) pkt_num = (data_len + qp->mtu - 1) / qp->mtu; if (!pkt_num) @@ -1718,16 +1813,16 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, case BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM: case BNXT_QPLIB_SWQE_TYPE_RDMA_READ: { - struct sq_rdma *sqe = (struct sq_rdma *)hw_sq_send_hdr; + struct sq_rdma_ext_hdr *ext_sqe = ext_hdr; + struct sq_rdma_hdr *sqe = base_hdr; sqe->wqe_type = wqe->type; sqe->flags = wqe->flags; - sqe->wqe_size = wqe_size16 + - ((offsetof(typeof(*sqe), data) + 15) >> 4); + sqe->wqe_size = wqe_sz; sqe->imm_data = cpu_to_le32(wqe->rdma.inv_key); sqe->length = cpu_to_le32((u32)data_len); - sqe->remote_va = cpu_to_le64(wqe->rdma.remote_va); - sqe->remote_key = cpu_to_le32(wqe->rdma.r_key); + ext_sqe->remote_va = cpu_to_le64(wqe->rdma.remote_va); + ext_sqe->remote_key = cpu_to_le32(wqe->rdma.r_key); if (qp->mtu) pkt_num = (data_len + qp->mtu - 1) / qp->mtu; if (!pkt_num) @@ -1738,14 +1833,15 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, case BNXT_QPLIB_SWQE_TYPE_ATOMIC_CMP_AND_SWP: case BNXT_QPLIB_SWQE_TYPE_ATOMIC_FETCH_AND_ADD: { - struct sq_atomic *sqe = (struct sq_atomic *)hw_sq_send_hdr; + struct sq_atomic_ext_hdr *ext_sqe = ext_hdr; + struct sq_atomic_hdr *sqe = base_hdr; sqe->wqe_type = wqe->type; sqe->flags = wqe->flags; sqe->remote_key = cpu_to_le32(wqe->atomic.r_key); sqe->remote_va = cpu_to_le64(wqe->atomic.remote_va); - sqe->swap_data = cpu_to_le64(wqe->atomic.swap_data); - sqe->cmp_data = cpu_to_le64(wqe->atomic.cmp_data); + ext_sqe->swap_data = cpu_to_le64(wqe->atomic.swap_data); + ext_sqe->cmp_data = cpu_to_le64(wqe->atomic.cmp_data); if (qp->mtu) pkt_num = (data_len + qp->mtu - 1) / qp->mtu; if (!pkt_num) @@ -1755,8 +1851,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, } case BNXT_QPLIB_SWQE_TYPE_LOCAL_INV: { - struct sq_localinvalidate *sqe = - (struct sq_localinvalidate *)hw_sq_send_hdr; + struct sq_localinvalidate *sqe = base_hdr; sqe->wqe_type = wqe->type; sqe->flags = wqe->flags; @@ -1766,7 +1861,8 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, } case BNXT_QPLIB_SWQE_TYPE_FAST_REG_MR: { - struct sq_fr_pmr *sqe = (struct sq_fr_pmr *)hw_sq_send_hdr; + struct sq_fr_pmr_ext_hdr *ext_sqe = ext_hdr; + struct sq_fr_pmr_hdr *sqe = base_hdr; sqe->wqe_type = wqe->type; sqe->flags = wqe->flags; @@ -1790,14 +1886,15 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, wqe->frmr.pbl_ptr[i] = cpu_to_le64( wqe->frmr.page_list[i] | PTU_PTE_VALID); - sqe->pblptr = cpu_to_le64(wqe->frmr.pbl_dma_ptr); - sqe->va = cpu_to_le64(wqe->frmr.va); + ext_sqe->pblptr = cpu_to_le64(wqe->frmr.pbl_dma_ptr); + ext_sqe->va = cpu_to_le64(wqe->frmr.va); break; } case BNXT_QPLIB_SWQE_TYPE_BIND_MW: { - struct sq_bind *sqe = (struct sq_bind *)hw_sq_send_hdr; + struct sq_bind_ext_hdr *ext_sqe = ext_hdr; + struct sq_bind_hdr *sqe = base_hdr; sqe->wqe_type = wqe->type; sqe->flags = wqe->flags; @@ -1806,9 +1903,8 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, (wqe->bind.zero_based ? SQ_BIND_ZERO_BASED : 0); sqe->parent_l_key = cpu_to_le32(wqe->bind.parent_l_key); sqe->l_key = cpu_to_le32(wqe->bind.r_key); - sqe->va = cpu_to_le64(wqe->bind.va); - temp32 = cpu_to_le32(wqe->bind.length); - memcpy(&sqe->length, &temp32, sizeof(wqe->bind.length)); + ext_sqe->va = cpu_to_le64(wqe->bind.va); + ext_sqe->length_lo = cpu_to_le32(wqe->bind.length); break; } default: @@ -1817,23 +1913,11 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, goto done; } swq->next_psn = sq->psn & BTH_PSN_MASK; - if (qp->type == CMDQ_CREATE_QP_TYPE_RC) - bnxt_qplib_fill_psn_search(qp, wqe, swq); + bnxt_qplib_fill_psn_search(qp, wqe, swq); queue_err: - if (sch_handler) { - /* Store the ULP info in the software structures */ - sw_prod = HWQ_CMP(sq->hwq.prod, &sq->hwq); - swq = &sq->swq[sw_prod]; - swq->wr_id = wqe->wr_id; - swq->type = wqe->type; - swq->flags = wqe->flags; - if (qp->sig_type) - swq->flags |= SQ_SEND_FLAGS_SIGNAL_COMP; - swq->start_psn = sq->psn & BTH_PSN_MASK; - } - sq->hwq.prod++; + bnxt_qplib_swq_mod_start(sq, wqe_idx); + bnxt_qplib_hwq_incr_prod(hwq, swq->slots); qp->wqe_cnt++; - done: if (sch_handler) { nq_work = kzalloc(sizeof(*nq_work), GFP_ATOMIC); @@ -1843,7 +1927,7 @@ done: INIT_WORK(&nq_work->work, bnxt_qpn_cqn_sched_task); queue_work(qp->scq->nq->cqn_wq, &nq_work->work); } else { - dev_err(&sq->hwq.pdev->dev, + dev_err(&hwq->pdev->dev, "FP: Failed to allocate SQ nq_work!\n"); rc = -ENOMEM; } @@ -1863,58 +1947,65 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp, { struct bnxt_qplib_nq_work *nq_work = NULL; struct bnxt_qplib_q *rq = &qp->rq; + struct rq_wqe_hdr *base_hdr; + struct rq_ext_hdr *ext_hdr; + struct bnxt_qplib_hwq *hwq; + struct bnxt_qplib_swq *swq; bool sch_handler = false; - struct sq_sge *hw_sge; - struct rq_wqe *rqe; - int i, rc = 0; - u32 sw_prod; + u16 wqe_sz, idx; + u32 wqe_idx; + int rc = 0; - if (qp->state == CMDQ_MODIFY_QP_NEW_STATE_ERR) { - sch_handler = true; - dev_dbg(&rq->hwq.pdev->dev, - "%s: Error QP. Scheduling for poll_cq\n", __func__); - goto queue_err; + hwq = &rq->hwq; + if (qp->state == CMDQ_MODIFY_QP_NEW_STATE_RESET) { + dev_err(&hwq->pdev->dev, + "QPLIB: FP: QP (0x%x) is in the 0x%x state", + qp->id, qp->state); + rc = -EINVAL; + goto done; } - if (bnxt_qplib_queue_full(rq)) { - dev_err(&rq->hwq.pdev->dev, + + if (bnxt_qplib_queue_full(rq, rq->dbinfo.max_slot)) { + dev_err(&hwq->pdev->dev, "FP: QP (0x%x) RQ is full!\n", qp->id); rc = -EINVAL; goto done; } - sw_prod = HWQ_CMP(rq->hwq.prod, &rq->hwq); - rq->swq[sw_prod].wr_id = wqe->wr_id; - rqe = bnxt_qplib_get_qe(&rq->hwq, sw_prod, NULL); - memset(rqe, 0, rq->wqe_size); + swq = bnxt_qplib_get_swqe(rq, &wqe_idx); + swq->wr_id = wqe->wr_id; + swq->slots = rq->dbinfo.max_slot; - /* Calculate wqe_size16 and data_len */ - for (i = 0, hw_sge = (struct sq_sge *)rqe->data; - i < wqe->num_sge; i++, hw_sge++) { - hw_sge->va_or_pa = cpu_to_le64(wqe->sg_list[i].addr); - hw_sge->l_key = cpu_to_le32(wqe->sg_list[i].lkey); - hw_sge->size = cpu_to_le32(wqe->sg_list[i].size); + if (qp->state == CMDQ_MODIFY_QP_NEW_STATE_ERR) { + sch_handler = true; + dev_dbg(&hwq->pdev->dev, + "%s: Error QP. Scheduling for poll_cq\n", __func__); + goto queue_err; } - rqe->wqe_type = wqe->type; - rqe->flags = wqe->flags; - rqe->wqe_size = wqe->num_sge + - ((offsetof(typeof(*rqe), data) + 15) >> 4); - /* HW requires wqe size has room for atleast one SGE even if none - * was supplied by ULP - */ - if (!wqe->num_sge) - rqe->wqe_size++; - - /* Supply the rqe->wr_id index to the wr_id_tbl for now */ - rqe->wr_id[0] = cpu_to_le32(sw_prod); + idx = 0; + base_hdr = bnxt_qplib_get_prod_qe(hwq, idx++); + ext_hdr = bnxt_qplib_get_prod_qe(hwq, idx++); + memset(base_hdr, 0, sizeof(struct sq_sge)); + memset(ext_hdr, 0, sizeof(struct sq_sge)); + wqe_sz = (sizeof(struct rq_wqe_hdr) + + wqe->num_sge * sizeof(struct sq_sge)) >> 4; + bnxt_qplib_put_sges(hwq, wqe->sg_list, wqe->num_sge, &idx); + if (!wqe->num_sge) { + struct sq_sge *sge; + + sge = bnxt_qplib_get_prod_qe(hwq, idx++); + sge->size = 0; + wqe_sz++; + } + base_hdr->wqe_type = wqe->type; + base_hdr->flags = wqe->flags; + base_hdr->wqe_size = wqe_sz; + base_hdr->wr_id[0] = cpu_to_le32(wqe_idx); queue_err: - if (sch_handler) { - /* Store the ULP info in the software structures */ - sw_prod = HWQ_CMP(rq->hwq.prod, &rq->hwq); - rq->swq[sw_prod].wr_id = wqe->wr_id; - } - - rq->hwq.prod++; + bnxt_qplib_swq_mod_start(rq, wqe_idx); + bnxt_qplib_hwq_incr_prod(hwq, swq->slots); +done: if (sch_handler) { nq_work = kzalloc(sizeof(*nq_work), GFP_ATOMIC); if (nq_work) { @@ -1923,12 +2014,12 @@ queue_err: INIT_WORK(&nq_work->work, bnxt_qpn_cqn_sched_task); queue_work(qp->rcq->nq->cqn_wq, &nq_work->work); } else { - dev_err(&rq->hwq.pdev->dev, + dev_err(&hwq->pdev->dev, "FP: Failed to allocate RQ nq_work!\n"); rc = -ENOMEM; } } -done: + return rc; } @@ -2026,20 +2117,19 @@ int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) static int __flush_sq(struct bnxt_qplib_q *sq, struct bnxt_qplib_qp *qp, struct bnxt_qplib_cqe **pcqe, int *budget) { - u32 sw_prod, sw_cons; struct bnxt_qplib_cqe *cqe; + u32 start, last; int rc = 0; /* Now complete all outstanding SQEs with FLUSHED_ERR */ - sw_prod = HWQ_CMP(sq->hwq.prod, &sq->hwq); + start = sq->swq_start; cqe = *pcqe; while (*budget) { - sw_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq); - if (sw_cons == sw_prod) { + last = sq->swq_last; + if (start == last) break; - } /* Skip the FENCE WQE completions */ - if (sq->swq[sw_cons].wr_id == BNXT_QPLIB_FENCE_WRID) { + if (sq->swq[last].wr_id == BNXT_QPLIB_FENCE_WRID) { bnxt_qplib_cancel_phantom_processing(qp); goto skip_compl; } @@ -2047,16 +2137,17 @@ static int __flush_sq(struct bnxt_qplib_q *sq, struct bnxt_qplib_qp *qp, cqe->status = CQ_REQ_STATUS_WORK_REQUEST_FLUSHED_ERR; cqe->opcode = CQ_BASE_CQE_TYPE_REQ; cqe->qp_handle = (u64)(unsigned long)qp; - cqe->wr_id = sq->swq[sw_cons].wr_id; + cqe->wr_id = sq->swq[last].wr_id; cqe->src_qp = qp->id; - cqe->type = sq->swq[sw_cons].type; + cqe->type = sq->swq[last].type; cqe++; (*budget)--; skip_compl: - sq->hwq.cons++; + bnxt_qplib_hwq_incr_cons(&sq->hwq, sq->swq[last].slots); + sq->swq_last = sq->swq[last].next_idx; } *pcqe = cqe; - if (!(*budget) && HWQ_CMP(sq->hwq.cons, &sq->hwq) != sw_prod) + if (!(*budget) && sq->swq_last != start) /* Out of budget */ rc = -EAGAIN; @@ -2067,9 +2158,9 @@ static int __flush_rq(struct bnxt_qplib_q *rq, struct bnxt_qplib_qp *qp, struct bnxt_qplib_cqe **pcqe, int *budget) { struct bnxt_qplib_cqe *cqe; - u32 sw_prod, sw_cons; - int rc = 0; + u32 start, last; int opcode = 0; + int rc = 0; switch (qp->type) { case CMDQ_CREATE_QP1_TYPE_GSI: @@ -2085,24 +2176,25 @@ static int __flush_rq(struct bnxt_qplib_q *rq, struct bnxt_qplib_qp *qp, } /* Flush the rest of the RQ */ - sw_prod = HWQ_CMP(rq->hwq.prod, &rq->hwq); + start = rq->swq_start; cqe = *pcqe; while (*budget) { - sw_cons = HWQ_CMP(rq->hwq.cons, &rq->hwq); - if (sw_cons == sw_prod) + last = rq->swq_last; + if (last == start) break; memset(cqe, 0, sizeof(*cqe)); cqe->status = CQ_RES_RC_STATUS_WORK_REQUEST_FLUSHED_ERR; cqe->opcode = opcode; cqe->qp_handle = (unsigned long)qp; - cqe->wr_id = rq->swq[sw_cons].wr_id; + cqe->wr_id = rq->swq[last].wr_id; cqe++; (*budget)--; - rq->hwq.cons++; + bnxt_qplib_hwq_incr_cons(&rq->hwq, rq->swq[last].slots); + rq->swq_last = rq->swq[last].next_idx; } *pcqe = cqe; - if (!*budget && HWQ_CMP(rq->hwq.cons, &rq->hwq) != sw_prod) + if (!*budget && rq->swq_last != start) /* Out of budget */ rc = -EAGAIN; @@ -2125,7 +2217,7 @@ void bnxt_qplib_mark_qp_error(void *qp_handle) * CQE is track from sw_cq_cons to max_element but valid only if VALID=1 */ static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq, - u32 cq_cons, u32 sw_sq_cons, u32 cqe_sq_cons) + u32 cq_cons, u32 swq_last, u32 cqe_sq_cons) { u32 peek_sw_cq_cons, peek_raw_cq_cons, peek_sq_cons_idx; struct bnxt_qplib_q *sq = &qp->sq; @@ -2138,7 +2230,7 @@ static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq, /* Normal mode */ /* Check for the psn_search marking before completing */ - swq = &sq->swq[sw_sq_cons]; + swq = &sq->swq[swq_last]; if (swq->psn_search && le32_to_cpu(swq->psn_search->flags_next_psn) & 0x80000000) { /* Unmark */ @@ -2147,7 +2239,7 @@ static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq, & ~0x80000000); dev_dbg(&cq->hwq.pdev->dev, "FP: Process Req cq_cons=0x%x qp=0x%x sq cons sw=0x%x cqe=0x%x marked!\n", - cq_cons, qp->id, sw_sq_cons, cqe_sq_cons); + cq_cons, qp->id, swq_last, cqe_sq_cons); sq->condition = true; sq->send_phantom = true; @@ -2184,9 +2276,10 @@ static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq, le64_to_cpu (peek_req_hwcqe->qp_handle)); peek_sq = &peek_qp->sq; - peek_sq_cons_idx = HWQ_CMP(le16_to_cpu( - peek_req_hwcqe->sq_cons_idx) - 1 - , &sq->hwq); + peek_sq_cons_idx = + ((le16_to_cpu( + peek_req_hwcqe->sq_cons_idx) + - 1) % sq->max_wqe); /* If the hwcqe's sq's wr_id matches */ if (peek_sq == sq && sq->swq[peek_sq_cons_idx].wr_id == @@ -2214,7 +2307,7 @@ static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq, } dev_err(&cq->hwq.pdev->dev, "Should not have come here! cq_cons=0x%x qp=0x%x sq cons sw=0x%x hw=0x%x\n", - cq_cons, qp->id, sw_sq_cons, cqe_sq_cons); + cq_cons, qp->id, swq_last, cqe_sq_cons); rc = -EINVAL; } out: @@ -2226,11 +2319,11 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe **pcqe, int *budget, u32 cq_cons, struct bnxt_qplib_qp **lib_qp) { - u32 sw_sq_cons, cqe_sq_cons; struct bnxt_qplib_swq *swq; struct bnxt_qplib_cqe *cqe; struct bnxt_qplib_qp *qp; struct bnxt_qplib_q *sq; + u32 cqe_sq_cons; int rc = 0; qp = (struct bnxt_qplib_qp *)((unsigned long) @@ -2242,14 +2335,7 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, } sq = &qp->sq; - cqe_sq_cons = HWQ_CMP(le16_to_cpu(hwcqe->sq_cons_idx), &sq->hwq); - if (cqe_sq_cons > sq->hwq.max_elements) { - dev_err(&cq->hwq.pdev->dev, - "FP: CQ Process req reported sq_cons_idx 0x%x which exceeded max 0x%x\n", - cqe_sq_cons, sq->hwq.max_elements); - return -EINVAL; - } - + cqe_sq_cons = le16_to_cpu(hwcqe->sq_cons_idx) % sq->max_wqe; if (qp->sq.flushed) { dev_dbg(&cq->hwq.pdev->dev, "%s: QP in Flush QP = %p\n", __func__, qp); @@ -2261,12 +2347,11 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, */ cqe = *pcqe; while (*budget) { - sw_sq_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq); - if (sw_sq_cons == cqe_sq_cons) + if (sq->swq_last == cqe_sq_cons) /* Done */ break; - swq = &sq->swq[sw_sq_cons]; + swq = &sq->swq[sq->swq_last]; memset(cqe, 0, sizeof(*cqe)); cqe->opcode = CQ_BASE_CQE_TYPE_REQ; cqe->qp_handle = (u64)(unsigned long)qp; @@ -2280,12 +2365,12 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, * of the request being signaled or not, it must complete with * the hwcqe error status */ - if (HWQ_CMP((sw_sq_cons + 1), &sq->hwq) == cqe_sq_cons && + if (swq->next_idx == cqe_sq_cons && hwcqe->status != CQ_REQ_STATUS_OK) { cqe->status = hwcqe->status; dev_err(&cq->hwq.pdev->dev, "FP: CQ Processed Req wr_id[%d] = 0x%llx with status 0x%x\n", - sw_sq_cons, cqe->wr_id, cqe->status); + sq->swq_last, cqe->wr_id, cqe->status); cqe++; (*budget)--; bnxt_qplib_mark_qp_error(qp); @@ -2293,7 +2378,7 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, bnxt_qplib_add_flush_qp(qp); } else { /* Before we complete, do WA 9060 */ - if (do_wa9060(qp, cq, cq_cons, sw_sq_cons, + if (do_wa9060(qp, cq, cq_cons, sq->swq_last, cqe_sq_cons)) { *lib_qp = qp; goto out; @@ -2305,13 +2390,14 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, } } skip: - sq->hwq.cons++; + bnxt_qplib_hwq_incr_cons(&sq->hwq, swq->slots); + sq->swq_last = swq->next_idx; if (sq->single) break; } out: *pcqe = cqe; - if (HWQ_CMP(sq->hwq.cons, &sq->hwq) != cqe_sq_cons) { + if (sq->swq_last != cqe_sq_cons) { /* Out of budget */ rc = -EAGAIN; goto done; @@ -2386,17 +2472,23 @@ static int bnxt_qplib_cq_process_res_rc(struct bnxt_qplib_cq *cq, (*budget)--; *pcqe = cqe; } else { + struct bnxt_qplib_swq *swq; + rq = &qp->rq; - if (wr_id_idx >= rq->hwq.max_elements) { + if (wr_id_idx > (rq->max_wqe - 1)) { dev_err(&cq->hwq.pdev->dev, "FP: CQ Process RC wr_id idx 0x%x exceeded RQ max 0x%x\n", - wr_id_idx, rq->hwq.max_elements); + wr_id_idx, rq->max_wqe); return -EINVAL; } - cqe->wr_id = rq->swq[wr_id_idx].wr_id; + if (wr_id_idx != rq->swq_last) + return -EINVAL; + swq = &rq->swq[rq->swq_last]; + cqe->wr_id = swq->wr_id; cqe++; (*budget)--; - rq->hwq.cons++; + bnxt_qplib_hwq_incr_cons(&rq->hwq, swq->slots); + rq->swq_last = swq->next_idx; *pcqe = cqe; if (hwcqe->status != CQ_RES_RC_STATUS_OK) { @@ -2467,18 +2559,24 @@ static int bnxt_qplib_cq_process_res_ud(struct bnxt_qplib_cq *cq, (*budget)--; *pcqe = cqe; } else { + struct bnxt_qplib_swq *swq; + rq = &qp->rq; - if (wr_id_idx >= rq->hwq.max_elements) { + if (wr_id_idx > (rq->max_wqe - 1)) { dev_err(&cq->hwq.pdev->dev, "FP: CQ Process UD wr_id idx 0x%x exceeded RQ max 0x%x\n", - wr_id_idx, rq->hwq.max_elements); + wr_id_idx, rq->max_wqe); return -EINVAL; } - cqe->wr_id = rq->swq[wr_id_idx].wr_id; + if (rq->swq_last != wr_id_idx) + return -EINVAL; + swq = &rq->swq[rq->swq_last]; + cqe->wr_id = swq->wr_id; cqe++; (*budget)--; - rq->hwq.cons++; + bnxt_qplib_hwq_incr_cons(&rq->hwq, swq->slots); + rq->swq_last = swq->next_idx; *pcqe = cqe; if (hwcqe->status != CQ_RES_RC_STATUS_OK) { @@ -2569,17 +2667,23 @@ static int bnxt_qplib_cq_process_res_raweth_qp1(struct bnxt_qplib_cq *cq, (*budget)--; *pcqe = cqe; } else { + struct bnxt_qplib_swq *swq; + rq = &qp->rq; - if (wr_id_idx >= rq->hwq.max_elements) { + if (wr_id_idx > (rq->max_wqe - 1)) { dev_err(&cq->hwq.pdev->dev, "FP: CQ Process Raw/QP1 RQ wr_id idx 0x%x exceeded RQ max 0x%x\n", - wr_id_idx, rq->hwq.max_elements); + wr_id_idx, rq->max_wqe); return -EINVAL; } - cqe->wr_id = rq->swq[wr_id_idx].wr_id; + if (rq->swq_last != wr_id_idx) + return -EINVAL; + swq = &rq->swq[rq->swq_last]; + cqe->wr_id = swq->wr_id; cqe++; (*budget)--; - rq->hwq.cons++; + bnxt_qplib_hwq_incr_cons(&rq->hwq, swq->slots); + rq->swq_last = swq->next_idx; *pcqe = cqe; if (hwcqe->status != CQ_RES_RC_STATUS_OK) { @@ -2601,7 +2705,7 @@ static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq, struct bnxt_qplib_qp *qp; struct bnxt_qplib_q *sq, *rq; struct bnxt_qplib_cqe *cqe; - u32 sw_cons = 0, cqe_cons; + u32 swq_last = 0, cqe_cons; int rc = 0; /* Check the Status */ @@ -2627,13 +2731,7 @@ static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq, cqe_cons = le16_to_cpu(hwcqe->sq_cons_idx); if (cqe_cons == 0xFFFF) goto do_rq; - - if (cqe_cons > sq->hwq.max_elements) { - dev_err(&cq->hwq.pdev->dev, - "FP: CQ Process terminal reported sq_cons_idx 0x%x which exceeded max 0x%x\n", - cqe_cons, sq->hwq.max_elements); - goto do_rq; - } + cqe_cons %= sq->max_wqe; if (qp->sq.flushed) { dev_dbg(&cq->hwq.pdev->dev, @@ -2647,24 +2745,25 @@ static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq, */ cqe = *pcqe; while (*budget) { - sw_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq); - if (sw_cons == cqe_cons) + swq_last = sq->swq_last; + if (swq_last == cqe_cons) break; - if (sq->swq[sw_cons].flags & SQ_SEND_FLAGS_SIGNAL_COMP) { + if (sq->swq[swq_last].flags & SQ_SEND_FLAGS_SIGNAL_COMP) { memset(cqe, 0, sizeof(*cqe)); cqe->status = CQ_REQ_STATUS_OK; cqe->opcode = CQ_BASE_CQE_TYPE_REQ; cqe->qp_handle = (u64)(unsigned long)qp; cqe->src_qp = qp->id; - cqe->wr_id = sq->swq[sw_cons].wr_id; - cqe->type = sq->swq[sw_cons].type; + cqe->wr_id = sq->swq[swq_last].wr_id; + cqe->type = sq->swq[swq_last].type; cqe++; (*budget)--; } - sq->hwq.cons++; + bnxt_qplib_hwq_incr_cons(&sq->hwq, sq->swq[swq_last].slots); + sq->swq_last = sq->swq[swq_last].next_idx; } *pcqe = cqe; - if (!(*budget) && sw_cons != cqe_cons) { + if (!(*budget) && swq_last != cqe_cons) { /* Out of budget */ rc = -EAGAIN; goto sq_done; @@ -2676,10 +2775,10 @@ do_rq: cqe_cons = le16_to_cpu(hwcqe->rq_cons_idx); if (cqe_cons == 0xFFFF) { goto done; - } else if (cqe_cons > rq->hwq.max_elements) { + } else if (cqe_cons > rq->max_wqe - 1) { dev_err(&cq->hwq.pdev->dev, "FP: CQ Processed terminal reported rq_cons_idx 0x%x exceeds max 0x%x\n", - cqe_cons, rq->hwq.max_elements); + cqe_cons, rq->max_wqe); goto done; } diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h index 568ca390322c7bf29559557604e6384b6b68c776..f50784405e27ec4876344cfae0f00837bd441f5c 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h @@ -39,6 +39,51 @@ #ifndef __BNXT_QPLIB_FP_H__ #define __BNXT_QPLIB_FP_H__ +/* Few helper structures temporarily defined here + * should get rid of these when roce_hsi.h is updated + * in original code base + */ +struct sq_ud_ext_hdr { + __le32 dst_qp; + __le32 avid; + __le64 rsvd; +}; + +struct sq_raw_ext_hdr { + __le32 cfa_meta; + __le32 rsvd0; + __le64 rsvd1; +}; + +struct sq_rdma_ext_hdr { + __le64 remote_va; + __le32 remote_key; + __le32 rsvd; +}; + +struct sq_atomic_ext_hdr { + __le64 swap_data; + __le64 cmp_data; +}; + +struct sq_fr_pmr_ext_hdr { + __le64 pblptr; + __le64 va; +}; + +struct sq_bind_ext_hdr { + __le64 va; + __le32 length_lo; + __le32 length_hi; +}; + +struct rq_ext_hdr { + __le64 rsvd1; + __le64 rsvd2; +}; + +/* Helper structures end */ + struct bnxt_qplib_srq { struct bnxt_qplib_pd *pd; struct bnxt_qplib_dpi *dpi; @@ -74,6 +119,8 @@ struct bnxt_qplib_swq { u8 flags; u32 start_psn; u32 next_psn; + u32 slot_idx; + u8 slots; struct sq_psn_search *psn_search; struct sq_psn_search_ext *psn_ext; }; @@ -213,6 +260,8 @@ struct bnxt_qplib_q { u32 phantom_cqe_cnt; u32 next_cq_cons; bool flushed; + u32 swq_start; + u32 swq_last; }; struct bnxt_qplib_qp { @@ -224,9 +273,10 @@ struct bnxt_qplib_qp { u32 id; u8 type; u8 sig_type; - u32 modify_flags; + u8 wqe_mode; u8 state; u8 cur_qp_state; + u64 modify_flags; u32 max_inline_data; u32 mtu; u8 path_mtu; @@ -300,11 +350,18 @@ struct bnxt_qplib_qp { (!!((hdr)->cqe_type_toggle & CQ_BASE_TOGGLE) == \ !((raw_cons) & (cp_bit))) -static inline bool bnxt_qplib_queue_full(struct bnxt_qplib_q *qplib_q) +static inline bool bnxt_qplib_queue_full(struct bnxt_qplib_q *que, + u8 slots) { - return HWQ_CMP((qplib_q->hwq.prod + qplib_q->q_full_delta), - &qplib_q->hwq) == HWQ_CMP(qplib_q->hwq.cons, - &qplib_q->hwq); + struct bnxt_qplib_hwq *hwq; + int avail; + + hwq = &que->hwq; + /* False full is possible, retrying post-send makes sense */ + avail = hwq->cons - hwq->prod; + if (hwq->cons <= hwq->prod) + avail += hwq->depth; + return avail <= slots; } struct bnxt_qplib_cqe { @@ -489,4 +546,64 @@ int bnxt_qplib_process_flush_list(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe, int num_cqes); void bnxt_qplib_flush_cqn_wq(struct bnxt_qplib_qp *qp); + +static inline void *bnxt_qplib_get_swqe(struct bnxt_qplib_q *que, u32 *swq_idx) +{ + u32 idx; + + idx = que->swq_start; + if (swq_idx) + *swq_idx = idx; + return &que->swq[idx]; +} + +static inline void bnxt_qplib_swq_mod_start(struct bnxt_qplib_q *que, u32 idx) +{ + que->swq_start = que->swq[idx].next_idx; +} + +static inline u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que) +{ + return (que->wqe_size * que->max_wqe) / sizeof(struct sq_sge); +} + +static inline u32 bnxt_qplib_set_sq_size(struct bnxt_qplib_q *que, u8 wqe_mode) +{ + return (wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? + que->max_wqe : bnxt_qplib_get_depth(que); +} + +static inline u32 bnxt_qplib_set_sq_max_slot(u8 wqe_mode) +{ + return (wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? + sizeof(struct sq_send) / sizeof(struct sq_sge) : 1; +} + +static inline u32 bnxt_qplib_set_rq_max_slot(u32 wqe_size) +{ + return (wqe_size / sizeof(struct sq_sge)); +} + +static inline u16 __xlate_qfd(u16 delta, u16 wqe_bytes) +{ + /* For Cu/Wh delta = 128, stride = 16, wqe_bytes = 128 + * For Gen-p5 B/C mode delta = 0, stride = 16, wqe_bytes = 128. + * For Gen-p5 delta = 0, stride = 16, 32 <= wqe_bytes <= 512. + * when 8916 is disabled. + */ + return (delta * wqe_bytes) / sizeof(struct sq_sge); +} + +static inline u16 bnxt_qplib_calc_ilsize(struct bnxt_qplib_swqe *wqe, u16 max) +{ + u16 size = 0; + int indx; + + for (indx = 0; indx < wqe->num_sge; indx++) + size += wqe->sg_list[indx].size; + if (size > max) + size = max; + + return size; +} #endif /* __BNXT_QPLIB_FP_H__ */ diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h index c29cbd3a2d7b0addcf3db9895115a8cafbe67ef0..9da470d1e4a3c2cd7f64376f7040e82b1661ac1d 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_res.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h @@ -41,6 +41,28 @@ extern const struct bnxt_qplib_gid bnxt_qplib_gid_zero; +#define CHIP_NUM_57508 0x1750 +#define CHIP_NUM_57504 0x1751 +#define CHIP_NUM_57502 0x1752 + +enum bnxt_qplib_wqe_mode { + BNXT_QPLIB_WQE_MODE_STATIC = 0x00, + BNXT_QPLIB_WQE_MODE_VARIABLE = 0x01, + BNXT_QPLIB_WQE_MODE_INVALID = 0x02 +}; + +struct bnxt_qplib_drv_modes { + u8 wqe_mode; + /* Other modes to follow here */ +}; + +struct bnxt_qplib_chip_ctx { + u16 chip_num; + u8 chip_rev; + u8 chip_metal; + struct bnxt_qplib_drv_modes modes; +}; + #define PTR_CNT_PER_PG (PAGE_SIZE / sizeof(void *)) #define PTR_MAX_IDX_PER_PG (PTR_CNT_PER_PG - 1) #define PTR_PG(x) (((x) & ~PTR_MAX_IDX_PER_PG) / PTR_CNT_PER_PG) @@ -141,6 +163,9 @@ struct bnxt_qplib_hwq { u32 cons; /* raw */ u8 cp_bit; u8 is_user; + u64 *pad_pg; + u32 pad_stride; + u32 pad_pgofft; }; struct bnxt_qplib_db_info { @@ -148,6 +173,7 @@ struct bnxt_qplib_db_info { void __iomem *priv_db; struct bnxt_qplib_hwq *hwq; u32 xid; + u32 max_slot; }; /* Tables */ @@ -230,16 +256,6 @@ struct bnxt_qplib_ctx { u64 hwrm_intf_ver; }; -struct bnxt_qplib_chip_ctx { - u16 chip_num; - u8 chip_rev; - u8 chip_metal; -}; - -#define CHIP_NUM_57508 0x1750 -#define CHIP_NUM_57504 0x1751 -#define CHIP_NUM_57502 0x1752 - struct bnxt_qplib_res { struct pci_dev *pdev; struct bnxt_qplib_chip_ctx *cctx; @@ -317,6 +333,14 @@ static inline void *bnxt_qplib_get_qe(struct bnxt_qplib_hwq *hwq, return (void *)(hwq->pbl_ptr[pg_num] + hwq->element_size * pg_idx); } +static inline void *bnxt_qplib_get_prod_qe(struct bnxt_qplib_hwq *hwq, u32 idx) +{ + idx += hwq->prod; + if (idx >= hwq->depth) + idx -= hwq->depth; + return bnxt_qplib_get_qe(hwq, idx, NULL); +} + #define to_bnxt_qplib(ptr, type, member) \ container_of(ptr, type, member) @@ -351,6 +375,17 @@ int bnxt_qplib_alloc_ctx(struct bnxt_qplib_res *res, struct bnxt_qplib_ctx *ctx, bool virt_fn, bool is_p5); +static inline void bnxt_qplib_hwq_incr_prod(struct bnxt_qplib_hwq *hwq, u32 cnt) +{ + hwq->prod = (hwq->prod + cnt) % hwq->depth; +} + +static inline void bnxt_qplib_hwq_incr_cons(struct bnxt_qplib_hwq *hwq, + u32 cnt) +{ + hwq->cons = (hwq->cons + cnt) % hwq->depth; +} + static inline void bnxt_qplib_ring_db32(struct bnxt_qplib_db_info *info, bool arm) { @@ -383,8 +418,7 @@ static inline void bnxt_qplib_ring_prod_db(struct bnxt_qplib_db_info *info, key = (info->xid & DBC_DBC_XID_MASK) | DBC_DBC_PATH_ROCE | type; key <<= 32; - key |= (info->hwq->prod & (info->hwq->max_elements - 1)) & - DBC_DBC_INDEX_MASK; + key |= ((info->hwq->prod / info->max_slot)) & DBC_DBC_INDEX_MASK; writeq(key, info->db); } diff --git a/drivers/infiniband/hw/bnxt_re/roce_hsi.h b/drivers/infiniband/hw/bnxt_re/roce_hsi.h index 6f00f07420b74050ff5b825f5e19f14829e71dd2..3e40e0d76efd74b31c2c345faa00069e47359630 100644 --- a/drivers/infiniband/hw/bnxt_re/roce_hsi.h +++ b/drivers/infiniband/hw/bnxt_re/roce_hsi.h @@ -1126,6 +1126,7 @@ struct cmdq_create_qp { #define CMDQ_CREATE_QP_QP_FLAGS_FORCE_COMPLETION 0x2UL #define CMDQ_CREATE_QP_QP_FLAGS_RESERVED_LKEY_ENABLE 0x4UL #define CMDQ_CREATE_QP_QP_FLAGS_FR_PMR_ENABLED 0x8UL + #define CMDQ_CREATE_QP_QP_FLAGS_VARIABLE_SIZED_WQE_ENABLED 0x10UL u8 type; #define CMDQ_CREATE_QP_TYPE_RC 0x2UL #define CMDQ_CREATE_QP_TYPE_UD 0x4UL diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index e8e11bd95e4296e9bd8a5f11d56891c8ba26663a..2b2b009b371af1431403eb310d2aa57cbbdc1de3 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h @@ -980,7 +980,7 @@ int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len); void c4iw_qp_add_ref(struct ib_qp *qp); void c4iw_qp_rem_ref(struct ib_qp *qp); struct ib_mr *c4iw_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata); + u32 max_num_sg); int c4iw_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, unsigned int *sg_offset); int c4iw_dealloc_mw(struct ib_mw *mw); @@ -1053,8 +1053,9 @@ int c4iw_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr, const struct ib_recv_wr **bad_wr); struct c4iw_wr_wait *c4iw_alloc_wr_wait(gfp_t gfp); -typedef int c4iw_restrack_func(struct sk_buff *msg, - struct rdma_restrack_entry *res); -extern c4iw_restrack_func *c4iw_restrack_funcs[RDMA_RESTRACK_MAX]; +int c4iw_fill_res_mr_entry(struct sk_buff *msg, struct ib_mr *ibmr); +int c4iw_fill_res_cq_entry(struct sk_buff *msg, struct ib_cq *ibcq); +int c4iw_fill_res_qp_entry(struct sk_buff *msg, struct ib_qp *ibqp); +int c4iw_fill_res_cm_id_entry(struct sk_buff *msg, struct rdma_cm_id *cm_id); #endif diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index 962dc97a8ff2bc837cecf151c758677443fa009a..73936c3341b77ca23f73083256ab96e28446c6f0 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -399,7 +399,6 @@ static int finish_mem_reg(struct c4iw_mr *mhp, u32 stag) mmid = stag >> 8; mhp->ibmr.rkey = mhp->ibmr.lkey = stag; mhp->ibmr.length = mhp->attr.len; - mhp->ibmr.iova = mhp->attr.va_fbo; mhp->ibmr.page_size = 1U << (mhp->attr.page_size + 12); pr_debug("mmid 0x%x mhp %p\n", mmid, mhp); return xa_insert_irq(&mhp->rhp->mrs, mmid, mhp, GFP_KERNEL); @@ -691,7 +690,7 @@ int c4iw_dealloc_mw(struct ib_mw *mw) } struct ib_mr *c4iw_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata) + u32 max_num_sg) { struct c4iw_dev *rhp; struct c4iw_pd *php; diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c index ba83d942997c1b397b7c33fda2d842d82c3d4928..6c579d2d399749e5c9fbaf2bc532903ebd4c2da8 100644 --- a/drivers/infiniband/hw/cxgb4/provider.c +++ b/drivers/infiniband/hw/cxgb4/provider.c @@ -236,14 +236,6 @@ static int c4iw_allocate_pd(struct ib_pd *pd, struct ib_udata *udata) return 0; } -static int c4iw_query_pkey(struct ib_device *ibdev, u8 port, u16 index, - u16 *pkey) -{ - pr_debug("ibdev %p\n", ibdev); - *pkey = 0; - return 0; -} - static int c4iw_query_gid(struct ib_device *ibdev, u8 port, int index, union ib_gid *gid) { @@ -317,7 +309,6 @@ static int c4iw_query_port(struct ib_device *ibdev, u8 port, IB_PORT_DEVICE_MGMT_SUP | IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP; props->gid_tbl_len = 1; - props->pkey_tbl_len = 1; props->max_msg_sz = -1; return ret; @@ -439,7 +430,6 @@ static int c4iw_port_immutable(struct ib_device *ibdev, u8 port_num, if (err) return err; - immutable->pkey_tbl_len = attr.pkey_tbl_len; immutable->gid_tbl_len = attr.gid_tbl_len; return 0; @@ -458,13 +448,6 @@ static void get_dev_fw_str(struct ib_device *dev, char *str) FW_HDR_FW_VER_BUILD_G(c4iw_dev->rdev.lldi.fw_vers)); } -static int fill_res_entry(struct sk_buff *msg, struct rdma_restrack_entry *res) -{ - return (res->type < ARRAY_SIZE(c4iw_restrack_funcs) && - c4iw_restrack_funcs[res->type]) ? - c4iw_restrack_funcs[res->type](msg, res) : 0; -} - static const struct ib_device_ops c4iw_dev_ops = { .owner = THIS_MODULE, .driver_id = RDMA_DRIVER_CXGB4, @@ -485,7 +468,9 @@ static const struct ib_device_ops c4iw_dev_ops = { .destroy_cq = c4iw_destroy_cq, .destroy_qp = c4iw_destroy_qp, .destroy_srq = c4iw_destroy_srq, - .fill_res_entry = fill_res_entry, + .fill_res_cq_entry = c4iw_fill_res_cq_entry, + .fill_res_cm_id_entry = c4iw_fill_res_cm_id_entry, + .fill_res_mr_entry = c4iw_fill_res_mr_entry, .get_dev_fw_str = get_dev_fw_str, .get_dma_mr = c4iw_get_dma_mr, .get_hw_stats = c4iw_get_mib, @@ -508,7 +493,6 @@ static const struct ib_device_ops c4iw_dev_ops = { .post_srq_recv = c4iw_post_srq_recv, .query_device = c4iw_query_device, .query_gid = c4iw_query_gid, - .query_pkey = c4iw_query_pkey, .query_port = c4iw_query_port, .query_qp = c4iw_ib_query_qp, .reg_user_mr = c4iw_reg_user_mr, diff --git a/drivers/infiniband/hw/cxgb4/restrack.c b/drivers/infiniband/hw/cxgb4/restrack.c index f82d46ed969d9212ba5f3a65b42ea3e856af74cd..b32e6516d65fe93fc054d00fcad4197b2890c88e 100644 --- a/drivers/infiniband/hw/cxgb4/restrack.c +++ b/drivers/infiniband/hw/cxgb4/restrack.c @@ -134,10 +134,8 @@ err: return -EMSGSIZE; } -static int fill_res_qp_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res) +int c4iw_fill_res_qp_entry(struct sk_buff *msg, struct ib_qp *ibqp) { - struct ib_qp *ibqp = container_of(res, struct ib_qp, res); struct t4_swsqe *fsp = NULL, *lsp = NULL; struct c4iw_qp *qhp = to_c4iw_qp(ibqp); u16 first_sq_idx = 0, last_sq_idx = 0; @@ -195,10 +193,9 @@ union union_ep { struct c4iw_ep ep; }; -static int fill_res_ep_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res) +int c4iw_fill_res_cm_id_entry(struct sk_buff *msg, + struct rdma_cm_id *cm_id) { - struct rdma_cm_id *cm_id = rdma_res_to_id(res); struct nlattr *table_attr; struct c4iw_ep_common *epcp; struct c4iw_listen_ep *listen_ep = NULL; @@ -372,10 +369,8 @@ err: return -EMSGSIZE; } -static int fill_res_cq_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res) +int c4iw_fill_res_cq_entry(struct sk_buff *msg, struct ib_cq *ibcq) { - struct ib_cq *ibcq = container_of(res, struct ib_cq, res); struct c4iw_cq *chp = to_c4iw_cq(ibcq); struct nlattr *table_attr; struct t4_cqe hwcqes[2]; @@ -433,10 +428,8 @@ err: return -EMSGSIZE; } -static int fill_res_mr_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res) +int c4iw_fill_res_mr_entry(struct sk_buff *msg, struct ib_mr *ibmr) { - struct ib_mr *ibmr = container_of(res, struct ib_mr, res); struct c4iw_mr *mhp = to_c4iw_mr(ibmr); struct c4iw_dev *dev = mhp->rhp; u32 stag = mhp->attr.stag; @@ -492,10 +485,3 @@ err_cancel_table: err: return -EMSGSIZE; } - -c4iw_restrack_func *c4iw_restrack_funcs[RDMA_RESTRACK_MAX] = { - [RDMA_RESTRACK_QP] = fill_res_qp_entry, - [RDMA_RESTRACK_CM_ID] = fill_res_ep_entry, - [RDMA_RESTRACK_CQ] = fill_res_cq_entry, - [RDMA_RESTRACK_MR] = fill_res_mr_entry, -}; diff --git a/drivers/infiniband/hw/efa/efa_admin_cmds_defs.h b/drivers/infiniband/hw/efa/efa_admin_cmds_defs.h index bef2bd2910542934a6d1caef678da488b6c2808f..5484b08bbc5da390c98584871a34b1f3aac98ab8 100644 --- a/drivers/infiniband/hw/efa/efa_admin_cmds_defs.h +++ b/drivers/infiniband/hw/efa/efa_admin_cmds_defs.h @@ -606,8 +606,8 @@ struct efa_admin_feature_queue_attr_desc { /* Number of sub-CQs to be created for each CQ */ u16 sub_cqs_per_cq; - /* MBZ */ - u16 reserved; + /* Minimum number of WQEs per SQ */ + u16 min_sq_depth; /* Maximum number of SGEs (buffers) allowed for a single send WQE */ u16 max_wr_send_sges; @@ -632,6 +632,17 @@ struct efa_admin_feature_queue_attr_desc { /* Maximum number of SGEs for a single RDMA read WQE */ u16 max_wr_rdma_sges; + + /* + * Maximum number of bytes that can be written to SQ between two + * consecutive doorbells (in units of 64B). Driver must ensure that only + * complete WQEs are written to queue before issuing a doorbell. + * Examples: max_tx_batch=16 and WQE size = 64B, means up to 16 WQEs can + * be written to SQ between two consecutive doorbells. max_tx_batch=11 + * and WQE size = 128B, means up to 5 WQEs can be written to SQ between + * two consecutive doorbells. Zero means unlimited. + */ + u16 max_tx_batch; }; struct efa_admin_feature_aenq_desc { diff --git a/drivers/infiniband/hw/efa/efa_com_cmd.c b/drivers/infiniband/hw/efa/efa_com_cmd.c index fabd8df2e78f83b0f3d29f7a21bdb33b5440a07a..6ac23627f65ad29993ea4cef879163f8f0cddbb3 100644 --- a/drivers/infiniband/hw/efa/efa_com_cmd.c +++ b/drivers/infiniband/hw/efa/efa_com_cmd.c @@ -480,6 +480,8 @@ int efa_com_get_device_attr(struct efa_com_dev *edev, result->max_llq_size = resp.u.queue_attr.max_llq_size; result->sub_cqs_per_cq = resp.u.queue_attr.sub_cqs_per_cq; result->max_wr_rdma_sge = resp.u.queue_attr.max_wr_rdma_sges; + result->max_tx_batch = resp.u.queue_attr.max_tx_batch; + result->min_sq_depth = resp.u.queue_attr.min_sq_depth; err = efa_com_get_feature(edev, &resp, EFA_ADMIN_NETWORK_ATTR); if (err) { diff --git a/drivers/infiniband/hw/efa/efa_com_cmd.h b/drivers/infiniband/hw/efa/efa_com_cmd.h index 41ce4a476ee62f1ce1cbd0bd83fd6f47e81f5548..190bac23f5857453df380c73332e6a01aba66d73 100644 --- a/drivers/infiniband/hw/efa/efa_com_cmd.h +++ b/drivers/infiniband/hw/efa/efa_com_cmd.h @@ -127,6 +127,8 @@ struct efa_com_get_device_attr_result { u16 max_sq_sge; u16 max_rq_sge; u16 max_wr_rdma_sge; + u16 max_tx_batch; + u16 min_sq_depth; u8 db_bar; }; diff --git a/drivers/infiniband/hw/efa/efa_main.c b/drivers/infiniband/hw/efa/efa_main.c index 82145574c9286cb7da13a8b7ce99e31b4a4ff6f5..92d7011463203cef205f7f4b7ca2e1bd1ddc6b96 100644 --- a/drivers/infiniband/hw/efa/efa_main.c +++ b/drivers/infiniband/hw/efa/efa_main.c @@ -12,10 +12,12 @@ #include "efa.h" -#define PCI_DEV_ID_EFA_VF 0xefa0 +#define PCI_DEV_ID_EFA0_VF 0xefa0 +#define PCI_DEV_ID_EFA1_VF 0xefa1 static const struct pci_device_id efa_pci_tbl[] = { - { PCI_VDEVICE(AMAZON, PCI_DEV_ID_EFA_VF) }, + { PCI_VDEVICE(AMAZON, PCI_DEV_ID_EFA0_VF) }, + { PCI_VDEVICE(AMAZON, PCI_DEV_ID_EFA1_VF) }, { } }; diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c index 7dd082441333c8dd431cb77de8cf9e0b4a25b09e..9e201f169289282e63fbfcc4978931d130f67682 100644 --- a/drivers/infiniband/hw/efa/efa_verbs.c +++ b/drivers/infiniband/hw/efa/efa_verbs.c @@ -1502,11 +1502,39 @@ static int efa_dealloc_uar(struct efa_dev *dev, u16 uarn) return efa_com_dealloc_uar(&dev->edev, ¶ms); } +#define EFA_CHECK_USER_COMP(_dev, _comp_mask, _attr, _mask, _attr_str) \ + (_attr_str = (!(_dev)->dev_attr._attr || ((_comp_mask) & (_mask))) ? \ + NULL : #_attr) + +static int efa_user_comp_handshake(const struct ib_ucontext *ibucontext, + const struct efa_ibv_alloc_ucontext_cmd *cmd) +{ + struct efa_dev *dev = to_edev(ibucontext->device); + char *attr_str; + + if (EFA_CHECK_USER_COMP(dev, cmd->comp_mask, max_tx_batch, + EFA_ALLOC_UCONTEXT_CMD_COMP_TX_BATCH, attr_str)) + goto err; + + if (EFA_CHECK_USER_COMP(dev, cmd->comp_mask, min_sq_depth, + EFA_ALLOC_UCONTEXT_CMD_COMP_MIN_SQ_WR, + attr_str)) + goto err; + + return 0; + +err: + ibdev_dbg(&dev->ibdev, "Userspace handshake failed for %s attribute\n", + attr_str); + return -EOPNOTSUPP; +} + int efa_alloc_ucontext(struct ib_ucontext *ibucontext, struct ib_udata *udata) { struct efa_ucontext *ucontext = to_eucontext(ibucontext); struct efa_dev *dev = to_edev(ibucontext->device); struct efa_ibv_alloc_ucontext_resp resp = {}; + struct efa_ibv_alloc_ucontext_cmd cmd = {}; struct efa_com_alloc_uar_result result; int err; @@ -1515,6 +1543,18 @@ int efa_alloc_ucontext(struct ib_ucontext *ibucontext, struct ib_udata *udata) * we will ack input fields in our response. */ + err = ib_copy_from_udata(&cmd, udata, + min(sizeof(cmd), udata->inlen)); + if (err) { + ibdev_dbg(&dev->ibdev, + "Cannot copy udata for alloc_ucontext\n"); + goto err_out; + } + + err = efa_user_comp_handshake(ibucontext, &cmd); + if (err) + goto err_out; + err = efa_com_alloc_uar(&dev->edev, &result); if (err) goto err_out; @@ -1526,6 +1566,8 @@ int efa_alloc_ucontext(struct ib_ucontext *ibucontext, struct ib_udata *udata) resp.sub_cqs_per_cq = dev->dev_attr.sub_cqs_per_cq; resp.inline_buf_size = dev->dev_attr.inline_buf_size; resp.max_llq_size = dev->dev_attr.max_llq_size; + resp.max_tx_batch = dev->dev_attr.max_tx_batch; + resp.min_sq_wr = dev->dev_attr.min_sq_depth; if (udata && udata->outlen) { err = ib_copy_to_udata(udata, &resp, diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index 15f9c635f292dbee3d01cbd5079e5429b1ced272..7eaf995382168803c955489bacb014d57e7ba18c 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -7317,11 +7317,11 @@ static u16 link_width_to_bits(struct hfi1_devdata *dd, u16 width) case 1: return OPA_LINK_WIDTH_1X; case 2: return OPA_LINK_WIDTH_2X; case 3: return OPA_LINK_WIDTH_3X; + case 4: return OPA_LINK_WIDTH_4X; default: dd_dev_info(dd, "%s: invalid width %d, using 4\n", __func__, width); - /* fall through */ - case 4: return OPA_LINK_WIDTH_4X; + return OPA_LINK_WIDTH_4X; } } @@ -7376,12 +7376,13 @@ static void get_link_widths(struct hfi1_devdata *dd, u16 *tx_width, case 0: dd->pport[0].link_speed_active = OPA_LINK_SPEED_12_5G; break; + case 1: + dd->pport[0].link_speed_active = OPA_LINK_SPEED_25G; + break; default: dd_dev_err(dd, "%s: unexpected max rate %d, using 25Gb\n", __func__, (int)max_rate); - /* fall through */ - case 1: dd->pport[0].link_speed_active = OPA_LINK_SPEED_25G; break; } @@ -12878,11 +12879,6 @@ bail: static u32 chip_to_opa_lstate(struct hfi1_devdata *dd, u32 chip_lstate) { switch (chip_lstate) { - default: - dd_dev_err(dd, - "Unknown logical state 0x%x, reporting IB_PORT_DOWN\n", - chip_lstate); - /* fall through */ case LSTATE_DOWN: return IB_PORT_DOWN; case LSTATE_INIT: @@ -12891,6 +12887,11 @@ static u32 chip_to_opa_lstate(struct hfi1_devdata *dd, u32 chip_lstate) return IB_PORT_ARMED; case LSTATE_ACTIVE: return IB_PORT_ACTIVE; + default: + dd_dev_err(dd, + "Unknown logical state 0x%x, reporting IB_PORT_DOWN\n", + chip_lstate); + return IB_PORT_DOWN; } } @@ -12898,10 +12899,6 @@ u32 chip_to_opa_pstate(struct hfi1_devdata *dd, u32 chip_pstate) { /* look at the HFI meta-states only */ switch (chip_pstate & 0xf0) { - default: - dd_dev_err(dd, "Unexpected chip physical state of 0x%x\n", - chip_pstate); - /* fall through */ case PLS_DISABLED: return IB_PORTPHYSSTATE_DISABLED; case PLS_OFFLINE: @@ -12914,6 +12911,10 @@ u32 chip_to_opa_pstate(struct hfi1_devdata *dd, u32 chip_pstate) return IB_PORTPHYSSTATE_LINKUP; case PLS_PHYTEST: return IB_PORTPHYSSTATE_PHY_TEST; + default: + dd_dev_err(dd, "Unexpected chip physical state of 0x%x\n", + chip_pstate); + return IB_PORTPHYSSTATE_DISABLED; } } diff --git a/drivers/infiniband/hw/hfi1/firmware.c b/drivers/infiniband/hw/hfi1/firmware.c index 2b57ba70ddd6afa7f1333f7ab74bb979b35932da..0e83d4b61e463eb3b4878c614e67747d6213a50d 100644 --- a/drivers/infiniband/hw/hfi1/firmware.c +++ b/drivers/infiniband/hw/hfi1/firmware.c @@ -1868,11 +1868,8 @@ int parse_platform_config(struct hfi1_devdata *dd) 2; break; case PLATFORM_CONFIG_RX_PRESET_TABLE: - /* fall through */ case PLATFORM_CONFIG_TX_PRESET_TABLE: - /* fall through */ case PLATFORM_CONFIG_QSFP_ATTEN_TABLE: - /* fall through */ case PLATFORM_CONFIG_VARIABLE_SETTINGS_TABLE: pcfgcache->config_tables[table_type].num_table = table_length_dwords; @@ -1890,15 +1887,10 @@ int parse_platform_config(struct hfi1_devdata *dd) /* metadata table */ switch (table_type) { case PLATFORM_CONFIG_SYSTEM_TABLE: - /* fall through */ case PLATFORM_CONFIG_PORT_TABLE: - /* fall through */ case PLATFORM_CONFIG_RX_PRESET_TABLE: - /* fall through */ case PLATFORM_CONFIG_TX_PRESET_TABLE: - /* fall through */ case PLATFORM_CONFIG_QSFP_ATTEN_TABLE: - /* fall through */ case PLATFORM_CONFIG_VARIABLE_SETTINGS_TABLE: break; default: @@ -2027,15 +2019,10 @@ static int get_platform_fw_field_metadata(struct hfi1_devdata *dd, int table, switch (table) { case PLATFORM_CONFIG_SYSTEM_TABLE: - /* fall through */ case PLATFORM_CONFIG_PORT_TABLE: - /* fall through */ case PLATFORM_CONFIG_RX_PRESET_TABLE: - /* fall through */ case PLATFORM_CONFIG_TX_PRESET_TABLE: - /* fall through */ case PLATFORM_CONFIG_QSFP_ATTEN_TABLE: - /* fall through */ case PLATFORM_CONFIG_VARIABLE_SETTINGS_TABLE: if (field && field < platform_config_table_limits[table]) src_ptr = @@ -2138,11 +2125,8 @@ int get_platform_config_field(struct hfi1_devdata *dd, pcfgcache->config_tables[table_type].table; break; case PLATFORM_CONFIG_RX_PRESET_TABLE: - /* fall through */ case PLATFORM_CONFIG_TX_PRESET_TABLE: - /* fall through */ case PLATFORM_CONFIG_QSFP_ATTEN_TABLE: - /* fall through */ case PLATFORM_CONFIG_VARIABLE_SETTINGS_TABLE: src_ptr = pcfgcache->config_tables[table_type].table; diff --git a/drivers/infiniband/hw/hfi1/mad.c b/drivers/infiniband/hw/hfi1/mad.c index 7073f237a9493864cad7dd0dd9418ce31e18d3d9..3222e3acb79c6aedbf521187e82cb15c24148692 100644 --- a/drivers/infiniband/hw/hfi1/mad.c +++ b/drivers/infiniband/hw/hfi1/mad.c @@ -721,7 +721,7 @@ static int check_mkey(struct hfi1_ibport *ibp, struct ib_mad_hdr *mad, /* Bad mkey not a violation below level 2 */ if (ibp->rvp.mkeyprot < 2) break; - /* fall through */ + fallthrough; case IB_MGMT_METHOD_SET: case IB_MGMT_METHOD_TRAP_REPRESS: if (ibp->rvp.mkey_violations != 0xFFFF) @@ -1272,7 +1272,7 @@ static int set_port_states(struct hfi1_pportdata *ppd, struct opa_smp *smp, case IB_PORT_NOP: if (phys_state == IB_PORTPHYSSTATE_NOP) break; - /* FALLTHROUGH */ + fallthrough; case IB_PORT_DOWN: if (phys_state == IB_PORTPHYSSTATE_NOP) { link_state = HLS_DN_DOWNDEF; @@ -2300,7 +2300,6 @@ static int __subn_set_opa_vl_arb(struct opa_smp *smp, u32 am, u8 *data, * can be changed from the default values */ case OPA_VLARB_PREEMPT_ELEMENTS: - /* FALLTHROUGH */ case OPA_VLARB_PREEMPT_MATRIX: smp->status |= IB_SMP_UNSUP_METH_ATTR; break; @@ -4170,7 +4169,7 @@ static int subn_get_opa_sma(__be16 attr_id, struct opa_smp *smp, u32 am, return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; if (ibp->rvp.port_cap_flags & IB_PORT_SM) return IB_MAD_RESULT_SUCCESS; - /* FALLTHROUGH */ + fallthrough; default: smp->status |= IB_SMP_UNSUP_METH_ATTR; ret = reply((struct ib_mad_hdr *)smp); @@ -4240,7 +4239,7 @@ static int subn_set_opa_sma(__be16 attr_id, struct opa_smp *smp, u32 am, return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; if (ibp->rvp.port_cap_flags & IB_PORT_SM) return IB_MAD_RESULT_SUCCESS; - /* FALLTHROUGH */ + fallthrough; default: smp->status |= IB_SMP_UNSUP_METH_ATTR; ret = reply((struct ib_mad_hdr *)smp); diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c index 1a6268d61977aa0bac0649d57fdda94be36a20ba..18d32f053d26e4b8bc475b4374bacac4d762f170 100644 --- a/drivers/infiniband/hw/hfi1/pcie.c +++ b/drivers/infiniband/hw/hfi1/pcie.c @@ -306,7 +306,7 @@ int pcie_speeds(struct hfi1_devdata *dd) ret = pcie_capability_read_dword(dd->pcidev, PCI_EXP_LNKCAP, &linkcap); if (ret) { dd_dev_err(dd, "Unable to read from PCI config\n"); - return ret; + return pcibios_err_to_errno(ret); } if ((linkcap & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_8_0GB) { @@ -334,10 +334,14 @@ int pcie_speeds(struct hfi1_devdata *dd) return 0; } -/* restore command and BARs after a reset has wiped them out */ +/** + * Restore command and BARs after a reset has wiped them out + * + * Returns 0 on success, otherwise a negative error value + */ int restore_pci_variables(struct hfi1_devdata *dd) { - int ret = 0; + int ret; ret = pci_write_config_word(dd->pcidev, PCI_COMMAND, dd->pci_command); if (ret) @@ -386,13 +390,17 @@ int restore_pci_variables(struct hfi1_devdata *dd) error: dd_dev_err(dd, "Unable to write to PCI config\n"); - return ret; + return pcibios_err_to_errno(ret); } -/* Save BARs and command to rewrite after device reset */ +/** + * Save BARs and command to rewrite after device reset + * + * Returns 0 on success, otherwise a negative error value + */ int save_pci_variables(struct hfi1_devdata *dd) { - int ret = 0; + int ret; ret = pci_read_config_dword(dd->pcidev, PCI_BASE_ADDRESS_0, &dd->pcibar0); @@ -441,7 +449,7 @@ int save_pci_variables(struct hfi1_devdata *dd) error: dd_dev_err(dd, "Unable to read from PCI config\n"); - return ret; + return pcibios_err_to_errno(ret); } /* diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c index 79126b2b14ab036f6865a5a06fa7db00256202ad..ff864f6f02667bf33e9b697c5d2c9d6298755d3d 100644 --- a/drivers/infiniband/hw/hfi1/pio.c +++ b/drivers/infiniband/hw/hfi1/pio.c @@ -86,7 +86,7 @@ void pio_send_control(struct hfi1_devdata *dd, int op) switch (op) { case PSC_GLOBAL_ENABLE: reg |= SEND_CTRL_SEND_ENABLE_SMASK; - /* Fall through */ + fallthrough; case PSC_DATA_VL_ENABLE: mask = 0; for (i = 0; i < ARRAY_SIZE(dd->vld); i++) diff --git a/drivers/infiniband/hw/hfi1/pio_copy.c b/drivers/infiniband/hw/hfi1/pio_copy.c index 03024cec78dd867b10e5b66cb5d22e3e1b808c41..b12e4665c9ab1be2c8d80ff9b64010b46747dbb8 100644 --- a/drivers/infiniband/hw/hfi1/pio_copy.c +++ b/drivers/infiniband/hw/hfi1/pio_copy.c @@ -191,22 +191,22 @@ static inline void jcopy(u8 *dest, const u8 *src, u32 n) switch (n) { case 7: *dest++ = *src++; - /* fall through */ + fallthrough; case 6: *dest++ = *src++; - /* fall through */ + fallthrough; case 5: *dest++ = *src++; - /* fall through */ + fallthrough; case 4: *dest++ = *src++; - /* fall through */ + fallthrough; case 3: *dest++ = *src++; - /* fall through */ + fallthrough; case 2: *dest++ = *src++; - /* fall through */ + fallthrough; case 1: *dest++ = *src++; /* fall through */ diff --git a/drivers/infiniband/hw/hfi1/platform.c b/drivers/infiniband/hw/hfi1/platform.c index 36593f2efe26f2e69e64ff86e86fa0ac676ce58b..4642d6ceb89033bb8009a967c3d2f78d68de942b 100644 --- a/drivers/infiniband/hw/hfi1/platform.c +++ b/drivers/infiniband/hw/hfi1/platform.c @@ -668,8 +668,8 @@ static u8 aoc_low_power_setting(struct hfi1_pportdata *ppd) /* active optical cables only */ switch ((cache[QSFP_MOD_TECH_OFFS] & 0xF0) >> 4) { - case 0x0 ... 0x9: /* fallthrough */ - case 0xC: /* fallthrough */ + case 0x0 ... 0x9: fallthrough; + case 0xC: fallthrough; case 0xE: /* active AOC */ power_class = get_qsfp_power_class(cache[QSFP_MOD_PWR_OFFS]); @@ -899,8 +899,8 @@ static int tune_qsfp(struct hfi1_pportdata *ppd, *ptr_tuning_method = OPA_PASSIVE_TUNING; break; - case 0x0 ... 0x9: /* fallthrough */ - case 0xC: /* fallthrough */ + case 0x0 ... 0x9: fallthrough; + case 0xC: fallthrough; case 0xE: ret = tune_active_qsfp(ppd, ptr_tx_preset, ptr_rx_preset, ptr_total_atten); @@ -909,7 +909,7 @@ static int tune_qsfp(struct hfi1_pportdata *ppd, *ptr_tuning_method = OPA_ACTIVE_TUNING; break; - case 0xD: /* fallthrough */ + case 0xD: fallthrough; case 0xF: default: dd_dev_warn(ppd->dd, "%s: Unknown/unsupported cable\n", diff --git a/drivers/infiniband/hw/hfi1/qp.c b/drivers/infiniband/hw/hfi1/qp.c index be62284e42d9aff47007b68f9b3aacaafa0aed96..356518e17fa6c495aca72b6ac1bb55ae7da50177 100644 --- a/drivers/infiniband/hw/hfi1/qp.c +++ b/drivers/infiniband/hw/hfi1/qp.c @@ -312,7 +312,7 @@ int hfi1_setup_wqe(struct rvt_qp *qp, struct rvt_swqe *wqe, bool *call_send) switch (qp->ibqp.qp_type) { case IB_QPT_RC: hfi1_setup_tid_rdma_wqe(qp, wqe); - /* fall through */ + fallthrough; case IB_QPT_UC: if (wqe->length > 0x80000000U) return -EINVAL; diff --git a/drivers/infiniband/hw/hfi1/qp.h b/drivers/infiniband/hw/hfi1/qp.h index b670321365d31137b4df6f84a01a9798390629c6..b0d053d12129ece3d420af51ce22f2bb88d143da 100644 --- a/drivers/infiniband/hw/hfi1/qp.h +++ b/drivers/infiniband/hw/hfi1/qp.h @@ -112,20 +112,6 @@ static inline void clear_ahg(struct rvt_qp *qp) qp->s_ahgidx = -1; } -/** - * hfi1_create_qp - create a queue pair for a device - * @ibpd: the protection domain who's device we create the queue pair for - * @init_attr: the attributes of the queue pair - * @udata: user data for libibverbs.so - * - * Returns the queue pair on success, otherwise returns an errno. - * - * Called by the ib_create_qp() core verbs function. - */ -struct ib_qp *hfi1_create_qp(struct ib_pd *ibpd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata); - /** * hfi1_qp_wakeup - wake up on the indicated event * @qp: the QP diff --git a/drivers/infiniband/hw/hfi1/qsfp.c b/drivers/infiniband/hw/hfi1/qsfp.c index b5966991d64744e710dbb7e38574b91c676bacf8..8386c84c2d92bf41f6db63fffc73d551c2400439 100644 --- a/drivers/infiniband/hw/hfi1/qsfp.c +++ b/drivers/infiniband/hw/hfi1/qsfp.c @@ -231,7 +231,7 @@ static int i2c_bus_write(struct hfi1_devdata *dd, struct hfi1_i2c_bus *i2c, break; case 2: offset_bytes[1] = (offset >> 8) & 0xff; - /* fall through */ + fallthrough; case 1: num_msgs = 2; offset_bytes[0] = offset & 0xff; @@ -279,7 +279,7 @@ static int i2c_bus_read(struct hfi1_devdata *dd, struct hfi1_i2c_bus *bus, break; case 2: offset_bytes[1] = (offset >> 8) & 0xff; - /* fall through */ + fallthrough; case 1: num_msgs = 2; offset_bytes[0] = offset & 0xff; diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c index f1734e5e9ac43a0b349282f65bc83d9a6f95c4f9..1bb5f57152d3525ebd1a30214e41039dcd99dac0 100644 --- a/drivers/infiniband/hw/hfi1/rc.c +++ b/drivers/infiniband/hw/hfi1/rc.c @@ -141,7 +141,7 @@ static int make_rc_ack(struct hfi1_ibdev *dev, struct rvt_qp *qp, case OP(RDMA_READ_RESPONSE_ONLY): e = &qp->s_ack_queue[qp->s_tail_ack_queue]; release_rdma_sge_mr(e); - /* FALLTHROUGH */ + fallthrough; case OP(ATOMIC_ACKNOWLEDGE): /* * We can increment the tail pointer now that the last @@ -160,7 +160,7 @@ static int make_rc_ack(struct hfi1_ibdev *dev, struct rvt_qp *qp, qp->s_acked_ack_queue = next; qp->s_tail_ack_queue = next; trace_hfi1_rsp_make_rc_ack(qp, e->psn); - /* FALLTHROUGH */ + fallthrough; case OP(SEND_ONLY): case OP(ACKNOWLEDGE): /* Check for no next entry in the queue. */ @@ -267,7 +267,7 @@ static int make_rc_ack(struct hfi1_ibdev *dev, struct rvt_qp *qp, case OP(RDMA_READ_RESPONSE_FIRST): qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE); - /* FALLTHROUGH */ + fallthrough; case OP(RDMA_READ_RESPONSE_MIDDLE): ps->s_txreq->ss = &qp->s_ack_rdma_sge; ps->s_txreq->mr = qp->s_ack_rdma_sge.sge.mr; @@ -881,8 +881,7 @@ no_flow_control: goto bail; } qp->s_num_rd_atomic++; - - /* FALLTHROUGH */ + fallthrough; case IB_WR_OPFN: if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) qp->s_lsn++; @@ -946,10 +945,10 @@ no_flow_control: * See restart_rc(). */ qp->s_len = restart_sge(&qp->s_sge, wqe, qp->s_psn, pmtu); - /* FALLTHROUGH */ + fallthrough; case OP(SEND_FIRST): qp->s_state = OP(SEND_MIDDLE); - /* FALLTHROUGH */ + fallthrough; case OP(SEND_MIDDLE): bth2 = mask_psn(qp->s_psn++); ss = &qp->s_sge; @@ -991,10 +990,10 @@ no_flow_control: * See restart_rc(). */ qp->s_len = restart_sge(&qp->s_sge, wqe, qp->s_psn, pmtu); - /* FALLTHROUGH */ + fallthrough; case OP(RDMA_WRITE_FIRST): qp->s_state = OP(RDMA_WRITE_MIDDLE); - /* FALLTHROUGH */ + fallthrough; case OP(RDMA_WRITE_MIDDLE): bth2 = mask_psn(qp->s_psn++); ss = &qp->s_sge; @@ -2901,7 +2900,7 @@ void hfi1_rc_rcv(struct hfi1_packet *packet) if (!ret) goto rnr_nak; qp->r_rcv_len = 0; - /* FALLTHROUGH */ + fallthrough; case OP(SEND_MIDDLE): case OP(RDMA_WRITE_MIDDLE): send_middle: @@ -2941,7 +2940,7 @@ send_middle: goto no_immediate_data; if (opcode == OP(SEND_ONLY_WITH_INVALIDATE)) goto send_last_inv; - /* FALLTHROUGH -- for SEND_ONLY_WITH_IMMEDIATE */ + fallthrough; /* for SEND_ONLY_WITH_IMMEDIATE */ case OP(SEND_LAST_WITH_IMMEDIATE): send_last_imm: wc.ex.imm_data = ohdr->u.imm_data; @@ -2957,7 +2956,7 @@ send_last_inv: goto send_last; case OP(RDMA_WRITE_LAST): copy_last = rvt_is_user_qp(qp); - /* fall through */ + fallthrough; case OP(SEND_LAST): no_immediate_data: wc.wc_flags = 0; @@ -3010,7 +3009,7 @@ send_last: case OP(RDMA_WRITE_ONLY): copy_last = rvt_is_user_qp(qp); - /* fall through */ + fallthrough; case OP(RDMA_WRITE_FIRST): case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE))) diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c index c93ea021cf4939ac78898acaa71a609d833653c9..04575c9afd61e5a97d230f6a487b59de6ba7eebb 100644 --- a/drivers/infiniband/hw/hfi1/sdma.c +++ b/drivers/infiniband/hw/hfi1/sdma.c @@ -2584,7 +2584,7 @@ static void __sdma_process_event(struct sdma_engine *sde, * 7220, e.g. */ ss->go_s99_running = 1; - /* fall through -- and start dma engine */ + fallthrough; /* and start dma engine */ case sdma_event_e10_go_hw_start: /* This reference means the state machine is started */ sdma_get(&sde->state); @@ -2726,7 +2726,6 @@ static void __sdma_process_event(struct sdma_engine *sde, case sdma_event_e70_go_idle: break; case sdma_event_e85_link_down: - /* fall through */ case sdma_event_e80_hw_freeze: sdma_set_state(sde, sdma_state_s80_hw_freeze); atomic_dec(&sde->dd->sdma_unfreeze_count); @@ -3007,7 +3006,7 @@ static void __sdma_process_event(struct sdma_engine *sde, case sdma_event_e60_hw_halted: need_progress = 1; sdma_err_progress_check_schedule(sde); - /* fall through */ + fallthrough; case sdma_event_e90_sw_halted: /* * SW initiated halt does not perform engines @@ -3021,7 +3020,7 @@ static void __sdma_process_event(struct sdma_engine *sde, break; case sdma_event_e85_link_down: ss->go_s99_running = 0; - /* fall through */ + fallthrough; case sdma_event_e80_hw_freeze: sdma_set_state(sde, sdma_state_s80_hw_freeze); atomic_dec(&sde->dd->sdma_unfreeze_count); @@ -3252,7 +3251,7 @@ void _sdma_txreq_ahgadd( tx->num_desc++; tx->descs[2].qw[0] = 0; tx->descs[2].qw[1] = 0; - /* FALLTHROUGH */ + fallthrough; case SDMA_AHG_APPLY_UPDATE2: tx->num_desc++; tx->descs[1].qw[0] = 0; diff --git a/drivers/infiniband/hw/hfi1/tid_rdma.c b/drivers/infiniband/hw/hfi1/tid_rdma.c index facff133139a9597299c0b151001ab4de0cb718f..9af82ff933d7335664dad97b46b0c4df36c6d0a9 100644 --- a/drivers/infiniband/hw/hfi1/tid_rdma.c +++ b/drivers/infiniband/hw/hfi1/tid_rdma.c @@ -3227,7 +3227,7 @@ bool hfi1_tid_rdma_wqe_interlock(struct rvt_qp *qp, struct rvt_swqe *wqe) case IB_WR_RDMA_READ: if (prev->wr.opcode != IB_WR_TID_RDMA_WRITE) break; - /* fall through */ + fallthrough; case IB_WR_TID_RDMA_READ: switch (prev->wr.opcode) { case IB_WR_RDMA_READ: @@ -5067,7 +5067,7 @@ int hfi1_make_tid_rdma_pkt(struct rvt_qp *qp, struct hfi1_pkt_state *ps) if (priv->s_state == TID_OP(WRITE_REQ)) hfi1_tid_rdma_restart_req(qp, wqe, &bth2); priv->s_state = TID_OP(WRITE_DATA); - /* fall through */ + fallthrough; case TID_OP(WRITE_DATA): /* diff --git a/drivers/infiniband/hw/hfi1/uc.c b/drivers/infiniband/hw/hfi1/uc.c index 0c77f18120edb3d8f230eaee49e1f933dd5aa122..1fb918399da0600bb399e2b9830911dfaaa1ee5d 100644 --- a/drivers/infiniband/hw/hfi1/uc.c +++ b/drivers/infiniband/hw/hfi1/uc.c @@ -216,7 +216,7 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) case OP(SEND_FIRST): qp->s_state = OP(SEND_MIDDLE); - /* FALLTHROUGH */ + fallthrough; case OP(SEND_MIDDLE): len = qp->s_len; if (len > pmtu) { @@ -241,7 +241,7 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) case OP(RDMA_WRITE_FIRST): qp->s_state = OP(RDMA_WRITE_MIDDLE); - /* FALLTHROUGH */ + fallthrough; case OP(RDMA_WRITE_MIDDLE): len = qp->s_len; if (len > pmtu) { @@ -414,7 +414,7 @@ send_first: goto no_immediate_data; else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE)) goto send_last_imm; - /* FALLTHROUGH */ + fallthrough; case OP(SEND_MIDDLE): /* Check for invalid length PMTU or posted rwqe len. */ /* @@ -515,7 +515,7 @@ rdma_first: wc.ex.imm_data = ohdr->u.rc.imm_data; goto rdma_last_imm; } - /* FALLTHROUGH */ + fallthrough; case OP(RDMA_WRITE_MIDDLE): /* Check for invalid length PMTU or posted rwqe len. */ if (unlikely(tlen != (hdrsize + pmtu + 4))) diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h index 479fa557993e776ea12d62898437c75af685160c..da9888deff8c21c6745910232b0536f1bebf3804 100644 --- a/drivers/infiniband/hw/hns/hns_roce_device.h +++ b/drivers/infiniband/hw/hns/hns_roce_device.h @@ -37,9 +37,8 @@ #define DRV_NAME "hns_roce" -/* hip08 is a pci device, it includes two version according pci version id */ -#define PCI_REVISION_ID_HIP08_A 0x20 -#define PCI_REVISION_ID_HIP08_B 0x21 +/* hip08 is a pci device */ +#define PCI_REVISION_ID_HIP08 0x21 #define HNS_ROCE_HW_VER1 ('h' << 24 | 'i' << 16 | '0' << 8 | '6') @@ -348,20 +347,22 @@ struct hns_roce_buf_attr { bool mtt_only; /* only alloc buffer-required MTT memory */ }; +struct hns_roce_hem_cfg { + dma_addr_t root_ba; /* root BA table's address */ + bool is_direct; /* addressing without BA table */ + unsigned int ba_pg_shift; /* BA table page shift */ + unsigned int buf_pg_shift; /* buffer page shift */ + unsigned int buf_pg_count; /* buffer page count */ + struct hns_roce_buf_region region[HNS_ROCE_MAX_BT_REGION]; + int region_count; +}; + /* memory translate region */ struct hns_roce_mtr { struct hns_roce_hem_list hem_list; /* multi-hop addressing resource */ struct ib_umem *umem; /* user space buffer */ struct hns_roce_buf *kmem; /* kernel space buffer */ - struct { - dma_addr_t root_ba; /* root BA table's address */ - bool is_direct; /* addressing without BA table */ - unsigned int ba_pg_shift; /* BA table page shift */ - unsigned int buf_pg_shift; /* buffer page shift */ - int buf_pg_count; /* buffer page count */ - struct hns_roce_buf_region region[HNS_ROCE_MAX_BT_REGION]; - unsigned int region_count; - } hem_cfg; /* config for hardware addressing */ + struct hns_roce_hem_cfg hem_cfg; /* config for hardware addressing */ }; struct hns_roce_mw { @@ -1192,7 +1193,7 @@ int hns_roce_rereg_user_mr(struct ib_mr *mr, int flags, u64 start, u64 length, u64 virt_addr, int mr_access_flags, struct ib_pd *pd, struct ib_udata *udata); struct ib_mr *hns_roce_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata); + u32 max_num_sg); int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, unsigned int *sg_offset); int hns_roce_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata); @@ -1267,6 +1268,6 @@ void hns_roce_handle_device_err(struct hns_roce_dev *hr_dev); int hns_roce_init(struct hns_roce_dev *hr_dev); void hns_roce_exit(struct hns_roce_dev *hr_dev); -int hns_roce_fill_res_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res); +int hns_roce_fill_res_cq_entry(struct sk_buff *msg, + struct ib_cq *ib_cq); #endif /* _HNS_ROCE_DEVICE_H */ diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c index cf39f560b80013d440f8b6e1b885263a3c87f5f0..07b4c85d341db864139f8653582dd3f46822933c 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c @@ -2483,7 +2483,6 @@ static int find_wqe_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp, u64 *sq_ba, u64 *rq_ba, dma_addr_t *bt_ba) { struct ib_device *ibdev = &hr_dev->ib_dev; - int rq_pa_start; int count; count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, 0, sq_ba, 1, bt_ba); @@ -2491,9 +2490,9 @@ static int find_wqe_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp, ibdev_err(ibdev, "Failed to find SQ ba\n"); return -ENOBUFS; } - rq_pa_start = hr_qp->rq.offset >> hr_qp->mtr.hem_cfg.buf_pg_shift; - count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, rq_pa_start, rq_ba, 1, - NULL); + + count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, hr_qp->rq.offset, rq_ba, + 1, NULL); if (!count) { ibdev_err(ibdev, "Failed to find RQ ba\n"); return -ENOBUFS; diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 0618ced45bf80a5c36d3b8e30e33e0bbd6c371ea..d2968594664bbbf95b5217249c420ba595aff599 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -91,10 +91,11 @@ static u32 to_hr_opcode(u32 ib_opcode) } static void set_frmr_seg(struct hns_roce_v2_rc_send_wqe *rc_sq_wqe, - void *wqe, const struct ib_reg_wr *wr) + const struct ib_reg_wr *wr) { + struct hns_roce_wqe_frmr_seg *fseg = + (void *)rc_sq_wqe + sizeof(struct hns_roce_v2_rc_send_wqe); struct hns_roce_mr *mr = to_hr_mr(wr->mr); - struct hns_roce_wqe_frmr_seg *fseg = wqe; u64 pbl_ba; /* use ib_access_flags */ @@ -128,14 +129,16 @@ static void set_frmr_seg(struct hns_roce_v2_rc_send_wqe *rc_sq_wqe, V2_RC_FRMR_WQE_BYTE_40_BLK_MODE_S, 0); } -static void set_atomic_seg(const struct ib_send_wr *wr, void *wqe, +static void set_atomic_seg(const struct ib_send_wr *wr, struct hns_roce_v2_rc_send_wqe *rc_sq_wqe, unsigned int valid_num_sge) { - struct hns_roce_wqe_atomic_seg *aseg; + struct hns_roce_v2_wqe_data_seg *dseg = + (void *)rc_sq_wqe + sizeof(struct hns_roce_v2_rc_send_wqe); + struct hns_roce_wqe_atomic_seg *aseg = + (void *)dseg + sizeof(struct hns_roce_v2_wqe_data_seg); - set_data_seg_v2(wqe, wr->sg_list); - aseg = wqe + sizeof(struct hns_roce_v2_wqe_data_seg); + set_data_seg_v2(dseg, wr->sg_list); if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP) { aseg->fetchadd_swap_data = cpu_to_le64(atomic_wr(wr)->swap); @@ -143,7 +146,7 @@ static void set_atomic_seg(const struct ib_send_wr *wr, void *wqe, } else { aseg->fetchadd_swap_data = cpu_to_le64(atomic_wr(wr)->compare_add); - aseg->cmp_data = 0; + aseg->cmp_data = 0; } roce_set_field(rc_sq_wqe->byte_16, V2_RC_SEND_WQE_BYTE_16_SGE_NUM_M, @@ -176,13 +179,15 @@ static void set_extend_sge(struct hns_roce_qp *qp, const struct ib_send_wr *wr, static int set_rwqe_data_seg(struct ib_qp *ibqp, const struct ib_send_wr *wr, struct hns_roce_v2_rc_send_wqe *rc_sq_wqe, - void *wqe, unsigned int *sge_ind, + unsigned int *sge_ind, unsigned int valid_num_sge) { struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device); - struct hns_roce_v2_wqe_data_seg *dseg = wqe; + struct hns_roce_v2_wqe_data_seg *dseg = + (void *)rc_sq_wqe + sizeof(struct hns_roce_v2_rc_send_wqe); struct ib_device *ibdev = &hr_dev->ib_dev; struct hns_roce_qp *qp = to_hr_qp(ibqp); + void *wqe = dseg; int j = 0; int i; @@ -438,7 +443,6 @@ static inline int set_rc_wqe(struct hns_roce_qp *qp, roce_set_bit(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_OWNER_S, owner_bit); - wqe += sizeof(struct hns_roce_v2_rc_send_wqe); switch (wr->opcode) { case IB_WR_RDMA_READ: case IB_WR_RDMA_WRITE: @@ -451,7 +455,7 @@ static inline int set_rc_wqe(struct hns_roce_qp *qp, rc_sq_wqe->inv_key = cpu_to_le32(wr->ex.invalidate_rkey); break; case IB_WR_REG_MR: - set_frmr_seg(rc_sq_wqe, wqe, reg_wr(wr)); + set_frmr_seg(rc_sq_wqe, reg_wr(wr)); break; case IB_WR_ATOMIC_CMP_AND_SWP: case IB_WR_ATOMIC_FETCH_AND_ADD: @@ -468,10 +472,10 @@ static inline int set_rc_wqe(struct hns_roce_qp *qp, if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP || wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) - set_atomic_seg(wr, wqe, rc_sq_wqe, valid_num_sge); + set_atomic_seg(wr, rc_sq_wqe, valid_num_sge); else if (wr->opcode != IB_WR_REG_MR) ret = set_rwqe_data_seg(&qp->ibqp, wr, rc_sq_wqe, - wqe, &curr_idx, valid_num_sge); + &curr_idx, valid_num_sge); *sge_idx = curr_idx; @@ -1510,8 +1514,6 @@ static int hns_roce_alloc_vf_resource(struct hns_roce_dev *hr_dev) req_a = (struct hns_roce_vf_res_a *)desc[0].data; req_b = (struct hns_roce_vf_res_b *)desc[1].data; - memset(req_a, 0, sizeof(*req_a)); - memset(req_b, 0, sizeof(*req_b)); for (i = 0; i < 2; i++) { hns_roce_cmq_setup_basic_desc(&desc[i], HNS_ROCE_OPC_ALLOC_VF_RES, false); @@ -1744,27 +1746,25 @@ static void set_default_caps(struct hns_roce_dev *hr_dev) caps->max_srq_wrs = HNS_ROCE_V2_MAX_SRQ_WR; caps->max_srq_sges = HNS_ROCE_V2_MAX_SRQ_SGE; - if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP08_B) { - caps->flags |= HNS_ROCE_CAP_FLAG_ATOMIC | HNS_ROCE_CAP_FLAG_MW | - HNS_ROCE_CAP_FLAG_SRQ | HNS_ROCE_CAP_FLAG_FRMR | - HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL; + caps->flags |= HNS_ROCE_CAP_FLAG_ATOMIC | HNS_ROCE_CAP_FLAG_MW | + HNS_ROCE_CAP_FLAG_SRQ | HNS_ROCE_CAP_FLAG_FRMR | + HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL; - caps->num_qpc_timer = HNS_ROCE_V2_MAX_QPC_TIMER_NUM; - caps->qpc_timer_entry_sz = HNS_ROCE_V2_QPC_TIMER_ENTRY_SZ; - caps->qpc_timer_ba_pg_sz = 0; - caps->qpc_timer_buf_pg_sz = 0; - caps->qpc_timer_hop_num = HNS_ROCE_HOP_NUM_0; - caps->num_cqc_timer = HNS_ROCE_V2_MAX_CQC_TIMER_NUM; - caps->cqc_timer_entry_sz = HNS_ROCE_V2_CQC_TIMER_ENTRY_SZ; - caps->cqc_timer_ba_pg_sz = 0; - caps->cqc_timer_buf_pg_sz = 0; - caps->cqc_timer_hop_num = HNS_ROCE_HOP_NUM_0; + caps->num_qpc_timer = HNS_ROCE_V2_MAX_QPC_TIMER_NUM; + caps->qpc_timer_entry_sz = HNS_ROCE_V2_QPC_TIMER_ENTRY_SZ; + caps->qpc_timer_ba_pg_sz = 0; + caps->qpc_timer_buf_pg_sz = 0; + caps->qpc_timer_hop_num = HNS_ROCE_HOP_NUM_0; + caps->num_cqc_timer = HNS_ROCE_V2_MAX_CQC_TIMER_NUM; + caps->cqc_timer_entry_sz = HNS_ROCE_V2_CQC_TIMER_ENTRY_SZ; + caps->cqc_timer_ba_pg_sz = 0; + caps->cqc_timer_buf_pg_sz = 0; + caps->cqc_timer_hop_num = HNS_ROCE_HOP_NUM_0; - caps->sccc_entry_sz = HNS_ROCE_V2_SCCC_ENTRY_SZ; - caps->sccc_ba_pg_sz = 0; - caps->sccc_buf_pg_sz = 0; - caps->sccc_hop_num = HNS_ROCE_SCCC_HOP_NUM; - } + caps->sccc_entry_sz = HNS_ROCE_V2_SCCC_ENTRY_SZ; + caps->sccc_ba_pg_sz = 0; + caps->sccc_buf_pg_sz = 0; + caps->sccc_hop_num = HNS_ROCE_SCCC_HOP_NUM; } static void calc_pg_sz(int obj_num, int obj_size, int hop_num, int ctx_bt_num, @@ -1995,20 +1995,18 @@ static int hns_roce_query_pf_caps(struct hns_roce_dev *hr_dev) caps->srqc_bt_num, &caps->srqc_buf_pg_sz, &caps->srqc_ba_pg_sz, HEM_TYPE_SRQC); - if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP08_B) { - caps->sccc_hop_num = ctx_hop_num; - caps->qpc_timer_hop_num = HNS_ROCE_HOP_NUM_0; - caps->cqc_timer_hop_num = HNS_ROCE_HOP_NUM_0; + caps->sccc_hop_num = ctx_hop_num; + caps->qpc_timer_hop_num = HNS_ROCE_HOP_NUM_0; + caps->cqc_timer_hop_num = HNS_ROCE_HOP_NUM_0; - calc_pg_sz(caps->num_qps, caps->sccc_entry_sz, - caps->sccc_hop_num, caps->sccc_bt_num, - &caps->sccc_buf_pg_sz, &caps->sccc_ba_pg_sz, - HEM_TYPE_SCCC); - calc_pg_sz(caps->num_cqc_timer, caps->cqc_timer_entry_sz, - caps->cqc_timer_hop_num, caps->cqc_timer_bt_num, - &caps->cqc_timer_buf_pg_sz, - &caps->cqc_timer_ba_pg_sz, HEM_TYPE_CQC_TIMER); - } + calc_pg_sz(caps->num_qps, caps->sccc_entry_sz, + caps->sccc_hop_num, caps->sccc_bt_num, + &caps->sccc_buf_pg_sz, &caps->sccc_ba_pg_sz, + HEM_TYPE_SCCC); + calc_pg_sz(caps->num_cqc_timer, caps->cqc_timer_entry_sz, + caps->cqc_timer_hop_num, caps->cqc_timer_bt_num, + &caps->cqc_timer_buf_pg_sz, + &caps->cqc_timer_ba_pg_sz, HEM_TYPE_CQC_TIMER); calc_pg_sz(caps->num_cqe_segs, caps->mtt_entry_sz, caps->cqe_hop_num, 1, &caps->cqe_buf_pg_sz, &caps->cqe_ba_pg_sz, HEM_TYPE_CQE); @@ -2055,22 +2053,19 @@ static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev) return ret; } - if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP08_B) { - ret = hns_roce_query_pf_timer_resource(hr_dev); - if (ret) { - dev_err(hr_dev->dev, - "Query pf timer resource fail, ret = %d.\n", - ret); - return ret; - } + ret = hns_roce_query_pf_timer_resource(hr_dev); + if (ret) { + dev_err(hr_dev->dev, + "failed to query pf timer resource, ret = %d.\n", ret); + return ret; + } - ret = hns_roce_set_vf_switch_param(hr_dev, 0); - if (ret) { - dev_err(hr_dev->dev, - "Set function switch param fail, ret = %d.\n", - ret); - return ret; - } + ret = hns_roce_set_vf_switch_param(hr_dev, 0); + if (ret) { + dev_err(hr_dev->dev, + "failed to set function switch param, ret = %d.\n", + ret); + return ret; } hr_dev->vendor_part_id = hr_dev->pci_dev->device; @@ -2336,8 +2331,7 @@ static void hns_roce_v2_exit(struct hns_roce_dev *hr_dev) { struct hns_roce_v2_priv *priv = hr_dev->priv; - if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP08_B) - hns_roce_function_clear(hr_dev); + hns_roce_function_clear(hr_dev); hns_roce_free_link_table(hr_dev, &priv->tpq); hns_roce_free_link_table(hr_dev, &priv->tsq); @@ -3053,6 +3047,7 @@ static void get_cqe_status(struct hns_roce_dev *hr_dev, struct hns_roce_qp *qp, IB_WC_RETRY_EXC_ERR }, { HNS_ROCE_CQE_V2_RNR_RETRY_EXC_ERR, IB_WC_RNR_RETRY_EXC_ERR }, { HNS_ROCE_CQE_V2_REMOTE_ABORT_ERR, IB_WC_REM_ABORT_ERR }, + { HNS_ROCE_CQE_V2_GENERAL_ERR, IB_WC_GENERAL_ERR} }; u32 cqe_status = roce_get_field(cqe->byte_4, V2_CQE_BYTE_4_STATUS_M, @@ -3074,6 +3069,14 @@ static void get_cqe_status(struct hns_roce_dev *hr_dev, struct hns_roce_qp *qp, print_hex_dump(KERN_ERR, "", DUMP_PREFIX_NONE, 16, 4, cqe, sizeof(*cqe), false); + /* + * For hns ROCEE, GENERAL_ERR is an error type that is not defined in + * the standard protocol, the driver must ignore it and needn't to set + * the QP to an error state. + */ + if (cqe_status == HNS_ROCE_CQE_V2_GENERAL_ERR) + return; + /* * Hip08 hardware cannot flush the WQEs in SQ/RQ if the QP state gets * into errored mode. Hence, as a workaround to this hardware @@ -3170,51 +3173,51 @@ static int hns_roce_v2_poll_one(struct hns_roce_cq *hr_cq, /* SQ corresponding to CQE */ switch (roce_get_field(cqe->byte_4, V2_CQE_BYTE_4_OPCODE_M, V2_CQE_BYTE_4_OPCODE_S) & 0x1f) { - case HNS_ROCE_SQ_OPCODE_SEND: + case HNS_ROCE_V2_WQE_OP_SEND: wc->opcode = IB_WC_SEND; break; - case HNS_ROCE_SQ_OPCODE_SEND_WITH_INV: + case HNS_ROCE_V2_WQE_OP_SEND_WITH_INV: wc->opcode = IB_WC_SEND; break; - case HNS_ROCE_SQ_OPCODE_SEND_WITH_IMM: + case HNS_ROCE_V2_WQE_OP_SEND_WITH_IMM: wc->opcode = IB_WC_SEND; wc->wc_flags |= IB_WC_WITH_IMM; break; - case HNS_ROCE_SQ_OPCODE_RDMA_READ: + case HNS_ROCE_V2_WQE_OP_RDMA_READ: wc->opcode = IB_WC_RDMA_READ; wc->byte_len = le32_to_cpu(cqe->byte_cnt); break; - case HNS_ROCE_SQ_OPCODE_RDMA_WRITE: + case HNS_ROCE_V2_WQE_OP_RDMA_WRITE: wc->opcode = IB_WC_RDMA_WRITE; break; - case HNS_ROCE_SQ_OPCODE_RDMA_WRITE_WITH_IMM: + case HNS_ROCE_V2_WQE_OP_RDMA_WRITE_WITH_IMM: wc->opcode = IB_WC_RDMA_WRITE; wc->wc_flags |= IB_WC_WITH_IMM; break; - case HNS_ROCE_SQ_OPCODE_LOCAL_INV: + case HNS_ROCE_V2_WQE_OP_LOCAL_INV: wc->opcode = IB_WC_LOCAL_INV; wc->wc_flags |= IB_WC_WITH_INVALIDATE; break; - case HNS_ROCE_SQ_OPCODE_ATOMIC_COMP_AND_SWAP: + case HNS_ROCE_V2_WQE_OP_ATOM_CMP_AND_SWAP: wc->opcode = IB_WC_COMP_SWAP; wc->byte_len = 8; break; - case HNS_ROCE_SQ_OPCODE_ATOMIC_FETCH_AND_ADD: + case HNS_ROCE_V2_WQE_OP_ATOM_FETCH_AND_ADD: wc->opcode = IB_WC_FETCH_ADD; wc->byte_len = 8; break; - case HNS_ROCE_SQ_OPCODE_ATOMIC_MASK_COMP_AND_SWAP: + case HNS_ROCE_V2_WQE_OP_ATOM_MSK_CMP_AND_SWAP: wc->opcode = IB_WC_MASKED_COMP_SWAP; wc->byte_len = 8; break; - case HNS_ROCE_SQ_OPCODE_ATOMIC_MASK_FETCH_AND_ADD: + case HNS_ROCE_V2_WQE_OP_ATOM_MSK_FETCH_AND_ADD: wc->opcode = IB_WC_MASKED_FETCH_ADD; wc->byte_len = 8; break; - case HNS_ROCE_SQ_OPCODE_FAST_REG_WR: + case HNS_ROCE_V2_WQE_OP_FAST_REG_PMR: wc->opcode = IB_WC_REG_MR; break; - case HNS_ROCE_SQ_OPCODE_BIND_MW: + case HNS_ROCE_V2_WQE_OP_BIND_MW: wc->opcode = IB_WC_REG_MR; break; default: @@ -3374,11 +3377,33 @@ static int get_op_for_set_hem(struct hns_roce_dev *hr_dev, u32 type, return op + step_idx; } +static int set_hem_to_hw(struct hns_roce_dev *hr_dev, int obj, u64 bt_ba, + u32 hem_type, int step_idx) +{ + struct hns_roce_cmd_mailbox *mailbox; + int ret; + int op; + + op = get_op_for_set_hem(hr_dev, hem_type, step_idx); + if (op < 0) + return 0; + + mailbox = hns_roce_alloc_cmd_mailbox(hr_dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + ret = hns_roce_cmd_mbox(hr_dev, bt_ba, mailbox->dma, obj, + 0, op, HNS_ROCE_CMD_TIMEOUT_MSECS); + + hns_roce_free_cmd_mailbox(hr_dev, mailbox); + + return ret; +} + static int hns_roce_v2_set_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem_table *table, int obj, int step_idx) { - struct hns_roce_cmd_mailbox *mailbox; struct hns_roce_hem_iter iter; struct hns_roce_hem_mhop mhop; struct hns_roce_hem *hem; @@ -3390,7 +3415,6 @@ static int hns_roce_v2_set_hem(struct hns_roce_dev *hr_dev, u64 bt_ba = 0; u32 chunk_ba_num; u32 hop_num; - int op; if (!hns_roce_check_whether_mhop(hr_dev, table->type)) return 0; @@ -3412,14 +3436,6 @@ static int hns_roce_v2_set_hem(struct hns_roce_dev *hr_dev, hem_idx = i; } - op = get_op_for_set_hem(hr_dev, table->type, step_idx); - if (op == -EINVAL) - return 0; - - mailbox = hns_roce_alloc_cmd_mailbox(hr_dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - if (table->type == HEM_TYPE_SCCC) obj = mhop.l0_idx; @@ -3428,11 +3444,8 @@ static int hns_roce_v2_set_hem(struct hns_roce_dev *hr_dev, for (hns_roce_hem_first(hem, &iter); !hns_roce_hem_last(&iter); hns_roce_hem_next(&iter)) { bt_ba = hns_roce_hem_addr(&iter); - - /* configure the ba, tag, and op */ - ret = hns_roce_cmd_mbox(hr_dev, bt_ba, mailbox->dma, - obj, 0, op, - HNS_ROCE_CMD_TIMEOUT_MSECS); + ret = set_hem_to_hw(hr_dev, obj, bt_ba, table->type, + step_idx); } } else { if (step_idx == 0) @@ -3440,12 +3453,9 @@ static int hns_roce_v2_set_hem(struct hns_roce_dev *hr_dev, else if (step_idx == 1 && hop_num == 2) bt_ba = table->bt_l1_dma_addr[l1_idx]; - /* configure the ba, tag, and op */ - ret = hns_roce_cmd_mbox(hr_dev, bt_ba, mailbox->dma, obj, - 0, op, HNS_ROCE_CMD_TIMEOUT_MSECS); + ret = set_hem_to_hw(hr_dev, obj, bt_ba, table->type, step_idx); } - hns_roce_free_cmd_mailbox(hr_dev, mailbox); return ret; } @@ -3745,51 +3755,23 @@ static void modify_qp_init_to_init(struct ib_qp *ibqp, } } -static bool check_wqe_rq_mtt_count(struct hns_roce_dev *hr_dev, - struct hns_roce_qp *hr_qp, int mtt_cnt, - u32 page_size) -{ - struct ib_device *ibdev = &hr_dev->ib_dev; - - if (hr_qp->rq.wqe_cnt < 1) - return true; - - if (mtt_cnt < 1) { - ibdev_err(ibdev, "failed to find RQWQE buf ba of QP(0x%lx)\n", - hr_qp->qpn); - return false; - } - - if (mtt_cnt < MTT_MIN_COUNT && - (hr_qp->rq.offset + page_size) < hr_qp->buff_size) { - ibdev_err(ibdev, - "failed to find next RQWQE buf ba of QP(0x%lx)\n", - hr_qp->qpn); - return false; - } - - return true; -} - static int config_qp_rq_buf(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp, struct hns_roce_v2_qp_context *context, struct hns_roce_v2_qp_context *qpc_mask) { - struct ib_qp *ibqp = &hr_qp->ibqp; u64 mtts[MTT_MIN_COUNT] = { 0 }; u64 wqe_sge_ba; - u32 page_size; int count; /* Search qp buf's mtts */ - page_size = 1 << hr_qp->mtr.hem_cfg.buf_pg_shift; - count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, - hr_qp->rq.offset / page_size, mtts, + count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, hr_qp->rq.offset, mtts, MTT_MIN_COUNT, &wqe_sge_ba); - if (!ibqp->srq) - if (!check_wqe_rq_mtt_count(hr_dev, hr_qp, count, page_size)) - return -EINVAL; + if (hr_qp->rq.wqe_cnt && count < 1) { + ibdev_err(&hr_dev->ib_dev, + "failed to find RQ WQE, QPN = 0x%lx.\n", hr_qp->qpn); + return -EINVAL; + } context->wqe_sge_ba = cpu_to_le32(wqe_sge_ba >> 3); qpc_mask->wqe_sge_ba = 0; @@ -3891,7 +3873,6 @@ static int config_qp_sq_buf(struct hns_roce_dev *hr_dev, struct ib_device *ibdev = &hr_dev->ib_dev; u64 sge_cur_blk = 0; u64 sq_cur_blk = 0; - u32 page_size; int count; /* search qp buf's mtts */ @@ -3902,9 +3883,8 @@ static int config_qp_sq_buf(struct hns_roce_dev *hr_dev, return -EINVAL; } if (hr_qp->sge.sge_cnt > 0) { - page_size = 1 << hr_qp->mtr.hem_cfg.buf_pg_shift; count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, - hr_qp->sge.offset / page_size, + hr_qp->sge.offset, &sge_cur_blk, 1, NULL); if (count < 1) { ibdev_err(ibdev, "failed to find QP(0x%lx) SGE buf.\n", @@ -4265,12 +4245,13 @@ static int hns_roce_v2_set_path(struct ib_qp *ibqp, roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_HOP_LIMIT_M, V2_QPC_BYTE_24_HOP_LIMIT_S, 0); - if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP08_B && is_udp) + if (is_udp) roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_TC_M, V2_QPC_BYTE_24_TC_S, grh->traffic_class >> 2); else roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_TC_M, V2_QPC_BYTE_24_TC_S, grh->traffic_class); + roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_TC_M, V2_QPC_BYTE_24_TC_S, 0); roce_set_field(context->byte_28_at_fl, V2_QPC_BYTE_28_FL_M, @@ -4301,7 +4282,9 @@ static bool check_qp_state(enum ib_qp_state cur_state, [IB_QPS_RTR] = { [IB_QPS_RESET] = true, [IB_QPS_RTS] = true, [IB_QPS_ERR] = true }, - [IB_QPS_RTS] = { [IB_QPS_RESET] = true, [IB_QPS_ERR] = true }, + [IB_QPS_RTS] = { [IB_QPS_RESET] = true, + [IB_QPS_RTS] = true, + [IB_QPS_ERR] = true }, [IB_QPS_SQD] = {}, [IB_QPS_SQE] = {}, [IB_QPS_ERR] = { [IB_QPS_RESET] = true, [IB_QPS_ERR] = true } diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h index e176b0aaa4ac2a41cbf04df432e9bc450c2e0421..1fb1c583d0f8fbabf7dc3c0781684c50de50ecd9 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h @@ -179,26 +179,10 @@ enum { HNS_ROCE_V2_WQE_OP_ATOM_MSK_FETCH_AND_ADD = 0x9, HNS_ROCE_V2_WQE_OP_FAST_REG_PMR = 0xa, HNS_ROCE_V2_WQE_OP_LOCAL_INV = 0xb, - HNS_ROCE_V2_WQE_OP_BIND_MW_TYPE = 0xc, + HNS_ROCE_V2_WQE_OP_BIND_MW = 0xc, HNS_ROCE_V2_WQE_OP_MASK = 0x1f, }; -enum { - HNS_ROCE_SQ_OPCODE_SEND = 0x0, - HNS_ROCE_SQ_OPCODE_SEND_WITH_INV = 0x1, - HNS_ROCE_SQ_OPCODE_SEND_WITH_IMM = 0x2, - HNS_ROCE_SQ_OPCODE_RDMA_WRITE = 0x3, - HNS_ROCE_SQ_OPCODE_RDMA_WRITE_WITH_IMM = 0x4, - HNS_ROCE_SQ_OPCODE_RDMA_READ = 0x5, - HNS_ROCE_SQ_OPCODE_ATOMIC_COMP_AND_SWAP = 0x6, - HNS_ROCE_SQ_OPCODE_ATOMIC_FETCH_AND_ADD = 0x7, - HNS_ROCE_SQ_OPCODE_ATOMIC_MASK_COMP_AND_SWAP = 0x8, - HNS_ROCE_SQ_OPCODE_ATOMIC_MASK_FETCH_AND_ADD = 0x9, - HNS_ROCE_SQ_OPCODE_FAST_REG_WR = 0xa, - HNS_ROCE_SQ_OPCODE_LOCAL_INV = 0xb, - HNS_ROCE_SQ_OPCODE_BIND_MW = 0xc, -}; - enum { /* rq operations */ HNS_ROCE_V2_OPCODE_RDMA_WRITE_IMM = 0x0, @@ -230,6 +214,7 @@ enum { HNS_ROCE_CQE_V2_TRANSPORT_RETRY_EXC_ERR = 0x15, HNS_ROCE_CQE_V2_RNR_RETRY_EXC_ERR = 0x16, HNS_ROCE_CQE_V2_REMOTE_ABORT_ERR = 0x22, + HNS_ROCE_CQE_V2_GENERAL_ERR = 0x23, HNS_ROCE_V2_CQE_STATUS_MASK = 0xff, }; diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c index 50763cf4fa3da507b641231777d9205e6f8d1e34..5907cfd878a63d02f98740015c16fcfa4dc37784 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -428,7 +428,7 @@ static const struct ib_device_ops hns_roce_dev_ops = { .destroy_ah = hns_roce_destroy_ah, .destroy_cq = hns_roce_destroy_cq, .disassociate_ucontext = hns_roce_disassociate_ucontext, - .fill_res_entry = hns_roce_fill_res_entry, + .fill_res_cq_entry = hns_roce_fill_res_cq_entry, .get_dma_mr = hns_roce_get_dma_mr, .get_link_layer = hns_roce_get_link_layer, .get_port_immutable = hns_roce_port_immutable, diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c index 6b226a5eb7db6fbc808c6420d81675932f437107..e5df3884b41dda782483947eefe09ee004edbd12 100644 --- a/drivers/infiniband/hw/hns/hns_roce_mr.c +++ b/drivers/infiniband/hw/hns/hns_roce_mr.c @@ -415,7 +415,7 @@ int hns_roce_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) } struct ib_mr *hns_roce_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata) + u32 max_num_sg) { struct hns_roce_dev *hr_dev = to_hr_dev(pd->device); struct device *dev = hr_dev->dev; @@ -871,6 +871,15 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, int err; int i; + /* + * Only use the first page address as root ba when hopnum is 0, this + * is because the addresses of all pages are consecutive in this case. + */ + if (mtr->hem_cfg.is_direct) { + mtr->hem_cfg.root_ba = pages[0]; + return 0; + } + for (i = 0; i < mtr->hem_cfg.region_count; i++) { r = &mtr->hem_cfg.region[i]; if (r->offset + r->count > page_cnt) { @@ -896,6 +905,8 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, int offset, u64 *mtt_buf, int mtt_max, u64 *base_addr) { + struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg; + int start_index; int mtt_count; int total = 0; __le64 *mtts; @@ -907,26 +918,32 @@ int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, goto done; /* no mtt memory in direct mode, so just return the buffer address */ - if (mtr->hem_cfg.is_direct) { - npage = offset; - for (total = 0; total < mtt_max; total++, npage++) { - addr = mtr->hem_cfg.root_ba + - (npage << mtr->hem_cfg.buf_pg_shift); - + if (cfg->is_direct) { + start_index = offset >> HNS_HW_PAGE_SHIFT; + for (mtt_count = 0; mtt_count < cfg->region_count && + total < mtt_max; mtt_count++) { + npage = cfg->region[mtt_count].offset; + if (npage < start_index) + continue; + + addr = cfg->root_ba + (npage << HNS_HW_PAGE_SHIFT); if (hr_dev->hw_rev == HNS_ROCE_HW_VER1) mtt_buf[total] = to_hr_hw_page_addr(addr); else mtt_buf[total] = addr; + + total++; } goto done; } + start_index = offset >> cfg->buf_pg_shift; left = mtt_max; while (left > 0) { mtt_count = 0; mtts = hns_roce_hem_list_find_mtt(hr_dev, &mtr->hem_list, - offset + total, + start_index + total, &mtt_count, NULL); if (!mtts || !mtt_count) goto done; @@ -939,104 +956,136 @@ int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, done: if (base_addr) - *base_addr = mtr->hem_cfg.root_ba; + *base_addr = cfg->root_ba; return total; } -/* convert buffer size to page index and page count */ -static unsigned int mtr_init_region(struct hns_roce_buf_attr *attr, - int page_cnt, - struct hns_roce_buf_region *regions, - int region_cnt, unsigned int page_shift) +static int mtr_init_buf_cfg(struct hns_roce_dev *hr_dev, + struct hns_roce_buf_attr *attr, + struct hns_roce_hem_cfg *cfg, + unsigned int *buf_page_shift) { - unsigned int page_size = 1 << page_shift; - int max_region = attr->region_count; struct hns_roce_buf_region *r; - unsigned int i = 0; - int page_idx = 0; - - for (; i < region_cnt && i < max_region && page_idx < page_cnt; i++) { - r = ®ions[i]; - r->hopnum = attr->region[i].hopnum == HNS_ROCE_HOP_NUM_0 ? - 0 : attr->region[i].hopnum; - r->offset = page_idx; - r->count = DIV_ROUND_UP(attr->region[i].size, page_size); - page_idx += r->count; + unsigned int page_shift = 0; + int page_cnt = 0; + size_t buf_size; + int region_cnt; + + if (cfg->is_direct) { + buf_size = cfg->buf_pg_count << cfg->buf_pg_shift; + page_cnt = DIV_ROUND_UP(buf_size, HNS_HW_PAGE_SIZE); + /* + * When HEM buffer use level-0 addressing, the page size equals + * the buffer size, and the the page size = 4K * 2^N. + */ + cfg->buf_pg_shift = HNS_HW_PAGE_SHIFT + order_base_2(page_cnt); + if (attr->region_count > 1) { + cfg->buf_pg_count = page_cnt; + page_shift = HNS_HW_PAGE_SHIFT; + } else { + cfg->buf_pg_count = 1; + page_shift = cfg->buf_pg_shift; + if (buf_size != 1 << page_shift) { + ibdev_err(&hr_dev->ib_dev, + "failed to check direct size %zu shift %d.\n", + buf_size, page_shift); + return -EINVAL; + } + } + } else { + page_shift = cfg->buf_pg_shift; + } + + /* convert buffer size to page index and page count */ + for (page_cnt = 0, region_cnt = 0; page_cnt < cfg->buf_pg_count && + region_cnt < attr->region_count && + region_cnt < ARRAY_SIZE(cfg->region); region_cnt++) { + r = &cfg->region[region_cnt]; + r->offset = page_cnt; + buf_size = hr_hw_page_align(attr->region[region_cnt].size); + r->count = DIV_ROUND_UP(buf_size, 1 << page_shift); + page_cnt += r->count; + r->hopnum = to_hr_hem_hopnum(attr->region[region_cnt].hopnum, + r->count); + } + + if (region_cnt < 1) { + ibdev_err(&hr_dev->ib_dev, + "failed to check mtr region count, pages = %d.\n", + cfg->buf_pg_count); + return -ENOBUFS; } - return i; + cfg->region_count = region_cnt; + *buf_page_shift = page_shift; + + return page_cnt; } /** * hns_roce_mtr_create - Create hns memory translate region. * * @mtr: memory translate region - * @init_attr: init attribute for creating mtr - * @page_shift: page shift for multi-hop base address table + * @buf_attr: buffer attribute for creating mtr + * @ba_page_shift: page shift for multi-hop base address table * @udata: user space context, if it's NULL, means kernel space * @user_addr: userspace virtual address to start at - * @buf_alloced: mtr has private buffer, true means need to alloc */ int hns_roce_mtr_create(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, struct hns_roce_buf_attr *buf_attr, - unsigned int page_shift, struct ib_udata *udata, + unsigned int ba_page_shift, struct ib_udata *udata, unsigned long user_addr) { + struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg; struct ib_device *ibdev = &hr_dev->ib_dev; + unsigned int buf_page_shift = 0; dma_addr_t *pages = NULL; - int region_cnt = 0; int all_pg_cnt; int get_pg_cnt; - bool has_mtt; - int err = 0; + int ret = 0; + + /* if disable mtt, all pages must in a continuous address range */ + cfg->is_direct = !mtr_has_mtt(buf_attr); - has_mtt = mtr_has_mtt(buf_attr); /* if buffer only need mtt, just init the hem cfg */ if (buf_attr->mtt_only) { - mtr->hem_cfg.buf_pg_shift = buf_attr->page_shift; - mtr->hem_cfg.buf_pg_count = mtr_bufs_size(buf_attr) >> - buf_attr->page_shift; + cfg->buf_pg_shift = buf_attr->page_shift; + cfg->buf_pg_count = mtr_bufs_size(buf_attr) >> + buf_attr->page_shift; mtr->umem = NULL; mtr->kmem = NULL; } else { - err = mtr_alloc_bufs(hr_dev, mtr, buf_attr, !has_mtt, udata, - user_addr); - if (err) { - ibdev_err(ibdev, "Failed to alloc mtr bufs, err %d\n", - err); - return err; + ret = mtr_alloc_bufs(hr_dev, mtr, buf_attr, cfg->is_direct, + udata, user_addr); + if (ret) { + ibdev_err(ibdev, + "failed to alloc mtr bufs, ret = %d.\n", ret); + return ret; } } - /* alloc mtt memory */ - all_pg_cnt = mtr->hem_cfg.buf_pg_count; - hns_roce_hem_list_init(&mtr->hem_list); - mtr->hem_cfg.is_direct = !has_mtt; - mtr->hem_cfg.ba_pg_shift = page_shift; - mtr->hem_cfg.region_count = 0; - region_cnt = mtr_init_region(buf_attr, all_pg_cnt, - mtr->hem_cfg.region, - ARRAY_SIZE(mtr->hem_cfg.region), - mtr->hem_cfg.buf_pg_shift); - if (region_cnt < 1) { - err = -ENOBUFS; - ibdev_err(ibdev, "failed to init mtr region %d\n", region_cnt); + all_pg_cnt = mtr_init_buf_cfg(hr_dev, buf_attr, cfg, &buf_page_shift); + if (all_pg_cnt < 1) { + ret = -ENOBUFS; + ibdev_err(ibdev, "failed to init mtr buf cfg.\n"); goto err_alloc_bufs; } - mtr->hem_cfg.region_count = region_cnt; - - if (has_mtt) { - err = hns_roce_hem_list_request(hr_dev, &mtr->hem_list, - mtr->hem_cfg.region, region_cnt, - page_shift); - if (err) { - ibdev_err(ibdev, "Failed to request mtr hem, err %d\n", - err); + hns_roce_hem_list_init(&mtr->hem_list); + if (!cfg->is_direct) { + ret = hns_roce_hem_list_request(hr_dev, &mtr->hem_list, + cfg->region, cfg->region_count, + ba_page_shift); + if (ret) { + ibdev_err(ibdev, "failed to request mtr hem, ret = %d.\n", + ret); goto err_alloc_bufs; } - mtr->hem_cfg.root_ba = mtr->hem_list.root_ba; + cfg->root_ba = mtr->hem_list.root_ba; + cfg->ba_pg_shift = ba_page_shift; + } else { + cfg->ba_pg_shift = cfg->buf_pg_shift; } /* no buffer to map */ @@ -1046,31 +1095,26 @@ int hns_roce_mtr_create(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, /* alloc a tmp array to store buffer's dma address */ pages = kvcalloc(all_pg_cnt, sizeof(dma_addr_t), GFP_KERNEL); if (!pages) { - err = -ENOMEM; - ibdev_err(ibdev, "Failed to alloc mtr page list %d\n", + ret = -ENOMEM; + ibdev_err(ibdev, "failed to alloc mtr page list %d.\n", all_pg_cnt); goto err_alloc_hem_list; } get_pg_cnt = mtr_get_pages(hr_dev, mtr, pages, all_pg_cnt, - mtr->hem_cfg.buf_pg_shift); + buf_page_shift); if (get_pg_cnt != all_pg_cnt) { - ibdev_err(ibdev, "Failed to get mtr page %d != %d\n", + ibdev_err(ibdev, "failed to get mtr page %d != %d.\n", get_pg_cnt, all_pg_cnt); - err = -ENOBUFS; + ret = -ENOBUFS; goto err_alloc_page_list; } - if (!has_mtt) { - mtr->hem_cfg.root_ba = pages[0]; - } else { - /* write buffer's dma address to BA table */ - err = hns_roce_mtr_map(hr_dev, mtr, pages, all_pg_cnt); - if (err) { - ibdev_err(ibdev, "Failed to map mtr pages, err %d\n", - err); - goto err_alloc_page_list; - } + /* write buffer's dma address to BA table */ + ret = hns_roce_mtr_map(hr_dev, mtr, pages, all_pg_cnt); + if (ret) { + ibdev_err(ibdev, "failed to map mtr pages, ret = %d.\n", ret); + goto err_alloc_page_list; } /* drop tmp array */ @@ -1082,7 +1126,7 @@ err_alloc_hem_list: hns_roce_hem_list_release(hr_dev, &mtr->hem_list); err_alloc_bufs: mtr_free_bufs(hr_dev, mtr); - return err; + return ret; } void hns_roce_mtr_destroy(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr) diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c index a0a47bd669759c9e6169284b7ead17f5c2d50626..e94ca130ff5eb7fbfdcfc969d6f5a63057b7094e 100644 --- a/drivers/infiniband/hw/hns/hns_roce_qp.c +++ b/drivers/infiniband/hw/hns/hns_roce_qp.c @@ -411,7 +411,6 @@ static int set_extend_sge_param(struct hns_roce_dev *hr_dev, u32 sq_wqe_cnt, struct hns_roce_qp *hr_qp, struct ib_qp_cap *cap) { - struct ib_device *ibdev = &hr_dev->ib_dev; u32 cnt; cnt = max(1U, cap->max_send_sge); @@ -431,15 +430,6 @@ static int set_extend_sge_param(struct hns_roce_dev *hr_dev, u32 sq_wqe_cnt, } else if (hr_qp->sq.max_gs > HNS_ROCE_SGE_IN_WQE) { cnt = roundup_pow_of_two(sq_wqe_cnt * (hr_qp->sq.max_gs - HNS_ROCE_SGE_IN_WQE)); - - if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08_A) { - if (cnt > hr_dev->caps.max_extend_sg) { - ibdev_err(ibdev, - "failed to check exSGE num, exSGE num = %d.\n", - cnt); - return -EINVAL; - } - } } else { cnt = 0; } diff --git a/drivers/infiniband/hw/hns/hns_roce_restrack.c b/drivers/infiniband/hw/hns/hns_roce_restrack.c index 06871731ac43a72bde2c9df27ddde99740809732..259444c0a6301a547e76843bb9a488fa14b5fff8 100644 --- a/drivers/infiniband/hw/hns/hns_roce_restrack.c +++ b/drivers/infiniband/hw/hns/hns_roce_restrack.c @@ -76,10 +76,9 @@ err: return -EMSGSIZE; } -static int hns_roce_fill_res_cq_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res) +int hns_roce_fill_res_cq_entry(struct sk_buff *msg, + struct ib_cq *ib_cq) { - struct ib_cq *ib_cq = container_of(res, struct ib_cq, res); struct hns_roce_dev *hr_dev = to_hr_dev(ib_cq->device); struct hns_roce_cq *hr_cq = to_hr_cq(ib_cq); struct hns_roce_v2_cq_context *context; @@ -119,12 +118,3 @@ err: kfree(context); return ret; } - -int hns_roce_fill_res_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res) -{ - if (res->type == RDMA_RESTRACK_CQ) - return hns_roce_fill_res_cq_entry(msg, res); - - return 0; -} diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.c b/drivers/infiniband/hw/i40iw/i40iw_verbs.c index 19af29a48c55938f9c9f8a3d087a646ec74a9e57..6957e4f3404b10e78df64f1623fe22f3d2c5f2c6 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_verbs.c +++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.c @@ -101,7 +101,6 @@ static int i40iw_query_port(struct ib_device *ibdev, props->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_REINIT_SUP | IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP; props->gid_tbl_len = 1; - props->pkey_tbl_len = 1; props->active_width = IB_WIDTH_4X; props->active_speed = 1; props->max_msg_sz = I40IW_MAX_OUTBOUND_MESSAGE_SIZE; @@ -1543,10 +1542,9 @@ static int i40iw_hw_alloc_stag(struct i40iw_device *iwdev, struct i40iw_mr *iwmr * @pd: ibpd pointer * @mr_type: memory for stag registrion * @max_num_sg: man number of pages - * @udata: user data or NULL for kernel objects */ static struct ib_mr *i40iw_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata) + u32 max_num_sg) { struct i40iw_pd *iwpd = to_iwpd(pd); struct i40iw_device *iwdev = to_iwdev(pd->device); @@ -2460,7 +2458,6 @@ static int i40iw_port_immutable(struct ib_device *ibdev, u8 port_num, if (err) return err; - immutable->pkey_tbl_len = attr.pkey_tbl_len; immutable->gid_tbl_len = attr.gid_tbl_len; return 0; @@ -2616,22 +2613,6 @@ static int i40iw_query_gid(struct ib_device *ibdev, return 0; } -/** - * i40iw_query_pkey - Query partition key - * @ibdev: device pointer from stack - * @port: port number - * @index: index of pkey - * @pkey: pointer to store the pkey - */ -static int i40iw_query_pkey(struct ib_device *ibdev, - u8 port, - u16 index, - u16 *pkey) -{ - *pkey = 0; - return 0; -} - static const struct ib_device_ops i40iw_dev_ops = { .owner = THIS_MODULE, .driver_id = RDMA_DRIVER_I40IW, @@ -2671,7 +2652,6 @@ static const struct ib_device_ops i40iw_dev_ops = { .post_send = i40iw_post_send, .query_device = i40iw_query_device, .query_gid = i40iw_query_gid, - .query_pkey = i40iw_query_pkey, .query_port = i40iw_query_port, .query_qp = i40iw_query_qp, .reg_user_mr = i40iw_reg_user_mr, diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 816d28854a8e11a8d21a081b2adb60715e72e502..5e7910a517daefefb91635b92d43e5cf81c4e821 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -1219,56 +1219,47 @@ static void mlx4_ib_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata) mlx4_pd_free(to_mdev(pd->device)->dev, to_mpd(pd)->pdn); } -static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev, - struct ib_udata *udata) +static int mlx4_ib_alloc_xrcd(struct ib_xrcd *ibxrcd, struct ib_udata *udata) { - struct mlx4_ib_xrcd *xrcd; + struct mlx4_ib_dev *dev = to_mdev(ibxrcd->device); + struct mlx4_ib_xrcd *xrcd = to_mxrcd(ibxrcd); struct ib_cq_init_attr cq_attr = {}; int err; - if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)) - return ERR_PTR(-ENOSYS); - - xrcd = kmalloc(sizeof *xrcd, GFP_KERNEL); - if (!xrcd) - return ERR_PTR(-ENOMEM); + if (!(dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)) + return -EOPNOTSUPP; - err = mlx4_xrcd_alloc(to_mdev(ibdev)->dev, &xrcd->xrcdn); + err = mlx4_xrcd_alloc(dev->dev, &xrcd->xrcdn); if (err) - goto err1; + return err; - xrcd->pd = ib_alloc_pd(ibdev, 0); + xrcd->pd = ib_alloc_pd(ibxrcd->device, 0); if (IS_ERR(xrcd->pd)) { err = PTR_ERR(xrcd->pd); goto err2; } cq_attr.cqe = 1; - xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, &cq_attr); + xrcd->cq = ib_create_cq(ibxrcd->device, NULL, NULL, xrcd, &cq_attr); if (IS_ERR(xrcd->cq)) { err = PTR_ERR(xrcd->cq); goto err3; } - return &xrcd->ibxrcd; + return 0; err3: ib_dealloc_pd(xrcd->pd); err2: - mlx4_xrcd_free(to_mdev(ibdev)->dev, xrcd->xrcdn); -err1: - kfree(xrcd); - return ERR_PTR(err); + mlx4_xrcd_free(dev->dev, xrcd->xrcdn); + return err; } -static int mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata) +static void mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata) { ib_destroy_cq(to_mxrcd(xrcd)->cq); ib_dealloc_pd(to_mxrcd(xrcd)->pd); mlx4_xrcd_free(to_mdev(xrcd->device)->dev, to_mxrcd(xrcd)->xrcdn); - kfree(xrcd); - - return 0; } static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid) @@ -2607,6 +2598,8 @@ static const struct ib_device_ops mlx4_ib_dev_mw_ops = { static const struct ib_device_ops mlx4_ib_dev_xrc_ops = { .alloc_xrcd = mlx4_ib_alloc_xrcd, .dealloc_xrcd = mlx4_ib_dealloc_xrcd, + + INIT_RDMA_OBJ_SIZE(ib_xrcd, mlx4_ib_xrcd, ibxrcd), }; static const struct ib_device_ops mlx4_ib_dev_fs_ops = { diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index 6f4ea1067095e4f0d34df02d8ea27cfcd6850ab6..38e87a700a2a203df2cd7ff2b1246252c82b8f2a 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h @@ -729,7 +729,7 @@ struct ib_mw *mlx4_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type, struct ib_udata *udata); int mlx4_ib_dealloc_mw(struct ib_mw *mw); struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata); + u32 max_num_sg); int mlx4_ib_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, unsigned int *sg_offset); int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period); diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index 7e0b205c05eb30984b2c2b178bdcf11dcfdc98ce..1d5ef0de12c9509ad9192443f41bca5ee81b2830 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c @@ -439,7 +439,6 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; mr->ibmr.length = length; - mr->ibmr.iova = virt_addr; mr->ibmr.page_size = 1U << shift; return &mr->ibmr; @@ -655,7 +654,7 @@ int mlx4_ib_dealloc_mw(struct ib_mw *ibmw) } struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata) + u32 max_num_sg) { struct mlx4_ib_dev *dev = to_mdev(pd->device); struct mlx4_ib_mr *mr; diff --git a/drivers/infiniband/hw/mlx5/Makefile b/drivers/infiniband/hw/mlx5/Makefile index 8cca61c671f8d27ad9fa8c6315c4abfbbb919a8f..b4c009bb0db69d26c47ce0adb79e6f8c8f98d723 100644 --- a/drivers/infiniband/hw/mlx5/Makefile +++ b/drivers/infiniband/hw/mlx5/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_MLX5_INFINIBAND) += mlx5_ib.o mlx5_ib-y := ah.o \ cmd.o \ cong.o \ + counters.o \ cq.o \ doorbell.o \ gsi.o \ @@ -22,5 +23,6 @@ mlx5_ib-y := ah.o \ mlx5_ib-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += odp.o mlx5_ib-$(CONFIG_MLX5_ESWITCH) += ib_rep.o mlx5_ib-$(CONFIG_INFINIBAND_USER_ACCESS) += devx.o \ - flow.o \ - qos.o + fs.o \ + qos.o \ + std_types.o diff --git a/drivers/infiniband/hw/mlx5/cmd.c b/drivers/infiniband/hw/mlx5/cmd.c index cc24c711e92a082a4fac0e6e5cb3948e9f7ee38b..ebb2f108b64f14fd79eb8caa0bb7a456858f73e3 100644 --- a/drivers/infiniband/hw/mlx5/cmd.c +++ b/drivers/infiniband/hw/mlx5/cmd.c @@ -148,18 +148,6 @@ void mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length) spin_unlock(&dm->lock); } -int mlx5_cmd_query_ext_ppcnt_counters(struct mlx5_core_dev *dev, void *out) -{ - u32 in[MLX5_ST_SZ_DW(ppcnt_reg)] = {}; - int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); - - MLX5_SET(ppcnt_reg, in, local_port, 1); - - MLX5_SET(ppcnt_reg, in, grp, MLX5_ETHERNET_EXTENDED_COUNTERS_GROUP); - return mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPCNT, - 0, 0); -} - void mlx5_cmd_destroy_tir(struct mlx5_core_dev *dev, u32 tirn, u16 uid) { u32 in[MLX5_ST_SZ_DW(destroy_tir_in)] = {}; diff --git a/drivers/infiniband/hw/mlx5/cmd.h b/drivers/infiniband/hw/mlx5/cmd.h index f4d8558db434e69771fce7a725ce6e2cabfcc862..1d192a8ca87dc7f7024dd489129590f82cb9786e 100644 --- a/drivers/infiniband/hw/mlx5/cmd.h +++ b/drivers/infiniband/hw/mlx5/cmd.h @@ -41,7 +41,6 @@ int mlx5_cmd_dump_fill_mkey(struct mlx5_core_dev *dev, u32 *mkey); int mlx5_cmd_null_mkey(struct mlx5_core_dev *dev, u32 *null_mkey); int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point, void *out); -int mlx5_cmd_query_ext_ppcnt_counters(struct mlx5_core_dev *dev, void *out); int mlx5_cmd_alloc_memic(struct mlx5_dm *dm, phys_addr_t *addr, u64 length, u32 alignment); void mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length); diff --git a/drivers/infiniband/hw/mlx5/counters.c b/drivers/infiniband/hw/mlx5/counters.c new file mode 100644 index 0000000000000000000000000000000000000000..145f3cb40ccbaefd9b76e677c01f7fb19264b2ed --- /dev/null +++ b/drivers/infiniband/hw/mlx5/counters.c @@ -0,0 +1,709 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* + * Copyright (c) 2013-2020, Mellanox Technologies inc. All rights reserved. + */ + +#include "mlx5_ib.h" +#include +#include "counters.h" +#include "ib_rep.h" +#include "qp.h" + +struct mlx5_ib_counter { + const char *name; + size_t offset; +}; + +#define INIT_Q_COUNTER(_name) \ + { .name = #_name, .offset = MLX5_BYTE_OFF(query_q_counter_out, _name)} + +static const struct mlx5_ib_counter basic_q_cnts[] = { + INIT_Q_COUNTER(rx_write_requests), + INIT_Q_COUNTER(rx_read_requests), + INIT_Q_COUNTER(rx_atomic_requests), + INIT_Q_COUNTER(out_of_buffer), +}; + +static const struct mlx5_ib_counter out_of_seq_q_cnts[] = { + INIT_Q_COUNTER(out_of_sequence), +}; + +static const struct mlx5_ib_counter retrans_q_cnts[] = { + INIT_Q_COUNTER(duplicate_request), + INIT_Q_COUNTER(rnr_nak_retry_err), + INIT_Q_COUNTER(packet_seq_err), + INIT_Q_COUNTER(implied_nak_seq_err), + INIT_Q_COUNTER(local_ack_timeout_err), +}; + +#define INIT_CONG_COUNTER(_name) \ + { .name = #_name, .offset = \ + MLX5_BYTE_OFF(query_cong_statistics_out, _name ## _high)} + +static const struct mlx5_ib_counter cong_cnts[] = { + INIT_CONG_COUNTER(rp_cnp_ignored), + INIT_CONG_COUNTER(rp_cnp_handled), + INIT_CONG_COUNTER(np_ecn_marked_roce_packets), + INIT_CONG_COUNTER(np_cnp_sent), +}; + +static const struct mlx5_ib_counter extended_err_cnts[] = { + INIT_Q_COUNTER(resp_local_length_error), + INIT_Q_COUNTER(resp_cqe_error), + INIT_Q_COUNTER(req_cqe_error), + INIT_Q_COUNTER(req_remote_invalid_request), + INIT_Q_COUNTER(req_remote_access_errors), + INIT_Q_COUNTER(resp_remote_access_errors), + INIT_Q_COUNTER(resp_cqe_flush_error), + INIT_Q_COUNTER(req_cqe_flush_error), +}; + +static const struct mlx5_ib_counter roce_accl_cnts[] = { + INIT_Q_COUNTER(roce_adp_retrans), + INIT_Q_COUNTER(roce_adp_retrans_to), + INIT_Q_COUNTER(roce_slow_restart), + INIT_Q_COUNTER(roce_slow_restart_cnps), + INIT_Q_COUNTER(roce_slow_restart_trans), +}; + +#define INIT_EXT_PPCNT_COUNTER(_name) \ + { .name = #_name, .offset = \ + MLX5_BYTE_OFF(ppcnt_reg, \ + counter_set.eth_extended_cntrs_grp_data_layout._name##_high)} + +static const struct mlx5_ib_counter ext_ppcnt_cnts[] = { + INIT_EXT_PPCNT_COUNTER(rx_icrc_encapsulated), +}; + +static int mlx5_ib_read_counters(struct ib_counters *counters, + struct ib_counters_read_attr *read_attr, + struct uverbs_attr_bundle *attrs) +{ + struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); + struct mlx5_read_counters_attr mread_attr = {}; + struct mlx5_ib_flow_counters_desc *desc; + int ret, i; + + mutex_lock(&mcounters->mcntrs_mutex); + if (mcounters->cntrs_max_index > read_attr->ncounters) { + ret = -EINVAL; + goto err_bound; + } + + mread_attr.out = kcalloc(mcounters->counters_num, sizeof(u64), + GFP_KERNEL); + if (!mread_attr.out) { + ret = -ENOMEM; + goto err_bound; + } + + mread_attr.hw_cntrs_hndl = mcounters->hw_cntrs_hndl; + mread_attr.flags = read_attr->flags; + ret = mcounters->read_counters(counters->device, &mread_attr); + if (ret) + goto err_read; + + /* do the pass over the counters data array to assign according to the + * descriptions and indexing pairs + */ + desc = mcounters->counters_data; + for (i = 0; i < mcounters->ncounters; i++) + read_attr->counters_buff[desc[i].index] += mread_attr.out[desc[i].description]; + +err_read: + kfree(mread_attr.out); +err_bound: + mutex_unlock(&mcounters->mcntrs_mutex); + return ret; +} + +static void mlx5_ib_destroy_counters(struct ib_counters *counters) +{ + struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); + + mlx5_ib_counters_clear_description(counters); + if (mcounters->hw_cntrs_hndl) + mlx5_fc_destroy(to_mdev(counters->device)->mdev, + mcounters->hw_cntrs_hndl); +} + +static int mlx5_ib_create_counters(struct ib_counters *counters, + struct uverbs_attr_bundle *attrs) +{ + struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); + + mutex_init(&mcounters->mcntrs_mutex); + return 0; +} + + +static bool is_mdev_switchdev_mode(const struct mlx5_core_dev *mdev) +{ + return MLX5_ESWITCH_MANAGER(mdev) && + mlx5_ib_eswitch_mode(mdev->priv.eswitch) == + MLX5_ESWITCH_OFFLOADS; +} + +static const struct mlx5_ib_counters *get_counters(struct mlx5_ib_dev *dev, + u8 port_num) +{ + return is_mdev_switchdev_mode(dev->mdev) ? &dev->port[0].cnts : + &dev->port[port_num].cnts; +} + +/** + * mlx5_ib_get_counters_id - Returns counters id to use for device+port + * @dev: Pointer to mlx5 IB device + * @port_num: Zero based port number + * + * mlx5_ib_get_counters_id() Returns counters set id to use for given + * device port combination in switchdev and non switchdev mode of the + * parent device. + */ +u16 mlx5_ib_get_counters_id(struct mlx5_ib_dev *dev, u8 port_num) +{ + const struct mlx5_ib_counters *cnts = get_counters(dev, port_num); + + return cnts->set_id; +} + +static struct rdma_hw_stats *mlx5_ib_alloc_hw_stats(struct ib_device *ibdev, + u8 port_num) +{ + struct mlx5_ib_dev *dev = to_mdev(ibdev); + const struct mlx5_ib_counters *cnts; + bool is_switchdev = is_mdev_switchdev_mode(dev->mdev); + + if ((is_switchdev && port_num) || (!is_switchdev && !port_num)) + return NULL; + + cnts = get_counters(dev, port_num - 1); + + return rdma_alloc_hw_stats_struct(cnts->names, + cnts->num_q_counters + + cnts->num_cong_counters + + cnts->num_ext_ppcnt_counters, + RDMA_HW_STATS_DEFAULT_LIFESPAN); +} + +static int mlx5_ib_query_q_counters(struct mlx5_core_dev *mdev, + const struct mlx5_ib_counters *cnts, + struct rdma_hw_stats *stats, + u16 set_id) +{ + u32 out[MLX5_ST_SZ_DW(query_q_counter_out)] = {}; + u32 in[MLX5_ST_SZ_DW(query_q_counter_in)] = {}; + __be32 val; + int ret, i; + + MLX5_SET(query_q_counter_in, in, opcode, MLX5_CMD_OP_QUERY_Q_COUNTER); + MLX5_SET(query_q_counter_in, in, counter_set_id, set_id); + ret = mlx5_cmd_exec_inout(mdev, query_q_counter, in, out); + if (ret) + return ret; + + for (i = 0; i < cnts->num_q_counters; i++) { + val = *(__be32 *)((void *)out + cnts->offsets[i]); + stats->value[i] = (u64)be32_to_cpu(val); + } + + return 0; +} + +static int mlx5_ib_query_ext_ppcnt_counters(struct mlx5_ib_dev *dev, + const struct mlx5_ib_counters *cnts, + struct rdma_hw_stats *stats) +{ + int offset = cnts->num_q_counters + cnts->num_cong_counters; + u32 in[MLX5_ST_SZ_DW(ppcnt_reg)] = {}; + int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); + int ret, i; + void *out; + + out = kvzalloc(sz, GFP_KERNEL); + if (!out) + return -ENOMEM; + + MLX5_SET(ppcnt_reg, in, local_port, 1); + MLX5_SET(ppcnt_reg, in, grp, MLX5_ETHERNET_EXTENDED_COUNTERS_GROUP); + ret = mlx5_core_access_reg(dev->mdev, in, sz, out, sz, MLX5_REG_PPCNT, + 0, 0); + if (ret) + goto free; + + for (i = 0; i < cnts->num_ext_ppcnt_counters; i++) + stats->value[i + offset] = + be64_to_cpup((__be64 *)(out + + cnts->offsets[i + offset])); +free: + kvfree(out); + return ret; +} + +static int mlx5_ib_get_hw_stats(struct ib_device *ibdev, + struct rdma_hw_stats *stats, + u8 port_num, int index) +{ + struct mlx5_ib_dev *dev = to_mdev(ibdev); + const struct mlx5_ib_counters *cnts = get_counters(dev, port_num - 1); + struct mlx5_core_dev *mdev; + int ret, num_counters; + u8 mdev_port_num; + + if (!stats) + return -EINVAL; + + num_counters = cnts->num_q_counters + + cnts->num_cong_counters + + cnts->num_ext_ppcnt_counters; + + /* q_counters are per IB device, query the master mdev */ + ret = mlx5_ib_query_q_counters(dev->mdev, cnts, stats, cnts->set_id); + if (ret) + return ret; + + if (MLX5_CAP_PCAM_FEATURE(dev->mdev, rx_icrc_encapsulated_counter)) { + ret = mlx5_ib_query_ext_ppcnt_counters(dev, cnts, stats); + if (ret) + return ret; + } + + if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { + mdev = mlx5_ib_get_native_port_mdev(dev, port_num, + &mdev_port_num); + if (!mdev) { + /* If port is not affiliated yet, its in down state + * which doesn't have any counters yet, so it would be + * zero. So no need to read from the HCA. + */ + goto done; + } + ret = mlx5_lag_query_cong_counters(dev->mdev, + stats->value + + cnts->num_q_counters, + cnts->num_cong_counters, + cnts->offsets + + cnts->num_q_counters); + + mlx5_ib_put_native_port_mdev(dev, port_num); + if (ret) + return ret; + } + +done: + return num_counters; +} + +static struct rdma_hw_stats * +mlx5_ib_counter_alloc_stats(struct rdma_counter *counter) +{ + struct mlx5_ib_dev *dev = to_mdev(counter->device); + const struct mlx5_ib_counters *cnts = + get_counters(dev, counter->port - 1); + + return rdma_alloc_hw_stats_struct(cnts->names, + cnts->num_q_counters + + cnts->num_cong_counters + + cnts->num_ext_ppcnt_counters, + RDMA_HW_STATS_DEFAULT_LIFESPAN); +} + +static int mlx5_ib_counter_update_stats(struct rdma_counter *counter) +{ + struct mlx5_ib_dev *dev = to_mdev(counter->device); + const struct mlx5_ib_counters *cnts = + get_counters(dev, counter->port - 1); + + return mlx5_ib_query_q_counters(dev->mdev, cnts, + counter->stats, counter->id); +} + +static int mlx5_ib_counter_dealloc(struct rdma_counter *counter) +{ + struct mlx5_ib_dev *dev = to_mdev(counter->device); + u32 in[MLX5_ST_SZ_DW(dealloc_q_counter_in)] = {}; + + if (!counter->id) + return 0; + + MLX5_SET(dealloc_q_counter_in, in, opcode, + MLX5_CMD_OP_DEALLOC_Q_COUNTER); + MLX5_SET(dealloc_q_counter_in, in, counter_set_id, counter->id); + return mlx5_cmd_exec_in(dev->mdev, dealloc_q_counter, in); +} + +static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter, + struct ib_qp *qp) +{ + struct mlx5_ib_dev *dev = to_mdev(qp->device); + int err; + + if (!counter->id) { + u32 out[MLX5_ST_SZ_DW(alloc_q_counter_out)] = {}; + u32 in[MLX5_ST_SZ_DW(alloc_q_counter_in)] = {}; + + MLX5_SET(alloc_q_counter_in, in, opcode, + MLX5_CMD_OP_ALLOC_Q_COUNTER); + MLX5_SET(alloc_q_counter_in, in, uid, MLX5_SHARED_RESOURCE_UID); + err = mlx5_cmd_exec_inout(dev->mdev, alloc_q_counter, in, out); + if (err) + return err; + counter->id = + MLX5_GET(alloc_q_counter_out, out, counter_set_id); + } + + err = mlx5_ib_qp_set_counter(qp, counter); + if (err) + goto fail_set_counter; + + return 0; + +fail_set_counter: + mlx5_ib_counter_dealloc(counter); + counter->id = 0; + + return err; +} + +static int mlx5_ib_counter_unbind_qp(struct ib_qp *qp) +{ + return mlx5_ib_qp_set_counter(qp, NULL); +} + + +static void mlx5_ib_fill_counters(struct mlx5_ib_dev *dev, + const char **names, + size_t *offsets) +{ + int i; + int j = 0; + + for (i = 0; i < ARRAY_SIZE(basic_q_cnts); i++, j++) { + names[j] = basic_q_cnts[i].name; + offsets[j] = basic_q_cnts[i].offset; + } + + if (MLX5_CAP_GEN(dev->mdev, out_of_seq_cnt)) { + for (i = 0; i < ARRAY_SIZE(out_of_seq_q_cnts); i++, j++) { + names[j] = out_of_seq_q_cnts[i].name; + offsets[j] = out_of_seq_q_cnts[i].offset; + } + } + + if (MLX5_CAP_GEN(dev->mdev, retransmission_q_counters)) { + for (i = 0; i < ARRAY_SIZE(retrans_q_cnts); i++, j++) { + names[j] = retrans_q_cnts[i].name; + offsets[j] = retrans_q_cnts[i].offset; + } + } + + if (MLX5_CAP_GEN(dev->mdev, enhanced_error_q_counters)) { + for (i = 0; i < ARRAY_SIZE(extended_err_cnts); i++, j++) { + names[j] = extended_err_cnts[i].name; + offsets[j] = extended_err_cnts[i].offset; + } + } + + if (MLX5_CAP_GEN(dev->mdev, roce_accl)) { + for (i = 0; i < ARRAY_SIZE(roce_accl_cnts); i++, j++) { + names[j] = roce_accl_cnts[i].name; + offsets[j] = roce_accl_cnts[i].offset; + } + } + + if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { + for (i = 0; i < ARRAY_SIZE(cong_cnts); i++, j++) { + names[j] = cong_cnts[i].name; + offsets[j] = cong_cnts[i].offset; + } + } + + if (MLX5_CAP_PCAM_FEATURE(dev->mdev, rx_icrc_encapsulated_counter)) { + for (i = 0; i < ARRAY_SIZE(ext_ppcnt_cnts); i++, j++) { + names[j] = ext_ppcnt_cnts[i].name; + offsets[j] = ext_ppcnt_cnts[i].offset; + } + } +} + + +static int __mlx5_ib_alloc_counters(struct mlx5_ib_dev *dev, + struct mlx5_ib_counters *cnts) +{ + u32 num_counters; + + num_counters = ARRAY_SIZE(basic_q_cnts); + + if (MLX5_CAP_GEN(dev->mdev, out_of_seq_cnt)) + num_counters += ARRAY_SIZE(out_of_seq_q_cnts); + + if (MLX5_CAP_GEN(dev->mdev, retransmission_q_counters)) + num_counters += ARRAY_SIZE(retrans_q_cnts); + + if (MLX5_CAP_GEN(dev->mdev, enhanced_error_q_counters)) + num_counters += ARRAY_SIZE(extended_err_cnts); + + if (MLX5_CAP_GEN(dev->mdev, roce_accl)) + num_counters += ARRAY_SIZE(roce_accl_cnts); + + cnts->num_q_counters = num_counters; + + if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { + cnts->num_cong_counters = ARRAY_SIZE(cong_cnts); + num_counters += ARRAY_SIZE(cong_cnts); + } + if (MLX5_CAP_PCAM_FEATURE(dev->mdev, rx_icrc_encapsulated_counter)) { + cnts->num_ext_ppcnt_counters = ARRAY_SIZE(ext_ppcnt_cnts); + num_counters += ARRAY_SIZE(ext_ppcnt_cnts); + } + cnts->names = kcalloc(num_counters, sizeof(cnts->names), GFP_KERNEL); + if (!cnts->names) + return -ENOMEM; + + cnts->offsets = kcalloc(num_counters, + sizeof(cnts->offsets), GFP_KERNEL); + if (!cnts->offsets) + goto err_names; + + return 0; + +err_names: + kfree(cnts->names); + cnts->names = NULL; + return -ENOMEM; +} + +static void mlx5_ib_dealloc_counters(struct mlx5_ib_dev *dev) +{ + u32 in[MLX5_ST_SZ_DW(dealloc_q_counter_in)] = {}; + int num_cnt_ports; + int i; + + num_cnt_ports = is_mdev_switchdev_mode(dev->mdev) ? 1 : dev->num_ports; + + MLX5_SET(dealloc_q_counter_in, in, opcode, + MLX5_CMD_OP_DEALLOC_Q_COUNTER); + + for (i = 0; i < num_cnt_ports; i++) { + if (dev->port[i].cnts.set_id) { + MLX5_SET(dealloc_q_counter_in, in, counter_set_id, + dev->port[i].cnts.set_id); + mlx5_cmd_exec_in(dev->mdev, dealloc_q_counter, in); + } + kfree(dev->port[i].cnts.names); + kfree(dev->port[i].cnts.offsets); + } +} + +static int mlx5_ib_alloc_counters(struct mlx5_ib_dev *dev) +{ + u32 out[MLX5_ST_SZ_DW(alloc_q_counter_out)] = {}; + u32 in[MLX5_ST_SZ_DW(alloc_q_counter_in)] = {}; + int num_cnt_ports; + int err = 0; + int i; + bool is_shared; + + MLX5_SET(alloc_q_counter_in, in, opcode, MLX5_CMD_OP_ALLOC_Q_COUNTER); + is_shared = MLX5_CAP_GEN(dev->mdev, log_max_uctx) != 0; + num_cnt_ports = is_mdev_switchdev_mode(dev->mdev) ? 1 : dev->num_ports; + + for (i = 0; i < num_cnt_ports; i++) { + err = __mlx5_ib_alloc_counters(dev, &dev->port[i].cnts); + if (err) + goto err_alloc; + + mlx5_ib_fill_counters(dev, dev->port[i].cnts.names, + dev->port[i].cnts.offsets); + + MLX5_SET(alloc_q_counter_in, in, uid, + is_shared ? MLX5_SHARED_RESOURCE_UID : 0); + + err = mlx5_cmd_exec_inout(dev->mdev, alloc_q_counter, in, out); + if (err) { + mlx5_ib_warn(dev, + "couldn't allocate queue counter for port %d, err %d\n", + i + 1, err); + goto err_alloc; + } + + dev->port[i].cnts.set_id = + MLX5_GET(alloc_q_counter_out, out, counter_set_id); + } + return 0; + +err_alloc: + mlx5_ib_dealloc_counters(dev); + return err; +} + +static int read_flow_counters(struct ib_device *ibdev, + struct mlx5_read_counters_attr *read_attr) +{ + struct mlx5_fc *fc = read_attr->hw_cntrs_hndl; + struct mlx5_ib_dev *dev = to_mdev(ibdev); + + return mlx5_fc_query(dev->mdev, fc, + &read_attr->out[IB_COUNTER_PACKETS], + &read_attr->out[IB_COUNTER_BYTES]); +} + +/* flow counters currently expose two counters packets and bytes */ +#define FLOW_COUNTERS_NUM 2 +static int counters_set_description( + struct ib_counters *counters, enum mlx5_ib_counters_type counters_type, + struct mlx5_ib_flow_counters_desc *desc_data, u32 ncounters) +{ + struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); + u32 cntrs_max_index = 0; + int i; + + if (counters_type != MLX5_IB_COUNTERS_FLOW) + return -EINVAL; + + /* init the fields for the object */ + mcounters->type = counters_type; + mcounters->read_counters = read_flow_counters; + mcounters->counters_num = FLOW_COUNTERS_NUM; + mcounters->ncounters = ncounters; + /* each counter entry have both description and index pair */ + for (i = 0; i < ncounters; i++) { + if (desc_data[i].description > IB_COUNTER_BYTES) + return -EINVAL; + + if (cntrs_max_index <= desc_data[i].index) + cntrs_max_index = desc_data[i].index + 1; + } + + mutex_lock(&mcounters->mcntrs_mutex); + mcounters->counters_data = desc_data; + mcounters->cntrs_max_index = cntrs_max_index; + mutex_unlock(&mcounters->mcntrs_mutex); + + return 0; +} + +#define MAX_COUNTERS_NUM (USHRT_MAX / (sizeof(u32) * 2)) +int mlx5_ib_flow_counters_set_data(struct ib_counters *ibcounters, + struct mlx5_ib_create_flow *ucmd) +{ + struct mlx5_ib_mcounters *mcounters = to_mcounters(ibcounters); + struct mlx5_ib_flow_counters_data *cntrs_data = NULL; + struct mlx5_ib_flow_counters_desc *desc_data = NULL; + bool hw_hndl = false; + int ret = 0; + + if (ucmd && ucmd->ncounters_data != 0) { + cntrs_data = ucmd->data; + if (cntrs_data->ncounters > MAX_COUNTERS_NUM) + return -EINVAL; + + desc_data = kcalloc(cntrs_data->ncounters, + sizeof(*desc_data), + GFP_KERNEL); + if (!desc_data) + return -ENOMEM; + + if (copy_from_user(desc_data, + u64_to_user_ptr(cntrs_data->counters_data), + sizeof(*desc_data) * cntrs_data->ncounters)) { + ret = -EFAULT; + goto free; + } + } + + if (!mcounters->hw_cntrs_hndl) { + mcounters->hw_cntrs_hndl = mlx5_fc_create( + to_mdev(ibcounters->device)->mdev, false); + if (IS_ERR(mcounters->hw_cntrs_hndl)) { + ret = PTR_ERR(mcounters->hw_cntrs_hndl); + goto free; + } + hw_hndl = true; + } + + if (desc_data) { + /* counters already bound to at least one flow */ + if (mcounters->cntrs_max_index) { + ret = -EINVAL; + goto free_hndl; + } + + ret = counters_set_description(ibcounters, + MLX5_IB_COUNTERS_FLOW, + desc_data, + cntrs_data->ncounters); + if (ret) + goto free_hndl; + + } else if (!mcounters->cntrs_max_index) { + /* counters not bound yet, must have udata passed */ + ret = -EINVAL; + goto free_hndl; + } + + return 0; + +free_hndl: + if (hw_hndl) { + mlx5_fc_destroy(to_mdev(ibcounters->device)->mdev, + mcounters->hw_cntrs_hndl); + mcounters->hw_cntrs_hndl = NULL; + } +free: + kfree(desc_data); + return ret; +} + +void mlx5_ib_counters_clear_description(struct ib_counters *counters) +{ + struct mlx5_ib_mcounters *mcounters; + + if (!counters || atomic_read(&counters->usecnt) != 1) + return; + + mcounters = to_mcounters(counters); + + mutex_lock(&mcounters->mcntrs_mutex); + kfree(mcounters->counters_data); + mcounters->counters_data = NULL; + mcounters->cntrs_max_index = 0; + mutex_unlock(&mcounters->mcntrs_mutex); +} + +static const struct ib_device_ops hw_stats_ops = { + .alloc_hw_stats = mlx5_ib_alloc_hw_stats, + .get_hw_stats = mlx5_ib_get_hw_stats, + .counter_bind_qp = mlx5_ib_counter_bind_qp, + .counter_unbind_qp = mlx5_ib_counter_unbind_qp, + .counter_dealloc = mlx5_ib_counter_dealloc, + .counter_alloc_stats = mlx5_ib_counter_alloc_stats, + .counter_update_stats = mlx5_ib_counter_update_stats, +}; + +static const struct ib_device_ops counters_ops = { + .create_counters = mlx5_ib_create_counters, + .destroy_counters = mlx5_ib_destroy_counters, + .read_counters = mlx5_ib_read_counters, + + INIT_RDMA_OBJ_SIZE(ib_counters, mlx5_ib_mcounters, ibcntrs), +}; + +int mlx5_ib_counters_init(struct mlx5_ib_dev *dev) +{ + ib_set_device_ops(&dev->ib_dev, &counters_ops); + + if (!MLX5_CAP_GEN(dev->mdev, max_qp_cnt)) + return 0; + + ib_set_device_ops(&dev->ib_dev, &hw_stats_ops); + return mlx5_ib_alloc_counters(dev); +} + +void mlx5_ib_counters_cleanup(struct mlx5_ib_dev *dev) +{ + if (!MLX5_CAP_GEN(dev->mdev, max_qp_cnt)) + return; + + mlx5_ib_dealloc_counters(dev); +} diff --git a/drivers/infiniband/hw/mlx5/counters.h b/drivers/infiniband/hw/mlx5/counters.h new file mode 100644 index 0000000000000000000000000000000000000000..1aa30c2f3f4ddd4f1523b9bd6ea8da95ed8054a5 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/counters.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* + * Copyright (c) 2013-2020, Mellanox Technologies inc. All rights reserved. + */ + +#ifndef _MLX5_IB_COUNTERS_H +#define _MLX5_IB_COUNTERS_H + +#include "mlx5_ib.h" + +int mlx5_ib_counters_init(struct mlx5_ib_dev *dev); +void mlx5_ib_counters_cleanup(struct mlx5_ib_dev *dev); +void mlx5_ib_counters_clear_description(struct ib_counters *counters); +int mlx5_ib_flow_counters_set_data(struct ib_counters *ibcounters, + struct mlx5_ib_create_flow *ucmd); +u16 mlx5_ib_get_counters_id(struct mlx5_ib_dev *dev, u8 port_num); +#endif /* _MLX5_IB_COUNTERS_H */ diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c index 655ea9c984e10d82b4596e5ab093f0c5b80ad605..9e3d8b82649809a01455ec9bd74a99435162b41b 100644 --- a/drivers/infiniband/hw/mlx5/devx.c +++ b/drivers/infiniband/hw/mlx5/devx.c @@ -14,6 +14,7 @@ #include #include #include "mlx5_ib.h" +#include "devx.h" #include "qp.h" #include @@ -89,22 +90,6 @@ struct devx_async_event_file { u8 is_destroyed:1; }; -#define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in) -struct devx_obj { - struct mlx5_ib_dev *ib_dev; - u64 obj_id; - u32 dinlen; /* destroy inbox length */ - u32 dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW]; - u32 flags; - union { - struct mlx5_ib_devx_mr devx_mr; - struct mlx5_core_dct core_dct; - struct mlx5_core_cq core_cq; - u32 flow_counter_bulk_size; - }; - struct list_head event_sub; /* holds devx_event_subscription entries */ -}; - struct devx_umem { struct mlx5_core_dev *mdev; struct ib_umem *umem; @@ -171,48 +156,6 @@ void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid) mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out)); } -bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type) -{ - struct devx_obj *devx_obj = obj; - u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode); - - switch (opcode) { - case MLX5_CMD_OP_DESTROY_TIR: - *dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR; - *dest_id = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, - obj_id); - return true; - - case MLX5_CMD_OP_DESTROY_FLOW_TABLE: - *dest_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; - *dest_id = MLX5_GET(destroy_flow_table_in, devx_obj->dinbox, - table_id); - return true; - default: - return false; - } -} - -bool mlx5_ib_devx_is_flow_counter(void *obj, u32 offset, u32 *counter_id) -{ - struct devx_obj *devx_obj = obj; - u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode); - - if (opcode == MLX5_CMD_OP_DEALLOC_FLOW_COUNTER) { - - if (offset && offset >= devx_obj->flow_counter_bulk_size) - return false; - - *counter_id = MLX5_GET(dealloc_flow_counter_in, - devx_obj->dinbox, - flow_counter_id); - *counter_id += offset; - return true; - } - - return false; -} - static bool is_legacy_unaffiliated_event_num(u16 event_num) { switch (event_num) { @@ -2419,17 +2362,24 @@ static int devx_event_notifier(struct notifier_block *nb, return NOTIFY_OK; } -void mlx5_ib_devx_init_event_table(struct mlx5_ib_dev *dev) +int mlx5_ib_devx_init(struct mlx5_ib_dev *dev) { struct mlx5_devx_event_table *table = &dev->devx_event_table; + int uid; - xa_init(&table->event_xa); - mutex_init(&table->event_xa_lock); - MLX5_NB_INIT(&table->devx_nb, devx_event_notifier, NOTIFY_ANY); - mlx5_eq_notifier_register(dev->mdev, &table->devx_nb); + uid = mlx5_ib_devx_create(dev, false); + if (uid > 0) { + dev->devx_whitelist_uid = uid; + xa_init(&table->event_xa); + mutex_init(&table->event_xa_lock); + MLX5_NB_INIT(&table->devx_nb, devx_event_notifier, NOTIFY_ANY); + mlx5_eq_notifier_register(dev->mdev, &table->devx_nb); + } + + return 0; } -void mlx5_ib_devx_cleanup_event_table(struct mlx5_ib_dev *dev) +void mlx5_ib_devx_cleanup(struct mlx5_ib_dev *dev) { struct mlx5_devx_event_table *table = &dev->devx_event_table; struct devx_event_subscription *sub, *tmp; @@ -2437,17 +2387,21 @@ void mlx5_ib_devx_cleanup_event_table(struct mlx5_ib_dev *dev) void *entry; unsigned long id; - mlx5_eq_notifier_unregister(dev->mdev, &table->devx_nb); - mutex_lock(&dev->devx_event_table.event_xa_lock); - xa_for_each(&table->event_xa, id, entry) { - event = entry; - list_for_each_entry_safe(sub, tmp, &event->unaffiliated_list, - xa_list) - devx_cleanup_subscription(dev, sub); - kfree(entry); + if (dev->devx_whitelist_uid) { + mlx5_eq_notifier_unregister(dev->mdev, &table->devx_nb); + mutex_lock(&dev->devx_event_table.event_xa_lock); + xa_for_each(&table->event_xa, id, entry) { + event = entry; + list_for_each_entry_safe( + sub, tmp, &event->unaffiliated_list, xa_list) + devx_cleanup_subscription(dev, sub); + kfree(entry); + } + mutex_unlock(&dev->devx_event_table.event_xa_lock); + xa_destroy(&table->event_xa); + + mlx5_ib_devx_destroy(dev, dev->devx_whitelist_uid); } - mutex_unlock(&dev->devx_event_table.event_xa_lock); - xa_destroy(&table->event_xa); } static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf, diff --git a/drivers/infiniband/hw/mlx5/devx.h b/drivers/infiniband/hw/mlx5/devx.h new file mode 100644 index 0000000000000000000000000000000000000000..1f69866aed16ed664da158c2eaa9b5313177a477 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/devx.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* + * Copyright (c) 2019-2020, Mellanox Technologies inc. All rights reserved. + */ + +#ifndef _MLX5_IB_DEVX_H +#define _MLX5_IB_DEVX_H + +#include "mlx5_ib.h" + +#define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in) +struct devx_obj { + struct mlx5_ib_dev *ib_dev; + u64 obj_id; + u32 dinlen; /* destroy inbox length */ + u32 dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW]; + u32 flags; + union { + struct mlx5_ib_devx_mr devx_mr; + struct mlx5_core_dct core_dct; + struct mlx5_core_cq core_cq; + u32 flow_counter_bulk_size; + }; + struct list_head event_sub; /* holds devx_event_subscription entries */ +}; +#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS) +int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user); +void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid); +int mlx5_ib_devx_init(struct mlx5_ib_dev *dev); +void mlx5_ib_devx_cleanup(struct mlx5_ib_dev *dev); +#else +static inline int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user) +{ + return -EOPNOTSUPP; +} +static inline void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid) {} +static inline int mlx5_ib_devx_init(struct mlx5_ib_dev *dev) +{ + return 0; +} +static inline void mlx5_ib_devx_cleanup(struct mlx5_ib_dev *dev) +{ +} +#endif +#endif /* _MLX5_IB_DEVX_H */ diff --git a/drivers/infiniband/hw/mlx5/flow.c b/drivers/infiniband/hw/mlx5/flow.c deleted file mode 100644 index 216a1108ad34d847cb4a7a338e85aef4e919db3e..0000000000000000000000000000000000000000 --- a/drivers/infiniband/hw/mlx5/flow.c +++ /dev/null @@ -1,765 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB -/* - * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mlx5_ib.h" - -#define UVERBS_MODULE_NAME mlx5_ib -#include - -static int -mlx5_ib_ft_type_to_namespace(enum mlx5_ib_uapi_flow_table_type table_type, - enum mlx5_flow_namespace_type *namespace) -{ - switch (table_type) { - case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX: - *namespace = MLX5_FLOW_NAMESPACE_BYPASS; - break; - case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX: - *namespace = MLX5_FLOW_NAMESPACE_EGRESS; - break; - case MLX5_IB_UAPI_FLOW_TABLE_TYPE_FDB: - *namespace = MLX5_FLOW_NAMESPACE_FDB; - break; - case MLX5_IB_UAPI_FLOW_TABLE_TYPE_RDMA_RX: - *namespace = MLX5_FLOW_NAMESPACE_RDMA_RX; - break; - case MLX5_IB_UAPI_FLOW_TABLE_TYPE_RDMA_TX: - *namespace = MLX5_FLOW_NAMESPACE_RDMA_TX; - break; - default: - return -EINVAL; - } - - return 0; -} - -static const struct uverbs_attr_spec mlx5_ib_flow_type[] = { - [MLX5_IB_FLOW_TYPE_NORMAL] = { - .type = UVERBS_ATTR_TYPE_PTR_IN, - .u.ptr = { - .len = sizeof(u16), /* data is priority */ - .min_len = sizeof(u16), - } - }, - [MLX5_IB_FLOW_TYPE_SNIFFER] = { - .type = UVERBS_ATTR_TYPE_PTR_IN, - UVERBS_ATTR_NO_DATA(), - }, - [MLX5_IB_FLOW_TYPE_ALL_DEFAULT] = { - .type = UVERBS_ATTR_TYPE_PTR_IN, - UVERBS_ATTR_NO_DATA(), - }, - [MLX5_IB_FLOW_TYPE_MC_DEFAULT] = { - .type = UVERBS_ATTR_TYPE_PTR_IN, - UVERBS_ATTR_NO_DATA(), - }, -}; - -static int get_dests(struct uverbs_attr_bundle *attrs, - struct mlx5_ib_flow_matcher *fs_matcher, int *dest_id, - int *dest_type, struct ib_qp **qp, u32 *flags) -{ - bool dest_devx, dest_qp; - void *devx_obj; - int err; - - dest_devx = uverbs_attr_is_valid(attrs, - MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX); - dest_qp = uverbs_attr_is_valid(attrs, - MLX5_IB_ATTR_CREATE_FLOW_DEST_QP); - - *flags = 0; - err = uverbs_get_flags32(flags, attrs, MLX5_IB_ATTR_CREATE_FLOW_FLAGS, - MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS | - MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP); - if (err) - return err; - - /* Both flags are not allowed */ - if (*flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS && - *flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP) - return -EINVAL; - - if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS) { - if (dest_devx && (dest_qp || *flags)) - return -EINVAL; - else if (dest_qp && *flags) - return -EINVAL; - } - - /* Allow only DEVX object, drop as dest for FDB */ - if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB && !(dest_devx || - (*flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP))) - return -EINVAL; - - /* Allow only DEVX object or QP as dest when inserting to RDMA_RX */ - if ((fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) && - ((!dest_devx && !dest_qp) || (dest_devx && dest_qp))) - return -EINVAL; - - *qp = NULL; - if (dest_devx) { - devx_obj = - uverbs_attr_get_obj(attrs, - MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX); - - /* Verify that the given DEVX object is a flow - * steering destination. - */ - if (!mlx5_ib_devx_is_flow_dest(devx_obj, dest_id, dest_type)) - return -EINVAL; - /* Allow only flow table as dest when inserting to FDB or RDMA_RX */ - if ((fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB || - fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) && - *dest_type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) - return -EINVAL; - } else if (dest_qp) { - struct mlx5_ib_qp *mqp; - - *qp = uverbs_attr_get_obj(attrs, - MLX5_IB_ATTR_CREATE_FLOW_DEST_QP); - if (IS_ERR(*qp)) - return PTR_ERR(*qp); - - if ((*qp)->qp_type != IB_QPT_RAW_PACKET) - return -EINVAL; - - mqp = to_mqp(*qp); - if (mqp->is_rss) - *dest_id = mqp->rss_qp.tirn; - else - *dest_id = mqp->raw_packet_qp.rq.tirn; - *dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR; - } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS) { - *dest_type = MLX5_FLOW_DESTINATION_TYPE_PORT; - } - - if (*dest_type == MLX5_FLOW_DESTINATION_TYPE_TIR && - fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS) - return -EINVAL; - - return 0; -} - -#define MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS 2 -static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)( - struct uverbs_attr_bundle *attrs) -{ - struct mlx5_flow_context flow_context = {.flow_tag = - MLX5_FS_DEFAULT_FLOW_TAG}; - u32 *offset_attr, offset = 0, counter_id = 0; - int dest_id, dest_type, inlen, len, ret, i; - struct mlx5_ib_flow_handler *flow_handler; - struct mlx5_ib_flow_matcher *fs_matcher; - struct ib_uobject **arr_flow_actions; - struct ib_uflow_resources *uflow_res; - struct mlx5_flow_act flow_act = {}; - struct ib_qp *qp = NULL; - void *devx_obj, *cmd_in; - struct ib_uobject *uobj; - struct mlx5_ib_dev *dev; - u32 flags; - - if (!capable(CAP_NET_RAW)) - return -EPERM; - - fs_matcher = uverbs_attr_get_obj(attrs, - MLX5_IB_ATTR_CREATE_FLOW_MATCHER); - uobj = uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_CREATE_FLOW_HANDLE); - dev = mlx5_udata_to_mdev(&attrs->driver_udata); - - if (get_dests(attrs, fs_matcher, &dest_id, &dest_type, &qp, &flags)) - return -EINVAL; - - if (flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS) - flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS; - - if (flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP) - flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_DROP; - - len = uverbs_attr_get_uobjs_arr(attrs, - MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, &arr_flow_actions); - if (len) { - devx_obj = arr_flow_actions[0]->object; - - if (uverbs_attr_is_valid(attrs, - MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET)) { - - int num_offsets = uverbs_attr_ptr_get_array_size( - attrs, - MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET, - sizeof(u32)); - - if (num_offsets != 1) - return -EINVAL; - - offset_attr = uverbs_attr_get_alloced_ptr( - attrs, - MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET); - offset = *offset_attr; - } - - if (!mlx5_ib_devx_is_flow_counter(devx_obj, offset, - &counter_id)) - return -EINVAL; - - flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; - } - - cmd_in = uverbs_attr_get_alloced_ptr( - attrs, MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE); - inlen = uverbs_attr_get_len(attrs, - MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE); - - uflow_res = flow_resources_alloc(MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS); - if (!uflow_res) - return -ENOMEM; - - len = uverbs_attr_get_uobjs_arr(attrs, - MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS, &arr_flow_actions); - for (i = 0; i < len; i++) { - struct mlx5_ib_flow_action *maction = - to_mflow_act(arr_flow_actions[i]->object); - - ret = parse_flow_flow_action(maction, false, &flow_act); - if (ret) - goto err_out; - flow_resources_add(uflow_res, IB_FLOW_SPEC_ACTION_HANDLE, - arr_flow_actions[i]->object); - } - - ret = uverbs_copy_from(&flow_context.flow_tag, attrs, - MLX5_IB_ATTR_CREATE_FLOW_TAG); - if (!ret) { - if (flow_context.flow_tag >= BIT(24)) { - ret = -EINVAL; - goto err_out; - } - flow_context.flags |= FLOW_CONTEXT_HAS_TAG; - } - - flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher, - &flow_context, - &flow_act, - counter_id, - cmd_in, inlen, - dest_id, dest_type); - if (IS_ERR(flow_handler)) { - ret = PTR_ERR(flow_handler); - goto err_out; - } - - ib_set_flow(uobj, &flow_handler->ibflow, qp, &dev->ib_dev, uflow_res); - - return 0; -err_out: - ib_uverbs_flow_resources_free(uflow_res); - return ret; -} - -static int flow_matcher_cleanup(struct ib_uobject *uobject, - enum rdma_remove_reason why, - struct uverbs_attr_bundle *attrs) -{ - struct mlx5_ib_flow_matcher *obj = uobject->object; - int ret; - - ret = ib_destroy_usecnt(&obj->usecnt, why, uobject); - if (ret) - return ret; - - kfree(obj); - return 0; -} - -static int mlx5_ib_matcher_ns(struct uverbs_attr_bundle *attrs, - struct mlx5_ib_flow_matcher *obj) -{ - enum mlx5_ib_uapi_flow_table_type ft_type = - MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX; - u32 flags; - int err; - - /* New users should use MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE and older - * users should switch to it. We leave this to not break userspace - */ - if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE) && - uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS)) - return -EINVAL; - - if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE)) { - err = uverbs_get_const(&ft_type, attrs, - MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE); - if (err) - return err; - - err = mlx5_ib_ft_type_to_namespace(ft_type, &obj->ns_type); - if (err) - return err; - - return 0; - } - - if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS)) { - err = uverbs_get_flags32(&flags, attrs, - MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS, - IB_FLOW_ATTR_FLAGS_EGRESS); - if (err) - return err; - - if (flags) { - mlx5_ib_ft_type_to_namespace( - MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX, - &obj->ns_type); - return 0; - } - } - - obj->ns_type = MLX5_FLOW_NAMESPACE_BYPASS; - - return 0; -} - -static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)( - struct uverbs_attr_bundle *attrs) -{ - struct ib_uobject *uobj = uverbs_attr_get_uobject( - attrs, MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE); - struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata); - struct mlx5_ib_flow_matcher *obj; - int err; - - obj = kzalloc(sizeof(struct mlx5_ib_flow_matcher), GFP_KERNEL); - if (!obj) - return -ENOMEM; - - obj->mask_len = uverbs_attr_get_len( - attrs, MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK); - err = uverbs_copy_from(&obj->matcher_mask, - attrs, - MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK); - if (err) - goto end; - - obj->flow_type = uverbs_attr_get_enum_id( - attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE); - - if (obj->flow_type == MLX5_IB_FLOW_TYPE_NORMAL) { - err = uverbs_copy_from(&obj->priority, - attrs, - MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE); - if (err) - goto end; - } - - err = uverbs_copy_from(&obj->match_criteria_enable, - attrs, - MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA); - if (err) - goto end; - - err = mlx5_ib_matcher_ns(attrs, obj); - if (err) - goto end; - - uobj->object = obj; - obj->mdev = dev->mdev; - atomic_set(&obj->usecnt, 0); - return 0; - -end: - kfree(obj); - return err; -} - -void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction) -{ - switch (maction->flow_action_raw.sub_type) { - case MLX5_IB_FLOW_ACTION_MODIFY_HEADER: - mlx5_modify_header_dealloc(maction->flow_action_raw.dev->mdev, - maction->flow_action_raw.modify_hdr); - break; - case MLX5_IB_FLOW_ACTION_PACKET_REFORMAT: - mlx5_packet_reformat_dealloc(maction->flow_action_raw.dev->mdev, - maction->flow_action_raw.pkt_reformat); - break; - case MLX5_IB_FLOW_ACTION_DECAP: - break; - default: - break; - } -} - -static struct ib_flow_action * -mlx5_ib_create_modify_header(struct mlx5_ib_dev *dev, - enum mlx5_ib_uapi_flow_table_type ft_type, - u8 num_actions, void *in) -{ - enum mlx5_flow_namespace_type namespace; - struct mlx5_ib_flow_action *maction; - int ret; - - ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace); - if (ret) - return ERR_PTR(-EINVAL); - - maction = kzalloc(sizeof(*maction), GFP_KERNEL); - if (!maction) - return ERR_PTR(-ENOMEM); - - maction->flow_action_raw.modify_hdr = - mlx5_modify_header_alloc(dev->mdev, namespace, num_actions, in); - - if (IS_ERR(maction->flow_action_raw.modify_hdr)) { - ret = PTR_ERR(maction->flow_action_raw.modify_hdr); - kfree(maction); - return ERR_PTR(ret); - } - maction->flow_action_raw.sub_type = - MLX5_IB_FLOW_ACTION_MODIFY_HEADER; - maction->flow_action_raw.dev = dev; - - return &maction->ib_action; -} - -static bool mlx5_ib_modify_header_supported(struct mlx5_ib_dev *dev) -{ - return MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, - max_modify_header_actions) || - MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, - max_modify_header_actions) || - MLX5_CAP_FLOWTABLE_RDMA_TX(dev->mdev, - max_modify_header_actions); -} - -static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)( - struct uverbs_attr_bundle *attrs) -{ - struct ib_uobject *uobj = uverbs_attr_get_uobject( - attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE); - struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata); - enum mlx5_ib_uapi_flow_table_type ft_type; - struct ib_flow_action *action; - int num_actions; - void *in; - int ret; - - if (!mlx5_ib_modify_header_supported(mdev)) - return -EOPNOTSUPP; - - in = uverbs_attr_get_alloced_ptr(attrs, - MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM); - - num_actions = uverbs_attr_ptr_get_array_size( - attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM, - MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)); - if (num_actions < 0) - return num_actions; - - ret = uverbs_get_const(&ft_type, attrs, - MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE); - if (ret) - return ret; - action = mlx5_ib_create_modify_header(mdev, ft_type, num_actions, in); - if (IS_ERR(action)) - return PTR_ERR(action); - - uverbs_flow_action_fill_action(action, uobj, &mdev->ib_dev, - IB_FLOW_ACTION_UNSPECIFIED); - - return 0; -} - -static bool mlx5_ib_flow_action_packet_reformat_valid(struct mlx5_ib_dev *ibdev, - u8 packet_reformat_type, - u8 ft_type) -{ - switch (packet_reformat_type) { - case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL: - if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX) - return MLX5_CAP_FLOWTABLE(ibdev->mdev, - encap_general_header); - break; - case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL: - if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX) - return MLX5_CAP_FLOWTABLE_NIC_TX(ibdev->mdev, - reformat_l2_to_l3_tunnel); - break; - case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2: - if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX) - return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev, - reformat_l3_tunnel_to_l2); - break; - case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2: - if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX) - return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev, decap); - break; - default: - break; - } - - return false; -} - -static int mlx5_ib_dv_to_prm_packet_reforamt_type(u8 dv_prt, u8 *prm_prt) -{ - switch (dv_prt) { - case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL: - *prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL; - break; - case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2: - *prm_prt = MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2; - break; - case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL: - *prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int mlx5_ib_flow_action_create_packet_reformat_ctx( - struct mlx5_ib_dev *dev, - struct mlx5_ib_flow_action *maction, - u8 ft_type, u8 dv_prt, - void *in, size_t len) -{ - enum mlx5_flow_namespace_type namespace; - u8 prm_prt; - int ret; - - ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace); - if (ret) - return ret; - - ret = mlx5_ib_dv_to_prm_packet_reforamt_type(dv_prt, &prm_prt); - if (ret) - return ret; - - maction->flow_action_raw.pkt_reformat = - mlx5_packet_reformat_alloc(dev->mdev, prm_prt, len, - in, namespace); - if (IS_ERR(maction->flow_action_raw.pkt_reformat)) { - ret = PTR_ERR(maction->flow_action_raw.pkt_reformat); - return ret; - } - - maction->flow_action_raw.sub_type = - MLX5_IB_FLOW_ACTION_PACKET_REFORMAT; - maction->flow_action_raw.dev = dev; - - return 0; -} - -static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT)( - struct uverbs_attr_bundle *attrs) -{ - struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, - MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE); - struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata); - enum mlx5_ib_uapi_flow_action_packet_reformat_type dv_prt; - enum mlx5_ib_uapi_flow_table_type ft_type; - struct mlx5_ib_flow_action *maction; - int ret; - - ret = uverbs_get_const(&ft_type, attrs, - MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE); - if (ret) - return ret; - - ret = uverbs_get_const(&dv_prt, attrs, - MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE); - if (ret) - return ret; - - if (!mlx5_ib_flow_action_packet_reformat_valid(mdev, dv_prt, ft_type)) - return -EOPNOTSUPP; - - maction = kzalloc(sizeof(*maction), GFP_KERNEL); - if (!maction) - return -ENOMEM; - - if (dv_prt == - MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2) { - maction->flow_action_raw.sub_type = - MLX5_IB_FLOW_ACTION_DECAP; - maction->flow_action_raw.dev = mdev; - } else { - void *in; - int len; - - in = uverbs_attr_get_alloced_ptr(attrs, - MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF); - if (IS_ERR(in)) { - ret = PTR_ERR(in); - goto free_maction; - } - - len = uverbs_attr_get_len(attrs, - MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF); - - ret = mlx5_ib_flow_action_create_packet_reformat_ctx(mdev, - maction, ft_type, dv_prt, in, len); - if (ret) - goto free_maction; - } - - uverbs_flow_action_fill_action(&maction->ib_action, uobj, &mdev->ib_dev, - IB_FLOW_ACTION_UNSPECIFIED); - return 0; - -free_maction: - kfree(maction); - return ret; -} - -DECLARE_UVERBS_NAMED_METHOD( - MLX5_IB_METHOD_CREATE_FLOW, - UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE, - UVERBS_OBJECT_FLOW, - UVERBS_ACCESS_NEW, - UA_MANDATORY), - UVERBS_ATTR_PTR_IN( - MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE, - UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)), - UA_MANDATORY, - UA_ALLOC_AND_COPY), - UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_MATCHER, - MLX5_IB_OBJECT_FLOW_MATCHER, - UVERBS_ACCESS_READ, - UA_MANDATORY), - UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_QP, - UVERBS_OBJECT_QP, - UVERBS_ACCESS_READ), - UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX, - MLX5_IB_OBJECT_DEVX_OBJ, - UVERBS_ACCESS_READ), - UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS, - UVERBS_OBJECT_FLOW_ACTION, - UVERBS_ACCESS_READ, 1, - MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS, - UA_OPTIONAL), - UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_TAG, - UVERBS_ATTR_TYPE(u32), - UA_OPTIONAL), - UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, - MLX5_IB_OBJECT_DEVX_OBJ, - UVERBS_ACCESS_READ, 1, 1, - UA_OPTIONAL), - UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET, - UVERBS_ATTR_MIN_SIZE(sizeof(u32)), - UA_OPTIONAL, - UA_ALLOC_AND_COPY), - UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_CREATE_FLOW_FLAGS, - enum mlx5_ib_create_flow_flags, - UA_OPTIONAL)); - -DECLARE_UVERBS_NAMED_METHOD_DESTROY( - MLX5_IB_METHOD_DESTROY_FLOW, - UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE, - UVERBS_OBJECT_FLOW, - UVERBS_ACCESS_DESTROY, - UA_MANDATORY)); - -ADD_UVERBS_METHODS(mlx5_ib_fs, - UVERBS_OBJECT_FLOW, - &UVERBS_METHOD(MLX5_IB_METHOD_CREATE_FLOW), - &UVERBS_METHOD(MLX5_IB_METHOD_DESTROY_FLOW)); - -DECLARE_UVERBS_NAMED_METHOD( - MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER, - UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE, - UVERBS_OBJECT_FLOW_ACTION, - UVERBS_ACCESS_NEW, - UA_MANDATORY), - UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM, - UVERBS_ATTR_MIN_SIZE(MLX5_UN_SZ_BYTES( - set_add_copy_action_in_auto)), - UA_MANDATORY, - UA_ALLOC_AND_COPY), - UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE, - enum mlx5_ib_uapi_flow_table_type, - UA_MANDATORY)); - -DECLARE_UVERBS_NAMED_METHOD( - MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT, - UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE, - UVERBS_OBJECT_FLOW_ACTION, - UVERBS_ACCESS_NEW, - UA_MANDATORY), - UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF, - UVERBS_ATTR_MIN_SIZE(1), - UA_ALLOC_AND_COPY, - UA_OPTIONAL), - UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE, - enum mlx5_ib_uapi_flow_action_packet_reformat_type, - UA_MANDATORY), - UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE, - enum mlx5_ib_uapi_flow_table_type, - UA_MANDATORY)); - -ADD_UVERBS_METHODS( - mlx5_ib_flow_actions, - UVERBS_OBJECT_FLOW_ACTION, - &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER), - &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT)); - -DECLARE_UVERBS_NAMED_METHOD( - MLX5_IB_METHOD_FLOW_MATCHER_CREATE, - UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE, - MLX5_IB_OBJECT_FLOW_MATCHER, - UVERBS_ACCESS_NEW, - UA_MANDATORY), - UVERBS_ATTR_PTR_IN( - MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK, - UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)), - UA_MANDATORY), - UVERBS_ATTR_ENUM_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE, - mlx5_ib_flow_type, - UA_MANDATORY), - UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA, - UVERBS_ATTR_TYPE(u8), - UA_MANDATORY), - UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS, - enum ib_flow_flags, - UA_OPTIONAL), - UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE, - enum mlx5_ib_uapi_flow_table_type, - UA_OPTIONAL)); - -DECLARE_UVERBS_NAMED_METHOD_DESTROY( - MLX5_IB_METHOD_FLOW_MATCHER_DESTROY, - UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_DESTROY_HANDLE, - MLX5_IB_OBJECT_FLOW_MATCHER, - UVERBS_ACCESS_DESTROY, - UA_MANDATORY)); - -DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER, - UVERBS_TYPE_ALLOC_IDR(flow_matcher_cleanup), - &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_CREATE), - &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_DESTROY)); - -const struct uapi_definition mlx5_ib_flow_defs[] = { - UAPI_DEF_CHAIN_OBJ_TREE_NAMED( - MLX5_IB_OBJECT_FLOW_MATCHER), - UAPI_DEF_CHAIN_OBJ_TREE( - UVERBS_OBJECT_FLOW, - &mlx5_ib_fs), - UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION, - &mlx5_ib_flow_actions), - {}, -}; diff --git a/drivers/infiniband/hw/mlx5/fs.c b/drivers/infiniband/hw/mlx5/fs.c new file mode 100644 index 0000000000000000000000000000000000000000..e9cfb9a2ef41b397450fa678fd741899484ef56d --- /dev/null +++ b/drivers/infiniband/hw/mlx5/fs.c @@ -0,0 +1,2516 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* + * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mlx5_ib.h" +#include "counters.h" +#include "devx.h" +#include "fs.h" + +#define UVERBS_MODULE_NAME mlx5_ib +#include + +enum { + MATCH_CRITERIA_ENABLE_OUTER_BIT, + MATCH_CRITERIA_ENABLE_MISC_BIT, + MATCH_CRITERIA_ENABLE_INNER_BIT, + MATCH_CRITERIA_ENABLE_MISC2_BIT +}; + +#define HEADER_IS_ZERO(match_criteria, headers) \ + !(memchr_inv(MLX5_ADDR_OF(fte_match_param, match_criteria, headers), \ + 0, MLX5_FLD_SZ_BYTES(fte_match_param, headers))) \ + +static u8 get_match_criteria_enable(u32 *match_criteria) +{ + u8 match_criteria_enable; + + match_criteria_enable = + (!HEADER_IS_ZERO(match_criteria, outer_headers)) << + MATCH_CRITERIA_ENABLE_OUTER_BIT; + match_criteria_enable |= + (!HEADER_IS_ZERO(match_criteria, misc_parameters)) << + MATCH_CRITERIA_ENABLE_MISC_BIT; + match_criteria_enable |= + (!HEADER_IS_ZERO(match_criteria, inner_headers)) << + MATCH_CRITERIA_ENABLE_INNER_BIT; + match_criteria_enable |= + (!HEADER_IS_ZERO(match_criteria, misc_parameters_2)) << + MATCH_CRITERIA_ENABLE_MISC2_BIT; + + return match_criteria_enable; +} + +static int set_proto(void *outer_c, void *outer_v, u8 mask, u8 val) +{ + u8 entry_mask; + u8 entry_val; + int err = 0; + + if (!mask) + goto out; + + entry_mask = MLX5_GET(fte_match_set_lyr_2_4, outer_c, + ip_protocol); + entry_val = MLX5_GET(fte_match_set_lyr_2_4, outer_v, + ip_protocol); + if (!entry_mask) { + MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_protocol, mask); + MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_protocol, val); + goto out; + } + /* Don't override existing ip protocol */ + if (mask != entry_mask || val != entry_val) + err = -EINVAL; +out: + return err; +} + +static void set_flow_label(void *misc_c, void *misc_v, u32 mask, u32 val, + bool inner) +{ + if (inner) { + MLX5_SET(fte_match_set_misc, + misc_c, inner_ipv6_flow_label, mask); + MLX5_SET(fte_match_set_misc, + misc_v, inner_ipv6_flow_label, val); + } else { + MLX5_SET(fte_match_set_misc, + misc_c, outer_ipv6_flow_label, mask); + MLX5_SET(fte_match_set_misc, + misc_v, outer_ipv6_flow_label, val); + } +} + +static void set_tos(void *outer_c, void *outer_v, u8 mask, u8 val) +{ + MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_ecn, mask); + MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_ecn, val); + MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_dscp, mask >> 2); + MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_dscp, val >> 2); +} + +static int check_mpls_supp_fields(u32 field_support, const __be32 *set_mask) +{ + if (MLX5_GET(fte_match_mpls, set_mask, mpls_label) && + !(field_support & MLX5_FIELD_SUPPORT_MPLS_LABEL)) + return -EOPNOTSUPP; + + if (MLX5_GET(fte_match_mpls, set_mask, mpls_exp) && + !(field_support & MLX5_FIELD_SUPPORT_MPLS_EXP)) + return -EOPNOTSUPP; + + if (MLX5_GET(fte_match_mpls, set_mask, mpls_s_bos) && + !(field_support & MLX5_FIELD_SUPPORT_MPLS_S_BOS)) + return -EOPNOTSUPP; + + if (MLX5_GET(fte_match_mpls, set_mask, mpls_ttl) && + !(field_support & MLX5_FIELD_SUPPORT_MPLS_TTL)) + return -EOPNOTSUPP; + + return 0; +} + +#define LAST_ETH_FIELD vlan_tag +#define LAST_IB_FIELD sl +#define LAST_IPV4_FIELD tos +#define LAST_IPV6_FIELD traffic_class +#define LAST_TCP_UDP_FIELD src_port +#define LAST_TUNNEL_FIELD tunnel_id +#define LAST_FLOW_TAG_FIELD tag_id +#define LAST_DROP_FIELD size +#define LAST_COUNTERS_FIELD counters + +/* Field is the last supported field */ +#define FIELDS_NOT_SUPPORTED(filter, field)\ + memchr_inv((void *)&filter.field +\ + sizeof(filter.field), 0,\ + sizeof(filter) -\ + offsetof(typeof(filter), field) -\ + sizeof(filter.field)) + +int parse_flow_flow_action(struct mlx5_ib_flow_action *maction, + bool is_egress, + struct mlx5_flow_act *action) +{ + + switch (maction->ib_action.type) { + case IB_FLOW_ACTION_ESP: + if (action->action & (MLX5_FLOW_CONTEXT_ACTION_ENCRYPT | + MLX5_FLOW_CONTEXT_ACTION_DECRYPT)) + return -EINVAL; + /* Currently only AES_GCM keymat is supported by the driver */ + action->esp_id = (uintptr_t)maction->esp_aes_gcm.ctx; + action->action |= is_egress ? + MLX5_FLOW_CONTEXT_ACTION_ENCRYPT : + MLX5_FLOW_CONTEXT_ACTION_DECRYPT; + return 0; + case IB_FLOW_ACTION_UNSPECIFIED: + if (maction->flow_action_raw.sub_type == + MLX5_IB_FLOW_ACTION_MODIFY_HEADER) { + if (action->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) + return -EINVAL; + action->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; + action->modify_hdr = + maction->flow_action_raw.modify_hdr; + return 0; + } + if (maction->flow_action_raw.sub_type == + MLX5_IB_FLOW_ACTION_DECAP) { + if (action->action & MLX5_FLOW_CONTEXT_ACTION_DECAP) + return -EINVAL; + action->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP; + return 0; + } + if (maction->flow_action_raw.sub_type == + MLX5_IB_FLOW_ACTION_PACKET_REFORMAT) { + if (action->action & + MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) + return -EINVAL; + action->action |= + MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; + action->pkt_reformat = + maction->flow_action_raw.pkt_reformat; + return 0; + } + fallthrough; + default: + return -EOPNOTSUPP; + } +} + +static int parse_flow_attr(struct mlx5_core_dev *mdev, + struct mlx5_flow_spec *spec, + const union ib_flow_spec *ib_spec, + const struct ib_flow_attr *flow_attr, + struct mlx5_flow_act *action, u32 prev_type) +{ + struct mlx5_flow_context *flow_context = &spec->flow_context; + u32 *match_c = spec->match_criteria; + u32 *match_v = spec->match_value; + void *misc_params_c = MLX5_ADDR_OF(fte_match_param, match_c, + misc_parameters); + void *misc_params_v = MLX5_ADDR_OF(fte_match_param, match_v, + misc_parameters); + void *misc_params2_c = MLX5_ADDR_OF(fte_match_param, match_c, + misc_parameters_2); + void *misc_params2_v = MLX5_ADDR_OF(fte_match_param, match_v, + misc_parameters_2); + void *headers_c; + void *headers_v; + int match_ipv; + int ret; + + if (ib_spec->type & IB_FLOW_SPEC_INNER) { + headers_c = MLX5_ADDR_OF(fte_match_param, match_c, + inner_headers); + headers_v = MLX5_ADDR_OF(fte_match_param, match_v, + inner_headers); + match_ipv = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, + ft_field_support.inner_ip_version); + } else { + headers_c = MLX5_ADDR_OF(fte_match_param, match_c, + outer_headers); + headers_v = MLX5_ADDR_OF(fte_match_param, match_v, + outer_headers); + match_ipv = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, + ft_field_support.outer_ip_version); + } + + switch (ib_spec->type & ~IB_FLOW_SPEC_INNER) { + case IB_FLOW_SPEC_ETH: + if (FIELDS_NOT_SUPPORTED(ib_spec->eth.mask, LAST_ETH_FIELD)) + return -EOPNOTSUPP; + + ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, + dmac_47_16), + ib_spec->eth.mask.dst_mac); + ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, + dmac_47_16), + ib_spec->eth.val.dst_mac); + + ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, + smac_47_16), + ib_spec->eth.mask.src_mac); + ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, + smac_47_16), + ib_spec->eth.val.src_mac); + + if (ib_spec->eth.mask.vlan_tag) { + MLX5_SET(fte_match_set_lyr_2_4, headers_c, + cvlan_tag, 1); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, + cvlan_tag, 1); + + MLX5_SET(fte_match_set_lyr_2_4, headers_c, + first_vid, ntohs(ib_spec->eth.mask.vlan_tag)); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, + first_vid, ntohs(ib_spec->eth.val.vlan_tag)); + + MLX5_SET(fte_match_set_lyr_2_4, headers_c, + first_cfi, + ntohs(ib_spec->eth.mask.vlan_tag) >> 12); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, + first_cfi, + ntohs(ib_spec->eth.val.vlan_tag) >> 12); + + MLX5_SET(fte_match_set_lyr_2_4, headers_c, + first_prio, + ntohs(ib_spec->eth.mask.vlan_tag) >> 13); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, + first_prio, + ntohs(ib_spec->eth.val.vlan_tag) >> 13); + } + MLX5_SET(fte_match_set_lyr_2_4, headers_c, + ethertype, ntohs(ib_spec->eth.mask.ether_type)); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, + ethertype, ntohs(ib_spec->eth.val.ether_type)); + break; + case IB_FLOW_SPEC_IPV4: + if (FIELDS_NOT_SUPPORTED(ib_spec->ipv4.mask, LAST_IPV4_FIELD)) + return -EOPNOTSUPP; + + if (match_ipv) { + MLX5_SET(fte_match_set_lyr_2_4, headers_c, + ip_version, 0xf); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, + ip_version, MLX5_FS_IPV4_VERSION); + } else { + MLX5_SET(fte_match_set_lyr_2_4, headers_c, + ethertype, 0xffff); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, + ethertype, ETH_P_IP); + } + + memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, + src_ipv4_src_ipv6.ipv4_layout.ipv4), + &ib_spec->ipv4.mask.src_ip, + sizeof(ib_spec->ipv4.mask.src_ip)); + memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, + src_ipv4_src_ipv6.ipv4_layout.ipv4), + &ib_spec->ipv4.val.src_ip, + sizeof(ib_spec->ipv4.val.src_ip)); + memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, + dst_ipv4_dst_ipv6.ipv4_layout.ipv4), + &ib_spec->ipv4.mask.dst_ip, + sizeof(ib_spec->ipv4.mask.dst_ip)); + memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, + dst_ipv4_dst_ipv6.ipv4_layout.ipv4), + &ib_spec->ipv4.val.dst_ip, + sizeof(ib_spec->ipv4.val.dst_ip)); + + set_tos(headers_c, headers_v, + ib_spec->ipv4.mask.tos, ib_spec->ipv4.val.tos); + + if (set_proto(headers_c, headers_v, + ib_spec->ipv4.mask.proto, + ib_spec->ipv4.val.proto)) + return -EINVAL; + break; + case IB_FLOW_SPEC_IPV6: + if (FIELDS_NOT_SUPPORTED(ib_spec->ipv6.mask, LAST_IPV6_FIELD)) + return -EOPNOTSUPP; + + if (match_ipv) { + MLX5_SET(fte_match_set_lyr_2_4, headers_c, + ip_version, 0xf); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, + ip_version, MLX5_FS_IPV6_VERSION); + } else { + MLX5_SET(fte_match_set_lyr_2_4, headers_c, + ethertype, 0xffff); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, + ethertype, ETH_P_IPV6); + } + + memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, + src_ipv4_src_ipv6.ipv6_layout.ipv6), + &ib_spec->ipv6.mask.src_ip, + sizeof(ib_spec->ipv6.mask.src_ip)); + memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, + src_ipv4_src_ipv6.ipv6_layout.ipv6), + &ib_spec->ipv6.val.src_ip, + sizeof(ib_spec->ipv6.val.src_ip)); + memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, + dst_ipv4_dst_ipv6.ipv6_layout.ipv6), + &ib_spec->ipv6.mask.dst_ip, + sizeof(ib_spec->ipv6.mask.dst_ip)); + memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, + dst_ipv4_dst_ipv6.ipv6_layout.ipv6), + &ib_spec->ipv6.val.dst_ip, + sizeof(ib_spec->ipv6.val.dst_ip)); + + set_tos(headers_c, headers_v, + ib_spec->ipv6.mask.traffic_class, + ib_spec->ipv6.val.traffic_class); + + if (set_proto(headers_c, headers_v, + ib_spec->ipv6.mask.next_hdr, + ib_spec->ipv6.val.next_hdr)) + return -EINVAL; + + set_flow_label(misc_params_c, misc_params_v, + ntohl(ib_spec->ipv6.mask.flow_label), + ntohl(ib_spec->ipv6.val.flow_label), + ib_spec->type & IB_FLOW_SPEC_INNER); + break; + case IB_FLOW_SPEC_ESP: + if (ib_spec->esp.mask.seq) + return -EOPNOTSUPP; + + MLX5_SET(fte_match_set_misc, misc_params_c, outer_esp_spi, + ntohl(ib_spec->esp.mask.spi)); + MLX5_SET(fte_match_set_misc, misc_params_v, outer_esp_spi, + ntohl(ib_spec->esp.val.spi)); + break; + case IB_FLOW_SPEC_TCP: + if (FIELDS_NOT_SUPPORTED(ib_spec->tcp_udp.mask, + LAST_TCP_UDP_FIELD)) + return -EOPNOTSUPP; + + if (set_proto(headers_c, headers_v, 0xff, IPPROTO_TCP)) + return -EINVAL; + + MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_sport, + ntohs(ib_spec->tcp_udp.mask.src_port)); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport, + ntohs(ib_spec->tcp_udp.val.src_port)); + + MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_dport, + ntohs(ib_spec->tcp_udp.mask.dst_port)); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport, + ntohs(ib_spec->tcp_udp.val.dst_port)); + break; + case IB_FLOW_SPEC_UDP: + if (FIELDS_NOT_SUPPORTED(ib_spec->tcp_udp.mask, + LAST_TCP_UDP_FIELD)) + return -EOPNOTSUPP; + + if (set_proto(headers_c, headers_v, 0xff, IPPROTO_UDP)) + return -EINVAL; + + MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_sport, + ntohs(ib_spec->tcp_udp.mask.src_port)); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport, + ntohs(ib_spec->tcp_udp.val.src_port)); + + MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_dport, + ntohs(ib_spec->tcp_udp.mask.dst_port)); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, + ntohs(ib_spec->tcp_udp.val.dst_port)); + break; + case IB_FLOW_SPEC_GRE: + if (ib_spec->gre.mask.c_ks_res0_ver) + return -EOPNOTSUPP; + + if (set_proto(headers_c, headers_v, 0xff, IPPROTO_GRE)) + return -EINVAL; + + MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol, + 0xff); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, + IPPROTO_GRE); + + MLX5_SET(fte_match_set_misc, misc_params_c, gre_protocol, + ntohs(ib_spec->gre.mask.protocol)); + MLX5_SET(fte_match_set_misc, misc_params_v, gre_protocol, + ntohs(ib_spec->gre.val.protocol)); + + memcpy(MLX5_ADDR_OF(fte_match_set_misc, misc_params_c, + gre_key.nvgre.hi), + &ib_spec->gre.mask.key, + sizeof(ib_spec->gre.mask.key)); + memcpy(MLX5_ADDR_OF(fte_match_set_misc, misc_params_v, + gre_key.nvgre.hi), + &ib_spec->gre.val.key, + sizeof(ib_spec->gre.val.key)); + break; + case IB_FLOW_SPEC_MPLS: + switch (prev_type) { + case IB_FLOW_SPEC_UDP: + if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev, + ft_field_support.outer_first_mpls_over_udp), + &ib_spec->mpls.mask.tag)) + return -EOPNOTSUPP; + + memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v, + outer_first_mpls_over_udp), + &ib_spec->mpls.val.tag, + sizeof(ib_spec->mpls.val.tag)); + memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c, + outer_first_mpls_over_udp), + &ib_spec->mpls.mask.tag, + sizeof(ib_spec->mpls.mask.tag)); + break; + case IB_FLOW_SPEC_GRE: + if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev, + ft_field_support.outer_first_mpls_over_gre), + &ib_spec->mpls.mask.tag)) + return -EOPNOTSUPP; + + memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v, + outer_first_mpls_over_gre), + &ib_spec->mpls.val.tag, + sizeof(ib_spec->mpls.val.tag)); + memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c, + outer_first_mpls_over_gre), + &ib_spec->mpls.mask.tag, + sizeof(ib_spec->mpls.mask.tag)); + break; + default: + if (ib_spec->type & IB_FLOW_SPEC_INNER) { + if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev, + ft_field_support.inner_first_mpls), + &ib_spec->mpls.mask.tag)) + return -EOPNOTSUPP; + + memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v, + inner_first_mpls), + &ib_spec->mpls.val.tag, + sizeof(ib_spec->mpls.val.tag)); + memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c, + inner_first_mpls), + &ib_spec->mpls.mask.tag, + sizeof(ib_spec->mpls.mask.tag)); + } else { + if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev, + ft_field_support.outer_first_mpls), + &ib_spec->mpls.mask.tag)) + return -EOPNOTSUPP; + + memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v, + outer_first_mpls), + &ib_spec->mpls.val.tag, + sizeof(ib_spec->mpls.val.tag)); + memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c, + outer_first_mpls), + &ib_spec->mpls.mask.tag, + sizeof(ib_spec->mpls.mask.tag)); + } + } + break; + case IB_FLOW_SPEC_VXLAN_TUNNEL: + if (FIELDS_NOT_SUPPORTED(ib_spec->tunnel.mask, + LAST_TUNNEL_FIELD)) + return -EOPNOTSUPP; + + MLX5_SET(fte_match_set_misc, misc_params_c, vxlan_vni, + ntohl(ib_spec->tunnel.mask.tunnel_id)); + MLX5_SET(fte_match_set_misc, misc_params_v, vxlan_vni, + ntohl(ib_spec->tunnel.val.tunnel_id)); + break; + case IB_FLOW_SPEC_ACTION_TAG: + if (FIELDS_NOT_SUPPORTED(ib_spec->flow_tag, + LAST_FLOW_TAG_FIELD)) + return -EOPNOTSUPP; + if (ib_spec->flow_tag.tag_id >= BIT(24)) + return -EINVAL; + + flow_context->flow_tag = ib_spec->flow_tag.tag_id; + flow_context->flags |= FLOW_CONTEXT_HAS_TAG; + break; + case IB_FLOW_SPEC_ACTION_DROP: + if (FIELDS_NOT_SUPPORTED(ib_spec->drop, + LAST_DROP_FIELD)) + return -EOPNOTSUPP; + action->action |= MLX5_FLOW_CONTEXT_ACTION_DROP; + break; + case IB_FLOW_SPEC_ACTION_HANDLE: + ret = parse_flow_flow_action(to_mflow_act(ib_spec->action.act), + flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS, action); + if (ret) + return ret; + break; + case IB_FLOW_SPEC_ACTION_COUNT: + if (FIELDS_NOT_SUPPORTED(ib_spec->flow_count, + LAST_COUNTERS_FIELD)) + return -EOPNOTSUPP; + + /* for now support only one counters spec per flow */ + if (action->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) + return -EINVAL; + + action->counters = ib_spec->flow_count.counters; + action->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; + break; + default: + return -EINVAL; + } + + return 0; +} + +/* If a flow could catch both multicast and unicast packets, + * it won't fall into the multicast flow steering table and this rule + * could steal other multicast packets. + */ +static bool flow_is_multicast_only(const struct ib_flow_attr *ib_attr) +{ + union ib_flow_spec *flow_spec; + + if (ib_attr->type != IB_FLOW_ATTR_NORMAL || + ib_attr->num_of_specs < 1) + return false; + + flow_spec = (union ib_flow_spec *)(ib_attr + 1); + if (flow_spec->type == IB_FLOW_SPEC_IPV4) { + struct ib_flow_spec_ipv4 *ipv4_spec; + + ipv4_spec = (struct ib_flow_spec_ipv4 *)flow_spec; + if (ipv4_is_multicast(ipv4_spec->val.dst_ip)) + return true; + + return false; + } + + if (flow_spec->type == IB_FLOW_SPEC_ETH) { + struct ib_flow_spec_eth *eth_spec; + + eth_spec = (struct ib_flow_spec_eth *)flow_spec; + return is_multicast_ether_addr(eth_spec->mask.dst_mac) && + is_multicast_ether_addr(eth_spec->val.dst_mac); + } + + return false; +} + +enum valid_spec { + VALID_SPEC_INVALID, + VALID_SPEC_VALID, + VALID_SPEC_NA, +}; + +static enum valid_spec +is_valid_esp_aes_gcm(struct mlx5_core_dev *mdev, + const struct mlx5_flow_spec *spec, + const struct mlx5_flow_act *flow_act, + bool egress) +{ + const u32 *match_c = spec->match_criteria; + bool is_crypto = + (flow_act->action & (MLX5_FLOW_CONTEXT_ACTION_ENCRYPT | + MLX5_FLOW_CONTEXT_ACTION_DECRYPT)); + bool is_ipsec = mlx5_fs_is_ipsec_flow(match_c); + bool is_drop = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_DROP; + + /* + * Currently only crypto is supported in egress, when regular egress + * rules would be supported, always return VALID_SPEC_NA. + */ + if (!is_crypto) + return VALID_SPEC_NA; + + return is_crypto && is_ipsec && + (!egress || (!is_drop && + !(spec->flow_context.flags & FLOW_CONTEXT_HAS_TAG))) ? + VALID_SPEC_VALID : VALID_SPEC_INVALID; +} + +static bool is_valid_spec(struct mlx5_core_dev *mdev, + const struct mlx5_flow_spec *spec, + const struct mlx5_flow_act *flow_act, + bool egress) +{ + /* We curretly only support ipsec egress flow */ + return is_valid_esp_aes_gcm(mdev, spec, flow_act, egress) != VALID_SPEC_INVALID; +} + +static bool is_valid_ethertype(struct mlx5_core_dev *mdev, + const struct ib_flow_attr *flow_attr, + bool check_inner) +{ + union ib_flow_spec *ib_spec = (union ib_flow_spec *)(flow_attr + 1); + int match_ipv = check_inner ? + MLX5_CAP_FLOWTABLE_NIC_RX(mdev, + ft_field_support.inner_ip_version) : + MLX5_CAP_FLOWTABLE_NIC_RX(mdev, + ft_field_support.outer_ip_version); + int inner_bit = check_inner ? IB_FLOW_SPEC_INNER : 0; + bool ipv4_spec_valid, ipv6_spec_valid; + unsigned int ip_spec_type = 0; + bool has_ethertype = false; + unsigned int spec_index; + bool mask_valid = true; + u16 eth_type = 0; + bool type_valid; + + /* Validate that ethertype is correct */ + for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) { + if ((ib_spec->type == (IB_FLOW_SPEC_ETH | inner_bit)) && + ib_spec->eth.mask.ether_type) { + mask_valid = (ib_spec->eth.mask.ether_type == + htons(0xffff)); + has_ethertype = true; + eth_type = ntohs(ib_spec->eth.val.ether_type); + } else if ((ib_spec->type == (IB_FLOW_SPEC_IPV4 | inner_bit)) || + (ib_spec->type == (IB_FLOW_SPEC_IPV6 | inner_bit))) { + ip_spec_type = ib_spec->type; + } + ib_spec = (void *)ib_spec + ib_spec->size; + } + + type_valid = (!has_ethertype) || (!ip_spec_type); + if (!type_valid && mask_valid) { + ipv4_spec_valid = (eth_type == ETH_P_IP) && + (ip_spec_type == (IB_FLOW_SPEC_IPV4 | inner_bit)); + ipv6_spec_valid = (eth_type == ETH_P_IPV6) && + (ip_spec_type == (IB_FLOW_SPEC_IPV6 | inner_bit)); + + type_valid = (ipv4_spec_valid) || (ipv6_spec_valid) || + (((eth_type == ETH_P_MPLS_UC) || + (eth_type == ETH_P_MPLS_MC)) && match_ipv); + } + + return type_valid; +} + +static bool is_valid_attr(struct mlx5_core_dev *mdev, + const struct ib_flow_attr *flow_attr) +{ + return is_valid_ethertype(mdev, flow_attr, false) && + is_valid_ethertype(mdev, flow_attr, true); +} + +static void put_flow_table(struct mlx5_ib_dev *dev, + struct mlx5_ib_flow_prio *prio, bool ft_added) +{ + prio->refcount -= !!ft_added; + if (!prio->refcount) { + mlx5_destroy_flow_table(prio->flow_table); + prio->flow_table = NULL; + } +} + +static int mlx5_ib_destroy_flow(struct ib_flow *flow_id) +{ + struct mlx5_ib_flow_handler *handler = container_of(flow_id, + struct mlx5_ib_flow_handler, + ibflow); + struct mlx5_ib_flow_handler *iter, *tmp; + struct mlx5_ib_dev *dev = handler->dev; + + mutex_lock(&dev->flow_db->lock); + + list_for_each_entry_safe(iter, tmp, &handler->list, list) { + mlx5_del_flow_rules(iter->rule); + put_flow_table(dev, iter->prio, true); + list_del(&iter->list); + kfree(iter); + } + + mlx5_del_flow_rules(handler->rule); + put_flow_table(dev, handler->prio, true); + mlx5_ib_counters_clear_description(handler->ibcounters); + mutex_unlock(&dev->flow_db->lock); + if (handler->flow_matcher) + atomic_dec(&handler->flow_matcher->usecnt); + kfree(handler); + + return 0; +} + +static int ib_prio_to_core_prio(unsigned int priority, bool dont_trap) +{ + priority *= 2; + if (!dont_trap) + priority++; + return priority; +} + +enum flow_table_type { + MLX5_IB_FT_RX, + MLX5_IB_FT_TX +}; + +#define MLX5_FS_MAX_TYPES 6 +#define MLX5_FS_MAX_ENTRIES BIT(16) + +static struct mlx5_ib_flow_prio *_get_prio(struct mlx5_flow_namespace *ns, + struct mlx5_ib_flow_prio *prio, + int priority, + int num_entries, int num_groups, + u32 flags) +{ + struct mlx5_flow_table_attr ft_attr = {}; + struct mlx5_flow_table *ft; + + ft_attr.prio = priority; + ft_attr.max_fte = num_entries; + ft_attr.flags = flags; + ft_attr.autogroup.max_num_groups = num_groups; + ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); + if (IS_ERR(ft)) + return ERR_CAST(ft); + + prio->flow_table = ft; + prio->refcount = 0; + return prio; +} + +static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev, + struct ib_flow_attr *flow_attr, + enum flow_table_type ft_type) +{ + bool dont_trap = flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP; + struct mlx5_flow_namespace *ns = NULL; + struct mlx5_ib_flow_prio *prio; + struct mlx5_flow_table *ft; + int max_table_size; + int num_entries; + int num_groups; + bool esw_encap; + u32 flags = 0; + int priority; + + max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, + log_max_ft_size)); + esw_encap = mlx5_eswitch_get_encap_mode(dev->mdev) != + DEVLINK_ESWITCH_ENCAP_MODE_NONE; + if (flow_attr->type == IB_FLOW_ATTR_NORMAL) { + enum mlx5_flow_namespace_type fn_type; + + if (flow_is_multicast_only(flow_attr) && + !dont_trap) + priority = MLX5_IB_FLOW_MCAST_PRIO; + else + priority = ib_prio_to_core_prio(flow_attr->priority, + dont_trap); + if (ft_type == MLX5_IB_FT_RX) { + fn_type = MLX5_FLOW_NAMESPACE_BYPASS; + prio = &dev->flow_db->prios[priority]; + if (!dev->is_rep && !esw_encap && + MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap)) + flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP; + if (!dev->is_rep && !esw_encap && + MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, + reformat_l3_tunnel_to_l2)) + flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; + } else { + max_table_size = + BIT(MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, + log_max_ft_size)); + fn_type = MLX5_FLOW_NAMESPACE_EGRESS; + prio = &dev->flow_db->egress_prios[priority]; + if (!dev->is_rep && !esw_encap && + MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, reformat)) + flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; + } + ns = mlx5_get_flow_namespace(dev->mdev, fn_type); + num_entries = MLX5_FS_MAX_ENTRIES; + num_groups = MLX5_FS_MAX_TYPES; + } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || + flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) { + ns = mlx5_get_flow_namespace(dev->mdev, + MLX5_FLOW_NAMESPACE_LEFTOVERS); + build_leftovers_ft_param(&priority, + &num_entries, + &num_groups); + prio = &dev->flow_db->prios[MLX5_IB_FLOW_LEFTOVERS_PRIO]; + } else if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) { + if (!MLX5_CAP_FLOWTABLE(dev->mdev, + allow_sniffer_and_nic_rx_shared_tir)) + return ERR_PTR(-EOPNOTSUPP); + + ns = mlx5_get_flow_namespace(dev->mdev, ft_type == MLX5_IB_FT_RX ? + MLX5_FLOW_NAMESPACE_SNIFFER_RX : + MLX5_FLOW_NAMESPACE_SNIFFER_TX); + + prio = &dev->flow_db->sniffer[ft_type]; + priority = 0; + num_entries = 1; + num_groups = 1; + } + + if (!ns) + return ERR_PTR(-EOPNOTSUPP); + + max_table_size = min_t(int, num_entries, max_table_size); + + ft = prio->flow_table; + if (!ft) + return _get_prio(ns, prio, priority, max_table_size, num_groups, + flags); + + return prio; +} + +static void set_underlay_qp(struct mlx5_ib_dev *dev, + struct mlx5_flow_spec *spec, + u32 underlay_qpn) +{ + void *misc_params_c = MLX5_ADDR_OF(fte_match_param, + spec->match_criteria, + misc_parameters); + void *misc_params_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, + misc_parameters); + + if (underlay_qpn && + MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, + ft_field_support.bth_dst_qp)) { + MLX5_SET(fte_match_set_misc, + misc_params_v, bth_dst_qp, underlay_qpn); + MLX5_SET(fte_match_set_misc, + misc_params_c, bth_dst_qp, 0xffffff); + } +} + +static void mlx5_ib_set_rule_source_port(struct mlx5_ib_dev *dev, + struct mlx5_flow_spec *spec, + struct mlx5_eswitch_rep *rep) +{ + struct mlx5_eswitch *esw = dev->mdev->priv.eswitch; + void *misc; + + if (mlx5_eswitch_vport_match_metadata_enabled(esw)) { + misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, + misc_parameters_2); + + MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, + mlx5_eswitch_get_vport_metadata_for_match(esw, + rep->vport)); + misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, + misc_parameters_2); + + MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, + mlx5_eswitch_get_vport_metadata_mask()); + } else { + misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, + misc_parameters); + + MLX5_SET(fte_match_set_misc, misc, source_port, rep->vport); + + misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, + misc_parameters); + + MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); + } +} + +static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev, + struct mlx5_ib_flow_prio *ft_prio, + const struct ib_flow_attr *flow_attr, + struct mlx5_flow_destination *dst, + u32 underlay_qpn, + struct mlx5_ib_create_flow *ucmd) +{ + struct mlx5_flow_table *ft = ft_prio->flow_table; + struct mlx5_ib_flow_handler *handler; + struct mlx5_flow_act flow_act = {}; + struct mlx5_flow_spec *spec; + struct mlx5_flow_destination dest_arr[2] = {}; + struct mlx5_flow_destination *rule_dst = dest_arr; + const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr); + unsigned int spec_index; + u32 prev_type = 0; + int err = 0; + int dest_num = 0; + bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS; + + if (!is_valid_attr(dev->mdev, flow_attr)) + return ERR_PTR(-EINVAL); + + if (dev->is_rep && is_egress) + return ERR_PTR(-EINVAL); + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + handler = kzalloc(sizeof(*handler), GFP_KERNEL); + if (!handler || !spec) { + err = -ENOMEM; + goto free; + } + + INIT_LIST_HEAD(&handler->list); + + for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) { + err = parse_flow_attr(dev->mdev, spec, + ib_flow, flow_attr, &flow_act, + prev_type); + if (err < 0) + goto free; + + prev_type = ((union ib_flow_spec *)ib_flow)->type; + ib_flow += ((union ib_flow_spec *)ib_flow)->size; + } + + if (dst && !(flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP)) { + memcpy(&dest_arr[0], dst, sizeof(*dst)); + dest_num++; + } + + if (!flow_is_multicast_only(flow_attr)) + set_underlay_qp(dev, spec, underlay_qpn); + + if (dev->is_rep) { + struct mlx5_eswitch_rep *rep; + + rep = dev->port[flow_attr->port - 1].rep; + if (!rep) { + err = -EINVAL; + goto free; + } + + mlx5_ib_set_rule_source_port(dev, spec, rep); + } + + spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria); + + if (is_egress && + !is_valid_spec(dev->mdev, spec, &flow_act, is_egress)) { + err = -EINVAL; + goto free; + } + + if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { + struct mlx5_ib_mcounters *mcounters; + + err = mlx5_ib_flow_counters_set_data(flow_act.counters, ucmd); + if (err) + goto free; + + mcounters = to_mcounters(flow_act.counters); + handler->ibcounters = flow_act.counters; + dest_arr[dest_num].type = + MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest_arr[dest_num].counter_id = + mlx5_fc_id(mcounters->hw_cntrs_hndl); + dest_num++; + } + + if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP) { + if (!dest_num) + rule_dst = NULL; + } else { + if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP) + flow_act.action |= + MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; + if (is_egress) + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW; + else if (dest_num) + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + } + + if ((spec->flow_context.flags & FLOW_CONTEXT_HAS_TAG) && + (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || + flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) { + mlx5_ib_warn(dev, "Flow tag %u and attribute type %x isn't allowed in leftovers\n", + spec->flow_context.flow_tag, flow_attr->type); + err = -EINVAL; + goto free; + } + handler->rule = mlx5_add_flow_rules(ft, spec, + &flow_act, + rule_dst, dest_num); + + if (IS_ERR(handler->rule)) { + err = PTR_ERR(handler->rule); + goto free; + } + + ft_prio->refcount++; + handler->prio = ft_prio; + handler->dev = dev; + + ft_prio->flow_table = ft; +free: + if (err && handler) { + mlx5_ib_counters_clear_description(handler->ibcounters); + kfree(handler); + } + kvfree(spec); + return err ? ERR_PTR(err) : handler; +} + +static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev, + struct mlx5_ib_flow_prio *ft_prio, + const struct ib_flow_attr *flow_attr, + struct mlx5_flow_destination *dst) +{ + return _create_flow_rule(dev, ft_prio, flow_attr, dst, 0, NULL); +} + +enum { + LEFTOVERS_MC, + LEFTOVERS_UC, +}; + +static struct mlx5_ib_flow_handler *create_leftovers_rule(struct mlx5_ib_dev *dev, + struct mlx5_ib_flow_prio *ft_prio, + struct ib_flow_attr *flow_attr, + struct mlx5_flow_destination *dst) +{ + struct mlx5_ib_flow_handler *handler_ucast = NULL; + struct mlx5_ib_flow_handler *handler = NULL; + + static struct { + struct ib_flow_attr flow_attr; + struct ib_flow_spec_eth eth_flow; + } leftovers_specs[] = { + [LEFTOVERS_MC] = { + .flow_attr = { + .num_of_specs = 1, + .size = sizeof(leftovers_specs[0]) + }, + .eth_flow = { + .type = IB_FLOW_SPEC_ETH, + .size = sizeof(struct ib_flow_spec_eth), + .mask = {.dst_mac = {0x1} }, + .val = {.dst_mac = {0x1} } + } + }, + [LEFTOVERS_UC] = { + .flow_attr = { + .num_of_specs = 1, + .size = sizeof(leftovers_specs[0]) + }, + .eth_flow = { + .type = IB_FLOW_SPEC_ETH, + .size = sizeof(struct ib_flow_spec_eth), + .mask = {.dst_mac = {0x1} }, + .val = {.dst_mac = {} } + } + } + }; + + handler = create_flow_rule(dev, ft_prio, + &leftovers_specs[LEFTOVERS_MC].flow_attr, + dst); + if (!IS_ERR(handler) && + flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT) { + handler_ucast = create_flow_rule(dev, ft_prio, + &leftovers_specs[LEFTOVERS_UC].flow_attr, + dst); + if (IS_ERR(handler_ucast)) { + mlx5_del_flow_rules(handler->rule); + ft_prio->refcount--; + kfree(handler); + handler = handler_ucast; + } else { + list_add(&handler_ucast->list, &handler->list); + } + } + + return handler; +} + +static struct mlx5_ib_flow_handler *create_sniffer_rule(struct mlx5_ib_dev *dev, + struct mlx5_ib_flow_prio *ft_rx, + struct mlx5_ib_flow_prio *ft_tx, + struct mlx5_flow_destination *dst) +{ + struct mlx5_ib_flow_handler *handler_rx; + struct mlx5_ib_flow_handler *handler_tx; + int err; + static const struct ib_flow_attr flow_attr = { + .num_of_specs = 0, + .size = sizeof(flow_attr) + }; + + handler_rx = create_flow_rule(dev, ft_rx, &flow_attr, dst); + if (IS_ERR(handler_rx)) { + err = PTR_ERR(handler_rx); + goto err; + } + + handler_tx = create_flow_rule(dev, ft_tx, &flow_attr, dst); + if (IS_ERR(handler_tx)) { + err = PTR_ERR(handler_tx); + goto err_tx; + } + + list_add(&handler_tx->list, &handler_rx->list); + + return handler_rx; + +err_tx: + mlx5_del_flow_rules(handler_rx->rule); + ft_rx->refcount--; + kfree(handler_rx); +err: + return ERR_PTR(err); +} + + +static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp, + struct ib_flow_attr *flow_attr, + int domain, + struct ib_udata *udata) +{ + struct mlx5_ib_dev *dev = to_mdev(qp->device); + struct mlx5_ib_qp *mqp = to_mqp(qp); + struct mlx5_ib_flow_handler *handler = NULL; + struct mlx5_flow_destination *dst = NULL; + struct mlx5_ib_flow_prio *ft_prio_tx = NULL; + struct mlx5_ib_flow_prio *ft_prio; + bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS; + struct mlx5_ib_create_flow *ucmd = NULL, ucmd_hdr; + size_t min_ucmd_sz, required_ucmd_sz; + int err; + int underlay_qpn; + + if (udata && udata->inlen) { + min_ucmd_sz = offsetof(typeof(ucmd_hdr), reserved) + + sizeof(ucmd_hdr.reserved); + if (udata->inlen < min_ucmd_sz) + return ERR_PTR(-EOPNOTSUPP); + + err = ib_copy_from_udata(&ucmd_hdr, udata, min_ucmd_sz); + if (err) + return ERR_PTR(err); + + /* currently supports only one counters data */ + if (ucmd_hdr.ncounters_data > 1) + return ERR_PTR(-EINVAL); + + required_ucmd_sz = min_ucmd_sz + + sizeof(struct mlx5_ib_flow_counters_data) * + ucmd_hdr.ncounters_data; + if (udata->inlen > required_ucmd_sz && + !ib_is_udata_cleared(udata, required_ucmd_sz, + udata->inlen - required_ucmd_sz)) + return ERR_PTR(-EOPNOTSUPP); + + ucmd = kzalloc(required_ucmd_sz, GFP_KERNEL); + if (!ucmd) + return ERR_PTR(-ENOMEM); + + err = ib_copy_from_udata(ucmd, udata, required_ucmd_sz); + if (err) + goto free_ucmd; + } + + if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO) { + err = -ENOMEM; + goto free_ucmd; + } + + if (domain != IB_FLOW_DOMAIN_USER || + flow_attr->port > dev->num_ports || + (flow_attr->flags & ~(IB_FLOW_ATTR_FLAGS_DONT_TRAP | + IB_FLOW_ATTR_FLAGS_EGRESS))) { + err = -EINVAL; + goto free_ucmd; + } + + if (is_egress && + (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || + flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) { + err = -EINVAL; + goto free_ucmd; + } + + dst = kzalloc(sizeof(*dst), GFP_KERNEL); + if (!dst) { + err = -ENOMEM; + goto free_ucmd; + } + + mutex_lock(&dev->flow_db->lock); + + ft_prio = get_flow_table(dev, flow_attr, + is_egress ? MLX5_IB_FT_TX : MLX5_IB_FT_RX); + if (IS_ERR(ft_prio)) { + err = PTR_ERR(ft_prio); + goto unlock; + } + if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) { + ft_prio_tx = get_flow_table(dev, flow_attr, MLX5_IB_FT_TX); + if (IS_ERR(ft_prio_tx)) { + err = PTR_ERR(ft_prio_tx); + ft_prio_tx = NULL; + goto destroy_ft; + } + } + + if (is_egress) { + dst->type = MLX5_FLOW_DESTINATION_TYPE_PORT; + } else { + dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR; + if (mqp->is_rss) + dst->tir_num = mqp->rss_qp.tirn; + else + dst->tir_num = mqp->raw_packet_qp.rq.tirn; + } + + if (flow_attr->type == IB_FLOW_ATTR_NORMAL) { + underlay_qpn = (mqp->flags & IB_QP_CREATE_SOURCE_QPN) ? + mqp->underlay_qpn : + 0; + handler = _create_flow_rule(dev, ft_prio, flow_attr, dst, + underlay_qpn, ucmd); + } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || + flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) { + handler = create_leftovers_rule(dev, ft_prio, flow_attr, + dst); + } else if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) { + handler = create_sniffer_rule(dev, ft_prio, ft_prio_tx, dst); + } else { + err = -EINVAL; + goto destroy_ft; + } + + if (IS_ERR(handler)) { + err = PTR_ERR(handler); + handler = NULL; + goto destroy_ft; + } + + mutex_unlock(&dev->flow_db->lock); + kfree(dst); + kfree(ucmd); + + return &handler->ibflow; + +destroy_ft: + put_flow_table(dev, ft_prio, false); + if (ft_prio_tx) + put_flow_table(dev, ft_prio_tx, false); +unlock: + mutex_unlock(&dev->flow_db->lock); + kfree(dst); +free_ucmd: + kfree(ucmd); + return ERR_PTR(err); +} + +static struct mlx5_ib_flow_prio * +_get_flow_table(struct mlx5_ib_dev *dev, + struct mlx5_ib_flow_matcher *fs_matcher, + bool mcast) +{ + struct mlx5_flow_namespace *ns = NULL; + struct mlx5_ib_flow_prio *prio = NULL; + int max_table_size = 0; + bool esw_encap; + u32 flags = 0; + int priority; + + if (mcast) + priority = MLX5_IB_FLOW_MCAST_PRIO; + else + priority = ib_prio_to_core_prio(fs_matcher->priority, false); + + esw_encap = mlx5_eswitch_get_encap_mode(dev->mdev) != + DEVLINK_ESWITCH_ENCAP_MODE_NONE; + if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS) { + max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, + log_max_ft_size)); + if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap) && !esw_encap) + flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP; + if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, + reformat_l3_tunnel_to_l2) && + !esw_encap) + flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; + } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS) { + max_table_size = BIT( + MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, log_max_ft_size)); + if (MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, reformat) && !esw_encap) + flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; + } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB) { + max_table_size = BIT( + MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev, log_max_ft_size)); + if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev, decap) && esw_encap) + flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP; + if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev, reformat_l3_tunnel_to_l2) && + esw_encap) + flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; + priority = FDB_BYPASS_PATH; + } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) { + max_table_size = + BIT(MLX5_CAP_FLOWTABLE_RDMA_RX(dev->mdev, + log_max_ft_size)); + priority = fs_matcher->priority; + } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_TX) { + max_table_size = + BIT(MLX5_CAP_FLOWTABLE_RDMA_TX(dev->mdev, + log_max_ft_size)); + priority = fs_matcher->priority; + } + + max_table_size = min_t(int, max_table_size, MLX5_FS_MAX_ENTRIES); + + ns = mlx5_get_flow_namespace(dev->mdev, fs_matcher->ns_type); + if (!ns) + return ERR_PTR(-EOPNOTSUPP); + + if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS) + prio = &dev->flow_db->prios[priority]; + else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS) + prio = &dev->flow_db->egress_prios[priority]; + else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB) + prio = &dev->flow_db->fdb; + else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) + prio = &dev->flow_db->rdma_rx[priority]; + else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_TX) + prio = &dev->flow_db->rdma_tx[priority]; + + if (!prio) + return ERR_PTR(-EINVAL); + + if (prio->flow_table) + return prio; + + return _get_prio(ns, prio, priority, max_table_size, + MLX5_FS_MAX_TYPES, flags); +} + +static struct mlx5_ib_flow_handler * +_create_raw_flow_rule(struct mlx5_ib_dev *dev, + struct mlx5_ib_flow_prio *ft_prio, + struct mlx5_flow_destination *dst, + struct mlx5_ib_flow_matcher *fs_matcher, + struct mlx5_flow_context *flow_context, + struct mlx5_flow_act *flow_act, + void *cmd_in, int inlen, + int dst_num) +{ + struct mlx5_ib_flow_handler *handler; + struct mlx5_flow_spec *spec; + struct mlx5_flow_table *ft = ft_prio->flow_table; + int err = 0; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + handler = kzalloc(sizeof(*handler), GFP_KERNEL); + if (!handler || !spec) { + err = -ENOMEM; + goto free; + } + + INIT_LIST_HEAD(&handler->list); + + memcpy(spec->match_value, cmd_in, inlen); + memcpy(spec->match_criteria, fs_matcher->matcher_mask.match_params, + fs_matcher->mask_len); + spec->match_criteria_enable = fs_matcher->match_criteria_enable; + spec->flow_context = *flow_context; + + handler->rule = mlx5_add_flow_rules(ft, spec, + flow_act, dst, dst_num); + + if (IS_ERR(handler->rule)) { + err = PTR_ERR(handler->rule); + goto free; + } + + ft_prio->refcount++; + handler->prio = ft_prio; + handler->dev = dev; + ft_prio->flow_table = ft; + +free: + if (err) + kfree(handler); + kvfree(spec); + return err ? ERR_PTR(err) : handler; +} + +static bool raw_fs_is_multicast(struct mlx5_ib_flow_matcher *fs_matcher, + void *match_v) +{ + void *match_c; + void *match_v_set_lyr_2_4, *match_c_set_lyr_2_4; + void *dmac, *dmac_mask; + void *ipv4, *ipv4_mask; + + if (!(fs_matcher->match_criteria_enable & + (1 << MATCH_CRITERIA_ENABLE_OUTER_BIT))) + return false; + + match_c = fs_matcher->matcher_mask.match_params; + match_v_set_lyr_2_4 = MLX5_ADDR_OF(fte_match_param, match_v, + outer_headers); + match_c_set_lyr_2_4 = MLX5_ADDR_OF(fte_match_param, match_c, + outer_headers); + + dmac = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_v_set_lyr_2_4, + dmac_47_16); + dmac_mask = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_c_set_lyr_2_4, + dmac_47_16); + + if (is_multicast_ether_addr(dmac) && + is_multicast_ether_addr(dmac_mask)) + return true; + + ipv4 = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_v_set_lyr_2_4, + dst_ipv4_dst_ipv6.ipv4_layout.ipv4); + + ipv4_mask = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_c_set_lyr_2_4, + dst_ipv4_dst_ipv6.ipv4_layout.ipv4); + + if (ipv4_is_multicast(*(__be32 *)(ipv4)) && + ipv4_is_multicast(*(__be32 *)(ipv4_mask))) + return true; + + return false; +} + +static struct mlx5_ib_flow_handler *raw_fs_rule_add( + struct mlx5_ib_dev *dev, struct mlx5_ib_flow_matcher *fs_matcher, + struct mlx5_flow_context *flow_context, struct mlx5_flow_act *flow_act, + u32 counter_id, void *cmd_in, int inlen, int dest_id, int dest_type) +{ + struct mlx5_flow_destination *dst; + struct mlx5_ib_flow_prio *ft_prio; + struct mlx5_ib_flow_handler *handler; + int dst_num = 0; + bool mcast; + int err; + + if (fs_matcher->flow_type != MLX5_IB_FLOW_TYPE_NORMAL) + return ERR_PTR(-EOPNOTSUPP); + + if (fs_matcher->priority > MLX5_IB_FLOW_LAST_PRIO) + return ERR_PTR(-ENOMEM); + + dst = kcalloc(2, sizeof(*dst), GFP_KERNEL); + if (!dst) + return ERR_PTR(-ENOMEM); + + mcast = raw_fs_is_multicast(fs_matcher, cmd_in); + mutex_lock(&dev->flow_db->lock); + + ft_prio = _get_flow_table(dev, fs_matcher, mcast); + if (IS_ERR(ft_prio)) { + err = PTR_ERR(ft_prio); + goto unlock; + } + + if (dest_type == MLX5_FLOW_DESTINATION_TYPE_TIR) { + dst[dst_num].type = dest_type; + dst[dst_num++].tir_num = dest_id; + flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + } else if (dest_type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) { + dst[dst_num].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM; + dst[dst_num++].ft_num = dest_id; + flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + } else if (dest_type == MLX5_FLOW_DESTINATION_TYPE_PORT) { + dst[dst_num++].type = MLX5_FLOW_DESTINATION_TYPE_PORT; + flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW; + } + + + if (flow_act->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { + dst[dst_num].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dst[dst_num].counter_id = counter_id; + dst_num++; + } + + handler = _create_raw_flow_rule(dev, ft_prio, dst, fs_matcher, + flow_context, flow_act, + cmd_in, inlen, dst_num); + + if (IS_ERR(handler)) { + err = PTR_ERR(handler); + goto destroy_ft; + } + + mutex_unlock(&dev->flow_db->lock); + atomic_inc(&fs_matcher->usecnt); + handler->flow_matcher = fs_matcher; + + kfree(dst); + + return handler; + +destroy_ft: + put_flow_table(dev, ft_prio, false); +unlock: + mutex_unlock(&dev->flow_db->lock); + kfree(dst); + + return ERR_PTR(err); +} + +static u32 mlx5_ib_flow_action_flags_to_accel_xfrm_flags(u32 mlx5_flags) +{ + u32 flags = 0; + + if (mlx5_flags & MLX5_IB_UAPI_FLOW_ACTION_FLAGS_REQUIRE_METADATA) + flags |= MLX5_ACCEL_XFRM_FLAG_REQUIRE_METADATA; + + return flags; +} + +#define MLX5_FLOW_ACTION_ESP_CREATE_LAST_SUPPORTED \ + MLX5_IB_UAPI_FLOW_ACTION_FLAGS_REQUIRE_METADATA +static struct ib_flow_action * +mlx5_ib_create_flow_action_esp(struct ib_device *device, + const struct ib_flow_action_attrs_esp *attr, + struct uverbs_attr_bundle *attrs) +{ + struct mlx5_ib_dev *mdev = to_mdev(device); + struct ib_uverbs_flow_action_esp_keymat_aes_gcm *aes_gcm; + struct mlx5_accel_esp_xfrm_attrs accel_attrs = {}; + struct mlx5_ib_flow_action *action; + u64 action_flags; + u64 flags; + int err = 0; + + err = uverbs_get_flags64( + &action_flags, attrs, MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS, + ((MLX5_FLOW_ACTION_ESP_CREATE_LAST_SUPPORTED << 1) - 1)); + if (err) + return ERR_PTR(err); + + flags = mlx5_ib_flow_action_flags_to_accel_xfrm_flags(action_flags); + + /* We current only support a subset of the standard features. Only a + * keymat of type AES_GCM, with icv_len == 16, iv_algo == SEQ and esn + * (with overlap). Full offload mode isn't supported. + */ + if (!attr->keymat || attr->replay || attr->encap || + attr->spi || attr->seq || attr->tfc_pad || + attr->hard_limit_pkts || + (attr->flags & ~(IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED | + IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ENCRYPT))) + return ERR_PTR(-EOPNOTSUPP); + + if (attr->keymat->protocol != + IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM) + return ERR_PTR(-EOPNOTSUPP); + + aes_gcm = &attr->keymat->keymat.aes_gcm; + + if (aes_gcm->icv_len != 16 || + aes_gcm->iv_algo != IB_UVERBS_FLOW_ACTION_IV_ALGO_SEQ) + return ERR_PTR(-EOPNOTSUPP); + + action = kmalloc(sizeof(*action), GFP_KERNEL); + if (!action) + return ERR_PTR(-ENOMEM); + + action->esp_aes_gcm.ib_flags = attr->flags; + memcpy(&accel_attrs.keymat.aes_gcm.aes_key, &aes_gcm->aes_key, + sizeof(accel_attrs.keymat.aes_gcm.aes_key)); + accel_attrs.keymat.aes_gcm.key_len = aes_gcm->key_len * 8; + memcpy(&accel_attrs.keymat.aes_gcm.salt, &aes_gcm->salt, + sizeof(accel_attrs.keymat.aes_gcm.salt)); + memcpy(&accel_attrs.keymat.aes_gcm.seq_iv, &aes_gcm->iv, + sizeof(accel_attrs.keymat.aes_gcm.seq_iv)); + accel_attrs.keymat.aes_gcm.icv_len = aes_gcm->icv_len * 8; + accel_attrs.keymat.aes_gcm.iv_algo = MLX5_ACCEL_ESP_AES_GCM_IV_ALGO_SEQ; + accel_attrs.keymat_type = MLX5_ACCEL_ESP_KEYMAT_AES_GCM; + + accel_attrs.esn = attr->esn; + if (attr->flags & IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED) + accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED; + if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW) + accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP; + + if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ENCRYPT) + accel_attrs.action |= MLX5_ACCEL_ESP_ACTION_ENCRYPT; + + action->esp_aes_gcm.ctx = + mlx5_accel_esp_create_xfrm(mdev->mdev, &accel_attrs, flags); + if (IS_ERR(action->esp_aes_gcm.ctx)) { + err = PTR_ERR(action->esp_aes_gcm.ctx); + goto err_parse; + } + + action->esp_aes_gcm.ib_flags = attr->flags; + + return &action->ib_action; + +err_parse: + kfree(action); + return ERR_PTR(err); +} + +static int +mlx5_ib_modify_flow_action_esp(struct ib_flow_action *action, + const struct ib_flow_action_attrs_esp *attr, + struct uverbs_attr_bundle *attrs) +{ + struct mlx5_ib_flow_action *maction = to_mflow_act(action); + struct mlx5_accel_esp_xfrm_attrs accel_attrs; + int err = 0; + + if (attr->keymat || attr->replay || attr->encap || + attr->spi || attr->seq || attr->tfc_pad || + attr->hard_limit_pkts || + (attr->flags & ~(IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED | + IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS | + IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW))) + return -EOPNOTSUPP; + + /* Only the ESN value or the MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP can + * be modified. + */ + if (!(maction->esp_aes_gcm.ib_flags & + IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED) && + attr->flags & (IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED | + IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW)) + return -EINVAL; + + memcpy(&accel_attrs, &maction->esp_aes_gcm.ctx->attrs, + sizeof(accel_attrs)); + + accel_attrs.esn = attr->esn; + if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW) + accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP; + else + accel_attrs.flags &= ~MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP; + + err = mlx5_accel_esp_modify_xfrm(maction->esp_aes_gcm.ctx, + &accel_attrs); + if (err) + return err; + + maction->esp_aes_gcm.ib_flags &= + ~IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW; + maction->esp_aes_gcm.ib_flags |= + attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW; + + return 0; +} + +static void destroy_flow_action_raw(struct mlx5_ib_flow_action *maction) +{ + switch (maction->flow_action_raw.sub_type) { + case MLX5_IB_FLOW_ACTION_MODIFY_HEADER: + mlx5_modify_header_dealloc(maction->flow_action_raw.dev->mdev, + maction->flow_action_raw.modify_hdr); + break; + case MLX5_IB_FLOW_ACTION_PACKET_REFORMAT: + mlx5_packet_reformat_dealloc(maction->flow_action_raw.dev->mdev, + maction->flow_action_raw.pkt_reformat); + break; + case MLX5_IB_FLOW_ACTION_DECAP: + break; + default: + break; + } +} + +static int mlx5_ib_destroy_flow_action(struct ib_flow_action *action) +{ + struct mlx5_ib_flow_action *maction = to_mflow_act(action); + + switch (action->type) { + case IB_FLOW_ACTION_ESP: + /* + * We only support aes_gcm by now, so we implicitly know this is + * the underline crypto. + */ + mlx5_accel_esp_destroy_xfrm(maction->esp_aes_gcm.ctx); + break; + case IB_FLOW_ACTION_UNSPECIFIED: + destroy_flow_action_raw(maction); + break; + default: + WARN_ON(true); + break; + } + + kfree(maction); + return 0; +} + +static int +mlx5_ib_ft_type_to_namespace(enum mlx5_ib_uapi_flow_table_type table_type, + enum mlx5_flow_namespace_type *namespace) +{ + switch (table_type) { + case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX: + *namespace = MLX5_FLOW_NAMESPACE_BYPASS; + break; + case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX: + *namespace = MLX5_FLOW_NAMESPACE_EGRESS; + break; + case MLX5_IB_UAPI_FLOW_TABLE_TYPE_FDB: + *namespace = MLX5_FLOW_NAMESPACE_FDB; + break; + case MLX5_IB_UAPI_FLOW_TABLE_TYPE_RDMA_RX: + *namespace = MLX5_FLOW_NAMESPACE_RDMA_RX; + break; + case MLX5_IB_UAPI_FLOW_TABLE_TYPE_RDMA_TX: + *namespace = MLX5_FLOW_NAMESPACE_RDMA_TX; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct uverbs_attr_spec mlx5_ib_flow_type[] = { + [MLX5_IB_FLOW_TYPE_NORMAL] = { + .type = UVERBS_ATTR_TYPE_PTR_IN, + .u.ptr = { + .len = sizeof(u16), /* data is priority */ + .min_len = sizeof(u16), + } + }, + [MLX5_IB_FLOW_TYPE_SNIFFER] = { + .type = UVERBS_ATTR_TYPE_PTR_IN, + UVERBS_ATTR_NO_DATA(), + }, + [MLX5_IB_FLOW_TYPE_ALL_DEFAULT] = { + .type = UVERBS_ATTR_TYPE_PTR_IN, + UVERBS_ATTR_NO_DATA(), + }, + [MLX5_IB_FLOW_TYPE_MC_DEFAULT] = { + .type = UVERBS_ATTR_TYPE_PTR_IN, + UVERBS_ATTR_NO_DATA(), + }, +}; + +static bool is_flow_dest(void *obj, int *dest_id, int *dest_type) +{ + struct devx_obj *devx_obj = obj; + u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode); + + switch (opcode) { + case MLX5_CMD_OP_DESTROY_TIR: + *dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR; + *dest_id = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, + obj_id); + return true; + + case MLX5_CMD_OP_DESTROY_FLOW_TABLE: + *dest_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + *dest_id = MLX5_GET(destroy_flow_table_in, devx_obj->dinbox, + table_id); + return true; + default: + return false; + } +} + +static int get_dests(struct uverbs_attr_bundle *attrs, + struct mlx5_ib_flow_matcher *fs_matcher, int *dest_id, + int *dest_type, struct ib_qp **qp, u32 *flags) +{ + bool dest_devx, dest_qp; + void *devx_obj; + int err; + + dest_devx = uverbs_attr_is_valid(attrs, + MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX); + dest_qp = uverbs_attr_is_valid(attrs, + MLX5_IB_ATTR_CREATE_FLOW_DEST_QP); + + *flags = 0; + err = uverbs_get_flags32(flags, attrs, MLX5_IB_ATTR_CREATE_FLOW_FLAGS, + MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS | + MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP); + if (err) + return err; + + /* Both flags are not allowed */ + if (*flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS && + *flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP) + return -EINVAL; + + if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS) { + if (dest_devx && (dest_qp || *flags)) + return -EINVAL; + else if (dest_qp && *flags) + return -EINVAL; + } + + /* Allow only DEVX object, drop as dest for FDB */ + if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB && !(dest_devx || + (*flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP))) + return -EINVAL; + + /* Allow only DEVX object or QP as dest when inserting to RDMA_RX */ + if ((fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) && + ((!dest_devx && !dest_qp) || (dest_devx && dest_qp))) + return -EINVAL; + + *qp = NULL; + if (dest_devx) { + devx_obj = + uverbs_attr_get_obj(attrs, + MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX); + + /* Verify that the given DEVX object is a flow + * steering destination. + */ + if (!is_flow_dest(devx_obj, dest_id, dest_type)) + return -EINVAL; + /* Allow only flow table as dest when inserting to FDB or RDMA_RX */ + if ((fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB || + fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) && + *dest_type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) + return -EINVAL; + } else if (dest_qp) { + struct mlx5_ib_qp *mqp; + + *qp = uverbs_attr_get_obj(attrs, + MLX5_IB_ATTR_CREATE_FLOW_DEST_QP); + if (IS_ERR(*qp)) + return PTR_ERR(*qp); + + if ((*qp)->qp_type != IB_QPT_RAW_PACKET) + return -EINVAL; + + mqp = to_mqp(*qp); + if (mqp->is_rss) + *dest_id = mqp->rss_qp.tirn; + else + *dest_id = mqp->raw_packet_qp.rq.tirn; + *dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR; + } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS || + fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_TX) { + *dest_type = MLX5_FLOW_DESTINATION_TYPE_PORT; + } + + if (*dest_type == MLX5_FLOW_DESTINATION_TYPE_TIR && + (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS || + fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_TX)) + return -EINVAL; + + return 0; +} + +static bool is_flow_counter(void *obj, u32 offset, u32 *counter_id) +{ + struct devx_obj *devx_obj = obj; + u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode); + + if (opcode == MLX5_CMD_OP_DEALLOC_FLOW_COUNTER) { + + if (offset && offset >= devx_obj->flow_counter_bulk_size) + return false; + + *counter_id = MLX5_GET(dealloc_flow_counter_in, + devx_obj->dinbox, + flow_counter_id); + *counter_id += offset; + return true; + } + + return false; +} + +#define MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS 2 +static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)( + struct uverbs_attr_bundle *attrs) +{ + struct mlx5_flow_context flow_context = {.flow_tag = + MLX5_FS_DEFAULT_FLOW_TAG}; + u32 *offset_attr, offset = 0, counter_id = 0; + int dest_id, dest_type = -1, inlen, len, ret, i; + struct mlx5_ib_flow_handler *flow_handler; + struct mlx5_ib_flow_matcher *fs_matcher; + struct ib_uobject **arr_flow_actions; + struct ib_uflow_resources *uflow_res; + struct mlx5_flow_act flow_act = {}; + struct ib_qp *qp = NULL; + void *devx_obj, *cmd_in; + struct ib_uobject *uobj; + struct mlx5_ib_dev *dev; + u32 flags; + + if (!capable(CAP_NET_RAW)) + return -EPERM; + + fs_matcher = uverbs_attr_get_obj(attrs, + MLX5_IB_ATTR_CREATE_FLOW_MATCHER); + uobj = uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_CREATE_FLOW_HANDLE); + dev = mlx5_udata_to_mdev(&attrs->driver_udata); + + if (get_dests(attrs, fs_matcher, &dest_id, &dest_type, &qp, &flags)) + return -EINVAL; + + if (flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS) + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS; + + if (flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP) + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_DROP; + + len = uverbs_attr_get_uobjs_arr(attrs, + MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, &arr_flow_actions); + if (len) { + devx_obj = arr_flow_actions[0]->object; + + if (uverbs_attr_is_valid(attrs, + MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET)) { + + int num_offsets = uverbs_attr_ptr_get_array_size( + attrs, + MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET, + sizeof(u32)); + + if (num_offsets != 1) + return -EINVAL; + + offset_attr = uverbs_attr_get_alloced_ptr( + attrs, + MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET); + offset = *offset_attr; + } + + if (!is_flow_counter(devx_obj, offset, &counter_id)) + return -EINVAL; + + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; + } + + cmd_in = uverbs_attr_get_alloced_ptr( + attrs, MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE); + inlen = uverbs_attr_get_len(attrs, + MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE); + + uflow_res = flow_resources_alloc(MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS); + if (!uflow_res) + return -ENOMEM; + + len = uverbs_attr_get_uobjs_arr(attrs, + MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS, &arr_flow_actions); + for (i = 0; i < len; i++) { + struct mlx5_ib_flow_action *maction = + to_mflow_act(arr_flow_actions[i]->object); + + ret = parse_flow_flow_action(maction, false, &flow_act); + if (ret) + goto err_out; + flow_resources_add(uflow_res, IB_FLOW_SPEC_ACTION_HANDLE, + arr_flow_actions[i]->object); + } + + ret = uverbs_copy_from(&flow_context.flow_tag, attrs, + MLX5_IB_ATTR_CREATE_FLOW_TAG); + if (!ret) { + if (flow_context.flow_tag >= BIT(24)) { + ret = -EINVAL; + goto err_out; + } + flow_context.flags |= FLOW_CONTEXT_HAS_TAG; + } + + flow_handler = + raw_fs_rule_add(dev, fs_matcher, &flow_context, &flow_act, + counter_id, cmd_in, inlen, dest_id, dest_type); + if (IS_ERR(flow_handler)) { + ret = PTR_ERR(flow_handler); + goto err_out; + } + + ib_set_flow(uobj, &flow_handler->ibflow, qp, &dev->ib_dev, uflow_res); + + return 0; +err_out: + ib_uverbs_flow_resources_free(uflow_res); + return ret; +} + +static int flow_matcher_cleanup(struct ib_uobject *uobject, + enum rdma_remove_reason why, + struct uverbs_attr_bundle *attrs) +{ + struct mlx5_ib_flow_matcher *obj = uobject->object; + int ret; + + ret = ib_destroy_usecnt(&obj->usecnt, why, uobject); + if (ret) + return ret; + + kfree(obj); + return 0; +} + +static int mlx5_ib_matcher_ns(struct uverbs_attr_bundle *attrs, + struct mlx5_ib_flow_matcher *obj) +{ + enum mlx5_ib_uapi_flow_table_type ft_type = + MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX; + u32 flags; + int err; + + /* New users should use MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE and older + * users should switch to it. We leave this to not break userspace + */ + if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE) && + uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS)) + return -EINVAL; + + if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE)) { + err = uverbs_get_const(&ft_type, attrs, + MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE); + if (err) + return err; + + err = mlx5_ib_ft_type_to_namespace(ft_type, &obj->ns_type); + if (err) + return err; + + return 0; + } + + if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS)) { + err = uverbs_get_flags32(&flags, attrs, + MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS, + IB_FLOW_ATTR_FLAGS_EGRESS); + if (err) + return err; + + if (flags) { + mlx5_ib_ft_type_to_namespace( + MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX, + &obj->ns_type); + return 0; + } + } + + obj->ns_type = MLX5_FLOW_NAMESPACE_BYPASS; + + return 0; +} + +static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)( + struct uverbs_attr_bundle *attrs) +{ + struct ib_uobject *uobj = uverbs_attr_get_uobject( + attrs, MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE); + struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata); + struct mlx5_ib_flow_matcher *obj; + int err; + + obj = kzalloc(sizeof(struct mlx5_ib_flow_matcher), GFP_KERNEL); + if (!obj) + return -ENOMEM; + + obj->mask_len = uverbs_attr_get_len( + attrs, MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK); + err = uverbs_copy_from(&obj->matcher_mask, + attrs, + MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK); + if (err) + goto end; + + obj->flow_type = uverbs_attr_get_enum_id( + attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE); + + if (obj->flow_type == MLX5_IB_FLOW_TYPE_NORMAL) { + err = uverbs_copy_from(&obj->priority, + attrs, + MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE); + if (err) + goto end; + } + + err = uverbs_copy_from(&obj->match_criteria_enable, + attrs, + MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA); + if (err) + goto end; + + err = mlx5_ib_matcher_ns(attrs, obj); + if (err) + goto end; + + uobj->object = obj; + obj->mdev = dev->mdev; + atomic_set(&obj->usecnt, 0); + return 0; + +end: + kfree(obj); + return err; +} + +static struct ib_flow_action * +mlx5_ib_create_modify_header(struct mlx5_ib_dev *dev, + enum mlx5_ib_uapi_flow_table_type ft_type, + u8 num_actions, void *in) +{ + enum mlx5_flow_namespace_type namespace; + struct mlx5_ib_flow_action *maction; + int ret; + + ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace); + if (ret) + return ERR_PTR(-EINVAL); + + maction = kzalloc(sizeof(*maction), GFP_KERNEL); + if (!maction) + return ERR_PTR(-ENOMEM); + + maction->flow_action_raw.modify_hdr = + mlx5_modify_header_alloc(dev->mdev, namespace, num_actions, in); + + if (IS_ERR(maction->flow_action_raw.modify_hdr)) { + ret = PTR_ERR(maction->flow_action_raw.modify_hdr); + kfree(maction); + return ERR_PTR(ret); + } + maction->flow_action_raw.sub_type = + MLX5_IB_FLOW_ACTION_MODIFY_HEADER; + maction->flow_action_raw.dev = dev; + + return &maction->ib_action; +} + +static bool mlx5_ib_modify_header_supported(struct mlx5_ib_dev *dev) +{ + return MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, + max_modify_header_actions) || + MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, + max_modify_header_actions) || + MLX5_CAP_FLOWTABLE_RDMA_TX(dev->mdev, + max_modify_header_actions); +} + +static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)( + struct uverbs_attr_bundle *attrs) +{ + struct ib_uobject *uobj = uverbs_attr_get_uobject( + attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE); + struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata); + enum mlx5_ib_uapi_flow_table_type ft_type; + struct ib_flow_action *action; + int num_actions; + void *in; + int ret; + + if (!mlx5_ib_modify_header_supported(mdev)) + return -EOPNOTSUPP; + + in = uverbs_attr_get_alloced_ptr(attrs, + MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM); + + num_actions = uverbs_attr_ptr_get_array_size( + attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM, + MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)); + if (num_actions < 0) + return num_actions; + + ret = uverbs_get_const(&ft_type, attrs, + MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE); + if (ret) + return ret; + action = mlx5_ib_create_modify_header(mdev, ft_type, num_actions, in); + if (IS_ERR(action)) + return PTR_ERR(action); + + uverbs_flow_action_fill_action(action, uobj, &mdev->ib_dev, + IB_FLOW_ACTION_UNSPECIFIED); + + return 0; +} + +static bool mlx5_ib_flow_action_packet_reformat_valid(struct mlx5_ib_dev *ibdev, + u8 packet_reformat_type, + u8 ft_type) +{ + switch (packet_reformat_type) { + case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL: + if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX) + return MLX5_CAP_FLOWTABLE(ibdev->mdev, + encap_general_header); + break; + case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL: + if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX) + return MLX5_CAP_FLOWTABLE_NIC_TX(ibdev->mdev, + reformat_l2_to_l3_tunnel); + break; + case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2: + if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX) + return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev, + reformat_l3_tunnel_to_l2); + break; + case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2: + if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX) + return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev, decap); + break; + default: + break; + } + + return false; +} + +static int mlx5_ib_dv_to_prm_packet_reforamt_type(u8 dv_prt, u8 *prm_prt) +{ + switch (dv_prt) { + case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL: + *prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL; + break; + case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2: + *prm_prt = MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2; + break; + case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL: + *prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int mlx5_ib_flow_action_create_packet_reformat_ctx( + struct mlx5_ib_dev *dev, + struct mlx5_ib_flow_action *maction, + u8 ft_type, u8 dv_prt, + void *in, size_t len) +{ + enum mlx5_flow_namespace_type namespace; + u8 prm_prt; + int ret; + + ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace); + if (ret) + return ret; + + ret = mlx5_ib_dv_to_prm_packet_reforamt_type(dv_prt, &prm_prt); + if (ret) + return ret; + + maction->flow_action_raw.pkt_reformat = + mlx5_packet_reformat_alloc(dev->mdev, prm_prt, len, + in, namespace); + if (IS_ERR(maction->flow_action_raw.pkt_reformat)) { + ret = PTR_ERR(maction->flow_action_raw.pkt_reformat); + return ret; + } + + maction->flow_action_raw.sub_type = + MLX5_IB_FLOW_ACTION_PACKET_REFORMAT; + maction->flow_action_raw.dev = dev; + + return 0; +} + +static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT)( + struct uverbs_attr_bundle *attrs) +{ + struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, + MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE); + struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata); + enum mlx5_ib_uapi_flow_action_packet_reformat_type dv_prt; + enum mlx5_ib_uapi_flow_table_type ft_type; + struct mlx5_ib_flow_action *maction; + int ret; + + ret = uverbs_get_const(&ft_type, attrs, + MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE); + if (ret) + return ret; + + ret = uverbs_get_const(&dv_prt, attrs, + MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE); + if (ret) + return ret; + + if (!mlx5_ib_flow_action_packet_reformat_valid(mdev, dv_prt, ft_type)) + return -EOPNOTSUPP; + + maction = kzalloc(sizeof(*maction), GFP_KERNEL); + if (!maction) + return -ENOMEM; + + if (dv_prt == + MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2) { + maction->flow_action_raw.sub_type = + MLX5_IB_FLOW_ACTION_DECAP; + maction->flow_action_raw.dev = mdev; + } else { + void *in; + int len; + + in = uverbs_attr_get_alloced_ptr(attrs, + MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF); + if (IS_ERR(in)) { + ret = PTR_ERR(in); + goto free_maction; + } + + len = uverbs_attr_get_len(attrs, + MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF); + + ret = mlx5_ib_flow_action_create_packet_reformat_ctx(mdev, + maction, ft_type, dv_prt, in, len); + if (ret) + goto free_maction; + } + + uverbs_flow_action_fill_action(&maction->ib_action, uobj, &mdev->ib_dev, + IB_FLOW_ACTION_UNSPECIFIED); + return 0; + +free_maction: + kfree(maction); + return ret; +} + +DECLARE_UVERBS_NAMED_METHOD( + MLX5_IB_METHOD_CREATE_FLOW, + UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE, + UVERBS_OBJECT_FLOW, + UVERBS_ACCESS_NEW, + UA_MANDATORY), + UVERBS_ATTR_PTR_IN( + MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE, + UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)), + UA_MANDATORY, + UA_ALLOC_AND_COPY), + UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_MATCHER, + MLX5_IB_OBJECT_FLOW_MATCHER, + UVERBS_ACCESS_READ, + UA_MANDATORY), + UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_QP, + UVERBS_OBJECT_QP, + UVERBS_ACCESS_READ), + UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX, + MLX5_IB_OBJECT_DEVX_OBJ, + UVERBS_ACCESS_READ), + UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS, + UVERBS_OBJECT_FLOW_ACTION, + UVERBS_ACCESS_READ, 1, + MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS, + UA_OPTIONAL), + UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_TAG, + UVERBS_ATTR_TYPE(u32), + UA_OPTIONAL), + UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, + MLX5_IB_OBJECT_DEVX_OBJ, + UVERBS_ACCESS_READ, 1, 1, + UA_OPTIONAL), + UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET, + UVERBS_ATTR_MIN_SIZE(sizeof(u32)), + UA_OPTIONAL, + UA_ALLOC_AND_COPY), + UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_CREATE_FLOW_FLAGS, + enum mlx5_ib_create_flow_flags, + UA_OPTIONAL)); + +DECLARE_UVERBS_NAMED_METHOD_DESTROY( + MLX5_IB_METHOD_DESTROY_FLOW, + UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE, + UVERBS_OBJECT_FLOW, + UVERBS_ACCESS_DESTROY, + UA_MANDATORY)); + +ADD_UVERBS_METHODS(mlx5_ib_fs, + UVERBS_OBJECT_FLOW, + &UVERBS_METHOD(MLX5_IB_METHOD_CREATE_FLOW), + &UVERBS_METHOD(MLX5_IB_METHOD_DESTROY_FLOW)); + +DECLARE_UVERBS_NAMED_METHOD( + MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER, + UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE, + UVERBS_OBJECT_FLOW_ACTION, + UVERBS_ACCESS_NEW, + UA_MANDATORY), + UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM, + UVERBS_ATTR_MIN_SIZE(MLX5_UN_SZ_BYTES( + set_add_copy_action_in_auto)), + UA_MANDATORY, + UA_ALLOC_AND_COPY), + UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE, + enum mlx5_ib_uapi_flow_table_type, + UA_MANDATORY)); + +DECLARE_UVERBS_NAMED_METHOD( + MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT, + UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE, + UVERBS_OBJECT_FLOW_ACTION, + UVERBS_ACCESS_NEW, + UA_MANDATORY), + UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF, + UVERBS_ATTR_MIN_SIZE(1), + UA_ALLOC_AND_COPY, + UA_OPTIONAL), + UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE, + enum mlx5_ib_uapi_flow_action_packet_reformat_type, + UA_MANDATORY), + UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE, + enum mlx5_ib_uapi_flow_table_type, + UA_MANDATORY)); + +ADD_UVERBS_METHODS( + mlx5_ib_flow_actions, + UVERBS_OBJECT_FLOW_ACTION, + &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER), + &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT)); + +DECLARE_UVERBS_NAMED_METHOD( + MLX5_IB_METHOD_FLOW_MATCHER_CREATE, + UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE, + MLX5_IB_OBJECT_FLOW_MATCHER, + UVERBS_ACCESS_NEW, + UA_MANDATORY), + UVERBS_ATTR_PTR_IN( + MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK, + UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)), + UA_MANDATORY), + UVERBS_ATTR_ENUM_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE, + mlx5_ib_flow_type, + UA_MANDATORY), + UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA, + UVERBS_ATTR_TYPE(u8), + UA_MANDATORY), + UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS, + enum ib_flow_flags, + UA_OPTIONAL), + UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE, + enum mlx5_ib_uapi_flow_table_type, + UA_OPTIONAL)); + +DECLARE_UVERBS_NAMED_METHOD_DESTROY( + MLX5_IB_METHOD_FLOW_MATCHER_DESTROY, + UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_DESTROY_HANDLE, + MLX5_IB_OBJECT_FLOW_MATCHER, + UVERBS_ACCESS_DESTROY, + UA_MANDATORY)); + +DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER, + UVERBS_TYPE_ALLOC_IDR(flow_matcher_cleanup), + &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_CREATE), + &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_DESTROY)); + +const struct uapi_definition mlx5_ib_flow_defs[] = { + UAPI_DEF_CHAIN_OBJ_TREE_NAMED( + MLX5_IB_OBJECT_FLOW_MATCHER), + UAPI_DEF_CHAIN_OBJ_TREE( + UVERBS_OBJECT_FLOW, + &mlx5_ib_fs), + UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION, + &mlx5_ib_flow_actions), + {}, +}; + +static const struct ib_device_ops flow_ops = { + .create_flow = mlx5_ib_create_flow, + .destroy_flow = mlx5_ib_destroy_flow, + .destroy_flow_action = mlx5_ib_destroy_flow_action, +}; + +static const struct ib_device_ops flow_ipsec_ops = { + .create_flow_action_esp = mlx5_ib_create_flow_action_esp, + .modify_flow_action_esp = mlx5_ib_modify_flow_action_esp, +}; + +int mlx5_ib_fs_init(struct mlx5_ib_dev *dev) +{ + dev->flow_db = kzalloc(sizeof(*dev->flow_db), GFP_KERNEL); + + if (!dev->flow_db) + return -ENOMEM; + + mutex_init(&dev->flow_db->lock); + + ib_set_device_ops(&dev->ib_dev, &flow_ops); + if (mlx5_accel_ipsec_device_caps(dev->mdev) & + MLX5_ACCEL_IPSEC_CAP_DEVICE) + ib_set_device_ops(&dev->ib_dev, &flow_ipsec_ops); + + return 0; +} diff --git a/drivers/infiniband/hw/mlx5/fs.h b/drivers/infiniband/hw/mlx5/fs.h new file mode 100644 index 0000000000000000000000000000000000000000..ad320adaf32172e50a67401ac33eec9441b3be5a --- /dev/null +++ b/drivers/infiniband/hw/mlx5/fs.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* + * Copyright (c) 2013-2020, Mellanox Technologies inc. All rights reserved. + */ + +#ifndef _MLX5_IB_FS_H +#define _MLX5_IB_FS_H + +#include "mlx5_ib.h" + +#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS) +int mlx5_ib_fs_init(struct mlx5_ib_dev *dev); +#else +static inline int mlx5_ib_fs_init(struct mlx5_ib_dev *dev) +{ + dev->flow_db = kzalloc(sizeof(*dev->flow_db), GFP_KERNEL); + + if (!dev->flow_db) + return -ENOMEM; + + mutex_init(&dev->flow_db->lock); + return 0; +} +#endif +static inline void mlx5_ib_fs_cleanup(struct mlx5_ib_dev *dev) +{ + kfree(dev->flow_db); +} +#endif /* _MLX5_IB_FS_H */ diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 6f99ed03d88e74c25c62f50ee54325b943f0789c..fbc45a5e76c5c6f6a55021938fcaa76f7e521c64 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -1,33 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB /* - * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * Copyright (c) 2013-2020, Mellanox Technologies inc. All rights reserved. */ #include @@ -59,10 +32,13 @@ #include "mlx5_ib.h" #include "ib_rep.h" #include "cmd.h" +#include "devx.h" +#include "fs.h" #include "srq.h" #include "qp.h" #include "wr.h" -#include +#include "restrack.h" +#include "counters.h" #include #include #include @@ -311,9 +287,6 @@ struct mlx5_core_dev *mlx5_ib_get_native_port_mdev(struct mlx5_ib_dev *ibdev, *native_port_num = 1; port = &ibdev->port[ib_port_num - 1]; - if (!port) - return NULL; - spin_lock(&port->mp.mpi_lock); mpi = ibdev->port[ib_port_num - 1].mp.mpi; if (mpi && !mpi->unaffiliate) { @@ -1765,6 +1738,92 @@ static void mlx5_ib_dealloc_transport_domain(struct mlx5_ib_dev *dev, u32 tdn, mlx5_ib_disable_lb(dev, true, false); } +static int set_ucontext_resp(struct ib_ucontext *uctx, + struct mlx5_ib_alloc_ucontext_resp *resp) +{ + struct ib_device *ibdev = uctx->device; + struct mlx5_ib_dev *dev = to_mdev(ibdev); + struct mlx5_ib_ucontext *context = to_mucontext(uctx); + struct mlx5_bfreg_info *bfregi = &context->bfregi; + int err; + + if (MLX5_CAP_GEN(dev->mdev, dump_fill_mkey)) { + err = mlx5_cmd_dump_fill_mkey(dev->mdev, + &resp->dump_fill_mkey); + if (err) + return err; + resp->comp_mask |= + MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_DUMP_FILL_MKEY; + } + + resp->qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp); + if (dev->wc_support) + resp->bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, + log_bf_reg_size); + resp->cache_line_size = cache_line_size(); + resp->max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq); + resp->max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq); + resp->max_send_wqebb = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz); + resp->max_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz); + resp->max_srq_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz); + resp->cqe_version = context->cqe_version; + resp->log_uar_size = MLX5_CAP_GEN(dev->mdev, uar_4k) ? + MLX5_ADAPTER_PAGE_SHIFT : PAGE_SHIFT; + resp->num_uars_per_page = MLX5_CAP_GEN(dev->mdev, uar_4k) ? + MLX5_CAP_GEN(dev->mdev, + num_of_uars_per_page) : 1; + + if (mlx5_accel_ipsec_device_caps(dev->mdev) & + MLX5_ACCEL_IPSEC_CAP_DEVICE) { + if (mlx5_get_flow_namespace(dev->mdev, + MLX5_FLOW_NAMESPACE_EGRESS)) + resp->flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM; + if (mlx5_accel_ipsec_device_caps(dev->mdev) & + MLX5_ACCEL_IPSEC_CAP_REQUIRED_METADATA) + resp->flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_REQ_METADATA; + if (MLX5_CAP_FLOWTABLE(dev->mdev, flow_table_properties_nic_receive.ft_field_support.outer_esp_spi)) + resp->flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_SPI_STEERING; + if (mlx5_accel_ipsec_device_caps(dev->mdev) & + MLX5_ACCEL_IPSEC_CAP_TX_IV_IS_ESN) + resp->flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_TX_IV_IS_ESN; + /* MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_FULL_OFFLOAD is currently always 0 */ + } + + resp->tot_bfregs = bfregi->lib_uar_dyn ? 0 : + bfregi->total_num_bfregs - bfregi->num_dyn_bfregs; + resp->num_ports = dev->num_ports; + resp->cmds_supp_uhw |= MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE | + MLX5_USER_CMDS_SUPP_UHW_CREATE_AH; + + if (mlx5_ib_port_link_layer(ibdev, 1) == IB_LINK_LAYER_ETHERNET) { + mlx5_query_min_inline(dev->mdev, &resp->eth_min_inline); + resp->eth_min_inline++; + } + + if (dev->mdev->clock_info) + resp->clock_info_versions = BIT(MLX5_IB_CLOCK_INFO_V1); + + /* + * We don't want to expose information from the PCI bar that is located + * after 4096 bytes, so if the arch only supports larger pages, let's + * pretend we don't support reading the HCA's core clock. This is also + * forced by mmap function. + */ + if (PAGE_SIZE <= 4096) { + resp->comp_mask |= + MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET; + resp->hca_core_clock_offset = + offsetof(struct mlx5_init_seg, + internal_timer_h) % PAGE_SIZE; + } + + if (MLX5_CAP_GEN(dev->mdev, ece_support)) + resp->comp_mask |= MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_ECE; + + resp->num_dyn_bfregs = bfregi->num_dyn_bfregs; + return 0; +} + static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata) { @@ -1772,14 +1831,12 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx, struct mlx5_ib_dev *dev = to_mdev(ibdev); struct mlx5_ib_alloc_ucontext_req_v2 req = {}; struct mlx5_ib_alloc_ucontext_resp resp = {}; - struct mlx5_core_dev *mdev = dev->mdev; struct mlx5_ib_ucontext *context = to_mucontext(uctx); struct mlx5_bfreg_info *bfregi; int ver; int err; size_t min_req_v2 = offsetof(struct mlx5_ib_alloc_ucontext_req_v2, max_cqe_version); - u32 dump_fill_mkey; bool lib_uar_4k; bool lib_uar_dyn; @@ -1808,37 +1865,6 @@ static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx, if (req.num_low_latency_bfregs > req.total_num_bfregs - 1) return -EINVAL; - resp.qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp); - if (dev->wc_support) - resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size); - resp.cache_line_size = cache_line_size(); - resp.max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq); - resp.max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq); - resp.max_send_wqebb = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz); - resp.max_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz); - resp.max_srq_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz); - resp.cqe_version = min_t(__u8, - (__u8)MLX5_CAP_GEN(dev->mdev, cqe_version), - req.max_cqe_version); - resp.log_uar_size = MLX5_CAP_GEN(dev->mdev, uar_4k) ? - MLX5_ADAPTER_PAGE_SHIFT : PAGE_SHIFT; - resp.num_uars_per_page = MLX5_CAP_GEN(dev->mdev, uar_4k) ? - MLX5_CAP_GEN(dev->mdev, num_of_uars_per_page) : 1; - resp.response_length = min(offsetof(typeof(resp), response_length) + - sizeof(resp.response_length), udata->outlen); - - if (mlx5_accel_ipsec_device_caps(dev->mdev) & MLX5_ACCEL_IPSEC_CAP_DEVICE) { - if (mlx5_get_flow_namespace(dev->mdev, MLX5_FLOW_NAMESPACE_EGRESS)) - resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM; - if (mlx5_accel_ipsec_device_caps(dev->mdev) & MLX5_ACCEL_IPSEC_CAP_REQUIRED_METADATA) - resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_REQ_METADATA; - if (MLX5_CAP_FLOWTABLE(dev->mdev, flow_table_properties_nic_receive.ft_field_support.outer_esp_spi)) - resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_SPI_STEERING; - if (mlx5_accel_ipsec_device_caps(dev->mdev) & MLX5_ACCEL_IPSEC_CAP_TX_IV_IS_ESN) - resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_TX_IV_IS_ESN; - /* MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_FULL_OFFLOAD is currently always 0 */ - } - lib_uar_4k = req.lib_caps & MLX5_LIB_CAP_4K_UAR; lib_uar_dyn = req.lib_caps & MLX5_LIB_CAP_DYN_UAR; bfregi = &context->bfregi; @@ -1887,87 +1913,24 @@ uar_done: if (err) goto out_devx; - if (MLX5_CAP_GEN(dev->mdev, dump_fill_mkey)) { - err = mlx5_cmd_dump_fill_mkey(dev->mdev, &dump_fill_mkey); - if (err) - goto out_mdev; - } - INIT_LIST_HEAD(&context->db_page_list); mutex_init(&context->db_page_mutex); - resp.tot_bfregs = lib_uar_dyn ? 0 : req.total_num_bfregs; - resp.num_ports = dev->num_ports; - - if (offsetofend(typeof(resp), cqe_version) <= udata->outlen) - resp.response_length += sizeof(resp.cqe_version); - - if (offsetofend(typeof(resp), cmds_supp_uhw) <= udata->outlen) { - resp.cmds_supp_uhw |= MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE | - MLX5_USER_CMDS_SUPP_UHW_CREATE_AH; - resp.response_length += sizeof(resp.cmds_supp_uhw); - } - - if (offsetofend(typeof(resp), eth_min_inline) <= udata->outlen) { - if (mlx5_ib_port_link_layer(ibdev, 1) == IB_LINK_LAYER_ETHERNET) { - mlx5_query_min_inline(dev->mdev, &resp.eth_min_inline); - resp.eth_min_inline++; - } - resp.response_length += sizeof(resp.eth_min_inline); - } - - if (offsetofend(typeof(resp), clock_info_versions) <= udata->outlen) { - if (mdev->clock_info) - resp.clock_info_versions = BIT(MLX5_IB_CLOCK_INFO_V1); - resp.response_length += sizeof(resp.clock_info_versions); - } - - /* - * We don't want to expose information from the PCI bar that is located - * after 4096 bytes, so if the arch only supports larger pages, let's - * pretend we don't support reading the HCA's core clock. This is also - * forced by mmap function. - */ - if (offsetofend(typeof(resp), hca_core_clock_offset) <= udata->outlen) { - if (PAGE_SIZE <= 4096) { - resp.comp_mask |= - MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET; - resp.hca_core_clock_offset = - offsetof(struct mlx5_init_seg, internal_timer_h) % PAGE_SIZE; - } - resp.response_length += sizeof(resp.hca_core_clock_offset); - } - - if (offsetofend(typeof(resp), log_uar_size) <= udata->outlen) - resp.response_length += sizeof(resp.log_uar_size); - - if (offsetofend(typeof(resp), num_uars_per_page) <= udata->outlen) - resp.response_length += sizeof(resp.num_uars_per_page); - - if (offsetofend(typeof(resp), num_dyn_bfregs) <= udata->outlen) { - resp.num_dyn_bfregs = bfregi->num_dyn_bfregs; - resp.response_length += sizeof(resp.num_dyn_bfregs); - } - - if (offsetofend(typeof(resp), dump_fill_mkey) <= udata->outlen) { - if (MLX5_CAP_GEN(dev->mdev, dump_fill_mkey)) { - resp.dump_fill_mkey = dump_fill_mkey; - resp.comp_mask |= - MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_DUMP_FILL_MKEY; - } - resp.response_length += sizeof(resp.dump_fill_mkey); - } + context->cqe_version = min_t(__u8, + (__u8)MLX5_CAP_GEN(dev->mdev, cqe_version), + req.max_cqe_version); - if (MLX5_CAP_GEN(dev->mdev, ece_support)) - resp.comp_mask |= MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_ECE; + err = set_ucontext_resp(uctx, &resp); + if (err) + goto out_mdev; + resp.response_length = min(udata->outlen, sizeof(resp)); err = ib_copy_to_udata(udata, &resp, resp.response_length); if (err) goto out_mdev; bfregi->ver = ver; bfregi->num_low_latency_bfregs = req.num_low_latency_bfregs; - context->cqe_version = resp.cqe_version; context->lib_caps = req.lib_caps; print_lib_caps(dev, context->lib_caps); @@ -2000,6 +1963,29 @@ out_ctx: return err; } +static int mlx5_ib_query_ucontext(struct ib_ucontext *ibcontext, + struct uverbs_attr_bundle *attrs) +{ + struct mlx5_ib_alloc_ucontext_resp uctx_resp = {}; + int ret; + + ret = set_ucontext_resp(ibcontext, &uctx_resp); + if (ret) + return ret; + + uctx_resp.response_length = + min_t(size_t, + uverbs_attr_get_len(attrs, + MLX5_IB_ATTR_QUERY_CONTEXT_RESP_UCTX), + sizeof(uctx_resp)); + + ret = uverbs_copy_to_struct_or_zero(attrs, + MLX5_IB_ATTR_QUERY_CONTEXT_RESP_UCTX, + &uctx_resp, + sizeof(uctx_resp)); + return ret; +} + static void mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext) { struct mlx5_ib_ucontext *context = to_mucontext(ibcontext); @@ -2591,3205 +2577,786 @@ static void mlx5_ib_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata) mlx5_cmd_dealloc_pd(mdev->mdev, mpd->pdn, mpd->uid); } -enum { - MATCH_CRITERIA_ENABLE_OUTER_BIT, - MATCH_CRITERIA_ENABLE_MISC_BIT, - MATCH_CRITERIA_ENABLE_INNER_BIT, - MATCH_CRITERIA_ENABLE_MISC2_BIT -}; - -#define HEADER_IS_ZERO(match_criteria, headers) \ - !(memchr_inv(MLX5_ADDR_OF(fte_match_param, match_criteria, headers), \ - 0, MLX5_FLD_SZ_BYTES(fte_match_param, headers))) \ - -static u8 get_match_criteria_enable(u32 *match_criteria) +static int mlx5_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) { - u8 match_criteria_enable; - - match_criteria_enable = - (!HEADER_IS_ZERO(match_criteria, outer_headers)) << - MATCH_CRITERIA_ENABLE_OUTER_BIT; - match_criteria_enable |= - (!HEADER_IS_ZERO(match_criteria, misc_parameters)) << - MATCH_CRITERIA_ENABLE_MISC_BIT; - match_criteria_enable |= - (!HEADER_IS_ZERO(match_criteria, inner_headers)) << - MATCH_CRITERIA_ENABLE_INNER_BIT; - match_criteria_enable |= - (!HEADER_IS_ZERO(match_criteria, misc_parameters_2)) << - MATCH_CRITERIA_ENABLE_MISC2_BIT; + struct mlx5_ib_dev *dev = to_mdev(ibqp->device); + struct mlx5_ib_qp *mqp = to_mqp(ibqp); + int err; + u16 uid; - return match_criteria_enable; -} + uid = ibqp->pd ? + to_mpd(ibqp->pd)->uid : 0; -static int set_proto(void *outer_c, void *outer_v, u8 mask, u8 val) -{ - u8 entry_mask; - u8 entry_val; - int err = 0; + if (mqp->flags & IB_QP_CREATE_SOURCE_QPN) { + mlx5_ib_dbg(dev, "Attaching a multi cast group to underlay QP is not supported\n"); + return -EOPNOTSUPP; + } - if (!mask) - goto out; + err = mlx5_cmd_attach_mcg(dev->mdev, gid, ibqp->qp_num, uid); + if (err) + mlx5_ib_warn(dev, "failed attaching QPN 0x%x, MGID %pI6\n", + ibqp->qp_num, gid->raw); - entry_mask = MLX5_GET(fte_match_set_lyr_2_4, outer_c, - ip_protocol); - entry_val = MLX5_GET(fte_match_set_lyr_2_4, outer_v, - ip_protocol); - if (!entry_mask) { - MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_protocol, mask); - MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_protocol, val); - goto out; - } - /* Don't override existing ip protocol */ - if (mask != entry_mask || val != entry_val) - err = -EINVAL; -out: return err; } -static void set_flow_label(void *misc_c, void *misc_v, u32 mask, u32 val, - bool inner) +static int mlx5_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) { - if (inner) { - MLX5_SET(fte_match_set_misc, - misc_c, inner_ipv6_flow_label, mask); - MLX5_SET(fte_match_set_misc, - misc_v, inner_ipv6_flow_label, val); - } else { - MLX5_SET(fte_match_set_misc, - misc_c, outer_ipv6_flow_label, mask); - MLX5_SET(fte_match_set_misc, - misc_v, outer_ipv6_flow_label, val); - } -} + struct mlx5_ib_dev *dev = to_mdev(ibqp->device); + int err; + u16 uid; -static void set_tos(void *outer_c, void *outer_v, u8 mask, u8 val) -{ - MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_ecn, mask); - MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_ecn, val); - MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_dscp, mask >> 2); - MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_dscp, val >> 2); + uid = ibqp->pd ? + to_mpd(ibqp->pd)->uid : 0; + err = mlx5_cmd_detach_mcg(dev->mdev, gid, ibqp->qp_num, uid); + if (err) + mlx5_ib_warn(dev, "failed detaching QPN 0x%x, MGID %pI6\n", + ibqp->qp_num, gid->raw); + + return err; } -static int check_mpls_supp_fields(u32 field_support, const __be32 *set_mask) +static int init_node_data(struct mlx5_ib_dev *dev) { - if (MLX5_GET(fte_match_mpls, set_mask, mpls_label) && - !(field_support & MLX5_FIELD_SUPPORT_MPLS_LABEL)) - return -EOPNOTSUPP; - - if (MLX5_GET(fte_match_mpls, set_mask, mpls_exp) && - !(field_support & MLX5_FIELD_SUPPORT_MPLS_EXP)) - return -EOPNOTSUPP; - - if (MLX5_GET(fte_match_mpls, set_mask, mpls_s_bos) && - !(field_support & MLX5_FIELD_SUPPORT_MPLS_S_BOS)) - return -EOPNOTSUPP; + int err; - if (MLX5_GET(fte_match_mpls, set_mask, mpls_ttl) && - !(field_support & MLX5_FIELD_SUPPORT_MPLS_TTL)) - return -EOPNOTSUPP; + err = mlx5_query_node_desc(dev, dev->ib_dev.node_desc); + if (err) + return err; - return 0; -} + dev->mdev->rev_id = dev->mdev->pdev->revision; -#define LAST_ETH_FIELD vlan_tag -#define LAST_IB_FIELD sl -#define LAST_IPV4_FIELD tos -#define LAST_IPV6_FIELD traffic_class -#define LAST_TCP_UDP_FIELD src_port -#define LAST_TUNNEL_FIELD tunnel_id -#define LAST_FLOW_TAG_FIELD tag_id -#define LAST_DROP_FIELD size -#define LAST_COUNTERS_FIELD counters - -/* Field is the last supported field */ -#define FIELDS_NOT_SUPPORTED(filter, field)\ - memchr_inv((void *)&filter.field +\ - sizeof(filter.field), 0,\ - sizeof(filter) -\ - offsetof(typeof(filter), field) -\ - sizeof(filter.field)) - -int parse_flow_flow_action(struct mlx5_ib_flow_action *maction, - bool is_egress, - struct mlx5_flow_act *action) -{ - - switch (maction->ib_action.type) { - case IB_FLOW_ACTION_ESP: - if (action->action & (MLX5_FLOW_CONTEXT_ACTION_ENCRYPT | - MLX5_FLOW_CONTEXT_ACTION_DECRYPT)) - return -EINVAL; - /* Currently only AES_GCM keymat is supported by the driver */ - action->esp_id = (uintptr_t)maction->esp_aes_gcm.ctx; - action->action |= is_egress ? - MLX5_FLOW_CONTEXT_ACTION_ENCRYPT : - MLX5_FLOW_CONTEXT_ACTION_DECRYPT; - return 0; - case IB_FLOW_ACTION_UNSPECIFIED: - if (maction->flow_action_raw.sub_type == - MLX5_IB_FLOW_ACTION_MODIFY_HEADER) { - if (action->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) - return -EINVAL; - action->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; - action->modify_hdr = - maction->flow_action_raw.modify_hdr; - return 0; - } - if (maction->flow_action_raw.sub_type == - MLX5_IB_FLOW_ACTION_DECAP) { - if (action->action & MLX5_FLOW_CONTEXT_ACTION_DECAP) - return -EINVAL; - action->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP; - return 0; - } - if (maction->flow_action_raw.sub_type == - MLX5_IB_FLOW_ACTION_PACKET_REFORMAT) { - if (action->action & - MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) - return -EINVAL; - action->action |= - MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; - action->pkt_reformat = - maction->flow_action_raw.pkt_reformat; - return 0; - } - /* fall through */ - default: - return -EOPNOTSUPP; - } + return mlx5_query_node_guid(dev, &dev->ib_dev.node_guid); } -static int parse_flow_attr(struct mlx5_core_dev *mdev, - struct mlx5_flow_spec *spec, - const union ib_flow_spec *ib_spec, - const struct ib_flow_attr *flow_attr, - struct mlx5_flow_act *action, u32 prev_type) -{ - struct mlx5_flow_context *flow_context = &spec->flow_context; - u32 *match_c = spec->match_criteria; - u32 *match_v = spec->match_value; - void *misc_params_c = MLX5_ADDR_OF(fte_match_param, match_c, - misc_parameters); - void *misc_params_v = MLX5_ADDR_OF(fte_match_param, match_v, - misc_parameters); - void *misc_params2_c = MLX5_ADDR_OF(fte_match_param, match_c, - misc_parameters_2); - void *misc_params2_v = MLX5_ADDR_OF(fte_match_param, match_v, - misc_parameters_2); - void *headers_c; - void *headers_v; - int match_ipv; - int ret; +static ssize_t fw_pages_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct mlx5_ib_dev *dev = + rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev); - if (ib_spec->type & IB_FLOW_SPEC_INNER) { - headers_c = MLX5_ADDR_OF(fte_match_param, match_c, - inner_headers); - headers_v = MLX5_ADDR_OF(fte_match_param, match_v, - inner_headers); - match_ipv = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, - ft_field_support.inner_ip_version); - } else { - headers_c = MLX5_ADDR_OF(fte_match_param, match_c, - outer_headers); - headers_v = MLX5_ADDR_OF(fte_match_param, match_v, - outer_headers); - match_ipv = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, - ft_field_support.outer_ip_version); - } + return sprintf(buf, "%d\n", dev->mdev->priv.fw_pages); +} +static DEVICE_ATTR_RO(fw_pages); - switch (ib_spec->type & ~IB_FLOW_SPEC_INNER) { - case IB_FLOW_SPEC_ETH: - if (FIELDS_NOT_SUPPORTED(ib_spec->eth.mask, LAST_ETH_FIELD)) - return -EOPNOTSUPP; +static ssize_t reg_pages_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct mlx5_ib_dev *dev = + rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev); - ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, - dmac_47_16), - ib_spec->eth.mask.dst_mac); - ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, - dmac_47_16), - ib_spec->eth.val.dst_mac); - - ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, - smac_47_16), - ib_spec->eth.mask.src_mac); - ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, - smac_47_16), - ib_spec->eth.val.src_mac); - - if (ib_spec->eth.mask.vlan_tag) { - MLX5_SET(fte_match_set_lyr_2_4, headers_c, - cvlan_tag, 1); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, - cvlan_tag, 1); - - MLX5_SET(fte_match_set_lyr_2_4, headers_c, - first_vid, ntohs(ib_spec->eth.mask.vlan_tag)); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, - first_vid, ntohs(ib_spec->eth.val.vlan_tag)); - - MLX5_SET(fte_match_set_lyr_2_4, headers_c, - first_cfi, - ntohs(ib_spec->eth.mask.vlan_tag) >> 12); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, - first_cfi, - ntohs(ib_spec->eth.val.vlan_tag) >> 12); - - MLX5_SET(fte_match_set_lyr_2_4, headers_c, - first_prio, - ntohs(ib_spec->eth.mask.vlan_tag) >> 13); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, - first_prio, - ntohs(ib_spec->eth.val.vlan_tag) >> 13); - } - MLX5_SET(fte_match_set_lyr_2_4, headers_c, - ethertype, ntohs(ib_spec->eth.mask.ether_type)); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, - ethertype, ntohs(ib_spec->eth.val.ether_type)); - break; - case IB_FLOW_SPEC_IPV4: - if (FIELDS_NOT_SUPPORTED(ib_spec->ipv4.mask, LAST_IPV4_FIELD)) - return -EOPNOTSUPP; + return sprintf(buf, "%d\n", atomic_read(&dev->mdev->priv.reg_pages)); +} +static DEVICE_ATTR_RO(reg_pages); - if (match_ipv) { - MLX5_SET(fte_match_set_lyr_2_4, headers_c, - ip_version, 0xf); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, - ip_version, MLX5_FS_IPV4_VERSION); - } else { - MLX5_SET(fte_match_set_lyr_2_4, headers_c, - ethertype, 0xffff); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, - ethertype, ETH_P_IP); - } +static ssize_t hca_type_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct mlx5_ib_dev *dev = + rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev); - memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, - src_ipv4_src_ipv6.ipv4_layout.ipv4), - &ib_spec->ipv4.mask.src_ip, - sizeof(ib_spec->ipv4.mask.src_ip)); - memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, - src_ipv4_src_ipv6.ipv4_layout.ipv4), - &ib_spec->ipv4.val.src_ip, - sizeof(ib_spec->ipv4.val.src_ip)); - memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, - dst_ipv4_dst_ipv6.ipv4_layout.ipv4), - &ib_spec->ipv4.mask.dst_ip, - sizeof(ib_spec->ipv4.mask.dst_ip)); - memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, - dst_ipv4_dst_ipv6.ipv4_layout.ipv4), - &ib_spec->ipv4.val.dst_ip, - sizeof(ib_spec->ipv4.val.dst_ip)); - - set_tos(headers_c, headers_v, - ib_spec->ipv4.mask.tos, ib_spec->ipv4.val.tos); - - if (set_proto(headers_c, headers_v, - ib_spec->ipv4.mask.proto, - ib_spec->ipv4.val.proto)) - return -EINVAL; - break; - case IB_FLOW_SPEC_IPV6: - if (FIELDS_NOT_SUPPORTED(ib_spec->ipv6.mask, LAST_IPV6_FIELD)) - return -EOPNOTSUPP; + return sprintf(buf, "MT%d\n", dev->mdev->pdev->device); +} +static DEVICE_ATTR_RO(hca_type); - if (match_ipv) { - MLX5_SET(fte_match_set_lyr_2_4, headers_c, - ip_version, 0xf); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, - ip_version, MLX5_FS_IPV6_VERSION); - } else { - MLX5_SET(fte_match_set_lyr_2_4, headers_c, - ethertype, 0xffff); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, - ethertype, ETH_P_IPV6); - } +static ssize_t hw_rev_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct mlx5_ib_dev *dev = + rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev); - memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, - src_ipv4_src_ipv6.ipv6_layout.ipv6), - &ib_spec->ipv6.mask.src_ip, - sizeof(ib_spec->ipv6.mask.src_ip)); - memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, - src_ipv4_src_ipv6.ipv6_layout.ipv6), - &ib_spec->ipv6.val.src_ip, - sizeof(ib_spec->ipv6.val.src_ip)); - memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, - dst_ipv4_dst_ipv6.ipv6_layout.ipv6), - &ib_spec->ipv6.mask.dst_ip, - sizeof(ib_spec->ipv6.mask.dst_ip)); - memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, - dst_ipv4_dst_ipv6.ipv6_layout.ipv6), - &ib_spec->ipv6.val.dst_ip, - sizeof(ib_spec->ipv6.val.dst_ip)); - - set_tos(headers_c, headers_v, - ib_spec->ipv6.mask.traffic_class, - ib_spec->ipv6.val.traffic_class); - - if (set_proto(headers_c, headers_v, - ib_spec->ipv6.mask.next_hdr, - ib_spec->ipv6.val.next_hdr)) - return -EINVAL; + return sprintf(buf, "%x\n", dev->mdev->rev_id); +} +static DEVICE_ATTR_RO(hw_rev); - set_flow_label(misc_params_c, misc_params_v, - ntohl(ib_spec->ipv6.mask.flow_label), - ntohl(ib_spec->ipv6.val.flow_label), - ib_spec->type & IB_FLOW_SPEC_INNER); - break; - case IB_FLOW_SPEC_ESP: - if (ib_spec->esp.mask.seq) - return -EOPNOTSUPP; +static ssize_t board_id_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct mlx5_ib_dev *dev = + rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev); - MLX5_SET(fte_match_set_misc, misc_params_c, outer_esp_spi, - ntohl(ib_spec->esp.mask.spi)); - MLX5_SET(fte_match_set_misc, misc_params_v, outer_esp_spi, - ntohl(ib_spec->esp.val.spi)); - break; - case IB_FLOW_SPEC_TCP: - if (FIELDS_NOT_SUPPORTED(ib_spec->tcp_udp.mask, - LAST_TCP_UDP_FIELD)) - return -EOPNOTSUPP; + return sprintf(buf, "%.*s\n", MLX5_BOARD_ID_LEN, + dev->mdev->board_id); +} +static DEVICE_ATTR_RO(board_id); - if (set_proto(headers_c, headers_v, 0xff, IPPROTO_TCP)) - return -EINVAL; +static struct attribute *mlx5_class_attributes[] = { + &dev_attr_hw_rev.attr, + &dev_attr_hca_type.attr, + &dev_attr_board_id.attr, + &dev_attr_fw_pages.attr, + &dev_attr_reg_pages.attr, + NULL, +}; - MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_sport, - ntohs(ib_spec->tcp_udp.mask.src_port)); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport, - ntohs(ib_spec->tcp_udp.val.src_port)); +static const struct attribute_group mlx5_attr_group = { + .attrs = mlx5_class_attributes, +}; - MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_dport, - ntohs(ib_spec->tcp_udp.mask.dst_port)); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport, - ntohs(ib_spec->tcp_udp.val.dst_port)); - break; - case IB_FLOW_SPEC_UDP: - if (FIELDS_NOT_SUPPORTED(ib_spec->tcp_udp.mask, - LAST_TCP_UDP_FIELD)) - return -EOPNOTSUPP; +static void pkey_change_handler(struct work_struct *work) +{ + struct mlx5_ib_port_resources *ports = + container_of(work, struct mlx5_ib_port_resources, + pkey_change_work); - if (set_proto(headers_c, headers_v, 0xff, IPPROTO_UDP)) - return -EINVAL; + mutex_lock(&ports->devr->mutex); + mlx5_ib_gsi_pkey_change(ports->gsi); + mutex_unlock(&ports->devr->mutex); +} - MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_sport, - ntohs(ib_spec->tcp_udp.mask.src_port)); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport, - ntohs(ib_spec->tcp_udp.val.src_port)); +static void mlx5_ib_handle_internal_error(struct mlx5_ib_dev *ibdev) +{ + struct mlx5_ib_qp *mqp; + struct mlx5_ib_cq *send_mcq, *recv_mcq; + struct mlx5_core_cq *mcq; + struct list_head cq_armed_list; + unsigned long flags_qp; + unsigned long flags_cq; + unsigned long flags; - MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_dport, - ntohs(ib_spec->tcp_udp.mask.dst_port)); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, - ntohs(ib_spec->tcp_udp.val.dst_port)); - break; - case IB_FLOW_SPEC_GRE: - if (ib_spec->gre.mask.c_ks_res0_ver) - return -EOPNOTSUPP; + INIT_LIST_HEAD(&cq_armed_list); - if (set_proto(headers_c, headers_v, 0xff, IPPROTO_GRE)) - return -EINVAL; - - MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol, - 0xff); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, - IPPROTO_GRE); - - MLX5_SET(fte_match_set_misc, misc_params_c, gre_protocol, - ntohs(ib_spec->gre.mask.protocol)); - MLX5_SET(fte_match_set_misc, misc_params_v, gre_protocol, - ntohs(ib_spec->gre.val.protocol)); - - memcpy(MLX5_ADDR_OF(fte_match_set_misc, misc_params_c, - gre_key.nvgre.hi), - &ib_spec->gre.mask.key, - sizeof(ib_spec->gre.mask.key)); - memcpy(MLX5_ADDR_OF(fte_match_set_misc, misc_params_v, - gre_key.nvgre.hi), - &ib_spec->gre.val.key, - sizeof(ib_spec->gre.val.key)); - break; - case IB_FLOW_SPEC_MPLS: - switch (prev_type) { - case IB_FLOW_SPEC_UDP: - if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev, - ft_field_support.outer_first_mpls_over_udp), - &ib_spec->mpls.mask.tag)) - return -EOPNOTSUPP; - - memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v, - outer_first_mpls_over_udp), - &ib_spec->mpls.val.tag, - sizeof(ib_spec->mpls.val.tag)); - memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c, - outer_first_mpls_over_udp), - &ib_spec->mpls.mask.tag, - sizeof(ib_spec->mpls.mask.tag)); - break; - case IB_FLOW_SPEC_GRE: - if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev, - ft_field_support.outer_first_mpls_over_gre), - &ib_spec->mpls.mask.tag)) - return -EOPNOTSUPP; - - memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v, - outer_first_mpls_over_gre), - &ib_spec->mpls.val.tag, - sizeof(ib_spec->mpls.val.tag)); - memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c, - outer_first_mpls_over_gre), - &ib_spec->mpls.mask.tag, - sizeof(ib_spec->mpls.mask.tag)); - break; - default: - if (ib_spec->type & IB_FLOW_SPEC_INNER) { - if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev, - ft_field_support.inner_first_mpls), - &ib_spec->mpls.mask.tag)) - return -EOPNOTSUPP; - - memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v, - inner_first_mpls), - &ib_spec->mpls.val.tag, - sizeof(ib_spec->mpls.val.tag)); - memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c, - inner_first_mpls), - &ib_spec->mpls.mask.tag, - sizeof(ib_spec->mpls.mask.tag)); - } else { - if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev, - ft_field_support.outer_first_mpls), - &ib_spec->mpls.mask.tag)) - return -EOPNOTSUPP; - - memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v, - outer_first_mpls), - &ib_spec->mpls.val.tag, - sizeof(ib_spec->mpls.val.tag)); - memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c, - outer_first_mpls), - &ib_spec->mpls.mask.tag, - sizeof(ib_spec->mpls.mask.tag)); + /* Go over qp list reside on that ibdev, sync with create/destroy qp.*/ + spin_lock_irqsave(&ibdev->reset_flow_resource_lock, flags); + list_for_each_entry(mqp, &ibdev->qp_list, qps_list) { + spin_lock_irqsave(&mqp->sq.lock, flags_qp); + if (mqp->sq.tail != mqp->sq.head) { + send_mcq = to_mcq(mqp->ibqp.send_cq); + spin_lock_irqsave(&send_mcq->lock, flags_cq); + if (send_mcq->mcq.comp && + mqp->ibqp.send_cq->comp_handler) { + if (!send_mcq->mcq.reset_notify_added) { + send_mcq->mcq.reset_notify_added = 1; + list_add_tail(&send_mcq->mcq.reset_notify, + &cq_armed_list); + } } + spin_unlock_irqrestore(&send_mcq->lock, flags_cq); } - break; - case IB_FLOW_SPEC_VXLAN_TUNNEL: - if (FIELDS_NOT_SUPPORTED(ib_spec->tunnel.mask, - LAST_TUNNEL_FIELD)) - return -EOPNOTSUPP; - - MLX5_SET(fte_match_set_misc, misc_params_c, vxlan_vni, - ntohl(ib_spec->tunnel.mask.tunnel_id)); - MLX5_SET(fte_match_set_misc, misc_params_v, vxlan_vni, - ntohl(ib_spec->tunnel.val.tunnel_id)); - break; - case IB_FLOW_SPEC_ACTION_TAG: - if (FIELDS_NOT_SUPPORTED(ib_spec->flow_tag, - LAST_FLOW_TAG_FIELD)) - return -EOPNOTSUPP; - if (ib_spec->flow_tag.tag_id >= BIT(24)) - return -EINVAL; - - flow_context->flow_tag = ib_spec->flow_tag.tag_id; - flow_context->flags |= FLOW_CONTEXT_HAS_TAG; - break; - case IB_FLOW_SPEC_ACTION_DROP: - if (FIELDS_NOT_SUPPORTED(ib_spec->drop, - LAST_DROP_FIELD)) - return -EOPNOTSUPP; - action->action |= MLX5_FLOW_CONTEXT_ACTION_DROP; - break; - case IB_FLOW_SPEC_ACTION_HANDLE: - ret = parse_flow_flow_action(to_mflow_act(ib_spec->action.act), - flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS, action); - if (ret) - return ret; - break; - case IB_FLOW_SPEC_ACTION_COUNT: - if (FIELDS_NOT_SUPPORTED(ib_spec->flow_count, - LAST_COUNTERS_FIELD)) - return -EOPNOTSUPP; - - /* for now support only one counters spec per flow */ - if (action->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) - return -EINVAL; - - action->counters = ib_spec->flow_count.counters; - action->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; - break; - default: - return -EINVAL; - } - - return 0; -} - -/* If a flow could catch both multicast and unicast packets, - * it won't fall into the multicast flow steering table and this rule - * could steal other multicast packets. - */ -static bool flow_is_multicast_only(const struct ib_flow_attr *ib_attr) -{ - union ib_flow_spec *flow_spec; - - if (ib_attr->type != IB_FLOW_ATTR_NORMAL || - ib_attr->num_of_specs < 1) - return false; - - flow_spec = (union ib_flow_spec *)(ib_attr + 1); - if (flow_spec->type == IB_FLOW_SPEC_IPV4) { - struct ib_flow_spec_ipv4 *ipv4_spec; - - ipv4_spec = (struct ib_flow_spec_ipv4 *)flow_spec; - if (ipv4_is_multicast(ipv4_spec->val.dst_ip)) - return true; - - return false; + spin_unlock_irqrestore(&mqp->sq.lock, flags_qp); + spin_lock_irqsave(&mqp->rq.lock, flags_qp); + /* no handling is needed for SRQ */ + if (!mqp->ibqp.srq) { + if (mqp->rq.tail != mqp->rq.head) { + recv_mcq = to_mcq(mqp->ibqp.recv_cq); + spin_lock_irqsave(&recv_mcq->lock, flags_cq); + if (recv_mcq->mcq.comp && + mqp->ibqp.recv_cq->comp_handler) { + if (!recv_mcq->mcq.reset_notify_added) { + recv_mcq->mcq.reset_notify_added = 1; + list_add_tail(&recv_mcq->mcq.reset_notify, + &cq_armed_list); + } + } + spin_unlock_irqrestore(&recv_mcq->lock, + flags_cq); + } + } + spin_unlock_irqrestore(&mqp->rq.lock, flags_qp); } - - if (flow_spec->type == IB_FLOW_SPEC_ETH) { - struct ib_flow_spec_eth *eth_spec; - - eth_spec = (struct ib_flow_spec_eth *)flow_spec; - return is_multicast_ether_addr(eth_spec->mask.dst_mac) && - is_multicast_ether_addr(eth_spec->val.dst_mac); + /*At that point all inflight post send were put to be executed as of we + * lock/unlock above locks Now need to arm all involved CQs. + */ + list_for_each_entry(mcq, &cq_armed_list, reset_notify) { + mcq->comp(mcq, NULL); } - - return false; + spin_unlock_irqrestore(&ibdev->reset_flow_resource_lock, flags); } -enum valid_spec { - VALID_SPEC_INVALID, - VALID_SPEC_VALID, - VALID_SPEC_NA, -}; - -static enum valid_spec -is_valid_esp_aes_gcm(struct mlx5_core_dev *mdev, - const struct mlx5_flow_spec *spec, - const struct mlx5_flow_act *flow_act, - bool egress) +static void delay_drop_handler(struct work_struct *work) { - const u32 *match_c = spec->match_criteria; - bool is_crypto = - (flow_act->action & (MLX5_FLOW_CONTEXT_ACTION_ENCRYPT | - MLX5_FLOW_CONTEXT_ACTION_DECRYPT)); - bool is_ipsec = mlx5_fs_is_ipsec_flow(match_c); - bool is_drop = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_DROP; - - /* - * Currently only crypto is supported in egress, when regular egress - * rules would be supported, always return VALID_SPEC_NA. - */ - if (!is_crypto) - return VALID_SPEC_NA; - - return is_crypto && is_ipsec && - (!egress || (!is_drop && - !(spec->flow_context.flags & FLOW_CONTEXT_HAS_TAG))) ? - VALID_SPEC_VALID : VALID_SPEC_INVALID; -} - -static bool is_valid_spec(struct mlx5_core_dev *mdev, - const struct mlx5_flow_spec *spec, - const struct mlx5_flow_act *flow_act, - bool egress) -{ - /* We curretly only support ipsec egress flow */ - return is_valid_esp_aes_gcm(mdev, spec, flow_act, egress) != VALID_SPEC_INVALID; -} - -static bool is_valid_ethertype(struct mlx5_core_dev *mdev, - const struct ib_flow_attr *flow_attr, - bool check_inner) -{ - union ib_flow_spec *ib_spec = (union ib_flow_spec *)(flow_attr + 1); - int match_ipv = check_inner ? - MLX5_CAP_FLOWTABLE_NIC_RX(mdev, - ft_field_support.inner_ip_version) : - MLX5_CAP_FLOWTABLE_NIC_RX(mdev, - ft_field_support.outer_ip_version); - int inner_bit = check_inner ? IB_FLOW_SPEC_INNER : 0; - bool ipv4_spec_valid, ipv6_spec_valid; - unsigned int ip_spec_type = 0; - bool has_ethertype = false; - unsigned int spec_index; - bool mask_valid = true; - u16 eth_type = 0; - bool type_valid; - - /* Validate that ethertype is correct */ - for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) { - if ((ib_spec->type == (IB_FLOW_SPEC_ETH | inner_bit)) && - ib_spec->eth.mask.ether_type) { - mask_valid = (ib_spec->eth.mask.ether_type == - htons(0xffff)); - has_ethertype = true; - eth_type = ntohs(ib_spec->eth.val.ether_type); - } else if ((ib_spec->type == (IB_FLOW_SPEC_IPV4 | inner_bit)) || - (ib_spec->type == (IB_FLOW_SPEC_IPV6 | inner_bit))) { - ip_spec_type = ib_spec->type; - } - ib_spec = (void *)ib_spec + ib_spec->size; - } + int err; + struct mlx5_ib_delay_drop *delay_drop = + container_of(work, struct mlx5_ib_delay_drop, + delay_drop_work); - type_valid = (!has_ethertype) || (!ip_spec_type); - if (!type_valid && mask_valid) { - ipv4_spec_valid = (eth_type == ETH_P_IP) && - (ip_spec_type == (IB_FLOW_SPEC_IPV4 | inner_bit)); - ipv6_spec_valid = (eth_type == ETH_P_IPV6) && - (ip_spec_type == (IB_FLOW_SPEC_IPV6 | inner_bit)); + atomic_inc(&delay_drop->events_cnt); - type_valid = (ipv4_spec_valid) || (ipv6_spec_valid) || - (((eth_type == ETH_P_MPLS_UC) || - (eth_type == ETH_P_MPLS_MC)) && match_ipv); + mutex_lock(&delay_drop->lock); + err = mlx5_core_set_delay_drop(delay_drop->dev, delay_drop->timeout); + if (err) { + mlx5_ib_warn(delay_drop->dev, "Failed to set delay drop, timeout=%u\n", + delay_drop->timeout); + delay_drop->activate = false; } - - return type_valid; + mutex_unlock(&delay_drop->lock); } -static bool is_valid_attr(struct mlx5_core_dev *mdev, - const struct ib_flow_attr *flow_attr) +static void handle_general_event(struct mlx5_ib_dev *ibdev, struct mlx5_eqe *eqe, + struct ib_event *ibev) { - return is_valid_ethertype(mdev, flow_attr, false) && - is_valid_ethertype(mdev, flow_attr, true); -} + u8 port = (eqe->data.port.port >> 4) & 0xf; -static void put_flow_table(struct mlx5_ib_dev *dev, - struct mlx5_ib_flow_prio *prio, bool ft_added) -{ - prio->refcount -= !!ft_added; - if (!prio->refcount) { - mlx5_destroy_flow_table(prio->flow_table); - prio->flow_table = NULL; + switch (eqe->sub_type) { + case MLX5_GENERAL_SUBTYPE_DELAY_DROP_TIMEOUT: + if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) == + IB_LINK_LAYER_ETHERNET) + schedule_work(&ibdev->delay_drop.delay_drop_work); + break; + default: /* do nothing */ + return; } } -static void counters_clear_description(struct ib_counters *counters) +static int handle_port_change(struct mlx5_ib_dev *ibdev, struct mlx5_eqe *eqe, + struct ib_event *ibev) { - struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); + u8 port = (eqe->data.port.port >> 4) & 0xf; - mutex_lock(&mcounters->mcntrs_mutex); - kfree(mcounters->counters_data); - mcounters->counters_data = NULL; - mcounters->cntrs_max_index = 0; - mutex_unlock(&mcounters->mcntrs_mutex); -} + ibev->element.port_num = port; -static int mlx5_ib_destroy_flow(struct ib_flow *flow_id) -{ - struct mlx5_ib_flow_handler *handler = container_of(flow_id, - struct mlx5_ib_flow_handler, - ibflow); - struct mlx5_ib_flow_handler *iter, *tmp; - struct mlx5_ib_dev *dev = handler->dev; + switch (eqe->sub_type) { + case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE: + case MLX5_PORT_CHANGE_SUBTYPE_DOWN: + case MLX5_PORT_CHANGE_SUBTYPE_INITIALIZED: + /* In RoCE, port up/down events are handled in + * mlx5_netdev_event(). + */ + if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) == + IB_LINK_LAYER_ETHERNET) + return -EINVAL; + + ibev->event = (eqe->sub_type == MLX5_PORT_CHANGE_SUBTYPE_ACTIVE) ? + IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; + break; - mutex_lock(&dev->flow_db->lock); + case MLX5_PORT_CHANGE_SUBTYPE_LID: + ibev->event = IB_EVENT_LID_CHANGE; + break; - list_for_each_entry_safe(iter, tmp, &handler->list, list) { - mlx5_del_flow_rules(iter->rule); - put_flow_table(dev, iter->prio, true); - list_del(&iter->list); - kfree(iter); - } + case MLX5_PORT_CHANGE_SUBTYPE_PKEY: + ibev->event = IB_EVENT_PKEY_CHANGE; + schedule_work(&ibdev->devr.ports[port - 1].pkey_change_work); + break; - mlx5_del_flow_rules(handler->rule); - put_flow_table(dev, handler->prio, true); - if (handler->ibcounters && - atomic_read(&handler->ibcounters->usecnt) == 1) - counters_clear_description(handler->ibcounters); + case MLX5_PORT_CHANGE_SUBTYPE_GUID: + ibev->event = IB_EVENT_GID_CHANGE; + break; - mutex_unlock(&dev->flow_db->lock); - if (handler->flow_matcher) - atomic_dec(&handler->flow_matcher->usecnt); - kfree(handler); + case MLX5_PORT_CHANGE_SUBTYPE_CLIENT_REREG: + ibev->event = IB_EVENT_CLIENT_REREGISTER; + break; + default: + return -EINVAL; + } return 0; } -static int ib_prio_to_core_prio(unsigned int priority, bool dont_trap) -{ - priority *= 2; - if (!dont_trap) - priority++; - return priority; -} - -enum flow_table_type { - MLX5_IB_FT_RX, - MLX5_IB_FT_TX -}; - -#define MLX5_FS_MAX_TYPES 6 -#define MLX5_FS_MAX_ENTRIES BIT(16) - -static struct mlx5_ib_flow_prio *_get_prio(struct mlx5_flow_namespace *ns, - struct mlx5_ib_flow_prio *prio, - int priority, - int num_entries, int num_groups, - u32 flags) +static void mlx5_ib_handle_event(struct work_struct *_work) { - struct mlx5_flow_table_attr ft_attr = {}; - struct mlx5_flow_table *ft; - - ft_attr.prio = priority; - ft_attr.max_fte = num_entries; - ft_attr.flags = flags; - ft_attr.autogroup.max_num_groups = num_groups; - ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); - if (IS_ERR(ft)) - return ERR_CAST(ft); - - prio->flow_table = ft; - prio->refcount = 0; - return prio; -} + struct mlx5_ib_event_work *work = + container_of(_work, struct mlx5_ib_event_work, work); + struct mlx5_ib_dev *ibdev; + struct ib_event ibev; + bool fatal = false; -static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev, - struct ib_flow_attr *flow_attr, - enum flow_table_type ft_type) -{ - bool dont_trap = flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP; - struct mlx5_flow_namespace *ns = NULL; - struct mlx5_ib_flow_prio *prio; - struct mlx5_flow_table *ft; - int max_table_size; - int num_entries; - int num_groups; - bool esw_encap; - u32 flags = 0; - int priority; - - max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, - log_max_ft_size)); - esw_encap = mlx5_eswitch_get_encap_mode(dev->mdev) != - DEVLINK_ESWITCH_ENCAP_MODE_NONE; - if (flow_attr->type == IB_FLOW_ATTR_NORMAL) { - enum mlx5_flow_namespace_type fn_type; - - if (flow_is_multicast_only(flow_attr) && - !dont_trap) - priority = MLX5_IB_FLOW_MCAST_PRIO; - else - priority = ib_prio_to_core_prio(flow_attr->priority, - dont_trap); - if (ft_type == MLX5_IB_FT_RX) { - fn_type = MLX5_FLOW_NAMESPACE_BYPASS; - prio = &dev->flow_db->prios[priority]; - if (!dev->is_rep && !esw_encap && - MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap)) - flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP; - if (!dev->is_rep && !esw_encap && - MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, - reformat_l3_tunnel_to_l2)) - flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; - } else { - max_table_size = - BIT(MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, - log_max_ft_size)); - fn_type = MLX5_FLOW_NAMESPACE_EGRESS; - prio = &dev->flow_db->egress_prios[priority]; - if (!dev->is_rep && !esw_encap && - MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, reformat)) - flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; - } - ns = mlx5_get_flow_namespace(dev->mdev, fn_type); - num_entries = MLX5_FS_MAX_ENTRIES; - num_groups = MLX5_FS_MAX_TYPES; - } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || - flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) { - ns = mlx5_get_flow_namespace(dev->mdev, - MLX5_FLOW_NAMESPACE_LEFTOVERS); - build_leftovers_ft_param(&priority, - &num_entries, - &num_groups); - prio = &dev->flow_db->prios[MLX5_IB_FLOW_LEFTOVERS_PRIO]; - } else if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) { - if (!MLX5_CAP_FLOWTABLE(dev->mdev, - allow_sniffer_and_nic_rx_shared_tir)) - return ERR_PTR(-ENOTSUPP); - - ns = mlx5_get_flow_namespace(dev->mdev, ft_type == MLX5_IB_FT_RX ? - MLX5_FLOW_NAMESPACE_SNIFFER_RX : - MLX5_FLOW_NAMESPACE_SNIFFER_TX); - - prio = &dev->flow_db->sniffer[ft_type]; - priority = 0; - num_entries = 1; - num_groups = 1; + if (work->is_slave) { + ibdev = mlx5_ib_get_ibdev_from_mpi(work->mpi); + if (!ibdev) + goto out; + } else { + ibdev = work->dev; } - if (!ns) - return ERR_PTR(-ENOTSUPP); - - max_table_size = min_t(int, num_entries, max_table_size); - - ft = prio->flow_table; - if (!ft) - return _get_prio(ns, prio, priority, max_table_size, num_groups, - flags); - - return prio; -} + switch (work->event) { + case MLX5_DEV_EVENT_SYS_ERROR: + ibev.event = IB_EVENT_DEVICE_FATAL; + mlx5_ib_handle_internal_error(ibdev); + ibev.element.port_num = (u8)(unsigned long)work->param; + fatal = true; + break; + case MLX5_EVENT_TYPE_PORT_CHANGE: + if (handle_port_change(ibdev, work->param, &ibev)) + goto out; + break; + case MLX5_EVENT_TYPE_GENERAL_EVENT: + handle_general_event(ibdev, work->param, &ibev); + /* fall through */ + default: + goto out; + } -static void set_underlay_qp(struct mlx5_ib_dev *dev, - struct mlx5_flow_spec *spec, - u32 underlay_qpn) -{ - void *misc_params_c = MLX5_ADDR_OF(fte_match_param, - spec->match_criteria, - misc_parameters); - void *misc_params_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, - misc_parameters); + ibev.device = &ibdev->ib_dev; - if (underlay_qpn && - MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, - ft_field_support.bth_dst_qp)) { - MLX5_SET(fte_match_set_misc, - misc_params_v, bth_dst_qp, underlay_qpn); - MLX5_SET(fte_match_set_misc, - misc_params_c, bth_dst_qp, 0xffffff); + if (!rdma_is_port_valid(&ibdev->ib_dev, ibev.element.port_num)) { + mlx5_ib_warn(ibdev, "warning: event on port %d\n", ibev.element.port_num); + goto out; } -} -static int read_flow_counters(struct ib_device *ibdev, - struct mlx5_read_counters_attr *read_attr) -{ - struct mlx5_fc *fc = read_attr->hw_cntrs_hndl; - struct mlx5_ib_dev *dev = to_mdev(ibdev); + if (ibdev->ib_active) + ib_dispatch_event(&ibev); - return mlx5_fc_query(dev->mdev, fc, - &read_attr->out[IB_COUNTER_PACKETS], - &read_attr->out[IB_COUNTER_BYTES]); + if (fatal) + ibdev->ib_active = false; +out: + kfree(work); } -/* flow counters currently expose two counters packets and bytes */ -#define FLOW_COUNTERS_NUM 2 -static int counters_set_description(struct ib_counters *counters, - enum mlx5_ib_counters_type counters_type, - struct mlx5_ib_flow_counters_desc *desc_data, - u32 ncounters) +static int mlx5_ib_event(struct notifier_block *nb, + unsigned long event, void *param) { - struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); - u32 cntrs_max_index = 0; - int i; - - if (counters_type != MLX5_IB_COUNTERS_FLOW) - return -EINVAL; + struct mlx5_ib_event_work *work; - /* init the fields for the object */ - mcounters->type = counters_type; - mcounters->read_counters = read_flow_counters; - mcounters->counters_num = FLOW_COUNTERS_NUM; - mcounters->ncounters = ncounters; - /* each counter entry have both description and index pair */ - for (i = 0; i < ncounters; i++) { - if (desc_data[i].description > IB_COUNTER_BYTES) - return -EINVAL; + work = kmalloc(sizeof(*work), GFP_ATOMIC); + if (!work) + return NOTIFY_DONE; - if (cntrs_max_index <= desc_data[i].index) - cntrs_max_index = desc_data[i].index + 1; - } + INIT_WORK(&work->work, mlx5_ib_handle_event); + work->dev = container_of(nb, struct mlx5_ib_dev, mdev_events); + work->is_slave = false; + work->param = param; + work->event = event; - mutex_lock(&mcounters->mcntrs_mutex); - mcounters->counters_data = desc_data; - mcounters->cntrs_max_index = cntrs_max_index; - mutex_unlock(&mcounters->mcntrs_mutex); + queue_work(mlx5_ib_event_wq, &work->work); - return 0; + return NOTIFY_OK; } -#define MAX_COUNTERS_NUM (USHRT_MAX / (sizeof(u32) * 2)) -static int flow_counters_set_data(struct ib_counters *ibcounters, - struct mlx5_ib_create_flow *ucmd) +static int mlx5_ib_event_slave_port(struct notifier_block *nb, + unsigned long event, void *param) { - struct mlx5_ib_mcounters *mcounters = to_mcounters(ibcounters); - struct mlx5_ib_flow_counters_data *cntrs_data = NULL; - struct mlx5_ib_flow_counters_desc *desc_data = NULL; - bool hw_hndl = false; - int ret = 0; - - if (ucmd && ucmd->ncounters_data != 0) { - cntrs_data = ucmd->data; - if (cntrs_data->ncounters > MAX_COUNTERS_NUM) - return -EINVAL; - - desc_data = kcalloc(cntrs_data->ncounters, - sizeof(*desc_data), - GFP_KERNEL); - if (!desc_data) - return -ENOMEM; - - if (copy_from_user(desc_data, - u64_to_user_ptr(cntrs_data->counters_data), - sizeof(*desc_data) * cntrs_data->ncounters)) { - ret = -EFAULT; - goto free; - } - } - - if (!mcounters->hw_cntrs_hndl) { - mcounters->hw_cntrs_hndl = mlx5_fc_create( - to_mdev(ibcounters->device)->mdev, false); - if (IS_ERR(mcounters->hw_cntrs_hndl)) { - ret = PTR_ERR(mcounters->hw_cntrs_hndl); - goto free; - } - hw_hndl = true; - } - - if (desc_data) { - /* counters already bound to at least one flow */ - if (mcounters->cntrs_max_index) { - ret = -EINVAL; - goto free_hndl; - } - - ret = counters_set_description(ibcounters, - MLX5_IB_COUNTERS_FLOW, - desc_data, - cntrs_data->ncounters); - if (ret) - goto free_hndl; - - } else if (!mcounters->cntrs_max_index) { - /* counters not bound yet, must have udata passed */ - ret = -EINVAL; - goto free_hndl; - } - - return 0; - -free_hndl: - if (hw_hndl) { - mlx5_fc_destroy(to_mdev(ibcounters->device)->mdev, - mcounters->hw_cntrs_hndl); - mcounters->hw_cntrs_hndl = NULL; - } -free: - kfree(desc_data); - return ret; -} - -static void mlx5_ib_set_rule_source_port(struct mlx5_ib_dev *dev, - struct mlx5_flow_spec *spec, - struct mlx5_eswitch_rep *rep) -{ - struct mlx5_eswitch *esw = dev->mdev->priv.eswitch; - void *misc; - - if (mlx5_eswitch_vport_match_metadata_enabled(esw)) { - misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, - misc_parameters_2); - - MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, - mlx5_eswitch_get_vport_metadata_for_match(esw, - rep->vport)); - misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, - misc_parameters_2); - - MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, - mlx5_eswitch_get_vport_metadata_mask()); - } else { - misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, - misc_parameters); - - MLX5_SET(fte_match_set_misc, misc, source_port, rep->vport); - - misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, - misc_parameters); - - MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); - } -} - -static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev, - struct mlx5_ib_flow_prio *ft_prio, - const struct ib_flow_attr *flow_attr, - struct mlx5_flow_destination *dst, - u32 underlay_qpn, - struct mlx5_ib_create_flow *ucmd) -{ - struct mlx5_flow_table *ft = ft_prio->flow_table; - struct mlx5_ib_flow_handler *handler; - struct mlx5_flow_act flow_act = {}; - struct mlx5_flow_spec *spec; - struct mlx5_flow_destination dest_arr[2] = {}; - struct mlx5_flow_destination *rule_dst = dest_arr; - const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr); - unsigned int spec_index; - u32 prev_type = 0; - int err = 0; - int dest_num = 0; - bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS; - - if (!is_valid_attr(dev->mdev, flow_attr)) - return ERR_PTR(-EINVAL); - - if (dev->is_rep && is_egress) - return ERR_PTR(-EINVAL); - - spec = kvzalloc(sizeof(*spec), GFP_KERNEL); - handler = kzalloc(sizeof(*handler), GFP_KERNEL); - if (!handler || !spec) { - err = -ENOMEM; - goto free; - } - - INIT_LIST_HEAD(&handler->list); - - for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) { - err = parse_flow_attr(dev->mdev, spec, - ib_flow, flow_attr, &flow_act, - prev_type); - if (err < 0) - goto free; - - prev_type = ((union ib_flow_spec *)ib_flow)->type; - ib_flow += ((union ib_flow_spec *)ib_flow)->size; - } - - if (dst && !(flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP)) { - memcpy(&dest_arr[0], dst, sizeof(*dst)); - dest_num++; - } - - if (!flow_is_multicast_only(flow_attr)) - set_underlay_qp(dev, spec, underlay_qpn); - - if (dev->is_rep) { - struct mlx5_eswitch_rep *rep; - - rep = dev->port[flow_attr->port - 1].rep; - if (!rep) { - err = -EINVAL; - goto free; - } - - mlx5_ib_set_rule_source_port(dev, spec, rep); - } - - spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria); - - if (is_egress && - !is_valid_spec(dev->mdev, spec, &flow_act, is_egress)) { - err = -EINVAL; - goto free; - } - - if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { - struct mlx5_ib_mcounters *mcounters; - - err = flow_counters_set_data(flow_act.counters, ucmd); - if (err) - goto free; - - mcounters = to_mcounters(flow_act.counters); - handler->ibcounters = flow_act.counters; - dest_arr[dest_num].type = - MLX5_FLOW_DESTINATION_TYPE_COUNTER; - dest_arr[dest_num].counter_id = - mlx5_fc_id(mcounters->hw_cntrs_hndl); - dest_num++; - } - - if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP) { - if (!dest_num) - rule_dst = NULL; - } else { - if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP) - flow_act.action |= - MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; - if (is_egress) - flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW; - else if (dest_num) - flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; - } - - if ((spec->flow_context.flags & FLOW_CONTEXT_HAS_TAG) && - (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || - flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) { - mlx5_ib_warn(dev, "Flow tag %u and attribute type %x isn't allowed in leftovers\n", - spec->flow_context.flow_tag, flow_attr->type); - err = -EINVAL; - goto free; - } - handler->rule = mlx5_add_flow_rules(ft, spec, - &flow_act, - rule_dst, dest_num); - - if (IS_ERR(handler->rule)) { - err = PTR_ERR(handler->rule); - goto free; - } - - ft_prio->refcount++; - handler->prio = ft_prio; - handler->dev = dev; - - ft_prio->flow_table = ft; -free: - if (err && handler) { - if (handler->ibcounters && - atomic_read(&handler->ibcounters->usecnt) == 1) - counters_clear_description(handler->ibcounters); - kfree(handler); - } - kvfree(spec); - return err ? ERR_PTR(err) : handler; -} - -static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev, - struct mlx5_ib_flow_prio *ft_prio, - const struct ib_flow_attr *flow_attr, - struct mlx5_flow_destination *dst) -{ - return _create_flow_rule(dev, ft_prio, flow_attr, dst, 0, NULL); -} - -enum { - LEFTOVERS_MC, - LEFTOVERS_UC, -}; - -static struct mlx5_ib_flow_handler *create_leftovers_rule(struct mlx5_ib_dev *dev, - struct mlx5_ib_flow_prio *ft_prio, - struct ib_flow_attr *flow_attr, - struct mlx5_flow_destination *dst) -{ - struct mlx5_ib_flow_handler *handler_ucast = NULL; - struct mlx5_ib_flow_handler *handler = NULL; - - static struct { - struct ib_flow_attr flow_attr; - struct ib_flow_spec_eth eth_flow; - } leftovers_specs[] = { - [LEFTOVERS_MC] = { - .flow_attr = { - .num_of_specs = 1, - .size = sizeof(leftovers_specs[0]) - }, - .eth_flow = { - .type = IB_FLOW_SPEC_ETH, - .size = sizeof(struct ib_flow_spec_eth), - .mask = {.dst_mac = {0x1} }, - .val = {.dst_mac = {0x1} } - } - }, - [LEFTOVERS_UC] = { - .flow_attr = { - .num_of_specs = 1, - .size = sizeof(leftovers_specs[0]) - }, - .eth_flow = { - .type = IB_FLOW_SPEC_ETH, - .size = sizeof(struct ib_flow_spec_eth), - .mask = {.dst_mac = {0x1} }, - .val = {.dst_mac = {} } - } - } - }; - - handler = create_flow_rule(dev, ft_prio, - &leftovers_specs[LEFTOVERS_MC].flow_attr, - dst); - if (!IS_ERR(handler) && - flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT) { - handler_ucast = create_flow_rule(dev, ft_prio, - &leftovers_specs[LEFTOVERS_UC].flow_attr, - dst); - if (IS_ERR(handler_ucast)) { - mlx5_del_flow_rules(handler->rule); - ft_prio->refcount--; - kfree(handler); - handler = handler_ucast; - } else { - list_add(&handler_ucast->list, &handler->list); - } - } - - return handler; -} - -static struct mlx5_ib_flow_handler *create_sniffer_rule(struct mlx5_ib_dev *dev, - struct mlx5_ib_flow_prio *ft_rx, - struct mlx5_ib_flow_prio *ft_tx, - struct mlx5_flow_destination *dst) -{ - struct mlx5_ib_flow_handler *handler_rx; - struct mlx5_ib_flow_handler *handler_tx; - int err; - static const struct ib_flow_attr flow_attr = { - .num_of_specs = 0, - .size = sizeof(flow_attr) - }; - - handler_rx = create_flow_rule(dev, ft_rx, &flow_attr, dst); - if (IS_ERR(handler_rx)) { - err = PTR_ERR(handler_rx); - goto err; - } - - handler_tx = create_flow_rule(dev, ft_tx, &flow_attr, dst); - if (IS_ERR(handler_tx)) { - err = PTR_ERR(handler_tx); - goto err_tx; - } - - list_add(&handler_tx->list, &handler_rx->list); - - return handler_rx; - -err_tx: - mlx5_del_flow_rules(handler_rx->rule); - ft_rx->refcount--; - kfree(handler_rx); -err: - return ERR_PTR(err); -} - -static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp, - struct ib_flow_attr *flow_attr, - int domain, - struct ib_udata *udata) -{ - struct mlx5_ib_dev *dev = to_mdev(qp->device); - struct mlx5_ib_qp *mqp = to_mqp(qp); - struct mlx5_ib_flow_handler *handler = NULL; - struct mlx5_flow_destination *dst = NULL; - struct mlx5_ib_flow_prio *ft_prio_tx = NULL; - struct mlx5_ib_flow_prio *ft_prio; - bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS; - struct mlx5_ib_create_flow *ucmd = NULL, ucmd_hdr; - size_t min_ucmd_sz, required_ucmd_sz; - int err; - int underlay_qpn; - - if (udata && udata->inlen) { - min_ucmd_sz = offsetof(typeof(ucmd_hdr), reserved) + - sizeof(ucmd_hdr.reserved); - if (udata->inlen < min_ucmd_sz) - return ERR_PTR(-EOPNOTSUPP); - - err = ib_copy_from_udata(&ucmd_hdr, udata, min_ucmd_sz); - if (err) - return ERR_PTR(err); - - /* currently supports only one counters data */ - if (ucmd_hdr.ncounters_data > 1) - return ERR_PTR(-EINVAL); - - required_ucmd_sz = min_ucmd_sz + - sizeof(struct mlx5_ib_flow_counters_data) * - ucmd_hdr.ncounters_data; - if (udata->inlen > required_ucmd_sz && - !ib_is_udata_cleared(udata, required_ucmd_sz, - udata->inlen - required_ucmd_sz)) - return ERR_PTR(-EOPNOTSUPP); - - ucmd = kzalloc(required_ucmd_sz, GFP_KERNEL); - if (!ucmd) - return ERR_PTR(-ENOMEM); - - err = ib_copy_from_udata(ucmd, udata, required_ucmd_sz); - if (err) - goto free_ucmd; - } - - if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO) { - err = -ENOMEM; - goto free_ucmd; - } - - if (domain != IB_FLOW_DOMAIN_USER || - flow_attr->port > dev->num_ports || - (flow_attr->flags & ~(IB_FLOW_ATTR_FLAGS_DONT_TRAP | - IB_FLOW_ATTR_FLAGS_EGRESS))) { - err = -EINVAL; - goto free_ucmd; - } - - if (is_egress && - (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || - flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) { - err = -EINVAL; - goto free_ucmd; - } - - dst = kzalloc(sizeof(*dst), GFP_KERNEL); - if (!dst) { - err = -ENOMEM; - goto free_ucmd; - } - - mutex_lock(&dev->flow_db->lock); - - ft_prio = get_flow_table(dev, flow_attr, - is_egress ? MLX5_IB_FT_TX : MLX5_IB_FT_RX); - if (IS_ERR(ft_prio)) { - err = PTR_ERR(ft_prio); - goto unlock; - } - if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) { - ft_prio_tx = get_flow_table(dev, flow_attr, MLX5_IB_FT_TX); - if (IS_ERR(ft_prio_tx)) { - err = PTR_ERR(ft_prio_tx); - ft_prio_tx = NULL; - goto destroy_ft; - } - } - - if (is_egress) { - dst->type = MLX5_FLOW_DESTINATION_TYPE_PORT; - } else { - dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR; - if (mqp->is_rss) - dst->tir_num = mqp->rss_qp.tirn; - else - dst->tir_num = mqp->raw_packet_qp.rq.tirn; - } - - if (flow_attr->type == IB_FLOW_ATTR_NORMAL) { - underlay_qpn = (mqp->flags & IB_QP_CREATE_SOURCE_QPN) ? - mqp->underlay_qpn : - 0; - handler = _create_flow_rule(dev, ft_prio, flow_attr, dst, - underlay_qpn, ucmd); - } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || - flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) { - handler = create_leftovers_rule(dev, ft_prio, flow_attr, - dst); - } else if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) { - handler = create_sniffer_rule(dev, ft_prio, ft_prio_tx, dst); - } else { - err = -EINVAL; - goto destroy_ft; - } - - if (IS_ERR(handler)) { - err = PTR_ERR(handler); - handler = NULL; - goto destroy_ft; - } - - mutex_unlock(&dev->flow_db->lock); - kfree(dst); - kfree(ucmd); - - return &handler->ibflow; - -destroy_ft: - put_flow_table(dev, ft_prio, false); - if (ft_prio_tx) - put_flow_table(dev, ft_prio_tx, false); -unlock: - mutex_unlock(&dev->flow_db->lock); - kfree(dst); -free_ucmd: - kfree(ucmd); - return ERR_PTR(err); -} - -static struct mlx5_ib_flow_prio * -_get_flow_table(struct mlx5_ib_dev *dev, - struct mlx5_ib_flow_matcher *fs_matcher, - bool mcast) -{ - struct mlx5_flow_namespace *ns = NULL; - struct mlx5_ib_flow_prio *prio = NULL; - int max_table_size = 0; - bool esw_encap; - u32 flags = 0; - int priority; - - if (mcast) - priority = MLX5_IB_FLOW_MCAST_PRIO; - else - priority = ib_prio_to_core_prio(fs_matcher->priority, false); - - esw_encap = mlx5_eswitch_get_encap_mode(dev->mdev) != - DEVLINK_ESWITCH_ENCAP_MODE_NONE; - if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS) { - max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, - log_max_ft_size)); - if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap) && !esw_encap) - flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP; - if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, - reformat_l3_tunnel_to_l2) && - !esw_encap) - flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; - } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS) { - max_table_size = BIT( - MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, log_max_ft_size)); - if (MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, reformat) && !esw_encap) - flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; - } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB) { - max_table_size = BIT( - MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev, log_max_ft_size)); - if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev, decap) && esw_encap) - flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP; - if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev, reformat_l3_tunnel_to_l2) && - esw_encap) - flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; - priority = FDB_BYPASS_PATH; - } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) { - max_table_size = - BIT(MLX5_CAP_FLOWTABLE_RDMA_RX(dev->mdev, - log_max_ft_size)); - priority = fs_matcher->priority; - } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_TX) { - max_table_size = - BIT(MLX5_CAP_FLOWTABLE_RDMA_TX(dev->mdev, - log_max_ft_size)); - priority = fs_matcher->priority; - } - - max_table_size = min_t(int, max_table_size, MLX5_FS_MAX_ENTRIES); - - ns = mlx5_get_flow_namespace(dev->mdev, fs_matcher->ns_type); - if (!ns) - return ERR_PTR(-ENOTSUPP); - - if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS) - prio = &dev->flow_db->prios[priority]; - else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS) - prio = &dev->flow_db->egress_prios[priority]; - else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB) - prio = &dev->flow_db->fdb; - else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) - prio = &dev->flow_db->rdma_rx[priority]; - else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_TX) - prio = &dev->flow_db->rdma_tx[priority]; - - if (!prio) - return ERR_PTR(-EINVAL); - - if (prio->flow_table) - return prio; - - return _get_prio(ns, prio, priority, max_table_size, - MLX5_FS_MAX_TYPES, flags); -} - -static struct mlx5_ib_flow_handler * -_create_raw_flow_rule(struct mlx5_ib_dev *dev, - struct mlx5_ib_flow_prio *ft_prio, - struct mlx5_flow_destination *dst, - struct mlx5_ib_flow_matcher *fs_matcher, - struct mlx5_flow_context *flow_context, - struct mlx5_flow_act *flow_act, - void *cmd_in, int inlen, - int dst_num) -{ - struct mlx5_ib_flow_handler *handler; - struct mlx5_flow_spec *spec; - struct mlx5_flow_table *ft = ft_prio->flow_table; - int err = 0; - - spec = kvzalloc(sizeof(*spec), GFP_KERNEL); - handler = kzalloc(sizeof(*handler), GFP_KERNEL); - if (!handler || !spec) { - err = -ENOMEM; - goto free; - } - - INIT_LIST_HEAD(&handler->list); - - memcpy(spec->match_value, cmd_in, inlen); - memcpy(spec->match_criteria, fs_matcher->matcher_mask.match_params, - fs_matcher->mask_len); - spec->match_criteria_enable = fs_matcher->match_criteria_enable; - spec->flow_context = *flow_context; - - handler->rule = mlx5_add_flow_rules(ft, spec, - flow_act, dst, dst_num); - - if (IS_ERR(handler->rule)) { - err = PTR_ERR(handler->rule); - goto free; - } - - ft_prio->refcount++; - handler->prio = ft_prio; - handler->dev = dev; - ft_prio->flow_table = ft; - -free: - if (err) - kfree(handler); - kvfree(spec); - return err ? ERR_PTR(err) : handler; -} - -static bool raw_fs_is_multicast(struct mlx5_ib_flow_matcher *fs_matcher, - void *match_v) -{ - void *match_c; - void *match_v_set_lyr_2_4, *match_c_set_lyr_2_4; - void *dmac, *dmac_mask; - void *ipv4, *ipv4_mask; - - if (!(fs_matcher->match_criteria_enable & - (1 << MATCH_CRITERIA_ENABLE_OUTER_BIT))) - return false; - - match_c = fs_matcher->matcher_mask.match_params; - match_v_set_lyr_2_4 = MLX5_ADDR_OF(fte_match_param, match_v, - outer_headers); - match_c_set_lyr_2_4 = MLX5_ADDR_OF(fte_match_param, match_c, - outer_headers); - - dmac = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_v_set_lyr_2_4, - dmac_47_16); - dmac_mask = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_c_set_lyr_2_4, - dmac_47_16); - - if (is_multicast_ether_addr(dmac) && - is_multicast_ether_addr(dmac_mask)) - return true; - - ipv4 = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_v_set_lyr_2_4, - dst_ipv4_dst_ipv6.ipv4_layout.ipv4); - - ipv4_mask = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_c_set_lyr_2_4, - dst_ipv4_dst_ipv6.ipv4_layout.ipv4); - - if (ipv4_is_multicast(*(__be32 *)(ipv4)) && - ipv4_is_multicast(*(__be32 *)(ipv4_mask))) - return true; - - return false; -} - -struct mlx5_ib_flow_handler * -mlx5_ib_raw_fs_rule_add(struct mlx5_ib_dev *dev, - struct mlx5_ib_flow_matcher *fs_matcher, - struct mlx5_flow_context *flow_context, - struct mlx5_flow_act *flow_act, - u32 counter_id, - void *cmd_in, int inlen, int dest_id, - int dest_type) -{ - struct mlx5_flow_destination *dst; - struct mlx5_ib_flow_prio *ft_prio; - struct mlx5_ib_flow_handler *handler; - int dst_num = 0; - bool mcast; - int err; - - if (fs_matcher->flow_type != MLX5_IB_FLOW_TYPE_NORMAL) - return ERR_PTR(-EOPNOTSUPP); - - if (fs_matcher->priority > MLX5_IB_FLOW_LAST_PRIO) - return ERR_PTR(-ENOMEM); - - dst = kcalloc(2, sizeof(*dst), GFP_KERNEL); - if (!dst) - return ERR_PTR(-ENOMEM); - - mcast = raw_fs_is_multicast(fs_matcher, cmd_in); - mutex_lock(&dev->flow_db->lock); - - ft_prio = _get_flow_table(dev, fs_matcher, mcast); - if (IS_ERR(ft_prio)) { - err = PTR_ERR(ft_prio); - goto unlock; - } - - if (dest_type == MLX5_FLOW_DESTINATION_TYPE_TIR) { - dst[dst_num].type = dest_type; - dst[dst_num++].tir_num = dest_id; - flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; - } else if (dest_type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) { - dst[dst_num].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM; - dst[dst_num++].ft_num = dest_id; - flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; - } else if (dest_type == MLX5_FLOW_DESTINATION_TYPE_PORT) { - dst[dst_num++].type = MLX5_FLOW_DESTINATION_TYPE_PORT; - flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW; - } - - - if (flow_act->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { - dst[dst_num].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; - dst[dst_num].counter_id = counter_id; - dst_num++; - } - - handler = _create_raw_flow_rule(dev, ft_prio, dst, fs_matcher, - flow_context, flow_act, - cmd_in, inlen, dst_num); - - if (IS_ERR(handler)) { - err = PTR_ERR(handler); - goto destroy_ft; - } - - mutex_unlock(&dev->flow_db->lock); - atomic_inc(&fs_matcher->usecnt); - handler->flow_matcher = fs_matcher; - - kfree(dst); - - return handler; - -destroy_ft: - put_flow_table(dev, ft_prio, false); -unlock: - mutex_unlock(&dev->flow_db->lock); - kfree(dst); - - return ERR_PTR(err); -} - -static u32 mlx5_ib_flow_action_flags_to_accel_xfrm_flags(u32 mlx5_flags) -{ - u32 flags = 0; - - if (mlx5_flags & MLX5_IB_UAPI_FLOW_ACTION_FLAGS_REQUIRE_METADATA) - flags |= MLX5_ACCEL_XFRM_FLAG_REQUIRE_METADATA; - - return flags; -} - -#define MLX5_FLOW_ACTION_ESP_CREATE_LAST_SUPPORTED MLX5_IB_UAPI_FLOW_ACTION_FLAGS_REQUIRE_METADATA -static struct ib_flow_action * -mlx5_ib_create_flow_action_esp(struct ib_device *device, - const struct ib_flow_action_attrs_esp *attr, - struct uverbs_attr_bundle *attrs) -{ - struct mlx5_ib_dev *mdev = to_mdev(device); - struct ib_uverbs_flow_action_esp_keymat_aes_gcm *aes_gcm; - struct mlx5_accel_esp_xfrm_attrs accel_attrs = {}; - struct mlx5_ib_flow_action *action; - u64 action_flags; - u64 flags; - int err = 0; - - err = uverbs_get_flags64( - &action_flags, attrs, MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS, - ((MLX5_FLOW_ACTION_ESP_CREATE_LAST_SUPPORTED << 1) - 1)); - if (err) - return ERR_PTR(err); - - flags = mlx5_ib_flow_action_flags_to_accel_xfrm_flags(action_flags); - - /* We current only support a subset of the standard features. Only a - * keymat of type AES_GCM, with icv_len == 16, iv_algo == SEQ and esn - * (with overlap). Full offload mode isn't supported. - */ - if (!attr->keymat || attr->replay || attr->encap || - attr->spi || attr->seq || attr->tfc_pad || - attr->hard_limit_pkts || - (attr->flags & ~(IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED | - IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ENCRYPT))) - return ERR_PTR(-EOPNOTSUPP); - - if (attr->keymat->protocol != - IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM) - return ERR_PTR(-EOPNOTSUPP); - - aes_gcm = &attr->keymat->keymat.aes_gcm; - - if (aes_gcm->icv_len != 16 || - aes_gcm->iv_algo != IB_UVERBS_FLOW_ACTION_IV_ALGO_SEQ) - return ERR_PTR(-EOPNOTSUPP); - - action = kmalloc(sizeof(*action), GFP_KERNEL); - if (!action) - return ERR_PTR(-ENOMEM); - - action->esp_aes_gcm.ib_flags = attr->flags; - memcpy(&accel_attrs.keymat.aes_gcm.aes_key, &aes_gcm->aes_key, - sizeof(accel_attrs.keymat.aes_gcm.aes_key)); - accel_attrs.keymat.aes_gcm.key_len = aes_gcm->key_len * 8; - memcpy(&accel_attrs.keymat.aes_gcm.salt, &aes_gcm->salt, - sizeof(accel_attrs.keymat.aes_gcm.salt)); - memcpy(&accel_attrs.keymat.aes_gcm.seq_iv, &aes_gcm->iv, - sizeof(accel_attrs.keymat.aes_gcm.seq_iv)); - accel_attrs.keymat.aes_gcm.icv_len = aes_gcm->icv_len * 8; - accel_attrs.keymat.aes_gcm.iv_algo = MLX5_ACCEL_ESP_AES_GCM_IV_ALGO_SEQ; - accel_attrs.keymat_type = MLX5_ACCEL_ESP_KEYMAT_AES_GCM; - - accel_attrs.esn = attr->esn; - if (attr->flags & IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED) - accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED; - if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW) - accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP; - - if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ENCRYPT) - accel_attrs.action |= MLX5_ACCEL_ESP_ACTION_ENCRYPT; - - action->esp_aes_gcm.ctx = - mlx5_accel_esp_create_xfrm(mdev->mdev, &accel_attrs, flags); - if (IS_ERR(action->esp_aes_gcm.ctx)) { - err = PTR_ERR(action->esp_aes_gcm.ctx); - goto err_parse; - } - - action->esp_aes_gcm.ib_flags = attr->flags; - - return &action->ib_action; - -err_parse: - kfree(action); - return ERR_PTR(err); -} - -static int -mlx5_ib_modify_flow_action_esp(struct ib_flow_action *action, - const struct ib_flow_action_attrs_esp *attr, - struct uverbs_attr_bundle *attrs) -{ - struct mlx5_ib_flow_action *maction = to_mflow_act(action); - struct mlx5_accel_esp_xfrm_attrs accel_attrs; - int err = 0; - - if (attr->keymat || attr->replay || attr->encap || - attr->spi || attr->seq || attr->tfc_pad || - attr->hard_limit_pkts || - (attr->flags & ~(IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED | - IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS | - IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW))) - return -EOPNOTSUPP; - - /* Only the ESN value or the MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP can - * be modified. - */ - if (!(maction->esp_aes_gcm.ib_flags & - IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED) && - attr->flags & (IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED | - IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW)) - return -EINVAL; - - memcpy(&accel_attrs, &maction->esp_aes_gcm.ctx->attrs, - sizeof(accel_attrs)); - - accel_attrs.esn = attr->esn; - if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW) - accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP; - else - accel_attrs.flags &= ~MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP; - - err = mlx5_accel_esp_modify_xfrm(maction->esp_aes_gcm.ctx, - &accel_attrs); - if (err) - return err; - - maction->esp_aes_gcm.ib_flags &= - ~IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW; - maction->esp_aes_gcm.ib_flags |= - attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW; - - return 0; -} - -static int mlx5_ib_destroy_flow_action(struct ib_flow_action *action) -{ - struct mlx5_ib_flow_action *maction = to_mflow_act(action); - - switch (action->type) { - case IB_FLOW_ACTION_ESP: - /* - * We only support aes_gcm by now, so we implicitly know this is - * the underline crypto. - */ - mlx5_accel_esp_destroy_xfrm(maction->esp_aes_gcm.ctx); - break; - case IB_FLOW_ACTION_UNSPECIFIED: - mlx5_ib_destroy_flow_action_raw(maction); - break; - default: - WARN_ON(true); - break; - } - - kfree(maction); - return 0; -} - -static int mlx5_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - struct mlx5_ib_dev *dev = to_mdev(ibqp->device); - struct mlx5_ib_qp *mqp = to_mqp(ibqp); - int err; - u16 uid; - - uid = ibqp->pd ? - to_mpd(ibqp->pd)->uid : 0; - - if (mqp->flags & IB_QP_CREATE_SOURCE_QPN) { - mlx5_ib_dbg(dev, "Attaching a multi cast group to underlay QP is not supported\n"); - return -EOPNOTSUPP; - } - - err = mlx5_cmd_attach_mcg(dev->mdev, gid, ibqp->qp_num, uid); - if (err) - mlx5_ib_warn(dev, "failed attaching QPN 0x%x, MGID %pI6\n", - ibqp->qp_num, gid->raw); - - return err; -} - -static int mlx5_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - struct mlx5_ib_dev *dev = to_mdev(ibqp->device); - int err; - u16 uid; - - uid = ibqp->pd ? - to_mpd(ibqp->pd)->uid : 0; - err = mlx5_cmd_detach_mcg(dev->mdev, gid, ibqp->qp_num, uid); - if (err) - mlx5_ib_warn(dev, "failed detaching QPN 0x%x, MGID %pI6\n", - ibqp->qp_num, gid->raw); - - return err; -} - -static int init_node_data(struct mlx5_ib_dev *dev) -{ - int err; - - err = mlx5_query_node_desc(dev, dev->ib_dev.node_desc); - if (err) - return err; - - dev->mdev->rev_id = dev->mdev->pdev->revision; - - return mlx5_query_node_guid(dev, &dev->ib_dev.node_guid); -} - -static ssize_t fw_pages_show(struct device *device, - struct device_attribute *attr, char *buf) -{ - struct mlx5_ib_dev *dev = - rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev); - - return sprintf(buf, "%d\n", dev->mdev->priv.fw_pages); -} -static DEVICE_ATTR_RO(fw_pages); - -static ssize_t reg_pages_show(struct device *device, - struct device_attribute *attr, char *buf) -{ - struct mlx5_ib_dev *dev = - rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev); - - return sprintf(buf, "%d\n", atomic_read(&dev->mdev->priv.reg_pages)); -} -static DEVICE_ATTR_RO(reg_pages); - -static ssize_t hca_type_show(struct device *device, - struct device_attribute *attr, char *buf) -{ - struct mlx5_ib_dev *dev = - rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev); - - return sprintf(buf, "MT%d\n", dev->mdev->pdev->device); -} -static DEVICE_ATTR_RO(hca_type); - -static ssize_t hw_rev_show(struct device *device, - struct device_attribute *attr, char *buf) -{ - struct mlx5_ib_dev *dev = - rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev); - - return sprintf(buf, "%x\n", dev->mdev->rev_id); -} -static DEVICE_ATTR_RO(hw_rev); - -static ssize_t board_id_show(struct device *device, - struct device_attribute *attr, char *buf) -{ - struct mlx5_ib_dev *dev = - rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev); - - return sprintf(buf, "%.*s\n", MLX5_BOARD_ID_LEN, - dev->mdev->board_id); -} -static DEVICE_ATTR_RO(board_id); - -static struct attribute *mlx5_class_attributes[] = { - &dev_attr_hw_rev.attr, - &dev_attr_hca_type.attr, - &dev_attr_board_id.attr, - &dev_attr_fw_pages.attr, - &dev_attr_reg_pages.attr, - NULL, -}; - -static const struct attribute_group mlx5_attr_group = { - .attrs = mlx5_class_attributes, -}; - -static void pkey_change_handler(struct work_struct *work) -{ - struct mlx5_ib_port_resources *ports = - container_of(work, struct mlx5_ib_port_resources, - pkey_change_work); - - mutex_lock(&ports->devr->mutex); - mlx5_ib_gsi_pkey_change(ports->gsi); - mutex_unlock(&ports->devr->mutex); -} - -static void mlx5_ib_handle_internal_error(struct mlx5_ib_dev *ibdev) -{ - struct mlx5_ib_qp *mqp; - struct mlx5_ib_cq *send_mcq, *recv_mcq; - struct mlx5_core_cq *mcq; - struct list_head cq_armed_list; - unsigned long flags_qp; - unsigned long flags_cq; - unsigned long flags; - - INIT_LIST_HEAD(&cq_armed_list); - - /* Go over qp list reside on that ibdev, sync with create/destroy qp.*/ - spin_lock_irqsave(&ibdev->reset_flow_resource_lock, flags); - list_for_each_entry(mqp, &ibdev->qp_list, qps_list) { - spin_lock_irqsave(&mqp->sq.lock, flags_qp); - if (mqp->sq.tail != mqp->sq.head) { - send_mcq = to_mcq(mqp->ibqp.send_cq); - spin_lock_irqsave(&send_mcq->lock, flags_cq); - if (send_mcq->mcq.comp && - mqp->ibqp.send_cq->comp_handler) { - if (!send_mcq->mcq.reset_notify_added) { - send_mcq->mcq.reset_notify_added = 1; - list_add_tail(&send_mcq->mcq.reset_notify, - &cq_armed_list); - } - } - spin_unlock_irqrestore(&send_mcq->lock, flags_cq); - } - spin_unlock_irqrestore(&mqp->sq.lock, flags_qp); - spin_lock_irqsave(&mqp->rq.lock, flags_qp); - /* no handling is needed for SRQ */ - if (!mqp->ibqp.srq) { - if (mqp->rq.tail != mqp->rq.head) { - recv_mcq = to_mcq(mqp->ibqp.recv_cq); - spin_lock_irqsave(&recv_mcq->lock, flags_cq); - if (recv_mcq->mcq.comp && - mqp->ibqp.recv_cq->comp_handler) { - if (!recv_mcq->mcq.reset_notify_added) { - recv_mcq->mcq.reset_notify_added = 1; - list_add_tail(&recv_mcq->mcq.reset_notify, - &cq_armed_list); - } - } - spin_unlock_irqrestore(&recv_mcq->lock, - flags_cq); - } - } - spin_unlock_irqrestore(&mqp->rq.lock, flags_qp); - } - /*At that point all inflight post send were put to be executed as of we - * lock/unlock above locks Now need to arm all involved CQs. - */ - list_for_each_entry(mcq, &cq_armed_list, reset_notify) { - mcq->comp(mcq, NULL); - } - spin_unlock_irqrestore(&ibdev->reset_flow_resource_lock, flags); -} - -static void delay_drop_handler(struct work_struct *work) -{ - int err; - struct mlx5_ib_delay_drop *delay_drop = - container_of(work, struct mlx5_ib_delay_drop, - delay_drop_work); - - atomic_inc(&delay_drop->events_cnt); - - mutex_lock(&delay_drop->lock); - err = mlx5_core_set_delay_drop(delay_drop->dev, delay_drop->timeout); - if (err) { - mlx5_ib_warn(delay_drop->dev, "Failed to set delay drop, timeout=%u\n", - delay_drop->timeout); - delay_drop->activate = false; - } - mutex_unlock(&delay_drop->lock); -} - -static void handle_general_event(struct mlx5_ib_dev *ibdev, struct mlx5_eqe *eqe, - struct ib_event *ibev) -{ - u8 port = (eqe->data.port.port >> 4) & 0xf; - - switch (eqe->sub_type) { - case MLX5_GENERAL_SUBTYPE_DELAY_DROP_TIMEOUT: - if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) == - IB_LINK_LAYER_ETHERNET) - schedule_work(&ibdev->delay_drop.delay_drop_work); - break; - default: /* do nothing */ - return; - } -} - -static int handle_port_change(struct mlx5_ib_dev *ibdev, struct mlx5_eqe *eqe, - struct ib_event *ibev) -{ - u8 port = (eqe->data.port.port >> 4) & 0xf; - - ibev->element.port_num = port; - - switch (eqe->sub_type) { - case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE: - case MLX5_PORT_CHANGE_SUBTYPE_DOWN: - case MLX5_PORT_CHANGE_SUBTYPE_INITIALIZED: - /* In RoCE, port up/down events are handled in - * mlx5_netdev_event(). - */ - if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) == - IB_LINK_LAYER_ETHERNET) - return -EINVAL; - - ibev->event = (eqe->sub_type == MLX5_PORT_CHANGE_SUBTYPE_ACTIVE) ? - IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; - break; - - case MLX5_PORT_CHANGE_SUBTYPE_LID: - ibev->event = IB_EVENT_LID_CHANGE; - break; - - case MLX5_PORT_CHANGE_SUBTYPE_PKEY: - ibev->event = IB_EVENT_PKEY_CHANGE; - schedule_work(&ibdev->devr.ports[port - 1].pkey_change_work); - break; - - case MLX5_PORT_CHANGE_SUBTYPE_GUID: - ibev->event = IB_EVENT_GID_CHANGE; - break; - - case MLX5_PORT_CHANGE_SUBTYPE_CLIENT_REREG: - ibev->event = IB_EVENT_CLIENT_REREGISTER; - break; - default: - return -EINVAL; - } - - return 0; -} - -static void mlx5_ib_handle_event(struct work_struct *_work) -{ - struct mlx5_ib_event_work *work = - container_of(_work, struct mlx5_ib_event_work, work); - struct mlx5_ib_dev *ibdev; - struct ib_event ibev; - bool fatal = false; - - if (work->is_slave) { - ibdev = mlx5_ib_get_ibdev_from_mpi(work->mpi); - if (!ibdev) - goto out; - } else { - ibdev = work->dev; - } - - switch (work->event) { - case MLX5_DEV_EVENT_SYS_ERROR: - ibev.event = IB_EVENT_DEVICE_FATAL; - mlx5_ib_handle_internal_error(ibdev); - ibev.element.port_num = (u8)(unsigned long)work->param; - fatal = true; - break; - case MLX5_EVENT_TYPE_PORT_CHANGE: - if (handle_port_change(ibdev, work->param, &ibev)) - goto out; - break; - case MLX5_EVENT_TYPE_GENERAL_EVENT: - handle_general_event(ibdev, work->param, &ibev); - /* fall through */ - default: - goto out; - } - - ibev.device = &ibdev->ib_dev; - - if (!rdma_is_port_valid(&ibdev->ib_dev, ibev.element.port_num)) { - mlx5_ib_warn(ibdev, "warning: event on port %d\n", ibev.element.port_num); - goto out; - } - - if (ibdev->ib_active) - ib_dispatch_event(&ibev); - - if (fatal) - ibdev->ib_active = false; -out: - kfree(work); -} - -static int mlx5_ib_event(struct notifier_block *nb, - unsigned long event, void *param) -{ - struct mlx5_ib_event_work *work; - - work = kmalloc(sizeof(*work), GFP_ATOMIC); - if (!work) - return NOTIFY_DONE; - - INIT_WORK(&work->work, mlx5_ib_handle_event); - work->dev = container_of(nb, struct mlx5_ib_dev, mdev_events); - work->is_slave = false; - work->param = param; - work->event = event; - - queue_work(mlx5_ib_event_wq, &work->work); - - return NOTIFY_OK; -} - -static int mlx5_ib_event_slave_port(struct notifier_block *nb, - unsigned long event, void *param) -{ - struct mlx5_ib_event_work *work; - - work = kmalloc(sizeof(*work), GFP_ATOMIC); - if (!work) - return NOTIFY_DONE; - - INIT_WORK(&work->work, mlx5_ib_handle_event); - work->mpi = container_of(nb, struct mlx5_ib_multiport_info, mdev_events); - work->is_slave = true; - work->param = param; - work->event = event; - queue_work(mlx5_ib_event_wq, &work->work); - - return NOTIFY_OK; -} - -static int set_has_smi_cap(struct mlx5_ib_dev *dev) -{ - struct mlx5_hca_vport_context vport_ctx; - int err; - int port; - - for (port = 1; port <= ARRAY_SIZE(dev->mdev->port_caps); port++) { - dev->mdev->port_caps[port - 1].has_smi = false; - if (MLX5_CAP_GEN(dev->mdev, port_type) == - MLX5_CAP_PORT_TYPE_IB) { - if (MLX5_CAP_GEN(dev->mdev, ib_virt)) { - err = mlx5_query_hca_vport_context(dev->mdev, 0, - port, 0, - &vport_ctx); - if (err) { - mlx5_ib_err(dev, "query_hca_vport_context for port=%d failed %d\n", - port, err); - return err; - } - dev->mdev->port_caps[port - 1].has_smi = - vport_ctx.has_smi; - } else { - dev->mdev->port_caps[port - 1].has_smi = true; - } - } - } - return 0; -} - -static void get_ext_port_caps(struct mlx5_ib_dev *dev) -{ - int port; - - for (port = 1; port <= dev->num_ports; port++) - mlx5_query_ext_port_caps(dev, port); -} - -static int __get_port_caps(struct mlx5_ib_dev *dev, u8 port) -{ - struct ib_device_attr *dprops = NULL; - struct ib_port_attr *pprops = NULL; - int err = -ENOMEM; - - pprops = kzalloc(sizeof(*pprops), GFP_KERNEL); - if (!pprops) - goto out; - - dprops = kmalloc(sizeof(*dprops), GFP_KERNEL); - if (!dprops) - goto out; - - err = mlx5_ib_query_device(&dev->ib_dev, dprops, NULL); - if (err) { - mlx5_ib_warn(dev, "query_device failed %d\n", err); - goto out; - } - - err = mlx5_ib_query_port(&dev->ib_dev, port, pprops); - if (err) { - mlx5_ib_warn(dev, "query_port %d failed %d\n", - port, err); - goto out; - } - - dev->mdev->port_caps[port - 1].pkey_table_len = - dprops->max_pkeys; - dev->mdev->port_caps[port - 1].gid_table_len = - pprops->gid_tbl_len; - mlx5_ib_dbg(dev, "port %d: pkey_table_len %d, gid_table_len %d\n", - port, dprops->max_pkeys, pprops->gid_tbl_len); - -out: - kfree(pprops); - kfree(dprops); - - return err; -} - -static int get_port_caps(struct mlx5_ib_dev *dev, u8 port) -{ - /* For representors use port 1, is this is the only native - * port - */ - if (dev->is_rep) - return __get_port_caps(dev, 1); - return __get_port_caps(dev, port); -} - -static void destroy_umrc_res(struct mlx5_ib_dev *dev) -{ - int err; - - err = mlx5_mr_cache_cleanup(dev); - if (err) - mlx5_ib_warn(dev, "mr cache cleanup failed\n"); - - if (dev->umrc.qp) - mlx5_ib_destroy_qp(dev->umrc.qp, NULL); - if (dev->umrc.cq) - ib_free_cq(dev->umrc.cq); - if (dev->umrc.pd) - ib_dealloc_pd(dev->umrc.pd); -} - -enum { - MAX_UMR_WR = 128, -}; - -static int create_umr_res(struct mlx5_ib_dev *dev) -{ - struct ib_qp_init_attr *init_attr = NULL; - struct ib_qp_attr *attr = NULL; - struct ib_pd *pd; - struct ib_cq *cq; - struct ib_qp *qp; - int ret; - - attr = kzalloc(sizeof(*attr), GFP_KERNEL); - init_attr = kzalloc(sizeof(*init_attr), GFP_KERNEL); - if (!attr || !init_attr) { - ret = -ENOMEM; - goto error_0; - } - - pd = ib_alloc_pd(&dev->ib_dev, 0); - if (IS_ERR(pd)) { - mlx5_ib_dbg(dev, "Couldn't create PD for sync UMR QP\n"); - ret = PTR_ERR(pd); - goto error_0; - } - - cq = ib_alloc_cq(&dev->ib_dev, NULL, 128, 0, IB_POLL_SOFTIRQ); - if (IS_ERR(cq)) { - mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n"); - ret = PTR_ERR(cq); - goto error_2; - } - - init_attr->send_cq = cq; - init_attr->recv_cq = cq; - init_attr->sq_sig_type = IB_SIGNAL_ALL_WR; - init_attr->cap.max_send_wr = MAX_UMR_WR; - init_attr->cap.max_send_sge = 1; - init_attr->qp_type = MLX5_IB_QPT_REG_UMR; - init_attr->port_num = 1; - qp = mlx5_ib_create_qp(pd, init_attr, NULL); - if (IS_ERR(qp)) { - mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n"); - ret = PTR_ERR(qp); - goto error_3; - } - qp->device = &dev->ib_dev; - qp->real_qp = qp; - qp->uobject = NULL; - qp->qp_type = MLX5_IB_QPT_REG_UMR; - qp->send_cq = init_attr->send_cq; - qp->recv_cq = init_attr->recv_cq; - - attr->qp_state = IB_QPS_INIT; - attr->port_num = 1; - ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE | IB_QP_PKEY_INDEX | - IB_QP_PORT, NULL); - if (ret) { - mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n"); - goto error_4; - } - - memset(attr, 0, sizeof(*attr)); - attr->qp_state = IB_QPS_RTR; - attr->path_mtu = IB_MTU_256; - - ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL); - if (ret) { - mlx5_ib_dbg(dev, "Couldn't modify umr QP to rtr\n"); - goto error_4; - } - - memset(attr, 0, sizeof(*attr)); - attr->qp_state = IB_QPS_RTS; - ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL); - if (ret) { - mlx5_ib_dbg(dev, "Couldn't modify umr QP to rts\n"); - goto error_4; - } - - dev->umrc.qp = qp; - dev->umrc.cq = cq; - dev->umrc.pd = pd; - - sema_init(&dev->umrc.sem, MAX_UMR_WR); - ret = mlx5_mr_cache_init(dev); - if (ret) { - mlx5_ib_warn(dev, "mr cache init failed %d\n", ret); - goto error_4; - } - - kfree(attr); - kfree(init_attr); - - return 0; - -error_4: - mlx5_ib_destroy_qp(qp, NULL); - dev->umrc.qp = NULL; - -error_3: - ib_free_cq(cq); - dev->umrc.cq = NULL; - -error_2: - ib_dealloc_pd(pd); - dev->umrc.pd = NULL; - -error_0: - kfree(attr); - kfree(init_attr); - return ret; -} - -static u8 mlx5_get_umr_fence(u8 umr_fence_cap) -{ - switch (umr_fence_cap) { - case MLX5_CAP_UMR_FENCE_NONE: - return MLX5_FENCE_MODE_NONE; - case MLX5_CAP_UMR_FENCE_SMALL: - return MLX5_FENCE_MODE_INITIATOR_SMALL; - default: - return MLX5_FENCE_MODE_STRONG_ORDERING; - } -} - -static int create_dev_resources(struct mlx5_ib_resources *devr) -{ - struct ib_srq_init_attr attr; - struct mlx5_ib_dev *dev; - struct ib_device *ibdev; - struct ib_cq_init_attr cq_attr = {.cqe = 1}; - int port; - int ret = 0; - - dev = container_of(devr, struct mlx5_ib_dev, devr); - ibdev = &dev->ib_dev; - - mutex_init(&devr->mutex); - - devr->p0 = rdma_zalloc_drv_obj(ibdev, ib_pd); - if (!devr->p0) - return -ENOMEM; - - devr->p0->device = ibdev; - devr->p0->uobject = NULL; - atomic_set(&devr->p0->usecnt, 0); - - ret = mlx5_ib_alloc_pd(devr->p0, NULL); - if (ret) - goto error0; - - devr->c0 = rdma_zalloc_drv_obj(ibdev, ib_cq); - if (!devr->c0) { - ret = -ENOMEM; - goto error1; - } - - devr->c0->device = &dev->ib_dev; - atomic_set(&devr->c0->usecnt, 0); - - ret = mlx5_ib_create_cq(devr->c0, &cq_attr, NULL); - if (ret) - goto err_create_cq; - - devr->x0 = mlx5_ib_alloc_xrcd(&dev->ib_dev, NULL); - if (IS_ERR(devr->x0)) { - ret = PTR_ERR(devr->x0); - goto error2; - } - devr->x0->device = &dev->ib_dev; - devr->x0->inode = NULL; - atomic_set(&devr->x0->usecnt, 0); - mutex_init(&devr->x0->tgt_qp_mutex); - INIT_LIST_HEAD(&devr->x0->tgt_qp_list); - - devr->x1 = mlx5_ib_alloc_xrcd(&dev->ib_dev, NULL); - if (IS_ERR(devr->x1)) { - ret = PTR_ERR(devr->x1); - goto error3; - } - devr->x1->device = &dev->ib_dev; - devr->x1->inode = NULL; - atomic_set(&devr->x1->usecnt, 0); - mutex_init(&devr->x1->tgt_qp_mutex); - INIT_LIST_HEAD(&devr->x1->tgt_qp_list); - - memset(&attr, 0, sizeof(attr)); - attr.attr.max_sge = 1; - attr.attr.max_wr = 1; - attr.srq_type = IB_SRQT_XRC; - attr.ext.cq = devr->c0; - attr.ext.xrc.xrcd = devr->x0; - - devr->s0 = rdma_zalloc_drv_obj(ibdev, ib_srq); - if (!devr->s0) { - ret = -ENOMEM; - goto error4; - } - - devr->s0->device = &dev->ib_dev; - devr->s0->pd = devr->p0; - devr->s0->srq_type = IB_SRQT_XRC; - devr->s0->ext.xrc.xrcd = devr->x0; - devr->s0->ext.cq = devr->c0; - ret = mlx5_ib_create_srq(devr->s0, &attr, NULL); - if (ret) - goto err_create; - - atomic_inc(&devr->s0->ext.xrc.xrcd->usecnt); - atomic_inc(&devr->s0->ext.cq->usecnt); - atomic_inc(&devr->p0->usecnt); - atomic_set(&devr->s0->usecnt, 0); - - memset(&attr, 0, sizeof(attr)); - attr.attr.max_sge = 1; - attr.attr.max_wr = 1; - attr.srq_type = IB_SRQT_BASIC; - devr->s1 = rdma_zalloc_drv_obj(ibdev, ib_srq); - if (!devr->s1) { - ret = -ENOMEM; - goto error5; - } - - devr->s1->device = &dev->ib_dev; - devr->s1->pd = devr->p0; - devr->s1->srq_type = IB_SRQT_BASIC; - devr->s1->ext.cq = devr->c0; - - ret = mlx5_ib_create_srq(devr->s1, &attr, NULL); - if (ret) - goto error6; - - atomic_inc(&devr->p0->usecnt); - atomic_set(&devr->s1->usecnt, 0); - - for (port = 0; port < ARRAY_SIZE(devr->ports); ++port) { - INIT_WORK(&devr->ports[port].pkey_change_work, - pkey_change_handler); - devr->ports[port].devr = devr; - } - - return 0; - -error6: - kfree(devr->s1); -error5: - mlx5_ib_destroy_srq(devr->s0, NULL); -err_create: - kfree(devr->s0); -error4: - mlx5_ib_dealloc_xrcd(devr->x1, NULL); -error3: - mlx5_ib_dealloc_xrcd(devr->x0, NULL); -error2: - mlx5_ib_destroy_cq(devr->c0, NULL); -err_create_cq: - kfree(devr->c0); -error1: - mlx5_ib_dealloc_pd(devr->p0, NULL); -error0: - kfree(devr->p0); - return ret; -} - -static void destroy_dev_resources(struct mlx5_ib_resources *devr) -{ - int port; - - mlx5_ib_destroy_srq(devr->s1, NULL); - kfree(devr->s1); - mlx5_ib_destroy_srq(devr->s0, NULL); - kfree(devr->s0); - mlx5_ib_dealloc_xrcd(devr->x0, NULL); - mlx5_ib_dealloc_xrcd(devr->x1, NULL); - mlx5_ib_destroy_cq(devr->c0, NULL); - kfree(devr->c0); - mlx5_ib_dealloc_pd(devr->p0, NULL); - kfree(devr->p0); - - /* Make sure no change P_Key work items are still executing */ - for (port = 0; port < ARRAY_SIZE(devr->ports); ++port) - cancel_work_sync(&devr->ports[port].pkey_change_work); -} - -static u32 get_core_cap_flags(struct ib_device *ibdev, - struct mlx5_hca_vport_context *rep) -{ - struct mlx5_ib_dev *dev = to_mdev(ibdev); - enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, 1); - u8 l3_type_cap = MLX5_CAP_ROCE(dev->mdev, l3_type); - u8 roce_version_cap = MLX5_CAP_ROCE(dev->mdev, roce_version); - bool raw_support = !mlx5_core_mp_enabled(dev->mdev); - u32 ret = 0; - - if (rep->grh_required) - ret |= RDMA_CORE_CAP_IB_GRH_REQUIRED; - - if (ll == IB_LINK_LAYER_INFINIBAND) - return ret | RDMA_CORE_PORT_IBA_IB; - - if (raw_support) - ret |= RDMA_CORE_PORT_RAW_PACKET; - - if (!(l3_type_cap & MLX5_ROCE_L3_TYPE_IPV4_CAP)) - return ret; - - if (!(l3_type_cap & MLX5_ROCE_L3_TYPE_IPV6_CAP)) - return ret; - - if (roce_version_cap & MLX5_ROCE_VERSION_1_CAP) - ret |= RDMA_CORE_PORT_IBA_ROCE; - - if (roce_version_cap & MLX5_ROCE_VERSION_2_CAP) - ret |= RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP; - - return ret; -} - -static int mlx5_port_immutable(struct ib_device *ibdev, u8 port_num, - struct ib_port_immutable *immutable) -{ - struct ib_port_attr attr; - struct mlx5_ib_dev *dev = to_mdev(ibdev); - enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, port_num); - struct mlx5_hca_vport_context rep = {0}; - int err; - - err = ib_query_port(ibdev, port_num, &attr); - if (err) - return err; - - if (ll == IB_LINK_LAYER_INFINIBAND) { - err = mlx5_query_hca_vport_context(dev->mdev, 0, port_num, 0, - &rep); - if (err) - return err; - } - - immutable->pkey_tbl_len = attr.pkey_tbl_len; - immutable->gid_tbl_len = attr.gid_tbl_len; - immutable->core_cap_flags = get_core_cap_flags(ibdev, &rep); - immutable->max_mad_size = IB_MGMT_MAD_SIZE; - - return 0; -} - -static int mlx5_port_rep_immutable(struct ib_device *ibdev, u8 port_num, - struct ib_port_immutable *immutable) -{ - struct ib_port_attr attr; - int err; - - immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET; - - err = ib_query_port(ibdev, port_num, &attr); - if (err) - return err; - - immutable->pkey_tbl_len = attr.pkey_tbl_len; - immutable->gid_tbl_len = attr.gid_tbl_len; - immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET; - - return 0; -} - -static void get_dev_fw_str(struct ib_device *ibdev, char *str) -{ - struct mlx5_ib_dev *dev = - container_of(ibdev, struct mlx5_ib_dev, ib_dev); - snprintf(str, IB_FW_VERSION_NAME_MAX, "%d.%d.%04d", - fw_rev_maj(dev->mdev), fw_rev_min(dev->mdev), - fw_rev_sub(dev->mdev)); -} - -static int mlx5_eth_lag_init(struct mlx5_ib_dev *dev) -{ - struct mlx5_core_dev *mdev = dev->mdev; - struct mlx5_flow_namespace *ns = mlx5_get_flow_namespace(mdev, - MLX5_FLOW_NAMESPACE_LAG); - struct mlx5_flow_table *ft; - int err; - - if (!ns || !mlx5_lag_is_roce(mdev)) - return 0; - - err = mlx5_cmd_create_vport_lag(mdev); - if (err) - return err; - - ft = mlx5_create_lag_demux_flow_table(ns, 0, 0); - if (IS_ERR(ft)) { - err = PTR_ERR(ft); - goto err_destroy_vport_lag; - } - - dev->flow_db->lag_demux_ft = ft; - dev->lag_active = true; - return 0; - -err_destroy_vport_lag: - mlx5_cmd_destroy_vport_lag(mdev); - return err; -} - -static void mlx5_eth_lag_cleanup(struct mlx5_ib_dev *dev) -{ - struct mlx5_core_dev *mdev = dev->mdev; - - if (dev->lag_active) { - dev->lag_active = false; + struct mlx5_ib_event_work *work; - mlx5_destroy_flow_table(dev->flow_db->lag_demux_ft); - dev->flow_db->lag_demux_ft = NULL; + work = kmalloc(sizeof(*work), GFP_ATOMIC); + if (!work) + return NOTIFY_DONE; - mlx5_cmd_destroy_vport_lag(mdev); - } + INIT_WORK(&work->work, mlx5_ib_handle_event); + work->mpi = container_of(nb, struct mlx5_ib_multiport_info, mdev_events); + work->is_slave = true; + work->param = param; + work->event = event; + queue_work(mlx5_ib_event_wq, &work->work); + + return NOTIFY_OK; } -static int mlx5_add_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num) +static int set_has_smi_cap(struct mlx5_ib_dev *dev) { + struct mlx5_hca_vport_context vport_ctx; int err; + int port; - dev->port[port_num].roce.nb.notifier_call = mlx5_netdev_event; - err = register_netdevice_notifier(&dev->port[port_num].roce.nb); - if (err) { - dev->port[port_num].roce.nb.notifier_call = NULL; - return err; + for (port = 1; port <= ARRAY_SIZE(dev->mdev->port_caps); port++) { + dev->mdev->port_caps[port - 1].has_smi = false; + if (MLX5_CAP_GEN(dev->mdev, port_type) == + MLX5_CAP_PORT_TYPE_IB) { + if (MLX5_CAP_GEN(dev->mdev, ib_virt)) { + err = mlx5_query_hca_vport_context(dev->mdev, 0, + port, 0, + &vport_ctx); + if (err) { + mlx5_ib_err(dev, "query_hca_vport_context for port=%d failed %d\n", + port, err); + return err; + } + dev->mdev->port_caps[port - 1].has_smi = + vport_ctx.has_smi; + } else { + dev->mdev->port_caps[port - 1].has_smi = true; + } + } } - return 0; } -static void mlx5_remove_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num) +static void get_ext_port_caps(struct mlx5_ib_dev *dev) { - if (dev->port[port_num].roce.nb.notifier_call) { - unregister_netdevice_notifier(&dev->port[port_num].roce.nb); - dev->port[port_num].roce.nb.notifier_call = NULL; - } + int port; + + for (port = 1; port <= dev->num_ports; port++) + mlx5_query_ext_port_caps(dev, port); } -static int mlx5_enable_eth(struct mlx5_ib_dev *dev) +static int __get_port_caps(struct mlx5_ib_dev *dev, u8 port) { - int err; + struct ib_device_attr *dprops = NULL; + struct ib_port_attr *pprops = NULL; + int err = -ENOMEM; - err = mlx5_nic_vport_enable_roce(dev->mdev); - if (err) - return err; + pprops = kzalloc(sizeof(*pprops), GFP_KERNEL); + if (!pprops) + goto out; - err = mlx5_eth_lag_init(dev); - if (err) - goto err_disable_roce; + dprops = kmalloc(sizeof(*dprops), GFP_KERNEL); + if (!dprops) + goto out; - return 0; + err = mlx5_ib_query_device(&dev->ib_dev, dprops, NULL); + if (err) { + mlx5_ib_warn(dev, "query_device failed %d\n", err); + goto out; + } -err_disable_roce: - mlx5_nic_vport_disable_roce(dev->mdev); + err = mlx5_ib_query_port(&dev->ib_dev, port, pprops); + if (err) { + mlx5_ib_warn(dev, "query_port %d failed %d\n", + port, err); + goto out; + } + + dev->mdev->port_caps[port - 1].pkey_table_len = + dprops->max_pkeys; + dev->mdev->port_caps[port - 1].gid_table_len = + pprops->gid_tbl_len; + mlx5_ib_dbg(dev, "port %d: pkey_table_len %d, gid_table_len %d\n", + port, dprops->max_pkeys, pprops->gid_tbl_len); + +out: + kfree(pprops); + kfree(dprops); return err; } -static void mlx5_disable_eth(struct mlx5_ib_dev *dev) +static int get_port_caps(struct mlx5_ib_dev *dev, u8 port) { - mlx5_eth_lag_cleanup(dev); - mlx5_nic_vport_disable_roce(dev->mdev); + /* For representors use port 1, is this is the only native + * port + */ + if (dev->is_rep) + return __get_port_caps(dev, 1); + return __get_port_caps(dev, port); } -struct mlx5_ib_counter { - const char *name; - size_t offset; -}; - -#define INIT_Q_COUNTER(_name) \ - { .name = #_name, .offset = MLX5_BYTE_OFF(query_q_counter_out, _name)} +static u8 mlx5_get_umr_fence(u8 umr_fence_cap) +{ + switch (umr_fence_cap) { + case MLX5_CAP_UMR_FENCE_NONE: + return MLX5_FENCE_MODE_NONE; + case MLX5_CAP_UMR_FENCE_SMALL: + return MLX5_FENCE_MODE_INITIATOR_SMALL; + default: + return MLX5_FENCE_MODE_STRONG_ORDERING; + } +} -static const struct mlx5_ib_counter basic_q_cnts[] = { - INIT_Q_COUNTER(rx_write_requests), - INIT_Q_COUNTER(rx_read_requests), - INIT_Q_COUNTER(rx_atomic_requests), - INIT_Q_COUNTER(out_of_buffer), -}; +static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev) +{ + struct mlx5_ib_resources *devr = &dev->devr; + struct ib_srq_init_attr attr; + struct ib_device *ibdev; + struct ib_cq_init_attr cq_attr = {.cqe = 1}; + int port; + int ret = 0; -static const struct mlx5_ib_counter out_of_seq_q_cnts[] = { - INIT_Q_COUNTER(out_of_sequence), -}; + ibdev = &dev->ib_dev; -static const struct mlx5_ib_counter retrans_q_cnts[] = { - INIT_Q_COUNTER(duplicate_request), - INIT_Q_COUNTER(rnr_nak_retry_err), - INIT_Q_COUNTER(packet_seq_err), - INIT_Q_COUNTER(implied_nak_seq_err), - INIT_Q_COUNTER(local_ack_timeout_err), -}; + if (!MLX5_CAP_GEN(dev->mdev, xrc)) + return -EOPNOTSUPP; -#define INIT_CONG_COUNTER(_name) \ - { .name = #_name, .offset = \ - MLX5_BYTE_OFF(query_cong_statistics_out, _name ## _high)} + mutex_init(&devr->mutex); -static const struct mlx5_ib_counter cong_cnts[] = { - INIT_CONG_COUNTER(rp_cnp_ignored), - INIT_CONG_COUNTER(rp_cnp_handled), - INIT_CONG_COUNTER(np_ecn_marked_roce_packets), - INIT_CONG_COUNTER(np_cnp_sent), -}; + devr->p0 = rdma_zalloc_drv_obj(ibdev, ib_pd); + if (!devr->p0) + return -ENOMEM; -static const struct mlx5_ib_counter extended_err_cnts[] = { - INIT_Q_COUNTER(resp_local_length_error), - INIT_Q_COUNTER(resp_cqe_error), - INIT_Q_COUNTER(req_cqe_error), - INIT_Q_COUNTER(req_remote_invalid_request), - INIT_Q_COUNTER(req_remote_access_errors), - INIT_Q_COUNTER(resp_remote_access_errors), - INIT_Q_COUNTER(resp_cqe_flush_error), - INIT_Q_COUNTER(req_cqe_flush_error), -}; + devr->p0->device = ibdev; + devr->p0->uobject = NULL; + atomic_set(&devr->p0->usecnt, 0); -static const struct mlx5_ib_counter roce_accl_cnts[] = { - INIT_Q_COUNTER(roce_adp_retrans), - INIT_Q_COUNTER(roce_adp_retrans_to), - INIT_Q_COUNTER(roce_slow_restart), - INIT_Q_COUNTER(roce_slow_restart_cnps), - INIT_Q_COUNTER(roce_slow_restart_trans), -}; + ret = mlx5_ib_alloc_pd(devr->p0, NULL); + if (ret) + goto error0; -#define INIT_EXT_PPCNT_COUNTER(_name) \ - { .name = #_name, .offset = \ - MLX5_BYTE_OFF(ppcnt_reg, \ - counter_set.eth_extended_cntrs_grp_data_layout._name##_high)} + devr->c0 = rdma_zalloc_drv_obj(ibdev, ib_cq); + if (!devr->c0) { + ret = -ENOMEM; + goto error1; + } -static const struct mlx5_ib_counter ext_ppcnt_cnts[] = { - INIT_EXT_PPCNT_COUNTER(rx_icrc_encapsulated), -}; + devr->c0->device = &dev->ib_dev; + atomic_set(&devr->c0->usecnt, 0); -static bool is_mdev_switchdev_mode(const struct mlx5_core_dev *mdev) -{ - return MLX5_ESWITCH_MANAGER(mdev) && - mlx5_ib_eswitch_mode(mdev->priv.eswitch) == - MLX5_ESWITCH_OFFLOADS; -} + ret = mlx5_ib_create_cq(devr->c0, &cq_attr, NULL); + if (ret) + goto err_create_cq; -static void mlx5_ib_dealloc_counters(struct mlx5_ib_dev *dev) -{ - u32 in[MLX5_ST_SZ_DW(dealloc_q_counter_in)] = {}; - int num_cnt_ports; - int i; + ret = mlx5_cmd_xrcd_alloc(dev->mdev, &devr->xrcdn0, 0); + if (ret) + goto error2; - num_cnt_ports = is_mdev_switchdev_mode(dev->mdev) ? 1 : dev->num_ports; + ret = mlx5_cmd_xrcd_alloc(dev->mdev, &devr->xrcdn1, 0); + if (ret) + goto error3; - MLX5_SET(dealloc_q_counter_in, in, opcode, - MLX5_CMD_OP_DEALLOC_Q_COUNTER); + memset(&attr, 0, sizeof(attr)); + attr.attr.max_sge = 1; + attr.attr.max_wr = 1; + attr.srq_type = IB_SRQT_XRC; + attr.ext.cq = devr->c0; - for (i = 0; i < num_cnt_ports; i++) { - if (dev->port[i].cnts.set_id) { - MLX5_SET(dealloc_q_counter_in, in, counter_set_id, - dev->port[i].cnts.set_id); - mlx5_cmd_exec_in(dev->mdev, dealloc_q_counter, in); - } - kfree(dev->port[i].cnts.names); - kfree(dev->port[i].cnts.offsets); + devr->s0 = rdma_zalloc_drv_obj(ibdev, ib_srq); + if (!devr->s0) { + ret = -ENOMEM; + goto error4; } -} - -static int __mlx5_ib_alloc_counters(struct mlx5_ib_dev *dev, - struct mlx5_ib_counters *cnts) -{ - u32 num_counters; - num_counters = ARRAY_SIZE(basic_q_cnts); + devr->s0->device = &dev->ib_dev; + devr->s0->pd = devr->p0; + devr->s0->srq_type = IB_SRQT_XRC; + devr->s0->ext.cq = devr->c0; + ret = mlx5_ib_create_srq(devr->s0, &attr, NULL); + if (ret) + goto err_create; - if (MLX5_CAP_GEN(dev->mdev, out_of_seq_cnt)) - num_counters += ARRAY_SIZE(out_of_seq_q_cnts); + atomic_inc(&devr->s0->ext.cq->usecnt); + atomic_inc(&devr->p0->usecnt); + atomic_set(&devr->s0->usecnt, 0); - if (MLX5_CAP_GEN(dev->mdev, retransmission_q_counters)) - num_counters += ARRAY_SIZE(retrans_q_cnts); + memset(&attr, 0, sizeof(attr)); + attr.attr.max_sge = 1; + attr.attr.max_wr = 1; + attr.srq_type = IB_SRQT_BASIC; + devr->s1 = rdma_zalloc_drv_obj(ibdev, ib_srq); + if (!devr->s1) { + ret = -ENOMEM; + goto error5; + } - if (MLX5_CAP_GEN(dev->mdev, enhanced_error_q_counters)) - num_counters += ARRAY_SIZE(extended_err_cnts); + devr->s1->device = &dev->ib_dev; + devr->s1->pd = devr->p0; + devr->s1->srq_type = IB_SRQT_BASIC; + devr->s1->ext.cq = devr->c0; - if (MLX5_CAP_GEN(dev->mdev, roce_accl)) - num_counters += ARRAY_SIZE(roce_accl_cnts); + ret = mlx5_ib_create_srq(devr->s1, &attr, NULL); + if (ret) + goto error6; - cnts->num_q_counters = num_counters; + atomic_inc(&devr->p0->usecnt); + atomic_set(&devr->s1->usecnt, 0); - if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { - cnts->num_cong_counters = ARRAY_SIZE(cong_cnts); - num_counters += ARRAY_SIZE(cong_cnts); - } - if (MLX5_CAP_PCAM_FEATURE(dev->mdev, rx_icrc_encapsulated_counter)) { - cnts->num_ext_ppcnt_counters = ARRAY_SIZE(ext_ppcnt_cnts); - num_counters += ARRAY_SIZE(ext_ppcnt_cnts); + for (port = 0; port < ARRAY_SIZE(devr->ports); ++port) { + INIT_WORK(&devr->ports[port].pkey_change_work, + pkey_change_handler); + devr->ports[port].devr = devr; } - cnts->names = kcalloc(num_counters, sizeof(cnts->names), GFP_KERNEL); - if (!cnts->names) - return -ENOMEM; - - cnts->offsets = kcalloc(num_counters, - sizeof(cnts->offsets), GFP_KERNEL); - if (!cnts->offsets) - goto err_names; return 0; -err_names: - kfree(cnts->names); - cnts->names = NULL; - return -ENOMEM; +error6: + kfree(devr->s1); +error5: + mlx5_ib_destroy_srq(devr->s0, NULL); +err_create: + kfree(devr->s0); +error4: + mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn1, 0); +error3: + mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0); +error2: + mlx5_ib_destroy_cq(devr->c0, NULL); +err_create_cq: + kfree(devr->c0); +error1: + mlx5_ib_dealloc_pd(devr->p0, NULL); +error0: + kfree(devr->p0); + return ret; } -static void mlx5_ib_fill_counters(struct mlx5_ib_dev *dev, - const char **names, - size_t *offsets) +static void mlx5_ib_dev_res_cleanup(struct mlx5_ib_dev *dev) { - int i; - int j = 0; - - for (i = 0; i < ARRAY_SIZE(basic_q_cnts); i++, j++) { - names[j] = basic_q_cnts[i].name; - offsets[j] = basic_q_cnts[i].offset; - } - - if (MLX5_CAP_GEN(dev->mdev, out_of_seq_cnt)) { - for (i = 0; i < ARRAY_SIZE(out_of_seq_q_cnts); i++, j++) { - names[j] = out_of_seq_q_cnts[i].name; - offsets[j] = out_of_seq_q_cnts[i].offset; - } - } - - if (MLX5_CAP_GEN(dev->mdev, retransmission_q_counters)) { - for (i = 0; i < ARRAY_SIZE(retrans_q_cnts); i++, j++) { - names[j] = retrans_q_cnts[i].name; - offsets[j] = retrans_q_cnts[i].offset; - } - } - - if (MLX5_CAP_GEN(dev->mdev, enhanced_error_q_counters)) { - for (i = 0; i < ARRAY_SIZE(extended_err_cnts); i++, j++) { - names[j] = extended_err_cnts[i].name; - offsets[j] = extended_err_cnts[i].offset; - } - } - - if (MLX5_CAP_GEN(dev->mdev, roce_accl)) { - for (i = 0; i < ARRAY_SIZE(roce_accl_cnts); i++, j++) { - names[j] = roce_accl_cnts[i].name; - offsets[j] = roce_accl_cnts[i].offset; - } - } + struct mlx5_ib_resources *devr = &dev->devr; + int port; - if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { - for (i = 0; i < ARRAY_SIZE(cong_cnts); i++, j++) { - names[j] = cong_cnts[i].name; - offsets[j] = cong_cnts[i].offset; - } - } + mlx5_ib_destroy_srq(devr->s1, NULL); + kfree(devr->s1); + mlx5_ib_destroy_srq(devr->s0, NULL); + kfree(devr->s0); + mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn1, 0); + mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0); + mlx5_ib_destroy_cq(devr->c0, NULL); + kfree(devr->c0); + mlx5_ib_dealloc_pd(devr->p0, NULL); + kfree(devr->p0); - if (MLX5_CAP_PCAM_FEATURE(dev->mdev, rx_icrc_encapsulated_counter)) { - for (i = 0; i < ARRAY_SIZE(ext_ppcnt_cnts); i++, j++) { - names[j] = ext_ppcnt_cnts[i].name; - offsets[j] = ext_ppcnt_cnts[i].offset; - } - } + /* Make sure no change P_Key work items are still executing */ + for (port = 0; port < ARRAY_SIZE(devr->ports); ++port) + cancel_work_sync(&devr->ports[port].pkey_change_work); } -static int mlx5_ib_alloc_counters(struct mlx5_ib_dev *dev) +static u32 get_core_cap_flags(struct ib_device *ibdev, + struct mlx5_hca_vport_context *rep) { - u32 out[MLX5_ST_SZ_DW(alloc_q_counter_out)] = {}; - u32 in[MLX5_ST_SZ_DW(alloc_q_counter_in)] = {}; - int num_cnt_ports; - int err = 0; - int i; - bool is_shared; - - MLX5_SET(alloc_q_counter_in, in, opcode, MLX5_CMD_OP_ALLOC_Q_COUNTER); - is_shared = MLX5_CAP_GEN(dev->mdev, log_max_uctx) != 0; - num_cnt_ports = is_mdev_switchdev_mode(dev->mdev) ? 1 : dev->num_ports; - - for (i = 0; i < num_cnt_ports; i++) { - err = __mlx5_ib_alloc_counters(dev, &dev->port[i].cnts); - if (err) - goto err_alloc; + struct mlx5_ib_dev *dev = to_mdev(ibdev); + enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, 1); + u8 l3_type_cap = MLX5_CAP_ROCE(dev->mdev, l3_type); + u8 roce_version_cap = MLX5_CAP_ROCE(dev->mdev, roce_version); + bool raw_support = !mlx5_core_mp_enabled(dev->mdev); + u32 ret = 0; - mlx5_ib_fill_counters(dev, dev->port[i].cnts.names, - dev->port[i].cnts.offsets); + if (rep->grh_required) + ret |= RDMA_CORE_CAP_IB_GRH_REQUIRED; - MLX5_SET(alloc_q_counter_in, in, uid, - is_shared ? MLX5_SHARED_RESOURCE_UID : 0); + if (ll == IB_LINK_LAYER_INFINIBAND) + return ret | RDMA_CORE_PORT_IBA_IB; - err = mlx5_cmd_exec_inout(dev->mdev, alloc_q_counter, in, out); - if (err) { - mlx5_ib_warn(dev, - "couldn't allocate queue counter for port %d, err %d\n", - i + 1, err); - goto err_alloc; - } + if (raw_support) + ret |= RDMA_CORE_PORT_RAW_PACKET; - dev->port[i].cnts.set_id = - MLX5_GET(alloc_q_counter_out, out, counter_set_id); - } - return 0; + if (!(l3_type_cap & MLX5_ROCE_L3_TYPE_IPV4_CAP)) + return ret; -err_alloc: - mlx5_ib_dealloc_counters(dev); - return err; -} + if (!(l3_type_cap & MLX5_ROCE_L3_TYPE_IPV6_CAP)) + return ret; -static const struct mlx5_ib_counters *get_counters(struct mlx5_ib_dev *dev, - u8 port_num) -{ - return is_mdev_switchdev_mode(dev->mdev) ? &dev->port[0].cnts : - &dev->port[port_num].cnts; -} + if (roce_version_cap & MLX5_ROCE_VERSION_1_CAP) + ret |= RDMA_CORE_PORT_IBA_ROCE; -/** - * mlx5_ib_get_counters_id - Returns counters id to use for device+port - * @dev: Pointer to mlx5 IB device - * @port_num: Zero based port number - * - * mlx5_ib_get_counters_id() Returns counters set id to use for given - * device port combination in switchdev and non switchdev mode of the - * parent device. - */ -u16 mlx5_ib_get_counters_id(struct mlx5_ib_dev *dev, u8 port_num) -{ - const struct mlx5_ib_counters *cnts = get_counters(dev, port_num); + if (roce_version_cap & MLX5_ROCE_VERSION_2_CAP) + ret |= RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP; - return cnts->set_id; + return ret; } -static struct rdma_hw_stats *mlx5_ib_alloc_hw_stats(struct ib_device *ibdev, - u8 port_num) +static int mlx5_port_immutable(struct ib_device *ibdev, u8 port_num, + struct ib_port_immutable *immutable) { + struct ib_port_attr attr; struct mlx5_ib_dev *dev = to_mdev(ibdev); - const struct mlx5_ib_counters *cnts; - bool is_switchdev = is_mdev_switchdev_mode(dev->mdev); + enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, port_num); + struct mlx5_hca_vport_context rep = {0}; + int err; - if ((is_switchdev && port_num) || (!is_switchdev && !port_num)) - return NULL; + err = ib_query_port(ibdev, port_num, &attr); + if (err) + return err; + + if (ll == IB_LINK_LAYER_INFINIBAND) { + err = mlx5_query_hca_vport_context(dev->mdev, 0, port_num, 0, + &rep); + if (err) + return err; + } - cnts = get_counters(dev, port_num - 1); + immutable->pkey_tbl_len = attr.pkey_tbl_len; + immutable->gid_tbl_len = attr.gid_tbl_len; + immutable->core_cap_flags = get_core_cap_flags(ibdev, &rep); + immutable->max_mad_size = IB_MGMT_MAD_SIZE; - return rdma_alloc_hw_stats_struct(cnts->names, - cnts->num_q_counters + - cnts->num_cong_counters + - cnts->num_ext_ppcnt_counters, - RDMA_HW_STATS_DEFAULT_LIFESPAN); + return 0; } -static int mlx5_ib_query_q_counters(struct mlx5_core_dev *mdev, - const struct mlx5_ib_counters *cnts, - struct rdma_hw_stats *stats, - u16 set_id) +static int mlx5_port_rep_immutable(struct ib_device *ibdev, u8 port_num, + struct ib_port_immutable *immutable) { - u32 out[MLX5_ST_SZ_DW(query_q_counter_out)] = {}; - u32 in[MLX5_ST_SZ_DW(query_q_counter_in)] = {}; - __be32 val; - int ret, i; + struct ib_port_attr attr; + int err; - MLX5_SET(query_q_counter_in, in, opcode, MLX5_CMD_OP_QUERY_Q_COUNTER); - MLX5_SET(query_q_counter_in, in, counter_set_id, set_id); - ret = mlx5_cmd_exec_inout(mdev, query_q_counter, in, out); - if (ret) - return ret; + immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET; - for (i = 0; i < cnts->num_q_counters; i++) { - val = *(__be32 *)((void *)out + cnts->offsets[i]); - stats->value[i] = (u64)be32_to_cpu(val); - } + err = ib_query_port(ibdev, port_num, &attr); + if (err) + return err; + + immutable->pkey_tbl_len = attr.pkey_tbl_len; + immutable->gid_tbl_len = attr.gid_tbl_len; + immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET; return 0; } -static int mlx5_ib_query_ext_ppcnt_counters(struct mlx5_ib_dev *dev, - const struct mlx5_ib_counters *cnts, - struct rdma_hw_stats *stats) +static void get_dev_fw_str(struct ib_device *ibdev, char *str) { - int offset = cnts->num_q_counters + cnts->num_cong_counters; - int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); - int ret, i; - void *out; - - out = kvzalloc(sz, GFP_KERNEL); - if (!out) - return -ENOMEM; - - ret = mlx5_cmd_query_ext_ppcnt_counters(dev->mdev, out); - if (ret) - goto free; - - for (i = 0; i < cnts->num_ext_ppcnt_counters; i++) - stats->value[i + offset] = - be64_to_cpup((__be64 *)(out + - cnts->offsets[i + offset])); -free: - kvfree(out); - return ret; + struct mlx5_ib_dev *dev = + container_of(ibdev, struct mlx5_ib_dev, ib_dev); + snprintf(str, IB_FW_VERSION_NAME_MAX, "%d.%d.%04d", + fw_rev_maj(dev->mdev), fw_rev_min(dev->mdev), + fw_rev_sub(dev->mdev)); } -static int mlx5_ib_get_hw_stats(struct ib_device *ibdev, - struct rdma_hw_stats *stats, - u8 port_num, int index) +static int mlx5_eth_lag_init(struct mlx5_ib_dev *dev) { - struct mlx5_ib_dev *dev = to_mdev(ibdev); - const struct mlx5_ib_counters *cnts = get_counters(dev, port_num - 1); - struct mlx5_core_dev *mdev; - int ret, num_counters; - u8 mdev_port_num; - - if (!stats) - return -EINVAL; + struct mlx5_core_dev *mdev = dev->mdev; + struct mlx5_flow_namespace *ns = mlx5_get_flow_namespace(mdev, + MLX5_FLOW_NAMESPACE_LAG); + struct mlx5_flow_table *ft; + int err; - num_counters = cnts->num_q_counters + - cnts->num_cong_counters + - cnts->num_ext_ppcnt_counters; + if (!ns || !mlx5_lag_is_roce(mdev)) + return 0; - /* q_counters are per IB device, query the master mdev */ - ret = mlx5_ib_query_q_counters(dev->mdev, cnts, stats, cnts->set_id); - if (ret) - return ret; + err = mlx5_cmd_create_vport_lag(mdev); + if (err) + return err; - if (MLX5_CAP_PCAM_FEATURE(dev->mdev, rx_icrc_encapsulated_counter)) { - ret = mlx5_ib_query_ext_ppcnt_counters(dev, cnts, stats); - if (ret) - return ret; + ft = mlx5_create_lag_demux_flow_table(ns, 0, 0); + if (IS_ERR(ft)) { + err = PTR_ERR(ft); + goto err_destroy_vport_lag; } - if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { - mdev = mlx5_ib_get_native_port_mdev(dev, port_num, - &mdev_port_num); - if (!mdev) { - /* If port is not affiliated yet, its in down state - * which doesn't have any counters yet, so it would be - * zero. So no need to read from the HCA. - */ - goto done; - } - ret = mlx5_lag_query_cong_counters(dev->mdev, - stats->value + - cnts->num_q_counters, - cnts->num_cong_counters, - cnts->offsets + - cnts->num_q_counters); - - mlx5_ib_put_native_port_mdev(dev, port_num); - if (ret) - return ret; - } + dev->flow_db->lag_demux_ft = ft; + dev->lag_active = true; + return 0; -done: - return num_counters; +err_destroy_vport_lag: + mlx5_cmd_destroy_vport_lag(mdev); + return err; } -static struct rdma_hw_stats * -mlx5_ib_counter_alloc_stats(struct rdma_counter *counter) +static void mlx5_eth_lag_cleanup(struct mlx5_ib_dev *dev) { - struct mlx5_ib_dev *dev = to_mdev(counter->device); - const struct mlx5_ib_counters *cnts = - get_counters(dev, counter->port - 1); + struct mlx5_core_dev *mdev = dev->mdev; - return rdma_alloc_hw_stats_struct(cnts->names, - cnts->num_q_counters + - cnts->num_cong_counters + - cnts->num_ext_ppcnt_counters, - RDMA_HW_STATS_DEFAULT_LIFESPAN); -} + if (dev->lag_active) { + dev->lag_active = false; -static int mlx5_ib_counter_update_stats(struct rdma_counter *counter) -{ - struct mlx5_ib_dev *dev = to_mdev(counter->device); - const struct mlx5_ib_counters *cnts = - get_counters(dev, counter->port - 1); + mlx5_destroy_flow_table(dev->flow_db->lag_demux_ft); + dev->flow_db->lag_demux_ft = NULL; - return mlx5_ib_query_q_counters(dev->mdev, cnts, - counter->stats, counter->id); + mlx5_cmd_destroy_vport_lag(mdev); + } } -static int mlx5_ib_counter_dealloc(struct rdma_counter *counter) +static int mlx5_add_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num) { - struct mlx5_ib_dev *dev = to_mdev(counter->device); - u32 in[MLX5_ST_SZ_DW(dealloc_q_counter_in)] = {}; + int err; - if (!counter->id) - return 0; + dev->port[port_num].roce.nb.notifier_call = mlx5_netdev_event; + err = register_netdevice_notifier(&dev->port[port_num].roce.nb); + if (err) { + dev->port[port_num].roce.nb.notifier_call = NULL; + return err; + } - MLX5_SET(dealloc_q_counter_in, in, opcode, - MLX5_CMD_OP_DEALLOC_Q_COUNTER); - MLX5_SET(dealloc_q_counter_in, in, counter_set_id, counter->id); - return mlx5_cmd_exec_in(dev->mdev, dealloc_q_counter, in); + return 0; } -static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter, - struct ib_qp *qp) +static void mlx5_remove_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num) { - struct mlx5_ib_dev *dev = to_mdev(qp->device); - int err; + if (dev->port[port_num].roce.nb.notifier_call) { + unregister_netdevice_notifier(&dev->port[port_num].roce.nb); + dev->port[port_num].roce.nb.notifier_call = NULL; + } +} - if (!counter->id) { - u32 out[MLX5_ST_SZ_DW(alloc_q_counter_out)] = {}; - u32 in[MLX5_ST_SZ_DW(alloc_q_counter_in)] = {}; +static int mlx5_enable_eth(struct mlx5_ib_dev *dev) +{ + int err; - MLX5_SET(alloc_q_counter_in, in, opcode, - MLX5_CMD_OP_ALLOC_Q_COUNTER); - MLX5_SET(alloc_q_counter_in, in, uid, MLX5_SHARED_RESOURCE_UID); - err = mlx5_cmd_exec_inout(dev->mdev, alloc_q_counter, in, out); - if (err) - return err; - counter->id = - MLX5_GET(alloc_q_counter_out, out, counter_set_id); - } + err = mlx5_nic_vport_enable_roce(dev->mdev); + if (err) + return err; - err = mlx5_ib_qp_set_counter(qp, counter); + err = mlx5_eth_lag_init(dev); if (err) - goto fail_set_counter; + goto err_disable_roce; return 0; -fail_set_counter: - mlx5_ib_counter_dealloc(counter); - counter->id = 0; +err_disable_roce: + mlx5_nic_vport_disable_roce(dev->mdev); return err; } -static int mlx5_ib_counter_unbind_qp(struct ib_qp *qp) +static void mlx5_disable_eth(struct mlx5_ib_dev *dev) { - return mlx5_ib_qp_set_counter(qp, NULL); + mlx5_eth_lag_cleanup(dev); + mlx5_nic_vport_disable_roce(dev->mdev); } static int mlx5_ib_rn_get_params(struct ib_device *device, u8 port_num, @@ -5802,23 +3369,6 @@ static int mlx5_ib_rn_get_params(struct ib_device *device, u8 port_num, return mlx5_rdma_rn_get_params(to_mdev(device)->mdev, device, params); } -static void delay_drop_debugfs_cleanup(struct mlx5_ib_dev *dev) -{ - if (!dev->delay_drop.dir_debugfs) - return; - debugfs_remove_recursive(dev->delay_drop.dir_debugfs); - dev->delay_drop.dir_debugfs = NULL; -} - -static void cancel_delay_drop(struct mlx5_ib_dev *dev) -{ - if (!(dev->ib_dev.attrs.raw_packet_caps & IB_RAW_PACKET_CAP_DELAY_DROP)) - return; - - cancel_work_sync(&dev->delay_drop.delay_drop_work); - delay_drop_debugfs_cleanup(dev); -} - static ssize_t delay_drop_timeout_read(struct file *filp, char __user *buf, size_t count, loff_t *pos) { @@ -5858,40 +3408,6 @@ static const struct file_operations fops_delay_drop_timeout = { .read = delay_drop_timeout_read, }; -static void delay_drop_debugfs_init(struct mlx5_ib_dev *dev) -{ - struct dentry *root; - - if (!mlx5_debugfs_root) - return; - - root = debugfs_create_dir("delay_drop", dev->mdev->priv.dbg_root); - dev->delay_drop.dir_debugfs = root; - - debugfs_create_atomic_t("num_timeout_events", 0400, root, - &dev->delay_drop.events_cnt); - debugfs_create_atomic_t("num_rqs", 0400, root, - &dev->delay_drop.rqs_cnt); - debugfs_create_file("timeout", 0600, root, &dev->delay_drop, - &fops_delay_drop_timeout); -} - -static void init_delay_drop(struct mlx5_ib_dev *dev) -{ - if (!(dev->ib_dev.attrs.raw_packet_caps & IB_RAW_PACKET_CAP_DELAY_DROP)) - return; - - mutex_init(&dev->delay_drop.lock); - dev->delay_drop.dev = dev; - dev->delay_drop.activate = false; - dev->delay_drop.timeout = MLX5_MAX_DELAY_DROP_TIMEOUT_MS * 1000; - INIT_WORK(&dev->delay_drop.delay_drop_work, delay_drop_handler); - atomic_set(&dev->delay_drop.rqs_cnt, 0); - atomic_set(&dev->delay_drop.events_cnt, 0); - - delay_drop_debugfs_init(dev); -} - static void mlx5_ib_unbind_slave_port(struct mlx5_ib_dev *ibdev, struct mlx5_ib_multiport_info *mpi) { @@ -6385,90 +3901,32 @@ ADD_UVERBS_ATTRIBUTES_SIMPLE( UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS, enum mlx5_ib_uapi_flow_action_flags)); +ADD_UVERBS_ATTRIBUTES_SIMPLE( + mlx5_ib_query_context, + UVERBS_OBJECT_DEVICE, + UVERBS_METHOD_QUERY_CONTEXT, + UVERBS_ATTR_PTR_OUT( + MLX5_IB_ATTR_QUERY_CONTEXT_RESP_UCTX, + UVERBS_ATTR_STRUCT(struct mlx5_ib_alloc_ucontext_resp, + dump_fill_mkey), + UA_MANDATORY)); + static const struct uapi_definition mlx5_ib_defs[] = { UAPI_DEF_CHAIN(mlx5_ib_devx_defs), UAPI_DEF_CHAIN(mlx5_ib_flow_defs), UAPI_DEF_CHAIN(mlx5_ib_qos_defs), + UAPI_DEF_CHAIN(mlx5_ib_std_types_defs), UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION, &mlx5_ib_flow_action), UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_DM, &mlx5_ib_dm), + UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_DEVICE, &mlx5_ib_query_context), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_VAR, UAPI_DEF_IS_OBJ_SUPPORTED(var_is_supported)), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_UAR), {} }; -static int mlx5_ib_read_counters(struct ib_counters *counters, - struct ib_counters_read_attr *read_attr, - struct uverbs_attr_bundle *attrs) -{ - struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); - struct mlx5_read_counters_attr mread_attr = {}; - struct mlx5_ib_flow_counters_desc *desc; - int ret, i; - - mutex_lock(&mcounters->mcntrs_mutex); - if (mcounters->cntrs_max_index > read_attr->ncounters) { - ret = -EINVAL; - goto err_bound; - } - - mread_attr.out = kcalloc(mcounters->counters_num, sizeof(u64), - GFP_KERNEL); - if (!mread_attr.out) { - ret = -ENOMEM; - goto err_bound; - } - - mread_attr.hw_cntrs_hndl = mcounters->hw_cntrs_hndl; - mread_attr.flags = read_attr->flags; - ret = mcounters->read_counters(counters->device, &mread_attr); - if (ret) - goto err_read; - - /* do the pass over the counters data array to assign according to the - * descriptions and indexing pairs - */ - desc = mcounters->counters_data; - for (i = 0; i < mcounters->ncounters; i++) - read_attr->counters_buff[desc[i].index] += mread_attr.out[desc[i].description]; - -err_read: - kfree(mread_attr.out); -err_bound: - mutex_unlock(&mcounters->mcntrs_mutex); - return ret; -} - -static int mlx5_ib_destroy_counters(struct ib_counters *counters) -{ - struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); - - counters_clear_description(counters); - if (mcounters->hw_cntrs_hndl) - mlx5_fc_destroy(to_mdev(counters->device)->mdev, - mcounters->hw_cntrs_hndl); - - kfree(mcounters); - - return 0; -} - -static struct ib_counters *mlx5_ib_create_counters(struct ib_device *device, - struct uverbs_attr_bundle *attrs) -{ - struct mlx5_ib_mcounters *mcounters; - - mcounters = kzalloc(sizeof(*mcounters), GFP_KERNEL); - if (!mcounters) - return ERR_PTR(-ENOMEM); - - mutex_init(&mcounters->mcntrs_mutex); - - return &mcounters->ibcntrs; -} - static void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev) { mlx5_ib_cleanup_multiport_master(dev); @@ -6547,21 +4005,16 @@ err_mp: return -ENOMEM; } -static int mlx5_ib_stage_flow_db_init(struct mlx5_ib_dev *dev) +static int mlx5_ib_enable_driver(struct ib_device *dev) { - dev->flow_db = kzalloc(sizeof(*dev->flow_db), GFP_KERNEL); - - if (!dev->flow_db) - return -ENOMEM; - - mutex_init(&dev->flow_db->lock); + struct mlx5_ib_dev *mdev = to_mdev(dev); + int ret; - return 0; -} + ret = mlx5_ib_test_wc(mdev); + mlx5_ib_dbg(mdev, "Write-Combining %s", + mdev->wc_support ? "supported" : "not supported"); -static void mlx5_ib_stage_flow_db_cleanup(struct mlx5_ib_dev *dev) -{ - kfree(dev->flow_db); + return ret; } static const struct ib_device_ops mlx5_ib_dev_ops = { @@ -6577,9 +4030,7 @@ static const struct ib_device_ops mlx5_ib_dev_ops = { .attach_mcast = mlx5_ib_mcg_attach, .check_mr_status = mlx5_ib_check_mr_status, .create_ah = mlx5_ib_create_ah, - .create_counters = mlx5_ib_create_counters, .create_cq = mlx5_ib_create_cq, - .create_flow = mlx5_ib_create_flow, .create_qp = mlx5_ib_create_qp, .create_srq = mlx5_ib_create_srq, .dealloc_pd = mlx5_ib_dealloc_pd, @@ -6587,10 +4038,7 @@ static const struct ib_device_ops mlx5_ib_dev_ops = { .del_gid = mlx5_ib_del_gid, .dereg_mr = mlx5_ib_dereg_mr, .destroy_ah = mlx5_ib_destroy_ah, - .destroy_counters = mlx5_ib_destroy_counters, .destroy_cq = mlx5_ib_destroy_cq, - .destroy_flow = mlx5_ib_destroy_flow, - .destroy_flow_action = mlx5_ib_destroy_flow_action, .destroy_qp = mlx5_ib_destroy_qp, .destroy_srq = mlx5_ib_destroy_srq, .detach_mcast = mlx5_ib_mcg_detach, @@ -6598,8 +4046,6 @@ static const struct ib_device_ops mlx5_ib_dev_ops = { .drain_rq = mlx5_ib_drain_rq, .drain_sq = mlx5_ib_drain_sq, .enable_driver = mlx5_ib_enable_driver, - .fill_res_entry = mlx5_ib_fill_res_entry, - .fill_stat_entry = mlx5_ib_fill_stat_entry, .get_dev_fw_str = get_dev_fw_str, .get_dma_mr = mlx5_ib_get_dma_mr, .get_link_layer = mlx5_ib_port_link_layer, @@ -6623,24 +4069,20 @@ static const struct ib_device_ops mlx5_ib_dev_ops = { .query_pkey = mlx5_ib_query_pkey, .query_qp = mlx5_ib_query_qp, .query_srq = mlx5_ib_query_srq, - .read_counters = mlx5_ib_read_counters, + .query_ucontext = mlx5_ib_query_ucontext, .reg_user_mr = mlx5_ib_reg_user_mr, .req_notify_cq = mlx5_ib_arm_cq, .rereg_user_mr = mlx5_ib_rereg_user_mr, .resize_cq = mlx5_ib_resize_cq, INIT_RDMA_OBJ_SIZE(ib_ah, mlx5_ib_ah, ibah), + INIT_RDMA_OBJ_SIZE(ib_counters, mlx5_ib_mcounters, ibcntrs), INIT_RDMA_OBJ_SIZE(ib_cq, mlx5_ib_cq, ibcq), INIT_RDMA_OBJ_SIZE(ib_pd, mlx5_ib_pd, ibpd), INIT_RDMA_OBJ_SIZE(ib_srq, mlx5_ib_srq, ibsrq), INIT_RDMA_OBJ_SIZE(ib_ucontext, mlx5_ib_ucontext, ibucontext), }; -static const struct ib_device_ops mlx5_ib_dev_flow_ipsec_ops = { - .create_flow_action_esp = mlx5_ib_create_flow_action_esp, - .modify_flow_action_esp = mlx5_ib_modify_flow_action_esp, -}; - static const struct ib_device_ops mlx5_ib_dev_ipoib_enhanced_ops = { .rdma_netdev_get_params = mlx5_ib_rn_get_params, }; @@ -6661,6 +4103,8 @@ static const struct ib_device_ops mlx5_ib_dev_mw_ops = { static const struct ib_device_ops mlx5_ib_dev_xrc_ops = { .alloc_xrcd = mlx5_ib_alloc_xrcd, .dealloc_xrcd = mlx5_ib_dealloc_xrcd, + + INIT_RDMA_OBJ_SIZE(ib_xrcd, mlx5_ib_xrcd, ibxrcd), }; static const struct ib_device_ops mlx5_ib_dev_dm_ops = { @@ -6769,9 +4213,6 @@ static int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev) MLX5_GENERAL_OBJ_TYPES_CAP_SW_ICM) ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_dm_ops); - if (mlx5_accel_ipsec_device_caps(dev->mdev) & - MLX5_ACCEL_IPSEC_CAP_DEVICE) - ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_flow_ipsec_ops); ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_ops); if (IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)) @@ -6829,65 +4270,36 @@ static const struct ib_device_ops mlx5_ib_dev_common_roce_ops = { .modify_wq = mlx5_ib_modify_wq, }; -static int mlx5_ib_stage_common_roce_init(struct mlx5_ib_dev *dev) -{ - u8 port_num; - - dev->ib_dev.uverbs_ex_cmd_mask |= - (1ull << IB_USER_VERBS_EX_CMD_CREATE_WQ) | - (1ull << IB_USER_VERBS_EX_CMD_MODIFY_WQ) | - (1ull << IB_USER_VERBS_EX_CMD_DESTROY_WQ) | - (1ull << IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL) | - (1ull << IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL); - ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_common_roce_ops); - - port_num = mlx5_core_native_port_num(dev->mdev) - 1; - - /* Register only for native ports */ - return mlx5_add_netdev_notifier(dev, port_num); -} - -static void mlx5_ib_stage_common_roce_cleanup(struct mlx5_ib_dev *dev) -{ - u8 port_num = mlx5_core_native_port_num(dev->mdev) - 1; - - mlx5_remove_netdev_notifier(dev, port_num); -} - -static int mlx5_ib_stage_raw_eth_roce_init(struct mlx5_ib_dev *dev) -{ - struct mlx5_core_dev *mdev = dev->mdev; - enum rdma_link_layer ll; - int port_type_cap; - int err = 0; - - port_type_cap = MLX5_CAP_GEN(mdev, port_type); - ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap); - - if (ll == IB_LINK_LAYER_ETHERNET) - err = mlx5_ib_stage_common_roce_init(dev); - - return err; -} - -static void mlx5_ib_stage_raw_eth_roce_cleanup(struct mlx5_ib_dev *dev) -{ - mlx5_ib_stage_common_roce_cleanup(dev); -} - -static int mlx5_ib_stage_roce_init(struct mlx5_ib_dev *dev) +static int mlx5_ib_roce_init(struct mlx5_ib_dev *dev) { struct mlx5_core_dev *mdev = dev->mdev; enum rdma_link_layer ll; int port_type_cap; + u8 port_num = 0; int err; port_type_cap = MLX5_CAP_GEN(mdev, port_type); ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap); if (ll == IB_LINK_LAYER_ETHERNET) { - err = mlx5_ib_stage_common_roce_init(dev); - if (err) + dev->ib_dev.uverbs_ex_cmd_mask |= + (1ull << IB_USER_VERBS_EX_CMD_CREATE_WQ) | + (1ull << IB_USER_VERBS_EX_CMD_MODIFY_WQ) | + (1ull << IB_USER_VERBS_EX_CMD_DESTROY_WQ) | + (1ull << IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL) | + (1ull << IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL); + ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_common_roce_ops); + + port_num = mlx5_core_native_port_num(dev->mdev) - 1; + + /* Register only for native ports */ + err = mlx5_add_netdev_notifier(dev, port_num); + if (err || dev->is_rep || !mlx5_is_roce_enabled(mdev)) + /* + * We don't enable ETH interface for + * 1. IB representors + * 2. User disabled ROCE through devlink interface + */ return err; err = mlx5_enable_eth(dev); @@ -6897,71 +4309,27 @@ static int mlx5_ib_stage_roce_init(struct mlx5_ib_dev *dev) return 0; cleanup: - mlx5_ib_stage_common_roce_cleanup(dev); - + mlx5_remove_netdev_notifier(dev, port_num); return err; } -static void mlx5_ib_stage_roce_cleanup(struct mlx5_ib_dev *dev) +static void mlx5_ib_roce_cleanup(struct mlx5_ib_dev *dev) { struct mlx5_core_dev *mdev = dev->mdev; enum rdma_link_layer ll; int port_type_cap; + u8 port_num; port_type_cap = MLX5_CAP_GEN(mdev, port_type); ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap); if (ll == IB_LINK_LAYER_ETHERNET) { - mlx5_disable_eth(dev); - mlx5_ib_stage_common_roce_cleanup(dev); - } -} - -static int mlx5_ib_stage_dev_res_init(struct mlx5_ib_dev *dev) -{ - return create_dev_resources(&dev->devr); -} - -static void mlx5_ib_stage_dev_res_cleanup(struct mlx5_ib_dev *dev) -{ - destroy_dev_resources(&dev->devr); -} - -static int mlx5_ib_stage_odp_init(struct mlx5_ib_dev *dev) -{ - return mlx5_ib_odp_init_one(dev); -} - -static void mlx5_ib_stage_odp_cleanup(struct mlx5_ib_dev *dev) -{ - mlx5_ib_odp_cleanup_one(dev); -} - -static const struct ib_device_ops mlx5_ib_dev_hw_stats_ops = { - .alloc_hw_stats = mlx5_ib_alloc_hw_stats, - .get_hw_stats = mlx5_ib_get_hw_stats, - .counter_bind_qp = mlx5_ib_counter_bind_qp, - .counter_unbind_qp = mlx5_ib_counter_unbind_qp, - .counter_dealloc = mlx5_ib_counter_dealloc, - .counter_alloc_stats = mlx5_ib_counter_alloc_stats, - .counter_update_stats = mlx5_ib_counter_update_stats, -}; - -static int mlx5_ib_stage_counters_init(struct mlx5_ib_dev *dev) -{ - if (MLX5_CAP_GEN(dev->mdev, max_qp_cnt)) { - ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_hw_stats_ops); + if (!dev->is_rep) + mlx5_disable_eth(dev); - return mlx5_ib_alloc_counters(dev); + port_num = mlx5_core_native_port_num(dev->mdev) - 1; + mlx5_remove_netdev_notifier(dev, port_num); } - - return 0; -} - -static void mlx5_ib_stage_counters_cleanup(struct mlx5_ib_dev *dev) -{ - if (MLX5_CAP_GEN(dev->mdev, max_qp_cnt)) - mlx5_ib_dealloc_counters(dev); } static int mlx5_ib_stage_cong_debugfs_init(struct mlx5_ib_dev *dev) @@ -7023,7 +4391,18 @@ static int mlx5_ib_stage_ib_reg_init(struct mlx5_ib_dev *dev) static void mlx5_ib_stage_pre_ib_reg_umr_cleanup(struct mlx5_ib_dev *dev) { - destroy_umrc_res(dev); + int err; + + err = mlx5_mr_cache_cleanup(dev); + if (err) + mlx5_ib_warn(dev, "mr cache cleanup failed\n"); + + if (dev->umrc.qp) + mlx5_ib_destroy_qp(dev->umrc.qp, NULL); + if (dev->umrc.cq) + ib_free_cq(dev->umrc.cq); + if (dev->umrc.pd) + ib_dealloc_pd(dev->umrc.pd); } static void mlx5_ib_stage_ib_reg_cleanup(struct mlx5_ib_dev *dev) @@ -7031,21 +4410,162 @@ static void mlx5_ib_stage_ib_reg_cleanup(struct mlx5_ib_dev *dev) ib_unregister_device(&dev->ib_dev); } +enum { + MAX_UMR_WR = 128, +}; + static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev) { - return create_umr_res(dev); + struct ib_qp_init_attr *init_attr = NULL; + struct ib_qp_attr *attr = NULL; + struct ib_pd *pd; + struct ib_cq *cq; + struct ib_qp *qp; + int ret; + + attr = kzalloc(sizeof(*attr), GFP_KERNEL); + init_attr = kzalloc(sizeof(*init_attr), GFP_KERNEL); + if (!attr || !init_attr) { + ret = -ENOMEM; + goto error_0; + } + + pd = ib_alloc_pd(&dev->ib_dev, 0); + if (IS_ERR(pd)) { + mlx5_ib_dbg(dev, "Couldn't create PD for sync UMR QP\n"); + ret = PTR_ERR(pd); + goto error_0; + } + + cq = ib_alloc_cq(&dev->ib_dev, NULL, 128, 0, IB_POLL_SOFTIRQ); + if (IS_ERR(cq)) { + mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n"); + ret = PTR_ERR(cq); + goto error_2; + } + + init_attr->send_cq = cq; + init_attr->recv_cq = cq; + init_attr->sq_sig_type = IB_SIGNAL_ALL_WR; + init_attr->cap.max_send_wr = MAX_UMR_WR; + init_attr->cap.max_send_sge = 1; + init_attr->qp_type = MLX5_IB_QPT_REG_UMR; + init_attr->port_num = 1; + qp = mlx5_ib_create_qp(pd, init_attr, NULL); + if (IS_ERR(qp)) { + mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n"); + ret = PTR_ERR(qp); + goto error_3; + } + qp->device = &dev->ib_dev; + qp->real_qp = qp; + qp->uobject = NULL; + qp->qp_type = MLX5_IB_QPT_REG_UMR; + qp->send_cq = init_attr->send_cq; + qp->recv_cq = init_attr->recv_cq; + + attr->qp_state = IB_QPS_INIT; + attr->port_num = 1; + ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE | IB_QP_PKEY_INDEX | + IB_QP_PORT, NULL); + if (ret) { + mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n"); + goto error_4; + } + + memset(attr, 0, sizeof(*attr)); + attr->qp_state = IB_QPS_RTR; + attr->path_mtu = IB_MTU_256; + + ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL); + if (ret) { + mlx5_ib_dbg(dev, "Couldn't modify umr QP to rtr\n"); + goto error_4; + } + + memset(attr, 0, sizeof(*attr)); + attr->qp_state = IB_QPS_RTS; + ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL); + if (ret) { + mlx5_ib_dbg(dev, "Couldn't modify umr QP to rts\n"); + goto error_4; + } + + dev->umrc.qp = qp; + dev->umrc.cq = cq; + dev->umrc.pd = pd; + + sema_init(&dev->umrc.sem, MAX_UMR_WR); + ret = mlx5_mr_cache_init(dev); + if (ret) { + mlx5_ib_warn(dev, "mr cache init failed %d\n", ret); + goto error_4; + } + + kfree(attr); + kfree(init_attr); + + return 0; + +error_4: + mlx5_ib_destroy_qp(qp, NULL); + dev->umrc.qp = NULL; + +error_3: + ib_free_cq(cq); + dev->umrc.cq = NULL; + +error_2: + ib_dealloc_pd(pd); + dev->umrc.pd = NULL; + +error_0: + kfree(attr); + kfree(init_attr); + return ret; } static int mlx5_ib_stage_delay_drop_init(struct mlx5_ib_dev *dev) { - init_delay_drop(dev); + struct dentry *root; + + if (!(dev->ib_dev.attrs.raw_packet_caps & IB_RAW_PACKET_CAP_DELAY_DROP)) + return 0; + + mutex_init(&dev->delay_drop.lock); + dev->delay_drop.dev = dev; + dev->delay_drop.activate = false; + dev->delay_drop.timeout = MLX5_MAX_DELAY_DROP_TIMEOUT_MS * 1000; + INIT_WORK(&dev->delay_drop.delay_drop_work, delay_drop_handler); + atomic_set(&dev->delay_drop.rqs_cnt, 0); + atomic_set(&dev->delay_drop.events_cnt, 0); + + if (!mlx5_debugfs_root) + return 0; + + root = debugfs_create_dir("delay_drop", dev->mdev->priv.dbg_root); + dev->delay_drop.dir_debugfs = root; + debugfs_create_atomic_t("num_timeout_events", 0400, root, + &dev->delay_drop.events_cnt); + debugfs_create_atomic_t("num_rqs", 0400, root, + &dev->delay_drop.rqs_cnt); + debugfs_create_file("timeout", 0600, root, &dev->delay_drop, + &fops_delay_drop_timeout); return 0; } static void mlx5_ib_stage_delay_drop_cleanup(struct mlx5_ib_dev *dev) { - cancel_delay_drop(dev); + if (!(dev->ib_dev.attrs.raw_packet_caps & IB_RAW_PACKET_CAP_DELAY_DROP)) + return; + + cancel_work_sync(&dev->delay_drop.delay_drop_work); + if (!dev->delay_drop.dir_debugfs) + return; + + debugfs_remove_recursive(dev->delay_drop.dir_debugfs); + dev->delay_drop.dir_debugfs = NULL; } static int mlx5_ib_stage_dev_notifier_init(struct mlx5_ib_dev *dev) @@ -7060,38 +4580,6 @@ static void mlx5_ib_stage_dev_notifier_cleanup(struct mlx5_ib_dev *dev) mlx5_notifier_unregister(dev->mdev, &dev->mdev_events); } -static int mlx5_ib_stage_devx_init(struct mlx5_ib_dev *dev) -{ - int uid; - - uid = mlx5_ib_devx_create(dev, false); - if (uid > 0) { - dev->devx_whitelist_uid = uid; - mlx5_ib_devx_init_event_table(dev); - } - - return 0; -} -static void mlx5_ib_stage_devx_cleanup(struct mlx5_ib_dev *dev) -{ - if (dev->devx_whitelist_uid) { - mlx5_ib_devx_cleanup_event_table(dev); - mlx5_ib_devx_destroy(dev, dev->devx_whitelist_uid); - } -} - -int mlx5_ib_enable_driver(struct ib_device *dev) -{ - struct mlx5_ib_dev *mdev = to_mdev(dev); - int ret; - - ret = mlx5_ib_test_wc(mdev); - mlx5_ib_dbg(mdev, "Write-Combining %s", - mdev->wc_support ? "supported" : "not supported"); - - return ret; -} - void __mlx5_ib_remove(struct mlx5_ib_dev *dev, const struct mlx5_ib_profile *profile, int stage) @@ -7139,9 +4627,9 @@ static const struct mlx5_ib_profile pf_profile = { STAGE_CREATE(MLX5_IB_STAGE_INIT, mlx5_ib_stage_init_init, mlx5_ib_stage_init_cleanup), - STAGE_CREATE(MLX5_IB_STAGE_FLOW_DB, - mlx5_ib_stage_flow_db_init, - mlx5_ib_stage_flow_db_cleanup), + STAGE_CREATE(MLX5_IB_STAGE_FS, + mlx5_ib_fs_init, + mlx5_ib_fs_cleanup), STAGE_CREATE(MLX5_IB_STAGE_CAPS, mlx5_ib_stage_caps_init, mlx5_ib_stage_caps_cleanup), @@ -7149,8 +4637,8 @@ static const struct mlx5_ib_profile pf_profile = { mlx5_ib_stage_non_default_cb, NULL), STAGE_CREATE(MLX5_IB_STAGE_ROCE, - mlx5_ib_stage_roce_init, - mlx5_ib_stage_roce_cleanup), + mlx5_ib_roce_init, + mlx5_ib_roce_cleanup), STAGE_CREATE(MLX5_IB_STAGE_QP, mlx5_init_qp_table, mlx5_cleanup_qp_table), @@ -7158,17 +4646,17 @@ static const struct mlx5_ib_profile pf_profile = { mlx5_init_srq_table, mlx5_cleanup_srq_table), STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES, - mlx5_ib_stage_dev_res_init, - mlx5_ib_stage_dev_res_cleanup), + mlx5_ib_dev_res_init, + mlx5_ib_dev_res_cleanup), STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER, mlx5_ib_stage_dev_notifier_init, mlx5_ib_stage_dev_notifier_cleanup), STAGE_CREATE(MLX5_IB_STAGE_ODP, - mlx5_ib_stage_odp_init, - mlx5_ib_stage_odp_cleanup), + mlx5_ib_odp_init_one, + mlx5_ib_odp_cleanup_one), STAGE_CREATE(MLX5_IB_STAGE_COUNTERS, - mlx5_ib_stage_counters_init, - mlx5_ib_stage_counters_cleanup), + mlx5_ib_counters_init, + mlx5_ib_counters_cleanup), STAGE_CREATE(MLX5_IB_STAGE_CONG_DEBUGFS, mlx5_ib_stage_cong_debugfs_init, mlx5_ib_stage_cong_debugfs_cleanup), @@ -7182,8 +4670,8 @@ static const struct mlx5_ib_profile pf_profile = { NULL, mlx5_ib_stage_pre_ib_reg_umr_cleanup), STAGE_CREATE(MLX5_IB_STAGE_WHITELIST_UID, - mlx5_ib_stage_devx_init, - mlx5_ib_stage_devx_cleanup), + mlx5_ib_devx_init, + mlx5_ib_devx_cleanup), STAGE_CREATE(MLX5_IB_STAGE_IB_REG, mlx5_ib_stage_ib_reg_init, mlx5_ib_stage_ib_reg_cleanup), @@ -7193,15 +4681,18 @@ static const struct mlx5_ib_profile pf_profile = { STAGE_CREATE(MLX5_IB_STAGE_DELAY_DROP, mlx5_ib_stage_delay_drop_init, mlx5_ib_stage_delay_drop_cleanup), + STAGE_CREATE(MLX5_IB_STAGE_RESTRACK, + mlx5_ib_restrack_init, + NULL), }; const struct mlx5_ib_profile raw_eth_profile = { STAGE_CREATE(MLX5_IB_STAGE_INIT, mlx5_ib_stage_init_init, mlx5_ib_stage_init_cleanup), - STAGE_CREATE(MLX5_IB_STAGE_FLOW_DB, - mlx5_ib_stage_flow_db_init, - mlx5_ib_stage_flow_db_cleanup), + STAGE_CREATE(MLX5_IB_STAGE_FS, + mlx5_ib_fs_init, + mlx5_ib_fs_cleanup), STAGE_CREATE(MLX5_IB_STAGE_CAPS, mlx5_ib_stage_caps_init, mlx5_ib_stage_caps_cleanup), @@ -7209,8 +4700,8 @@ const struct mlx5_ib_profile raw_eth_profile = { mlx5_ib_stage_raw_eth_non_default_cb, NULL), STAGE_CREATE(MLX5_IB_STAGE_ROCE, - mlx5_ib_stage_raw_eth_roce_init, - mlx5_ib_stage_raw_eth_roce_cleanup), + mlx5_ib_roce_init, + mlx5_ib_roce_cleanup), STAGE_CREATE(MLX5_IB_STAGE_QP, mlx5_init_qp_table, mlx5_cleanup_qp_table), @@ -7218,14 +4709,14 @@ const struct mlx5_ib_profile raw_eth_profile = { mlx5_init_srq_table, mlx5_cleanup_srq_table), STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES, - mlx5_ib_stage_dev_res_init, - mlx5_ib_stage_dev_res_cleanup), + mlx5_ib_dev_res_init, + mlx5_ib_dev_res_cleanup), STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER, mlx5_ib_stage_dev_notifier_init, mlx5_ib_stage_dev_notifier_cleanup), STAGE_CREATE(MLX5_IB_STAGE_COUNTERS, - mlx5_ib_stage_counters_init, - mlx5_ib_stage_counters_cleanup), + mlx5_ib_counters_init, + mlx5_ib_counters_cleanup), STAGE_CREATE(MLX5_IB_STAGE_CONG_DEBUGFS, mlx5_ib_stage_cong_debugfs_init, mlx5_ib_stage_cong_debugfs_cleanup), @@ -7239,14 +4730,17 @@ const struct mlx5_ib_profile raw_eth_profile = { NULL, mlx5_ib_stage_pre_ib_reg_umr_cleanup), STAGE_CREATE(MLX5_IB_STAGE_WHITELIST_UID, - mlx5_ib_stage_devx_init, - mlx5_ib_stage_devx_cleanup), + mlx5_ib_devx_init, + mlx5_ib_devx_cleanup), STAGE_CREATE(MLX5_IB_STAGE_IB_REG, mlx5_ib_stage_ib_reg_init, mlx5_ib_stage_ib_reg_cleanup), STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR, mlx5_ib_stage_post_ib_reg_umr_init, NULL), + STAGE_CREATE(MLX5_IB_STAGE_RESTRACK, + mlx5_ib_restrack_init, + NULL), }; static void *mlx5_ib_add_slave_port(struct mlx5_core_dev *mdev) diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 5dbe3eb0d9cb9231766d7ea776b05506ef41a09c..5287fc8686627898ca04ddfc5cc0e4701587f201 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h @@ -1,33 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* - * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * Copyright (c) 2013-2020, Mellanox Technologies inc. All rights reserved. */ #ifndef MLX5_IB_H @@ -730,8 +703,8 @@ struct mlx5_ib_port_resources { struct mlx5_ib_resources { struct ib_cq *c0; - struct ib_xrcd *x0; - struct ib_xrcd *x1; + u32 xrcdn0; + u32 xrcdn1; struct ib_pd *p0; struct ib_srq *s0; struct ib_srq *s1; @@ -832,7 +805,7 @@ struct mlx5_ib_delay_drop { enum mlx5_ib_stages { MLX5_IB_STAGE_INIT, - MLX5_IB_STAGE_FLOW_DB, + MLX5_IB_STAGE_FS, MLX5_IB_STAGE_CAPS, MLX5_IB_STAGE_NON_DEFAULT_CB, MLX5_IB_STAGE_ROCE, @@ -850,7 +823,7 @@ enum mlx5_ib_stages { MLX5_IB_STAGE_IB_REG, MLX5_IB_STAGE_POST_IB_REG_UMR, MLX5_IB_STAGE_DELAY_DROP, - MLX5_IB_STAGE_CLASS_ATTR, + MLX5_IB_STAGE_RESTRACK, MLX5_IB_STAGE_MAX, }; @@ -1078,11 +1051,6 @@ static inline struct mlx5_ib_rwq *to_mibrwq(struct mlx5_core_qp *core_qp) return container_of(core_qp, struct mlx5_ib_rwq, core_qp); } -static inline struct mlx5_ib_mr *to_mibmr(struct mlx5_core_mkey *mmkey) -{ - return container_of(mmkey, struct mlx5_ib_mr, mmkey); -} - static inline struct mlx5_ib_pd *to_mpd(struct ib_pd *ibpd) { return container_of(ibpd, struct mlx5_ib_pd, ibpd); @@ -1210,7 +1178,7 @@ int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start, struct ib_pd *pd, struct ib_udata *udata); int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata); struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata); + u32 max_num_sg); struct ib_mr *mlx5_ib_alloc_mr_integrity(struct ib_pd *pd, u32 max_num_sg, u32 max_num_meta_sg); @@ -1224,9 +1192,8 @@ int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, const struct ib_wc *in_wc, const struct ib_grh *in_grh, const struct ib_mad *in, struct ib_mad *out, size_t *out_mad_size, u16 *out_mad_pkey_index); -struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev, - struct ib_udata *udata); -int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata); +int mlx5_ib_alloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata); +void mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata); int mlx5_ib_get_buf_offset(u64 addr, int page_shift, u32 *offset); int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port); int mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev, @@ -1375,46 +1342,12 @@ struct mlx5_core_dev *mlx5_ib_get_native_port_mdev(struct mlx5_ib_dev *dev, u8 *native_port_num); void mlx5_ib_put_native_port_mdev(struct mlx5_ib_dev *dev, u8 port_num); -int mlx5_ib_fill_res_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res); -int mlx5_ib_fill_stat_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res); extern const struct uapi_definition mlx5_ib_devx_defs[]; extern const struct uapi_definition mlx5_ib_flow_defs[]; extern const struct uapi_definition mlx5_ib_qos_defs[]; +extern const struct uapi_definition mlx5_ib_std_types_defs[]; -#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS) -int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user); -void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid); -void mlx5_ib_devx_init_event_table(struct mlx5_ib_dev *dev); -void mlx5_ib_devx_cleanup_event_table(struct mlx5_ib_dev *dev); -struct mlx5_ib_flow_handler *mlx5_ib_raw_fs_rule_add( - struct mlx5_ib_dev *dev, struct mlx5_ib_flow_matcher *fs_matcher, - struct mlx5_flow_context *flow_context, - struct mlx5_flow_act *flow_act, u32 counter_id, - void *cmd_in, int inlen, int dest_id, int dest_type); -bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type); -bool mlx5_ib_devx_is_flow_counter(void *obj, u32 offset, u32 *counter_id); -void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction); -#else -static inline int -mlx5_ib_devx_create(struct mlx5_ib_dev *dev, - bool is_user) { return -EOPNOTSUPP; } -static inline void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid) {} -static inline void mlx5_ib_devx_init_event_table(struct mlx5_ib_dev *dev) {} -static inline void mlx5_ib_devx_cleanup_event_table(struct mlx5_ib_dev *dev) {} -static inline bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, - int *dest_type) -{ - return false; -} -static inline void -mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction) -{ - return; -}; -#endif static inline void init_query_mad(struct ib_smp *mad) { mad->base_version = 1; @@ -1423,15 +1356,6 @@ static inline void init_query_mad(struct ib_smp *mad) mad->method = IB_MGMT_METHOD_GET; } -static inline u8 convert_access(int acc) -{ - return (acc & IB_ACCESS_REMOTE_ATOMIC ? MLX5_PERM_ATOMIC : 0) | - (acc & IB_ACCESS_REMOTE_WRITE ? MLX5_PERM_REMOTE_WRITE : 0) | - (acc & IB_ACCESS_REMOTE_READ ? MLX5_PERM_REMOTE_READ : 0) | - (acc & IB_ACCESS_LOCAL_WRITE ? MLX5_PERM_LOCAL_WRITE : 0) | - MLX5_PERM_LOCAL_READ; -} - static inline int is_qp1(enum ib_qp_type qp_type) { return qp_type == MLX5_IB_QPT_HW_GSI; @@ -1518,9 +1442,6 @@ int bfregn_to_uar_index(struct mlx5_ib_dev *dev, struct mlx5_bfreg_info *bfregi, u32 bfregn, bool dyn_bfreg); -int mlx5_ib_qp_set_counter(struct ib_qp *qp, struct rdma_counter *counter); -u16 mlx5_ib_get_counters_id(struct mlx5_ib_dev *dev, u8 port_num); - static inline bool mlx5_ib_can_use_umr(struct mlx5_ib_dev *dev, bool do_modify_atomic, int access_flags) { @@ -1533,14 +1454,18 @@ static inline bool mlx5_ib_can_use_umr(struct mlx5_ib_dev *dev, return false; if (access_flags & IB_ACCESS_RELAXED_ORDERING && - (MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write) || - MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read))) + MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write) && + !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr)) + return false; + + if (access_flags & IB_ACCESS_RELAXED_ORDERING && + MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read) && + !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr)) return false; return true; } -int mlx5_ib_enable_driver(struct ib_device *dev); int mlx5_ib_test_wc(struct mlx5_ib_dev *dev); static inline bool mlx5_ib_lag_should_assign_affinity(struct mlx5_ib_dev *dev) diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index 44683073be0c4a7988d6f3eb917936b444470de1..3e6f2f9c6655578adf4992413403cce991983350 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c @@ -1961,7 +1961,7 @@ err_free: } struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata) + u32 max_num_sg) { return __mlx5_ib_alloc_mr(pd, mr_type, max_num_sg, 0); } diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c index 77dca1e05bba8db7dc40c6346855c84386302f4b..cfd7efab114e2dfa062982d354b90556d7b449a1 100644 --- a/drivers/infiniband/hw/mlx5/odp.c +++ b/drivers/infiniband/hw/mlx5/odp.c @@ -816,6 +816,7 @@ static int pagefault_mr(struct mlx5_ib_mr *mr, u64 io_virt, size_t bcnt, { struct ib_umem_odp *odp = to_ib_umem_odp(mr->umem); + lockdep_assert_held(&mr->dev->odp_srcu); if (unlikely(io_virt < mr->mmkey.iova)) return -EFAULT; @@ -929,11 +930,6 @@ next_mr: if (ret < 0) goto srcu_unlock; - /* - * When prefetching a page, page fault is generated - * in order to bring the page to the main memory. - * In the current flow, page faults are being counted. - */ mlx5_update_odp_stats(mr, faults, ret); npages += ret; @@ -1770,13 +1766,26 @@ static void mlx5_ib_prefetch_mr_work(struct work_struct *w) { struct prefetch_mr_work *work = container_of(w, struct prefetch_mr_work, work); + struct mlx5_ib_dev *dev; u32 bytes_mapped = 0; + int srcu_key; + int ret; u32 i; - for (i = 0; i < work->num_sge; ++i) - pagefault_mr(work->frags[i].mr, work->frags[i].io_virt, - work->frags[i].length, &bytes_mapped, - work->pf_flags); + /* We rely on IB/core that work is executed if we have num_sge != 0 only. */ + WARN_ON(!work->num_sge); + dev = work->frags[0].mr->dev; + /* SRCU should be held when calling to mlx5_odp_populate_xlt() */ + srcu_key = srcu_read_lock(&dev->odp_srcu); + for (i = 0; i < work->num_sge; ++i) { + ret = pagefault_mr(work->frags[i].mr, work->frags[i].io_virt, + work->frags[i].length, &bytes_mapped, + work->pf_flags); + if (ret <= 0) + continue; + mlx5_update_odp_stats(work->frags[i].mr, prefetch, ret); + } + srcu_read_unlock(&dev->odp_srcu, srcu_key); destroy_prefetch_work(work); } @@ -1832,6 +1841,7 @@ static int mlx5_ib_prefetch_sg_list(struct ib_pd *pd, &bytes_mapped, pf_flags); if (ret < 0) goto out; + mlx5_update_odp_stats(mr, prefetch, ret); } ret = 0; diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 1225b8d77510f70d8dd503abeb8312e6ee0148c7..59fce5fac7a3342ef4d3ae07a3a62440b1328380 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -38,6 +38,7 @@ #include #include "mlx5_ib.h" #include "ib_rep.h" +#include "counters.h" #include "cmd.h" #include "qp.h" #include "wr.h" @@ -2031,15 +2032,15 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd, switch (init_attr->qp_type) { case IB_QPT_XRC_INI: MLX5_SET(qpc, qpc, cqn_rcv, to_mcq(devr->c0)->mcq.cqn); - MLX5_SET(qpc, qpc, xrcd, to_mxrcd(devr->x1)->xrcdn); + MLX5_SET(qpc, qpc, xrcd, devr->xrcdn1); MLX5_SET(qpc, qpc, srqn_rmpn_xrqn, to_msrq(devr->s0)->msrq.srqn); break; default: if (init_attr->srq) { - MLX5_SET(qpc, qpc, xrcd, to_mxrcd(devr->x0)->xrcdn); + MLX5_SET(qpc, qpc, xrcd, devr->xrcdn0); MLX5_SET(qpc, qpc, srqn_rmpn_xrqn, to_msrq(init_attr->srq)->msrq.srqn); } else { - MLX5_SET(qpc, qpc, xrcd, to_mxrcd(devr->x1)->xrcdn); + MLX5_SET(qpc, qpc, xrcd, devr->xrcdn1); MLX5_SET(qpc, qpc, srqn_rmpn_xrqn, to_msrq(devr->s1)->msrq.srqn); } } @@ -2178,11 +2179,11 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd, MLX5_SET(qpc, qpc, no_sq, 1); if (attr->srq) { - MLX5_SET(qpc, qpc, xrcd, to_mxrcd(devr->x0)->xrcdn); + MLX5_SET(qpc, qpc, xrcd, devr->xrcdn0); MLX5_SET(qpc, qpc, srqn_rmpn_xrqn, to_msrq(attr->srq)->msrq.srqn); } else { - MLX5_SET(qpc, qpc, xrcd, to_mxrcd(devr->x1)->xrcdn); + MLX5_SET(qpc, qpc, xrcd, devr->xrcdn1); MLX5_SET(qpc, qpc, srqn_rmpn_xrqn, to_msrq(devr->s1)->msrq.srqn); } @@ -3554,7 +3555,7 @@ static int modify_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp, switch (raw_qp_param->operation) { case MLX5_CMD_OP_RST2INIT_QP: rq_state = MLX5_RQC_STATE_RDY; - sq_state = MLX5_SQC_STATE_RDY; + sq_state = MLX5_SQC_STATE_RST; break; case MLX5_CMD_OP_2ERR_QP: rq_state = MLX5_RQC_STATE_ERR; @@ -3566,13 +3567,11 @@ static int modify_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp, break; case MLX5_CMD_OP_RTR2RTS_QP: case MLX5_CMD_OP_RTS2RTS_QP: - if (raw_qp_param->set_mask == - MLX5_RAW_QP_RATE_LIMIT) { - modify_rq = 0; - sq_state = sq->state; - } else { - return raw_qp_param->set_mask ? -EINVAL : 0; - } + if (raw_qp_param->set_mask & ~MLX5_RAW_QP_RATE_LIMIT) + return -EINVAL; + + modify_rq = 0; + sq_state = MLX5_SQC_STATE_RDY; break; case MLX5_CMD_OP_INIT2INIT_QP: case MLX5_CMD_OP_INIT2RTR_QP: @@ -4114,9 +4113,9 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr, struct mlx5_ib_qp *qp = to_mqp(ibqp); struct mlx5_ib_dev *dev = to_mdev(ibqp->device); enum ib_qp_state cur_state, new_state; - int err = 0; int required = IB_QP_STATE; void *dctc; + int err; if (!(attr_mask & IB_QP_STATE)) return -EINVAL; @@ -4208,11 +4207,9 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr, mlx5_ib_warn(dev, "Modify DCT: Invalid transition from %d to %d\n", cur_state, new_state); return -EINVAL; } - if (err) - qp->state = IB_QPS_ERR; - else - qp->state = new_state; - return err; + + qp->state = new_state; + return 0; } int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, @@ -4450,7 +4447,7 @@ static int sqrq_state_to_qp_state(u8 sq_state, u8 rq_state, [MLX5_SQ_STATE_NA] = IB_QPS_RESET, }, [MLX5_RQC_STATE_RDY] = { - [MLX5_SQC_STATE_RST] = MLX5_QP_STATE_BAD, + [MLX5_SQC_STATE_RST] = MLX5_QP_STATE, [MLX5_SQC_STATE_RDY] = MLX5_QP_STATE, [MLX5_SQC_STATE_ERR] = IB_QPS_SQE, [MLX5_SQ_STATE_NA] = MLX5_QP_STATE, @@ -4462,7 +4459,7 @@ static int sqrq_state_to_qp_state(u8 sq_state, u8 rq_state, [MLX5_SQ_STATE_NA] = IB_QPS_ERR, }, [MLX5_RQ_STATE_NA] = { - [MLX5_SQC_STATE_RST] = IB_QPS_RESET, + [MLX5_SQC_STATE_RST] = MLX5_QP_STATE, [MLX5_SQC_STATE_RDY] = MLX5_QP_STATE, [MLX5_SQC_STATE_ERR] = MLX5_QP_STATE, [MLX5_SQ_STATE_NA] = MLX5_QP_STATE_BAD, @@ -4708,41 +4705,23 @@ out: return err; } -struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev, - struct ib_udata *udata) +int mlx5_ib_alloc_xrcd(struct ib_xrcd *ibxrcd, struct ib_udata *udata) { - struct mlx5_ib_dev *dev = to_mdev(ibdev); - struct mlx5_ib_xrcd *xrcd; - int err; + struct mlx5_ib_dev *dev = to_mdev(ibxrcd->device); + struct mlx5_ib_xrcd *xrcd = to_mxrcd(ibxrcd); if (!MLX5_CAP_GEN(dev->mdev, xrc)) - return ERR_PTR(-ENOSYS); - - xrcd = kmalloc(sizeof(*xrcd), GFP_KERNEL); - if (!xrcd) - return ERR_PTR(-ENOMEM); - - err = mlx5_cmd_xrcd_alloc(dev->mdev, &xrcd->xrcdn, 0); - if (err) { - kfree(xrcd); - return ERR_PTR(-ENOMEM); - } + return -EOPNOTSUPP; - return &xrcd->ibxrcd; + return mlx5_cmd_xrcd_alloc(dev->mdev, &xrcd->xrcdn, 0); } -int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata) +void mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata) { struct mlx5_ib_dev *dev = to_mdev(xrcd->device); u32 xrcdn = to_mxrcd(xrcd)->xrcdn; - int err; - err = mlx5_cmd_xrcd_dealloc(dev->mdev, xrcdn, 0); - if (err) - mlx5_ib_warn(dev, "failed to dealloc xrcdn 0x%x\n", xrcdn); - - kfree(xrcd); - return 0; + mlx5_cmd_xrcd_dealloc(dev->mdev, xrcdn, 0); } static void mlx5_ib_wq_event(struct mlx5_core_qp *core_qp, int type) diff --git a/drivers/infiniband/hw/mlx5/qp.h b/drivers/infiniband/hw/mlx5/qp.h index 82ea2b94dfa6334b37dd5a256b5a44a4722289e8..ba899df44c5b446debd0fca318fe57e4ff2c01f1 100644 --- a/drivers/infiniband/hw/mlx5/qp.h +++ b/drivers/infiniband/hw/mlx5/qp.h @@ -43,4 +43,5 @@ void mlx5_core_res_put(struct mlx5_core_rsc_common *res); int mlx5_core_xrcd_alloc(struct mlx5_ib_dev *dev, u32 *xrcdn); int mlx5_core_xrcd_dealloc(struct mlx5_ib_dev *dev, u32 xrcdn); +int mlx5_ib_qp_set_counter(struct ib_qp *qp, struct rdma_counter *counter); #endif /* _MLX5_IB_QP_H */ diff --git a/drivers/infiniband/hw/mlx5/restrack.c b/drivers/infiniband/hw/mlx5/restrack.c index 8f6c04f12531c113c436808c1e847920e6e2c720..887270dd3ce207de8409f76d723ff28111a106ef 100644 --- a/drivers/infiniband/hw/mlx5/restrack.c +++ b/drivers/infiniband/hw/mlx5/restrack.c @@ -1,17 +1,85 @@ // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB /* - * Copyright (c) 2019, Mellanox Technologies inc. All rights reserved. + * Copyright (c) 2019-2020, Mellanox Technologies Ltd. All rights reserved. */ #include +#include #include #include #include "mlx5_ib.h" +#include "restrack.h" -static int fill_stat_mr_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res) +#define MAX_DUMP_SIZE 1024 + +static int dump_rsc(struct mlx5_core_dev *dev, enum mlx5_sgmt_type type, + int index, void *data, int *data_len) +{ + struct mlx5_core_dev *mdev = dev; + struct mlx5_rsc_dump_cmd *cmd; + struct mlx5_rsc_key key = {}; + struct page *page; + int offset = 0; + int err = 0; + int cmd_err; + int size; + + page = alloc_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + key.size = PAGE_SIZE; + key.rsc = type; + key.index1 = index; + key.num_of_obj1 = 1; + + cmd = mlx5_rsc_dump_cmd_create(mdev, &key); + if (IS_ERR(cmd)) { + err = PTR_ERR(cmd); + goto free_page; + } + + do { + cmd_err = mlx5_rsc_dump_next(mdev, cmd, page, &size); + if (cmd_err < 0 || size + offset > MAX_DUMP_SIZE) { + err = cmd_err; + goto destroy_cmd; + } + memcpy(data + offset, page_address(page), size); + offset += size; + } while (cmd_err > 0); + *data_len = offset; + +destroy_cmd: + mlx5_rsc_dump_cmd_destroy(cmd); +free_page: + __free_page(page); + return err; +} + +static int fill_res_raw(struct sk_buff *msg, struct mlx5_ib_dev *dev, + enum mlx5_sgmt_type type, u32 key) +{ + int len = 0; + void *data; + int err; + + data = kzalloc(MAX_DUMP_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + + err = dump_rsc(dev->mdev, type, key, data, &len); + if (err) + goto out; + + err = nla_put(msg, RDMA_NLDEV_ATTR_RES_RAW, len, data); +out: + kfree(data); + return err; +} + +static int fill_stat_mr_entry(struct sk_buff *msg, struct ib_mr *ibmr) { - struct ib_mr *ibmr = container_of(res, struct ib_mr, res); struct mlx5_ib_mr *mr = to_mmr(ibmr); struct nlattr *table_attr; @@ -31,6 +99,9 @@ static int fill_stat_mr_entry(struct sk_buff *msg, msg, "page_invalidations", atomic64_read(&mr->odp_stats.invalidations))) goto err_table; + if (rdma_nl_stat_hwcounter_entry(msg, "page_prefetch", + atomic64_read(&mr->odp_stats.prefetch))) + goto err_table; nla_nest_end(msg, table_attr); return 0; @@ -41,10 +112,16 @@ err: return -EMSGSIZE; } -static int fill_res_mr_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res) +static int fill_res_mr_entry_raw(struct sk_buff *msg, struct ib_mr *ibmr) +{ + struct mlx5_ib_mr *mr = to_mmr(ibmr); + + return fill_res_raw(msg, mr->dev, MLX5_SGMT_TYPE_PRM_QUERY_MKEY, + mlx5_mkey_to_idx(mr->mmkey.key)); +} + +static int fill_res_mr_entry(struct sk_buff *msg, struct ib_mr *ibmr) { - struct ib_mr *ibmr = container_of(res, struct ib_mr, res); struct mlx5_ib_mr *mr = to_mmr(ibmr); struct nlattr *table_attr; @@ -71,20 +148,32 @@ err: return -EMSGSIZE; } -int mlx5_ib_fill_res_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res) +static int fill_res_cq_entry_raw(struct sk_buff *msg, struct ib_cq *ibcq) { - if (res->type == RDMA_RESTRACK_MR) - return fill_res_mr_entry(msg, res); + struct mlx5_ib_dev *dev = to_mdev(ibcq->device); + struct mlx5_ib_cq *cq = to_mcq(ibcq); - return 0; + return fill_res_raw(msg, dev, MLX5_SGMT_TYPE_PRM_QUERY_CQ, cq->mcq.cqn); } -int mlx5_ib_fill_stat_entry(struct sk_buff *msg, - struct rdma_restrack_entry *res) +static int fill_res_qp_entry_raw(struct sk_buff *msg, struct ib_qp *ibqp) { - if (res->type == RDMA_RESTRACK_MR) - return fill_stat_mr_entry(msg, res); + struct mlx5_ib_dev *dev = to_mdev(ibqp->device); + + return fill_res_raw(msg, dev, MLX5_SGMT_TYPE_PRM_QUERY_QP, + ibqp->qp_num); +} +static const struct ib_device_ops restrack_ops = { + .fill_res_cq_entry_raw = fill_res_cq_entry_raw, + .fill_res_mr_entry = fill_res_mr_entry, + .fill_res_mr_entry_raw = fill_res_mr_entry_raw, + .fill_res_qp_entry_raw = fill_res_qp_entry_raw, + .fill_stat_mr_entry = fill_stat_mr_entry, +}; + +int mlx5_ib_restrack_init(struct mlx5_ib_dev *dev) +{ + ib_set_device_ops(&dev->ib_dev, &restrack_ops); return 0; } diff --git a/drivers/infiniband/hw/mlx5/restrack.h b/drivers/infiniband/hw/mlx5/restrack.h new file mode 100644 index 0000000000000000000000000000000000000000..e8d81270f1b67eb6e59ec28f85288742a9594f58 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/restrack.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* + * Copyright (c) 2013-2020, Mellanox Technologies Ltd. All rights reserved. + */ + +#ifndef _MLX5_IB_RESTRACK_H +#define _MLX5_IB_RESTRACK_H + +#include "mlx5_ib.h" + +int mlx5_ib_restrack_init(struct mlx5_ib_dev *dev); + +#endif /* _MLX5_IB_RESTRACK_H */ diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c index 6d1ff13d2283c8bd776a668141b397c046a6c669..7e10cbcb6d5c2acd1c06e294d3037e89441b636f 100644 --- a/drivers/infiniband/hw/mlx5/srq.c +++ b/drivers/infiniband/hw/mlx5/srq.c @@ -274,10 +274,10 @@ int mlx5_ib_create_srq(struct ib_srq *ib_srq, if (srq->wq_sig) in.flags |= MLX5_SRQ_FLAG_WQ_SIG; - if (init_attr->srq_type == IB_SRQT_XRC) + if (init_attr->srq_type == IB_SRQT_XRC && init_attr->ext.xrc.xrcd) in.xrcd = to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn; else - in.xrcd = to_mxrcd(dev->devr.x0)->xrcdn; + in.xrcd = dev->devr.xrcdn0; if (init_attr->srq_type == IB_SRQT_TM) { in.tm_log_list_size = diff --git a/drivers/infiniband/hw/mlx5/std_types.c b/drivers/infiniband/hw/mlx5/std_types.c new file mode 100644 index 0000000000000000000000000000000000000000..16145fda68d0d8e0ea0144151b0946f29460639f --- /dev/null +++ b/drivers/infiniband/hw/mlx5/std_types.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* + * Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. + */ + +#include +#include +#include +#include +#include "mlx5_ib.h" + +#define UVERBS_MODULE_NAME mlx5_ib +#include + +static int UVERBS_HANDLER(MLX5_IB_METHOD_PD_QUERY)( + struct uverbs_attr_bundle *attrs) +{ + struct ib_pd *pd = + uverbs_attr_get_obj(attrs, MLX5_IB_ATTR_QUERY_PD_HANDLE); + struct mlx5_ib_pd *mpd = to_mpd(pd); + + return uverbs_copy_to(attrs, MLX5_IB_ATTR_QUERY_PD_RESP_PDN, + &mpd->pdn, sizeof(mpd->pdn)); +} + +DECLARE_UVERBS_NAMED_METHOD( + MLX5_IB_METHOD_PD_QUERY, + UVERBS_ATTR_IDR(MLX5_IB_ATTR_QUERY_PD_HANDLE, + UVERBS_OBJECT_PD, + UVERBS_ACCESS_READ, + UA_MANDATORY), + UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_QUERY_PD_RESP_PDN, + UVERBS_ATTR_TYPE(u32), + UA_MANDATORY)); + +ADD_UVERBS_METHODS(mlx5_ib_pd, + UVERBS_OBJECT_PD, + &UVERBS_METHOD(MLX5_IB_METHOD_PD_QUERY)); + +const struct uapi_definition mlx5_ib_std_types_defs[] = { + UAPI_DEF_CHAIN_OBJ_TREE( + UVERBS_OBJECT_PD, + &mlx5_ib_pd), + {}, +}; diff --git a/drivers/infiniband/hw/mlx5/wr.c b/drivers/infiniband/hw/mlx5/wr.c index bc35dbe4855b7db5643de236a0e3ecde5a9b6cf1..43880973a512fe231382b0dd8daeb631c6c4e4f2 100644 --- a/drivers/infiniband/hw/mlx5/wr.c +++ b/drivers/infiniband/hw/mlx5/wr.c @@ -263,7 +263,9 @@ static __be64 get_umr_update_translation_mask(void) return cpu_to_be64(result); } -static __be64 get_umr_update_access_mask(int atomic) +static __be64 get_umr_update_access_mask(int atomic, + int relaxed_ordering_write, + int relaxed_ordering_read) { u64 result; @@ -275,6 +277,12 @@ static __be64 get_umr_update_access_mask(int atomic) if (atomic) result |= MLX5_MKEY_MASK_A; + if (relaxed_ordering_write) + result |= MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE; + + if (relaxed_ordering_read) + result |= MLX5_MKEY_MASK_RELAXED_ORDERING_READ; + return cpu_to_be64(result); } @@ -289,17 +297,28 @@ static __be64 get_umr_update_pd_mask(void) static int umr_check_mkey_mask(struct mlx5_ib_dev *dev, u64 mask) { - if ((mask & MLX5_MKEY_MASK_PAGE_SIZE && - MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled)) || - (mask & MLX5_MKEY_MASK_A && - MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled))) + if (mask & MLX5_MKEY_MASK_PAGE_SIZE && + MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled)) return -EPERM; + + if (mask & MLX5_MKEY_MASK_A && + MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled)) + return -EPERM; + + if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE && + !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr)) + return -EPERM; + + if (mask & MLX5_MKEY_MASK_RELAXED_ORDERING_READ && + !MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr)) + return -EPERM; + return 0; } static int set_reg_umr_segment(struct mlx5_ib_dev *dev, struct mlx5_wqe_umr_ctrl_seg *umr, - const struct ib_send_wr *wr, int atomic) + const struct ib_send_wr *wr) { const struct mlx5_umr_wr *umrwr = umr_wr(wr); @@ -325,7 +344,10 @@ static int set_reg_umr_segment(struct mlx5_ib_dev *dev, if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_TRANSLATION) umr->mkey_mask |= get_umr_update_translation_mask(); if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS) { - umr->mkey_mask |= get_umr_update_access_mask(atomic); + umr->mkey_mask |= get_umr_update_access_mask( + !!(MLX5_CAP_GEN(dev->mdev, atomic)), + !!(MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr)), + !!(MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr))); umr->mkey_mask |= get_umr_update_pd_mask(); } if (wr->send_flags & MLX5_IB_SEND_UMR_ENABLE_MR) @@ -383,20 +405,31 @@ static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg, memset(seg, 0, sizeof(*seg)); if (wr->send_flags & MLX5_IB_SEND_UMR_DISABLE_MR) - seg->status = MLX5_MKEY_STATUS_FREE; + MLX5_SET(mkc, seg, free, 1); + + MLX5_SET(mkc, seg, a, + !!(umrwr->access_flags & IB_ACCESS_REMOTE_ATOMIC)); + MLX5_SET(mkc, seg, rw, + !!(umrwr->access_flags & IB_ACCESS_REMOTE_WRITE)); + MLX5_SET(mkc, seg, rr, !!(umrwr->access_flags & IB_ACCESS_REMOTE_READ)); + MLX5_SET(mkc, seg, lw, !!(umrwr->access_flags & IB_ACCESS_LOCAL_WRITE)); + MLX5_SET(mkc, seg, lr, 1); + MLX5_SET(mkc, seg, relaxed_ordering_write, + !!(umrwr->access_flags & IB_ACCESS_RELAXED_ORDERING)); + MLX5_SET(mkc, seg, relaxed_ordering_read, + !!(umrwr->access_flags & IB_ACCESS_RELAXED_ORDERING)); - seg->flags = convert_access(umrwr->access_flags); if (umrwr->pd) - seg->flags_pd = cpu_to_be32(to_mpd(umrwr->pd)->pdn); + MLX5_SET(mkc, seg, pd, to_mpd(umrwr->pd)->pdn); if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_TRANSLATION && !umrwr->length) - seg->flags_pd |= cpu_to_be32(MLX5_MKEY_LEN64); + MLX5_SET(mkc, seg, length64, 1); - seg->start_addr = cpu_to_be64(umrwr->virt_addr); - seg->len = cpu_to_be64(umrwr->length); - seg->log2_page_size = umrwr->page_shift; - seg->qpn_mkey7_0 = cpu_to_be32(0xffffff00 | - mlx5_mkey_variant(umrwr->mkey)); + MLX5_SET64(mkc, seg, start_addr, umrwr->virt_addr); + MLX5_SET64(mkc, seg, len, umrwr->length); + MLX5_SET(mkc, seg, log_page_size, umrwr->page_shift); + MLX5_SET(mkc, seg, qpn, 0xffffff); + MLX5_SET(mkc, seg, mkey_7_0, mlx5_mkey_variant(umrwr->mkey)); } static void set_reg_data_seg(struct mlx5_wqe_data_seg *dseg, @@ -1224,8 +1257,7 @@ static int handle_qpt_reg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp, qp->sq.wr_data[idx] = MLX5_IB_WR_UMR; (*ctrl)->imm = cpu_to_be32(umr_wr(wr)->mkey); - err = set_reg_umr_segment(dev, *seg, wr, - !!(MLX5_CAP_GEN(dev->mdev, atomic))); + err = set_reg_umr_segment(dev, *seg, wr); if (unlikely(err)) goto out; *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg); diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index d11c74390a1242c332ca4120e227f8855d595a75..6cdbec13756af5ac7741202fcf38cc54ed5d6dbe 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -2901,7 +2901,7 @@ int ocrdma_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags cq_flags) } struct ib_mr *ocrdma_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata) + u32 max_num_sg) { int status; struct ocrdma_mr *mr; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h index 3a5010881be5b877d936f22e016851d97b905988..df8e3b923a440c9e7bd4c5008c028851ccd2fb6c 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h @@ -101,7 +101,7 @@ struct ib_mr *ocrdma_get_dma_mr(struct ib_pd *, int acc); struct ib_mr *ocrdma_reg_user_mr(struct ib_pd *, u64 start, u64 length, u64 virt, int acc, struct ib_udata *); struct ib_mr *ocrdma_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata); + u32 max_num_sg); int ocrdma_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, unsigned int *sg_offset); diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c index b1de8d608e4d1ee3740a7a88721538461f048c62..d85f992bac2991073343d32808441d9e72566297 100644 --- a/drivers/infiniband/hw/qedr/main.c +++ b/drivers/infiniband/hw/qedr/main.c @@ -110,7 +110,6 @@ static int qedr_iw_port_immutable(struct ib_device *ibdev, u8 port_num, if (err) return err; - immutable->pkey_tbl_len = 1; immutable->gid_tbl_len = 1; immutable->core_cap_flags = RDMA_CORE_PORT_IWARP; immutable->max_mad_size = 0; @@ -179,6 +178,7 @@ static int qedr_iw_register_device(struct qedr_dev *dev) static const struct ib_device_ops qedr_roce_dev_ops = { .get_port_immutable = qedr_roce_port_immutable, + .query_pkey = qedr_query_pkey, }; static void qedr_roce_register_device(struct qedr_dev *dev) @@ -221,7 +221,6 @@ static const struct ib_device_ops qedr_dev_ops = { .post_srq_recv = qedr_post_srq_recv, .process_mad = qedr_process_mad, .query_device = qedr_query_device, - .query_pkey = qedr_query_pkey, .query_port = qedr_query_port, .query_qp = qedr_query_qp, .query_srq = qedr_query_srq, diff --git a/drivers/infiniband/hw/qedr/qedr.h b/drivers/infiniband/hw/qedr/qedr.h index fdf90ecb26990f519f1bc0f634a2ecf1df13524b..460292179b327812611ce25be66c3168a3914f51 100644 --- a/drivers/infiniband/hw/qedr/qedr.h +++ b/drivers/infiniband/hw/qedr/qedr.h @@ -235,6 +235,7 @@ struct qedr_ucontext { u32 dpi_size; u16 dpi; bool db_rec; + u8 edpm_mode; }; union db_prod32 { @@ -344,10 +345,10 @@ struct qedr_srq_hwq_info { u32 wqe_prod; u32 sge_prod; u32 wr_prod_cnt; - u32 wr_cons_cnt; + atomic_t wr_cons_cnt; u32 num_elems; - u32 *virt_prod_pair_addr; + struct rdma_srq_producers *virt_prod_pair_addr; dma_addr_t phy_prod_pair_addr; }; diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index f5aa85a5377c32e3015a0af2d5b9363051c0f557..4ce4e2eef6ccdb4ba12ce193197126483e807360 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c @@ -239,7 +239,6 @@ int qedr_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr *attr) attr->ip_gids = true; if (rdma_protocol_iwarp(&dev->ibdev, 1)) { attr->gid_tbl_len = 1; - attr->pkey_tbl_len = 1; } else { attr->gid_tbl_len = QEDR_MAX_SGID; attr->pkey_tbl_len = QEDR_ROCE_PKEY_TABLE_LEN; @@ -275,7 +274,8 @@ int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata) DP_ERR(dev, "Problem copying data from user space\n"); return -EFAULT; } - + ctx->edpm_mode = !!(ureq.context_flags & + QEDR_ALLOC_UCTX_EDPM_MODE); ctx->db_rec = !!(ureq.context_flags & QEDR_ALLOC_UCTX_DB_REC); } @@ -316,11 +316,15 @@ int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata) uresp.dpm_flags = QEDR_DPM_TYPE_IWARP_LEGACY; else uresp.dpm_flags = QEDR_DPM_TYPE_ROCE_ENHANCED | - QEDR_DPM_TYPE_ROCE_LEGACY; + QEDR_DPM_TYPE_ROCE_LEGACY | + QEDR_DPM_TYPE_ROCE_EDPM_MODE; - uresp.dpm_flags |= QEDR_DPM_SIZES_SET; - uresp.ldpm_limit_size = QEDR_LDPM_MAX_SIZE; - uresp.edpm_trans_size = QEDR_EDPM_TRANS_SIZE; + if (ureq.context_flags & QEDR_SUPPORT_DPM_SIZES) { + uresp.dpm_flags |= QEDR_DPM_SIZES_SET; + uresp.ldpm_limit_size = QEDR_LDPM_MAX_SIZE; + uresp.edpm_trans_size = QEDR_EDPM_TRANS_SIZE; + uresp.edpm_limit_size = QEDR_EDPM_MAX_SIZE; + } uresp.wids_enabled = 1; uresp.wid_count = oparams.wid_count; @@ -1754,7 +1758,7 @@ static int qedr_create_user_qp(struct qedr_dev *dev, struct qed_rdma_create_qp_out_params out_params; struct qedr_pd *pd = get_qedr_pd(ibpd); struct qedr_create_qp_uresp uresp; - struct qedr_ucontext *ctx = NULL; + struct qedr_ucontext *ctx = pd ? pd->uctx : NULL; struct qedr_create_qp_ureq ureq; int alloc_and_init = rdma_protocol_roce(&dev->ibdev, 1); int rc = -EINVAL; @@ -1792,6 +1796,9 @@ static int qedr_create_user_qp(struct qedr_dev *dev, in_params.rq_pbl_ptr = qp->urq.pbl_tbl->pa; } + if (ctx) + SET_FIELD(in_params.flags, QED_ROCE_EDPM_MODE, ctx->edpm_mode); + qp->qed_qp = dev->ops->rdma_create_qp(dev->rdma_ctx, &in_params, &out_params); @@ -3004,7 +3011,7 @@ err0: } struct ib_mr *qedr_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata) + u32 max_num_sg) { struct qedr_mr *mr; @@ -3687,7 +3694,7 @@ static u32 qedr_srq_elem_left(struct qedr_srq_hwq_info *hw_srq) * count and consumer count and subtract it from max * work request supported so that we get elements left. */ - used = hw_srq->wr_prod_cnt - hw_srq->wr_cons_cnt; + used = hw_srq->wr_prod_cnt - (u32)atomic_read(&hw_srq->wr_cons_cnt); return hw_srq->max_wr - used; } @@ -3702,7 +3709,6 @@ int qedr_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr, unsigned long flags; int status = 0; u32 num_sge; - u32 offset; spin_lock_irqsave(&srq->lock, flags); @@ -3715,7 +3721,8 @@ int qedr_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr, if (!qedr_srq_elem_left(hw_srq) || wr->num_sge > srq->hw_srq.max_sges) { DP_ERR(dev, "Can't post WR (%d,%d) || (%d > %d)\n", - hw_srq->wr_prod_cnt, hw_srq->wr_cons_cnt, + hw_srq->wr_prod_cnt, + atomic_read(&hw_srq->wr_cons_cnt), wr->num_sge, srq->hw_srq.max_sges); status = -ENOMEM; *bad_wr = wr; @@ -3749,22 +3756,20 @@ int qedr_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr, hw_srq->sge_prod++; } - /* Flush WQE and SGE information before + /* Update WQE and SGE information before * updating producer. */ - wmb(); + dma_wmb(); /* SRQ producer is 8 bytes. Need to update SGE producer index * in first 4 bytes and need to update WQE producer in * next 4 bytes. */ - *srq->hw_srq.virt_prod_pair_addr = hw_srq->sge_prod; - offset = offsetof(struct rdma_srq_producers, wqe_prod); - *((u8 *)srq->hw_srq.virt_prod_pair_addr + offset) = - hw_srq->wqe_prod; + srq->hw_srq.virt_prod_pair_addr->sge_prod = hw_srq->sge_prod; + /* Make sure sge producer is updated first */ + dma_wmb(); + srq->hw_srq.virt_prod_pair_addr->wqe_prod = hw_srq->wqe_prod; - /* Flush producer after updating it. */ - wmb(); wr = wr->next; } @@ -4183,7 +4188,7 @@ static int process_resp_one_srq(struct qedr_dev *dev, struct qedr_qp *qp, } else { __process_resp_one(dev, qp, cq, wc, resp, wr_id); } - srq->hw_srq.wr_cons_cnt++; + atomic_inc(&srq->hw_srq.wr_cons_cnt); return 1; } diff --git a/drivers/infiniband/hw/qedr/verbs.h b/drivers/infiniband/hw/qedr/verbs.h index 5e02387e068d14fc0baa027bd6c6776b30f785e9..39dd6286ba39558f4af567640894f675fb195619 100644 --- a/drivers/infiniband/hw/qedr/verbs.h +++ b/drivers/infiniband/hw/qedr/verbs.h @@ -84,7 +84,7 @@ int qedr_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, unsigned int *sg_offset); struct ib_mr *qedr_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata); + u32 max_num_sg); int qedr_poll_cq(struct ib_cq *, int num_entries, struct ib_wc *wc); int qedr_post_send(struct ib_qp *, const struct ib_send_wr *, const struct ib_send_wr **bad_wr); diff --git a/drivers/infiniband/hw/usnic/usnic_fwd.c b/drivers/infiniband/hw/usnic/usnic_fwd.c index 7875883621f4eb165b50178a316dc46dd0383739..398c4c00b932d392494a9ab8b199ad64e95b968b 100644 --- a/drivers/infiniband/hw/usnic/usnic_fwd.c +++ b/drivers/infiniband/hw/usnic/usnic_fwd.c @@ -214,7 +214,7 @@ usnic_fwd_alloc_flow(struct usnic_fwd_dev *ufdev, struct filter *filter, if (!flow) return ERR_PTR(-ENOMEM); - tlv = pci_alloc_consistent(pdev, tlv_size, &tlv_pa); + tlv = dma_alloc_coherent(&pdev->dev, tlv_size, &tlv_pa, GFP_ATOMIC); if (!tlv) { usnic_err("Failed to allocate memory\n"); status = -ENOMEM; @@ -258,7 +258,7 @@ usnic_fwd_alloc_flow(struct usnic_fwd_dev *ufdev, struct filter *filter, out_free_tlv: spin_unlock(&ufdev->lock); - pci_free_consistent(pdev, tlv_size, tlv, tlv_pa); + dma_free_coherent(&pdev->dev, tlv_size, tlv, tlv_pa); if (!status) return flow; out_free_flow: diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c index b039f1f00e05abaa1848e3e36ee9d013147c4836..77a010e682081aa7e61c4b9f3da5a266e803a3ba 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c @@ -202,7 +202,7 @@ err_umem: * @return: ib_mr pointer on success, otherwise returns an errno. */ struct ib_mr *pvrdma_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata) + u32 max_num_sg) { struct pvrdma_dev *dev = to_vdev(pd->device); struct pvrdma_user_mr *mr; diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h index 267702226f108235eb6cabe9534adcc0d5fe12f8..699b20849a7efa0026efbf59e6b51b15cc232b87 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h @@ -406,7 +406,7 @@ struct ib_mr *pvrdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, struct ib_udata *udata); int pvrdma_dereg_mr(struct ib_mr *mr, struct ib_udata *udata); struct ib_mr *pvrdma_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata); + u32 max_num_sg); int pvrdma_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, unsigned int *sg_offset); int pvrdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, diff --git a/drivers/infiniband/sw/rdmavt/ah.c b/drivers/infiniband/sw/rdmavt/ah.c index 40480add7dd39913676f3b14c65f1ae97ae15bc4..75a04b1497c4e2b9f7efa017fc244824fc101799 100644 --- a/drivers/infiniband/sw/rdmavt/ah.c +++ b/drivers/infiniband/sw/rdmavt/ah.c @@ -90,8 +90,7 @@ EXPORT_SYMBOL(rvt_check_ah); /** * rvt_create_ah - create an address handle * @ibah: the IB address handle - * @ah_attr: the attributes of the AH - * @create_flags: create address handle flags (see enum rdma_create_ah_flags) + * @init_attr: the attributes of the AH * @udata: pointer to user's input output buffer information. * * This may be called from interrupt context. diff --git a/drivers/infiniband/sw/rdmavt/mr.c b/drivers/infiniband/sw/rdmavt/mr.c index 60864e5ca7cb674fa761322f14352f991ef4485f..2f7c25fea44a9ded22dcce36585872cd6727f6fe 100644 --- a/drivers/infiniband/sw/rdmavt/mr.c +++ b/drivers/infiniband/sw/rdmavt/mr.c @@ -576,7 +576,7 @@ out: * Return: the memory region on success, otherwise return an errno. */ struct ib_mr *rvt_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata) + u32 max_num_sg) { struct rvt_mr *mr; diff --git a/drivers/infiniband/sw/rdmavt/mr.h b/drivers/infiniband/sw/rdmavt/mr.h index 780fc63af98b75d177989160639f48651b99ac5c..b3aba359401bc9cc98805f3da4b8f839f0f2439b 100644 --- a/drivers/infiniband/sw/rdmavt/mr.h +++ b/drivers/infiniband/sw/rdmavt/mr.h @@ -71,7 +71,7 @@ struct ib_mr *rvt_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, struct ib_udata *udata); int rvt_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata); struct ib_mr *rvt_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata); + u32 max_num_sg); int rvt_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, unsigned int *sg_offset); diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c index 5642eefb4ba1c679b1c43207eca6b39248aa9c95..907203afbd99431cc900ae9d334d132f03666a46 100644 --- a/drivers/infiniband/sw/rxe/rxe.c +++ b/drivers/infiniband/sw/rxe/rxe.c @@ -40,14 +40,6 @@ MODULE_AUTHOR("Bob Pearson, Frank Zago, John Groves, Kamal Heib"); MODULE_DESCRIPTION("Soft RDMA transport"); MODULE_LICENSE("Dual BSD/GPL"); -/* free resources for all ports on a device */ -static void rxe_cleanup_ports(struct rxe_dev *rxe) -{ - kfree(rxe->port.pkey_tbl); - rxe->port.pkey_tbl = NULL; - -} - /* free resources for a rxe device all objects created for this device must * have been destroyed */ @@ -66,8 +58,6 @@ void rxe_dealloc(struct ib_device *ib_dev) rxe_pool_cleanup(&rxe->mc_grp_pool); rxe_pool_cleanup(&rxe->mc_elem_pool); - rxe_cleanup_ports(rxe); - if (rxe->tfm) crypto_free_shash(rxe->tfm); } @@ -111,7 +101,7 @@ static void rxe_init_device_param(struct rxe_dev *rxe) } /* initialize port attributes */ -static int rxe_init_port_param(struct rxe_port *port) +static void rxe_init_port_param(struct rxe_port *port) { port->attr.state = IB_PORT_DOWN; port->attr.max_mtu = IB_MTU_4096; @@ -134,35 +124,19 @@ static int rxe_init_port_param(struct rxe_port *port) port->attr.phys_state = RXE_PORT_PHYS_STATE; port->mtu_cap = ib_mtu_enum_to_int(IB_MTU_256); port->subnet_prefix = cpu_to_be64(RXE_PORT_SUBNET_PREFIX); - - return 0; } /* initialize port state, note IB convention that HCA ports are always * numbered from 1 */ -static int rxe_init_ports(struct rxe_dev *rxe) +static void rxe_init_ports(struct rxe_dev *rxe) { struct rxe_port *port = &rxe->port; rxe_init_port_param(port); - - if (!port->attr.pkey_tbl_len || !port->attr.gid_tbl_len) - return -EINVAL; - - port->pkey_tbl = kcalloc(port->attr.pkey_tbl_len, - sizeof(*port->pkey_tbl), GFP_KERNEL); - - if (!port->pkey_tbl) - return -ENOMEM; - - port->pkey_tbl[0] = 0xffff; addrconf_addr_eui48((unsigned char *)&port->port_guid, rxe->ndev->dev_addr); - spin_lock_init(&port->port_lock); - - return 0; } /* init pools of managed objects */ @@ -252,13 +226,11 @@ static int rxe_init(struct rxe_dev *rxe) /* init default device parameters */ rxe_init_device_param(rxe); - err = rxe_init_ports(rxe); - if (err) - goto err1; + rxe_init_ports(rxe); err = rxe_init_pools(rxe); if (err) - goto err2; + return err; /* init pending mmap list */ spin_lock_init(&rxe->mmap_offset_lock); @@ -268,11 +240,6 @@ static int rxe_init(struct rxe_dev *rxe) mutex_init(&rxe->usdev_lock); return 0; - -err2: - rxe_cleanup_ports(rxe); -err1: - return err; } void rxe_set_mtu(struct rxe_dev *rxe, unsigned int ndev_mtu) diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h index 775c23becaec0f6bebed79eeb81d1826631e41a3..39dc3bfa5d5de01166cc8aac4cd2ec48f7d0c829 100644 --- a/drivers/infiniband/sw/rxe/rxe_loc.h +++ b/drivers/infiniband/sw/rxe/rxe_loc.h @@ -103,8 +103,8 @@ enum copy_direction { from_mem_obj, }; -int rxe_mem_init_dma(struct rxe_pd *pd, - int access, struct rxe_mem *mem); +void rxe_mem_init_dma(struct rxe_pd *pd, + int access, struct rxe_mem *mem); int rxe_mem_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova, int access, struct ib_udata *udata, @@ -132,9 +132,6 @@ struct rxe_mem *lookup_mem(struct rxe_pd *pd, int access, u32 key, int mem_check_range(struct rxe_mem *mem, u64 iova, size_t length); -int rxe_mem_map_pages(struct rxe_dev *rxe, struct rxe_mem *mem, - u64 *page, int num_pages, u64 iova); - void rxe_mem_cleanup(struct rxe_pool_entry *arg); int advance_dma_data(struct rxe_dma_info *dma, unsigned int length); @@ -145,7 +142,6 @@ int rxe_send(struct rxe_pkt_info *pkt, struct sk_buff *skb); struct sk_buff *rxe_init_packet(struct rxe_dev *rxe, struct rxe_av *av, int paylen, struct rxe_pkt_info *pkt); int rxe_prepare(struct rxe_pkt_info *pkt, struct sk_buff *skb, u32 *crc); -enum rdma_link_layer rxe_link_layer(struct rxe_dev *rxe, unsigned int port_num); const char *rxe_parent_name(struct rxe_dev *rxe, unsigned int port_num); struct device *rxe_dma_device(struct rxe_dev *rxe); int rxe_mcast_add(struct rxe_dev *rxe, union ib_gid *mgid); diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c index e83c7b518bfa2a61cda15573755dea8d34757400..cdd811a45120f4e5a5b274895c84d6759f200a8e 100644 --- a/drivers/infiniband/sw/rxe/rxe_mr.c +++ b/drivers/infiniband/sw/rxe/rxe_mr.c @@ -144,8 +144,8 @@ err1: return -ENOMEM; } -int rxe_mem_init_dma(struct rxe_pd *pd, - int access, struct rxe_mem *mem) +void rxe_mem_init_dma(struct rxe_pd *pd, + int access, struct rxe_mem *mem) { rxe_mem_init(access, mem); @@ -153,8 +153,6 @@ int rxe_mem_init_dma(struct rxe_pd *pd, mem->access = access; mem->state = RXE_MEM_STATE_VALID; mem->type = RXE_MEM_TYPE_DMA; - - return 0; } int rxe_mem_init_user(struct rxe_pd *pd, u64 start, @@ -587,47 +585,3 @@ struct rxe_mem *lookup_mem(struct rxe_pd *pd, int access, u32 key, return mem; } - -int rxe_mem_map_pages(struct rxe_dev *rxe, struct rxe_mem *mem, - u64 *page, int num_pages, u64 iova) -{ - int i; - int num_buf; - int err; - struct rxe_map **map; - struct rxe_phys_buf *buf; - int page_size; - - if (num_pages > mem->max_buf) { - err = -EINVAL; - goto err1; - } - - num_buf = 0; - page_size = 1 << mem->page_shift; - map = mem->map; - buf = map[0]->buf; - - for (i = 0; i < num_pages; i++) { - buf->addr = *page++; - buf->size = page_size; - buf++; - num_buf++; - - if (num_buf == RXE_BUF_PER_MAP) { - map++; - buf = map[0]->buf; - num_buf = 0; - } - } - - mem->iova = iova; - mem->va = iova; - mem->length = num_pages << mem->page_shift; - mem->state = RXE_MEM_STATE_VALID; - - return 0; - -err1: - return err; -} diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c index 312c2fc961c00fb1c98fdbf9ab7e5df5108eda82..0c3808611f9508508fd8d6fafe0cb078450e81ba 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -520,11 +520,6 @@ const char *rxe_parent_name(struct rxe_dev *rxe, unsigned int port_num) return rxe->ndev->name; } -enum rdma_link_layer rxe_link_layer(struct rxe_dev *rxe, unsigned int port_num) -{ - return IB_LINK_LAYER_ETHERNET; -} - int rxe_net_add(const char *ibdev_name, struct net_device *ndev) { int err; diff --git a/drivers/infiniband/sw/rxe/rxe_param.h b/drivers/infiniband/sw/rxe/rxe_param.h index 99e9d8ba97678635ea1224ac2760a619c54191f5..2f381aeafcb57babbc83586177b98f3d998a488a 100644 --- a/drivers/infiniband/sw/rxe/rxe_param.h +++ b/drivers/infiniband/sw/rxe/rxe_param.h @@ -100,7 +100,7 @@ enum rxe_device_param { RXE_MAX_SRQ_SGE = 27, RXE_MIN_SRQ_SGE = 1, RXE_MAX_FMR_PAGE_LIST_LEN = 512, - RXE_MAX_PKEYS = 64, + RXE_MAX_PKEYS = 1, RXE_LOCAL_CA_ACK_DELAY = 15, RXE_MAX_UCONTEXT = 512, @@ -148,7 +148,7 @@ enum rxe_port_param { RXE_PORT_INIT_TYPE_REPLY = 0, RXE_PORT_ACTIVE_WIDTH = IB_WIDTH_1X, RXE_PORT_ACTIVE_SPEED = 1, - RXE_PORT_PKEY_TBL_LEN = 64, + RXE_PORT_PKEY_TBL_LEN = 1, RXE_PORT_PHYS_STATE = IB_PORT_PHYS_STATE_POLLING, RXE_PORT_SUBNET_PREFIX = 0xfe80000000000000ULL, }; diff --git a/drivers/infiniband/sw/rxe/rxe_recv.c b/drivers/infiniband/sw/rxe/rxe_recv.c index 831ad578a7b29d2ba61a3ed475f2c7ffdcffc7a3..7e123d3c4d09b062ca4fa41855df6c8d3df29e35 100644 --- a/drivers/infiniband/sw/rxe/rxe_recv.c +++ b/drivers/infiniband/sw/rxe/rxe_recv.c @@ -101,36 +101,15 @@ static void set_qkey_viol_cntr(struct rxe_port *port) static int check_keys(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, u32 qpn, struct rxe_qp *qp) { - int i; - int found_pkey = 0; struct rxe_port *port = &rxe->port; u16 pkey = bth_pkey(pkt); pkt->pkey_index = 0; - if (qpn == 1) { - for (i = 0; i < port->attr.pkey_tbl_len; i++) { - if (pkey_match(pkey, port->pkey_tbl[i])) { - pkt->pkey_index = i; - found_pkey = 1; - break; - } - } - - if (!found_pkey) { - pr_warn_ratelimited("bad pkey = 0x%x\n", pkey); - set_bad_pkey_cntr(port); - goto err1; - } - } else { - if (unlikely(!pkey_match(pkey, - port->pkey_tbl[qp->attr.pkey_index] - ))) { - pr_warn_ratelimited("bad pkey = 0x%0x\n", pkey); - set_bad_pkey_cntr(port); - goto err1; - } - pkt->pkey_index = qp->attr.pkey_index; + if (!pkey_match(pkey, IB_DEFAULT_PKEY_FULL)) { + pr_warn_ratelimited("bad pkey = 0x%x\n", pkey); + set_bad_pkey_cntr(port); + goto err1; } if ((qp_type(qp) == IB_QPT_UD || qp_type(qp) == IB_QPT_GSI) && @@ -330,10 +309,14 @@ err1: static int rxe_match_dgid(struct rxe_dev *rxe, struct sk_buff *skb) { + struct rxe_pkt_info *pkt = SKB_TO_PKT(skb); const struct ib_gid_attr *gid_attr; union ib_gid dgid; union ib_gid *pdgid; + if (pkt->mask & RXE_LOOPBACK_MASK) + return 0; + if (skb->protocol == htons(ETH_P_IP)) { ipv6_addr_set_v4mapped(ip_hdr(skb)->daddr, (struct in6_addr *)&dgid); @@ -366,7 +349,7 @@ void rxe_rcv(struct sk_buff *skb) if (unlikely(skb->len < pkt->offset + RXE_BTH_BYTES)) goto drop; - if (unlikely(rxe_match_dgid(rxe, skb) < 0)) { + if (rxe_match_dgid(rxe, skb) < 0) { pr_warn_ratelimited("failed matching dgid\n"); goto drop; } diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c index e5031172c0193ad3e2906210fe2e20f2da398a32..34df2b55e650d5ad1af819ffd87a8d52157b816e 100644 --- a/drivers/infiniband/sw/rxe/rxe_req.c +++ b/drivers/infiniband/sw/rxe/rxe_req.c @@ -381,7 +381,6 @@ static struct sk_buff *init_req_packet(struct rxe_qp *qp, struct rxe_pkt_info *pkt) { struct rxe_dev *rxe = to_rdev(qp->ibqp.device); - struct rxe_port *port = &rxe->port; struct sk_buff *skb; struct rxe_send_wr *ibwr = &wqe->wr; struct rxe_av *av; @@ -419,9 +418,7 @@ static struct sk_buff *init_req_packet(struct rxe_qp *qp, (pkt->mask & (RXE_WRITE_MASK | RXE_IMMDT_MASK)) == (RXE_WRITE_MASK | RXE_IMMDT_MASK)); - pkey = (qp_type(qp) == IB_QPT_GSI) ? - port->pkey_tbl[ibwr->wr.ud.pkey_index] : - port->pkey_tbl[qp->attr.pkey_index]; + pkey = IB_DEFAULT_PKEY_FULL; qp_num = (pkt->mask & RXE_DETH_MASK) ? ibwr->wr.ud.remote_qpn : qp->attr.dest_qp_num; diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c index b8a22af724e8b55fcc98f714f88d4ad9f66a76c0..bb61e534e468221ae7413c7833a0492d31bdfcaf 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.c +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c @@ -83,22 +83,11 @@ static int rxe_query_port(struct ib_device *dev, static int rxe_query_pkey(struct ib_device *device, u8 port_num, u16 index, u16 *pkey) { - struct rxe_dev *rxe = to_rdev(device); - struct rxe_port *port; - - port = &rxe->port; - - if (unlikely(index >= port->attr.pkey_tbl_len)) { - dev_warn(device->dev.parent, "invalid index = %d\n", - index); - goto err1; - } + if (index > 0) + return -EINVAL; - *pkey = port->pkey_tbl[index]; + *pkey = IB_DEFAULT_PKEY_FULL; return 0; - -err1: - return -EINVAL; } static int rxe_modify_device(struct ib_device *dev, @@ -141,9 +130,7 @@ static int rxe_modify_port(struct ib_device *dev, static enum rdma_link_layer rxe_get_link_layer(struct ib_device *dev, u8 port_num) { - struct rxe_dev *rxe = to_rdev(dev); - - return rxe_link_layer(rxe, port_num); + return IB_LINK_LAYER_ETHERNET; } static int rxe_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata) @@ -684,6 +671,7 @@ static int rxe_post_send_kernel(struct rxe_qp *qp, const struct ib_send_wr *wr, unsigned int mask; unsigned int length = 0; int i; + struct ib_send_wr *next; while (wr) { mask = wr_opcode_mask(wr->opcode, qp); @@ -700,6 +688,8 @@ static int rxe_post_send_kernel(struct rxe_qp *qp, const struct ib_send_wr *wr, break; } + next = wr->next; + length = 0; for (i = 0; i < wr->num_sge; i++) length += wr->sg_list[i].length; @@ -710,7 +700,7 @@ static int rxe_post_send_kernel(struct rxe_qp *qp, const struct ib_send_wr *wr, *bad_wr = wr; break; } - wr = wr->next; + wr = next; } rxe_run_task(&qp->req.task, 1); @@ -901,30 +891,16 @@ static struct ib_mr *rxe_get_dma_mr(struct ib_pd *ibpd, int access) struct rxe_dev *rxe = to_rdev(ibpd->device); struct rxe_pd *pd = to_rpd(ibpd); struct rxe_mem *mr; - int err; mr = rxe_alloc(&rxe->mr_pool); - if (!mr) { - err = -ENOMEM; - goto err1; - } + if (!mr) + return ERR_PTR(-ENOMEM); rxe_add_index(mr); - rxe_add_ref(pd); - - err = rxe_mem_init_dma(pd, access, mr); - if (err) - goto err2; + rxe_mem_init_dma(pd, access, mr); return &mr->ibmr; - -err2: - rxe_drop_ref(pd); - rxe_drop_index(mr); - rxe_drop_ref(mr); -err1: - return ERR_PTR(err); } static struct ib_mr *rxe_reg_user_mr(struct ib_pd *ibpd, @@ -975,7 +951,7 @@ static int rxe_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) } static struct ib_mr *rxe_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata) + u32 max_num_sg) { struct rxe_dev *rxe = to_rdev(ibpd->device); struct rxe_pd *pd = to_rpd(ibpd); diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h index 92de39c4a7c1ed3d25488e306816b97b92101790..c664c7f36ab5bd4ae897a909370e60bc596dbfe7 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.h +++ b/drivers/infiniband/sw/rxe/rxe_verbs.h @@ -371,7 +371,6 @@ struct rxe_mc_elem { struct rxe_port { struct ib_port_attr attr; - u16 *pkey_tbl; __be64 port_guid; __be64 subnet_prefix; spinlock_t port_lock; /* guard port */ diff --git a/drivers/infiniband/sw/siw/siw_main.c b/drivers/infiniband/sw/siw/siw_main.c index ed60c9e4643e84b16cee9be592b440e845cba130..d862bec843766fdb2282799e8fd372ceaa3b2b3c 100644 --- a/drivers/infiniband/sw/siw/siw_main.c +++ b/drivers/infiniband/sw/siw/siw_main.c @@ -289,7 +289,6 @@ static const struct ib_device_ops siw_device_ops = { .post_srq_recv = siw_post_srq_recv, .query_device = siw_query_device, .query_gid = siw_query_gid, - .query_pkey = siw_query_pkey, .query_port = siw_query_port, .query_qp = siw_query_qp, .query_srq = siw_query_srq, diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c index 987e2ba05dbc066b2c3e6544b6d79c70715e4c9a..adafa1b8bebe389db9012fc355ee6e27c3874c68 100644 --- a/drivers/infiniband/sw/siw/siw_verbs.c +++ b/drivers/infiniband/sw/siw/siw_verbs.c @@ -176,7 +176,6 @@ int siw_query_port(struct ib_device *base_dev, u8 port, attr->active_mtu = ib_mtu_int_to_enum(sdev->netdev->mtu); attr->phys_state = sdev->state == IB_PORT_ACTIVE ? IB_PORT_PHYS_STATE_LINK_UP : IB_PORT_PHYS_STATE_DISABLED; - attr->pkey_tbl_len = 1; attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_DEVICE_MGMT_SUP; attr->state = sdev->state; /* @@ -204,20 +203,12 @@ int siw_get_port_immutable(struct ib_device *base_dev, u8 port, if (rv) return rv; - port_immutable->pkey_tbl_len = attr.pkey_tbl_len; port_immutable->gid_tbl_len = attr.gid_tbl_len; port_immutable->core_cap_flags = RDMA_CORE_PORT_IWARP; return 0; } -int siw_query_pkey(struct ib_device *base_dev, u8 port, u16 idx, u16 *pkey) -{ - /* Report the default pkey */ - *pkey = 0xffff; - return 0; -} - int siw_query_gid(struct ib_device *base_dev, u8 port, int idx, union ib_gid *gid) { @@ -1373,7 +1364,7 @@ err_out: } struct ib_mr *siw_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_sge, struct ib_udata *udata) + u32 max_sge) { struct siw_device *sdev = to_siw_dev(pd->device); struct siw_mr *mr = NULL; diff --git a/drivers/infiniband/sw/siw/siw_verbs.h b/drivers/infiniband/sw/siw/siw_verbs.h index 1a731989fad60bd6487e539f0bb6a792763a7b72..d9572275a6b69557c7add81e331657f9238d0051 100644 --- a/drivers/infiniband/sw/siw/siw_verbs.h +++ b/drivers/infiniband/sw/siw/siw_verbs.h @@ -46,7 +46,6 @@ int siw_create_cq(struct ib_cq *base_cq, const struct ib_cq_init_attr *attr, struct ib_udata *udata); int siw_query_port(struct ib_device *base_dev, u8 port, struct ib_port_attr *attr); -int siw_query_pkey(struct ib_device *base_dev, u8 port, u16 idx, u16 *pkey); int siw_query_gid(struct ib_device *base_dev, u8 port, int idx, union ib_gid *gid); int siw_alloc_pd(struct ib_pd *base_pd, struct ib_udata *udata); @@ -69,7 +68,7 @@ int siw_req_notify_cq(struct ib_cq *base_cq, enum ib_cq_notify_flags flags); struct ib_mr *siw_reg_user_mr(struct ib_pd *base_pd, u64 start, u64 len, u64 rnic_va, int rights, struct ib_udata *udata); struct ib_mr *siw_alloc_mr(struct ib_pd *base_pd, enum ib_mr_type mr_type, - u32 max_sge, struct ib_udata *udata); + u32 max_sge); struct ib_mr *siw_get_dma_mr(struct ib_pd *base_pd, int rights); int siw_map_mr_sg(struct ib_mr *base_mr, struct scatterlist *sl, int num_sle, unsigned int *sg_off); diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 9a3379c49541fbe51a08e49db7757cc170bdd1bf..3440dc48d02c7fb91a64362259b533069b3a2687 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -515,7 +515,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev); int ipoib_ib_dev_open_default(struct net_device *dev); int ipoib_ib_dev_open(struct net_device *dev); -int ipoib_ib_dev_stop(struct net_device *dev); +void ipoib_ib_dev_stop(struct net_device *dev); void ipoib_ib_dev_up(struct net_device *dev); void ipoib_ib_dev_down(struct net_device *dev); int ipoib_ib_dev_stop_default(struct net_device *dev); @@ -527,7 +527,7 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb); void ipoib_mcast_restart_task(struct work_struct *work); void ipoib_mcast_start_thread(struct net_device *dev); -int ipoib_mcast_stop_thread(struct net_device *dev); +void ipoib_mcast_stop_thread(struct net_device *dev); void ipoib_mcast_dev_down(struct net_device *dev); void ipoib_mcast_dev_flush(struct net_device *dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index da3c5315bbb515649c7f265fe263f38cca5f9d6e..494f413dc3c6c4872b0d8ebb5d2e00ded95ee9ac 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -670,13 +670,12 @@ int ipoib_send(struct net_device *dev, struct sk_buff *skb, return rc; } -static void __ipoib_reap_ah(struct net_device *dev) +static void ipoib_reap_dead_ahs(struct ipoib_dev_priv *priv) { - struct ipoib_dev_priv *priv = ipoib_priv(dev); struct ipoib_ah *ah, *tah; unsigned long flags; - netif_tx_lock_bh(dev); + netif_tx_lock_bh(priv->dev); spin_lock_irqsave(&priv->lock, flags); list_for_each_entry_safe(ah, tah, &priv->dead_ahs, list) @@ -687,37 +686,37 @@ static void __ipoib_reap_ah(struct net_device *dev) } spin_unlock_irqrestore(&priv->lock, flags); - netif_tx_unlock_bh(dev); + netif_tx_unlock_bh(priv->dev); } void ipoib_reap_ah(struct work_struct *work) { struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, ah_reap_task.work); - struct net_device *dev = priv->dev; - __ipoib_reap_ah(dev); + ipoib_reap_dead_ahs(priv); if (!test_bit(IPOIB_STOP_REAPER, &priv->flags)) queue_delayed_work(priv->wq, &priv->ah_reap_task, round_jiffies_relative(HZ)); } -static void ipoib_flush_ah(struct net_device *dev) +static void ipoib_start_ah_reaper(struct ipoib_dev_priv *priv) { - struct ipoib_dev_priv *priv = ipoib_priv(dev); - - cancel_delayed_work(&priv->ah_reap_task); - flush_workqueue(priv->wq); - ipoib_reap_ah(&priv->ah_reap_task.work); + clear_bit(IPOIB_STOP_REAPER, &priv->flags); + queue_delayed_work(priv->wq, &priv->ah_reap_task, + round_jiffies_relative(HZ)); } -static void ipoib_stop_ah(struct net_device *dev) +static void ipoib_stop_ah_reaper(struct ipoib_dev_priv *priv) { - struct ipoib_dev_priv *priv = ipoib_priv(dev); - set_bit(IPOIB_STOP_REAPER, &priv->flags); - ipoib_flush_ah(dev); + cancel_delayed_work(&priv->ah_reap_task); + /* + * After ipoib_stop_ah_reaper() we always go through + * ipoib_reap_dead_ahs() which ensures the work is really stopped and + * does a final flush out of the dead_ah's list + */ } static int recvs_pending(struct net_device *dev) @@ -846,18 +845,6 @@ timeout: return 0; } -int ipoib_ib_dev_stop(struct net_device *dev) -{ - struct ipoib_dev_priv *priv = ipoib_priv(dev); - - priv->rn_ops->ndo_stop(dev); - - clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); - ipoib_flush_ah(dev); - - return 0; -} - int ipoib_ib_dev_open_default(struct net_device *dev) { struct ipoib_dev_priv *priv = ipoib_priv(dev); @@ -901,10 +888,7 @@ int ipoib_ib_dev_open(struct net_device *dev) return -1; } - clear_bit(IPOIB_STOP_REAPER, &priv->flags); - queue_delayed_work(priv->wq, &priv->ah_reap_task, - round_jiffies_relative(HZ)); - + ipoib_start_ah_reaper(priv); if (priv->rn_ops->ndo_open(dev)) { pr_warn("%s: Failed to open dev\n", dev->name); goto dev_stop; @@ -915,13 +899,20 @@ int ipoib_ib_dev_open(struct net_device *dev) return 0; dev_stop: - set_bit(IPOIB_STOP_REAPER, &priv->flags); - cancel_delayed_work(&priv->ah_reap_task); - set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); - ipoib_ib_dev_stop(dev); + ipoib_stop_ah_reaper(priv); return -1; } +void ipoib_ib_dev_stop(struct net_device *dev) +{ + struct ipoib_dev_priv *priv = ipoib_priv(dev); + + priv->rn_ops->ndo_stop(dev); + + clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); + ipoib_stop_ah_reaper(priv); +} + void ipoib_pkey_dev_check_presence(struct net_device *dev) { struct ipoib_dev_priv *priv = ipoib_priv(dev); @@ -1232,7 +1223,7 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, ipoib_mcast_dev_flush(dev); if (oper_up) set_bit(IPOIB_FLAG_OPER_UP, &priv->flags); - ipoib_flush_ah(dev); + ipoib_reap_dead_ahs(priv); } if (level >= IPOIB_FLUSH_NORMAL) @@ -1307,7 +1298,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) * the neighbor garbage collection is stopped and reaped. * That should all be done now, so make a final ah flush. */ - ipoib_stop_ah(dev); + ipoib_reap_dead_ahs(priv); clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 3cfb682b91b0a155a39527f057ea82e0ccb0bce5..752581a8627bd07a2e10c477337252f8a27496d5 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1892,8 +1892,15 @@ static void ipoib_child_init(struct net_device *ndev) priv->max_ib_mtu = ppriv->max_ib_mtu; set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags); - memcpy(priv->dev->dev_addr, ppriv->dev->dev_addr, INFINIBAND_ALEN); - memcpy(&priv->local_gid, &ppriv->local_gid, sizeof(priv->local_gid)); + if (memchr_inv(priv->dev->dev_addr, 0, INFINIBAND_ALEN)) + memcpy(&priv->local_gid, priv->dev->dev_addr + 4, + sizeof(priv->local_gid)); + else { + memcpy(priv->dev->dev_addr, ppriv->dev->dev_addr, + INFINIBAND_ALEN); + memcpy(&priv->local_gid, &ppriv->local_gid, + sizeof(priv->local_gid)); + } } static int ipoib_ndo_init(struct net_device *ndev) @@ -1976,6 +1983,8 @@ static void ipoib_ndo_uninit(struct net_device *dev) /* no more works over the priv->wq */ if (priv->wq) { + /* See ipoib_mcast_carrier_on_task() */ + WARN_ON(test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)); flush_workqueue(priv->wq); destroy_workqueue(priv->wq); priv->wq = NULL; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 9bfa514473d5e75b2ed184080092d905dccf2022..86e4ed64e4e21b6182bf2be0a5ccafe9f4864960 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -680,15 +680,13 @@ void ipoib_mcast_start_thread(struct net_device *dev) spin_unlock_irqrestore(&priv->lock, flags); } -int ipoib_mcast_stop_thread(struct net_device *dev) +void ipoib_mcast_stop_thread(struct net_device *dev) { struct ipoib_dev_priv *priv = ipoib_priv(dev); ipoib_dbg_mcast(priv, "stopping multicast thread\n"); cancel_delayed_work_sync(&priv->mcast_task); - - return 0; } static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast) diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index 1d77c7f42e38be0b75fde66846717845171fc5f7..78ee9445f8019356cdd40706156a0311e6cb2e61 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -299,18 +299,6 @@ struct iser_conn; struct ib_conn; struct iscsi_iser_task; -/** - * struct iser_comp - iSER completion context - * - * @cq: completion queue - * @active_qps: Number of active QPs attached - * to completion context - */ -struct iser_comp { - struct ib_cq *cq; - int active_qps; -}; - /** * struct iser_device - iSER device handle * @@ -320,9 +308,6 @@ struct iser_comp { * @event_handler: IB events handle routine * @ig_list: entry in devices list * @refcount: Reference counter, dominated by open iser connections - * @comps_used: Number of completion contexts used, Min between online - * cpus and device max completion vectors - * @comps: Dinamically allocated array of completion handlers */ struct iser_device { struct ib_device *ib_device; @@ -330,8 +315,6 @@ struct iser_device { struct ib_event_handler event_handler; struct list_head ig_list; int refcount; - int comps_used; - struct iser_comp *comps; }; /** @@ -353,6 +336,7 @@ struct iser_reg_resources { * @list: entry in connection fastreg pool * @rsc: data buffer registration resources * @sig_protected: is region protected indicator + * @all_list: first and last list members */ struct iser_fr_desc { struct list_head list; @@ -367,6 +351,7 @@ struct iser_fr_desc { * @list: list of fastreg descriptors * @lock: protects fastreg pool * @size: size of the pool + * @all_list: first and last list members */ struct iser_fr_pool { struct list_head list; @@ -380,11 +365,12 @@ struct iser_fr_pool { * * @cma_id: rdma_cm connection maneger handle * @qp: Connection Queue-pair + * @cq: Connection completion queue + * @cq_size: The number of max outstanding completions * @post_recv_buf_count: post receive counter * @sig_count: send work request signal count * @rx_wr: receive work request for batch posts * @device: reference to iser device - * @comp: iser completion context * @fr_pool: connection fast registration poool * @pi_support: Indicate device T10-PI support * @reg_cqe: completion handler @@ -392,11 +378,12 @@ struct iser_fr_pool { struct ib_conn { struct rdma_cm_id *cma_id; struct ib_qp *qp; + struct ib_cq *cq; + u32 cq_size; int post_recv_buf_count; u8 sig_count; struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX]; struct iser_device *device; - struct iser_comp *comp; struct iser_fr_pool fr_pool; bool pi_support; struct ib_cqe reg_cqe; diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index c1f44c41f501fd3decbd1c9b137efd39bb9c50a5..699e075ae1b366e69ef39bd44c21893ba01c162c 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -68,59 +68,23 @@ static void iser_event_handler(struct ib_event_handler *handler, static int iser_create_device_ib_res(struct iser_device *device) { struct ib_device *ib_dev = device->ib_device; - int i, max_cqe; if (!(ib_dev->attrs.device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS)) { iser_err("IB device does not support memory registrations\n"); return -1; } - device->comps_used = min_t(int, num_online_cpus(), - ib_dev->num_comp_vectors); - - device->comps = kcalloc(device->comps_used, sizeof(*device->comps), - GFP_KERNEL); - if (!device->comps) - goto comps_err; - - max_cqe = min(ISER_MAX_CQ_LEN, ib_dev->attrs.max_cqe); - - iser_info("using %d CQs, device %s supports %d vectors max_cqe %d\n", - device->comps_used, dev_name(&ib_dev->dev), - ib_dev->num_comp_vectors, max_cqe); - device->pd = ib_alloc_pd(ib_dev, iser_always_reg ? 0 : IB_PD_UNSAFE_GLOBAL_RKEY); if (IS_ERR(device->pd)) goto pd_err; - for (i = 0; i < device->comps_used; i++) { - struct iser_comp *comp = &device->comps[i]; - - comp->cq = ib_alloc_cq(ib_dev, comp, max_cqe, i, - IB_POLL_SOFTIRQ); - if (IS_ERR(comp->cq)) { - comp->cq = NULL; - goto cq_err; - } - } - INIT_IB_EVENT_HANDLER(&device->event_handler, ib_dev, iser_event_handler); ib_register_event_handler(&device->event_handler); return 0; -cq_err: - for (i = 0; i < device->comps_used; i++) { - struct iser_comp *comp = &device->comps[i]; - - if (comp->cq) - ib_free_cq(comp->cq); - } - ib_dealloc_pd(device->pd); pd_err: - kfree(device->comps); -comps_err: iser_err("failed to allocate an IB resource\n"); return -1; } @@ -131,20 +95,9 @@ comps_err: */ static void iser_free_device_ib_res(struct iser_device *device) { - int i; - - for (i = 0; i < device->comps_used; i++) { - struct iser_comp *comp = &device->comps[i]; - - ib_free_cq(comp->cq); - comp->cq = NULL; - } - ib_unregister_event_handler(&device->event_handler); ib_dealloc_pd(device->pd); - kfree(device->comps); - device->comps = NULL; device->pd = NULL; } @@ -287,70 +240,57 @@ static int iser_create_ib_conn_res(struct ib_conn *ib_conn) struct ib_device *ib_dev; struct ib_qp_init_attr init_attr; int ret = -ENOMEM; - int index, min_index = 0; + unsigned int max_send_wr, cq_size; BUG_ON(ib_conn->device == NULL); device = ib_conn->device; ib_dev = device->ib_device; - memset(&init_attr, 0, sizeof init_attr); + if (ib_conn->pi_support) + max_send_wr = ISER_QP_SIG_MAX_REQ_DTOS + 1; + else + max_send_wr = ISER_QP_MAX_REQ_DTOS + 1; + max_send_wr = min_t(unsigned int, max_send_wr, + (unsigned int)ib_dev->attrs.max_qp_wr); - mutex_lock(&ig.connlist_mutex); - /* select the CQ with the minimal number of usages */ - for (index = 0; index < device->comps_used; index++) { - if (device->comps[index].active_qps < - device->comps[min_index].active_qps) - min_index = index; + cq_size = max_send_wr + ISER_QP_MAX_RECV_DTOS; + ib_conn->cq = ib_cq_pool_get(ib_dev, cq_size, -1, IB_POLL_SOFTIRQ); + if (IS_ERR(ib_conn->cq)) { + ret = PTR_ERR(ib_conn->cq); + goto cq_err; } - ib_conn->comp = &device->comps[min_index]; - ib_conn->comp->active_qps++; - mutex_unlock(&ig.connlist_mutex); - iser_info("cq index %d used for ib_conn %p\n", min_index, ib_conn); + ib_conn->cq_size = cq_size; + + memset(&init_attr, 0, sizeof(init_attr)); init_attr.event_handler = iser_qp_event_callback; init_attr.qp_context = (void *)ib_conn; - init_attr.send_cq = ib_conn->comp->cq; - init_attr.recv_cq = ib_conn->comp->cq; + init_attr.send_cq = ib_conn->cq; + init_attr.recv_cq = ib_conn->cq; init_attr.cap.max_recv_wr = ISER_QP_MAX_RECV_DTOS; init_attr.cap.max_send_sge = 2; init_attr.cap.max_recv_sge = 1; init_attr.sq_sig_type = IB_SIGNAL_REQ_WR; init_attr.qp_type = IB_QPT_RC; - if (ib_conn->pi_support) { - init_attr.cap.max_send_wr = ISER_QP_SIG_MAX_REQ_DTOS + 1; + init_attr.cap.max_send_wr = max_send_wr; + if (ib_conn->pi_support) init_attr.create_flags |= IB_QP_CREATE_INTEGRITY_EN; - iser_conn->max_cmds = - ISER_GET_MAX_XMIT_CMDS(ISER_QP_SIG_MAX_REQ_DTOS); - } else { - if (ib_dev->attrs.max_qp_wr > ISER_QP_MAX_REQ_DTOS) { - init_attr.cap.max_send_wr = ISER_QP_MAX_REQ_DTOS + 1; - iser_conn->max_cmds = - ISER_GET_MAX_XMIT_CMDS(ISER_QP_MAX_REQ_DTOS); - } else { - init_attr.cap.max_send_wr = ib_dev->attrs.max_qp_wr; - iser_conn->max_cmds = - ISER_GET_MAX_XMIT_CMDS(ib_dev->attrs.max_qp_wr); - iser_dbg("device %s supports max_send_wr %d\n", - dev_name(&device->ib_device->dev), - ib_dev->attrs.max_qp_wr); - } - } + iser_conn->max_cmds = ISER_GET_MAX_XMIT_CMDS(max_send_wr - 1); ret = rdma_create_qp(ib_conn->cma_id, device->pd, &init_attr); if (ret) goto out_err; ib_conn->qp = ib_conn->cma_id->qp; - iser_info("setting conn %p cma_id %p qp %p\n", + iser_info("setting conn %p cma_id %p qp %p max_send_wr %d\n", ib_conn, ib_conn->cma_id, - ib_conn->cma_id->qp); + ib_conn->cma_id->qp, max_send_wr); return ret; out_err: - mutex_lock(&ig.connlist_mutex); - ib_conn->comp->active_qps--; - mutex_unlock(&ig.connlist_mutex); + ib_cq_pool_put(ib_conn->cq, ib_conn->cq_size); +cq_err: iser_err("unable to alloc mem or create resource, err %d\n", ret); return ret; @@ -462,10 +402,8 @@ static void iser_free_ib_conn_res(struct iser_conn *iser_conn, iser_conn, ib_conn->cma_id, ib_conn->qp); if (ib_conn->qp != NULL) { - mutex_lock(&ig.connlist_mutex); - ib_conn->comp->active_qps--; - mutex_unlock(&ig.connlist_mutex); rdma_destroy_qp(ib_conn->cma_id); + ib_cq_pool_put(ib_conn->cq, ib_conn->cq_size); ib_conn->qp = NULL; } diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index b7df38ee8ae056585a08d9b756fae3d3dee3d895..61e2f7fc513d060a4386fb6f7bd11e476a9d9889 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -24,13 +24,6 @@ #include "ib_isert.h" -#define ISERT_MAX_CONN 8 -#define ISER_MAX_RX_CQ_LEN (ISERT_QP_MAX_RECV_DTOS * ISERT_MAX_CONN) -#define ISER_MAX_TX_CQ_LEN \ - ((ISERT_QP_MAX_REQ_DTOS + ISCSI_DEF_XMIT_CMDS_MAX) * ISERT_MAX_CONN) -#define ISER_MAX_CQ_LEN (ISER_MAX_RX_CQ_LEN + ISER_MAX_TX_CQ_LEN + \ - ISERT_MAX_CONN) - static int isert_debug_level; module_param_named(debug_level, isert_debug_level, int, 0644); MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0 (default:0)"); @@ -82,53 +75,34 @@ isert_qp_event_callback(struct ib_event *e, void *context) } } -static struct isert_comp * -isert_comp_get(struct isert_conn *isert_conn) -{ - struct isert_device *device = isert_conn->device; - struct isert_comp *comp; - int i, min = 0; - - mutex_lock(&device_list_mutex); - for (i = 0; i < device->comps_used; i++) - if (device->comps[i].active_qps < - device->comps[min].active_qps) - min = i; - comp = &device->comps[min]; - comp->active_qps++; - mutex_unlock(&device_list_mutex); - - isert_info("conn %p, using comp %p min_index: %d\n", - isert_conn, comp, min); - - return comp; -} - -static void -isert_comp_put(struct isert_comp *comp) -{ - mutex_lock(&device_list_mutex); - comp->active_qps--; - mutex_unlock(&device_list_mutex); -} - static struct ib_qp * isert_create_qp(struct isert_conn *isert_conn, - struct isert_comp *comp, struct rdma_cm_id *cma_id) { + u32 cq_size = ISERT_QP_MAX_REQ_DTOS + ISERT_QP_MAX_RECV_DTOS + 2; struct isert_device *device = isert_conn->device; + struct ib_device *ib_dev = device->ib_device; struct ib_qp_init_attr attr; - int ret; + int ret, factor; + + isert_conn->cq = ib_cq_pool_get(ib_dev, cq_size, -1, IB_POLL_WORKQUEUE); + if (IS_ERR(isert_conn->cq)) { + isert_err("Unable to allocate cq\n"); + ret = PTR_ERR(isert_conn->cq); + return ERR_PTR(ret); + } + isert_conn->cq_size = cq_size; memset(&attr, 0, sizeof(struct ib_qp_init_attr)); attr.event_handler = isert_qp_event_callback; attr.qp_context = isert_conn; - attr.send_cq = comp->cq; - attr.recv_cq = comp->cq; + attr.send_cq = isert_conn->cq; + attr.recv_cq = isert_conn->cq; attr.cap.max_send_wr = ISERT_QP_MAX_REQ_DTOS + 1; attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS + 1; - attr.cap.max_rdma_ctxs = ISCSI_DEF_XMIT_CMDS_MAX; + factor = rdma_rw_mr_factor(device->ib_device, cma_id->port_num, + ISCSI_ISER_MAX_SG_TABLESIZE); + attr.cap.max_rdma_ctxs = ISCSI_DEF_XMIT_CMDS_MAX * factor; attr.cap.max_send_sge = device->ib_device->attrs.max_send_sge; attr.cap.max_recv_sge = 1; attr.sq_sig_type = IB_SIGNAL_REQ_WR; @@ -139,31 +113,14 @@ isert_create_qp(struct isert_conn *isert_conn, ret = rdma_create_qp(cma_id, device->pd, &attr); if (ret) { isert_err("rdma_create_qp failed for cma_id %d\n", ret); + ib_cq_pool_put(isert_conn->cq, isert_conn->cq_size); + return ERR_PTR(ret); } return cma_id->qp; } -static int -isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id) -{ - struct isert_comp *comp; - int ret; - - comp = isert_comp_get(isert_conn); - isert_conn->qp = isert_create_qp(isert_conn, comp, cma_id); - if (IS_ERR(isert_conn->qp)) { - ret = PTR_ERR(isert_conn->qp); - goto err; - } - - return 0; -err: - isert_comp_put(comp); - return ret; -} - static int isert_alloc_rx_descriptors(struct isert_conn *isert_conn) { @@ -231,61 +188,6 @@ isert_free_rx_descriptors(struct isert_conn *isert_conn) isert_conn->rx_descs = NULL; } -static void -isert_free_comps(struct isert_device *device) -{ - int i; - - for (i = 0; i < device->comps_used; i++) { - struct isert_comp *comp = &device->comps[i]; - - if (comp->cq) - ib_free_cq(comp->cq); - } - kfree(device->comps); -} - -static int -isert_alloc_comps(struct isert_device *device) -{ - int i, max_cqe, ret = 0; - - device->comps_used = min(ISERT_MAX_CQ, min_t(int, num_online_cpus(), - device->ib_device->num_comp_vectors)); - - isert_info("Using %d CQs, %s supports %d vectors support " - "pi_capable %d\n", - device->comps_used, dev_name(&device->ib_device->dev), - device->ib_device->num_comp_vectors, - device->pi_capable); - - device->comps = kcalloc(device->comps_used, sizeof(struct isert_comp), - GFP_KERNEL); - if (!device->comps) - return -ENOMEM; - - max_cqe = min(ISER_MAX_CQ_LEN, device->ib_device->attrs.max_cqe); - - for (i = 0; i < device->comps_used; i++) { - struct isert_comp *comp = &device->comps[i]; - - comp->device = device; - comp->cq = ib_alloc_cq(device->ib_device, comp, max_cqe, i, - IB_POLL_WORKQUEUE); - if (IS_ERR(comp->cq)) { - isert_err("Unable to allocate cq\n"); - ret = PTR_ERR(comp->cq); - comp->cq = NULL; - goto out_cq; - } - } - - return 0; -out_cq: - isert_free_comps(device); - return ret; -} - static int isert_create_device_ib_res(struct isert_device *device) { @@ -296,16 +198,12 @@ isert_create_device_ib_res(struct isert_device *device) ib_dev->attrs.max_send_sge, ib_dev->attrs.max_recv_sge); isert_dbg("devattr->max_sge_rd: %d\n", ib_dev->attrs.max_sge_rd); - ret = isert_alloc_comps(device); - if (ret) - goto out; - device->pd = ib_alloc_pd(ib_dev, 0); if (IS_ERR(device->pd)) { ret = PTR_ERR(device->pd); isert_err("failed to allocate pd, device %p, ret=%d\n", device, ret); - goto out_cq; + return ret; } /* Check signature cap */ @@ -313,13 +211,6 @@ isert_create_device_ib_res(struct isert_device *device) IB_DEVICE_INTEGRITY_HANDOVER ? true : false; return 0; - -out_cq: - isert_free_comps(device); -out: - if (ret > 0) - ret = -EINVAL; - return ret; } static void @@ -328,7 +219,6 @@ isert_free_device_ib_res(struct isert_device *device) isert_info("device %p\n", device); ib_dealloc_pd(device->pd); - isert_free_comps(device); } static void @@ -490,6 +380,13 @@ isert_set_nego_params(struct isert_conn *isert_conn, } } +static void +isert_destroy_qp(struct isert_conn *isert_conn) +{ + ib_destroy_qp(isert_conn->qp); + ib_cq_pool_put(isert_conn->cq, isert_conn->cq_size); +} + static int isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) { @@ -530,17 +427,19 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) isert_set_nego_params(isert_conn, &event->param.conn); - ret = isert_conn_setup_qp(isert_conn, cma_id); - if (ret) + isert_conn->qp = isert_create_qp(isert_conn, cma_id); + if (IS_ERR(isert_conn->qp)) { + ret = PTR_ERR(isert_conn->qp); goto out_conn_dev; + } ret = isert_login_post_recv(isert_conn); if (ret) - goto out_conn_dev; + goto out_destroy_qp; ret = isert_rdma_accept(isert_conn); if (ret) - goto out_conn_dev; + goto out_destroy_qp; mutex_lock(&isert_np->mutex); list_add_tail(&isert_conn->node, &isert_np->accepted); @@ -548,6 +447,8 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) return 0; +out_destroy_qp: + isert_destroy_qp(isert_conn); out_conn_dev: isert_device_put(device); out_rsp_dma_map: @@ -572,12 +473,8 @@ isert_connect_release(struct isert_conn *isert_conn) !isert_conn->dev_removed) rdma_destroy_id(isert_conn->cm_id); - if (isert_conn->qp) { - struct isert_comp *comp = isert_conn->qp->recv_cq->cq_context; - - isert_comp_put(comp); - ib_destroy_qp(isert_conn->qp); - } + if (isert_conn->qp) + isert_destroy_qp(isert_conn); if (isert_conn->login_req_buf) isert_free_login_buf(isert_conn); diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 3b296bac4f6039f356052e6110afc3016bd7b46e..c55f7d9bfced60cb51e67201fb74d5770b9f681d 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -63,7 +63,8 @@ (ISER_RX_PAYLOAD_SIZE + sizeof(u64) + sizeof(struct ib_sge) + \ sizeof(struct ib_cqe) + sizeof(bool))) -#define ISCSI_ISER_SG_TABLESIZE 256 +/* Maximum support is 16MB I/O size */ +#define ISCSI_ISER_MAX_SG_TABLESIZE 4096 enum isert_desc_type { ISCSI_TX_CONTROL, @@ -155,6 +156,8 @@ struct isert_conn { struct iser_tx_desc login_tx_desc; struct rdma_cm_id *cm_id; struct ib_qp *qp; + struct ib_cq *cq; + u32 cq_size; struct isert_device *device; struct mutex mutex; struct kref kref; @@ -165,22 +168,6 @@ struct isert_conn { bool dev_removed; }; -#define ISERT_MAX_CQ 64 - -/** - * struct isert_comp - iSER completion context - * - * @device: pointer to device handle - * @cq: completion queue - * @active_qps: Number of active QPs attached - * to completion context - */ -struct isert_comp { - struct isert_device *device; - struct ib_cq *cq; - int active_qps; -}; - struct isert_device { bool pi_capable; int refcount; diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.h b/drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.h index d324312a373c0a70749367826bfe796f456dc8f8..f64519872297e486bedfcf930412ec7d65aff472 100644 --- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.h +++ b/drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.h @@ -118,12 +118,17 @@ * struct opa_vesw_info - OPA vnic switch information * @fabric_id: 10-bit fabric id * @vesw_id: 12-bit virtual ethernet switch id + * @rsvd0: reserved bytes * @def_port_mask: bitmask of default ports + * @rsvd1: reserved bytes * @pkey: partition key + * @rsvd2: reserved bytes * @u_mcast_dlid: unknown multicast dlid * @u_ucast_dlid: array of unknown unicast dlids + * @rsvd3: reserved bytes * @rc: routing control * @eth_mtu: Ethernet MTU + * @rsvd4: reserved bytes */ struct opa_vesw_info { __be16 fabric_id; @@ -150,12 +155,14 @@ struct opa_vesw_info { * struct opa_per_veswport_info - OPA vnic per port information * @port_num: port number * @eth_link_status: current ethernet link state + * @rsvd0: reserved bytes * @base_mac_addr: base mac address * @config_state: configured port state * @oper_state: operational port state * @max_mac_tbl_ent: max number of mac table entries * @max_smac_ent: max smac entries in mac table * @mac_tbl_digest: mac table digest + * @rsvd1: reserved bytes * @encap_slid: base slid for the port * @pcp_to_sc_uc: sc by pcp index for unicast ethernet packets * @pcp_to_vl_uc: vl by pcp index for unicast ethernet packets @@ -165,8 +172,10 @@ struct opa_vesw_info { * @non_vlan_vl_uc: vl for non-vlan unicast ethernet packets * @non_vlan_sc_mc: sc for non-vlan multicast ethernet packets * @non_vlan_vl_mc: vl for non-vlan multicast ethernet packets + * @rsvd2: reserved bytes * @uc_macs_gen_count: generation count for unicast macs list * @mc_macs_gen_count: generation count for multicast macs list + * @rsvd3: reserved bytes */ struct opa_per_veswport_info { __be32 port_num; @@ -294,6 +303,7 @@ struct opa_veswport_mactable { * @rx_512_1023: received packet length is >=512 and < 1023 bytes * @rx_1024_1518: received packet length is >=1024 and < 1518 bytes * @rx_1519_max: received packet length >= 1519 bytes + * @reserved: reserved bytes * * All the above are counters of corresponding conditions. */ @@ -347,16 +357,26 @@ struct opa_veswport_summary_counters { * @veswport_num: virtual ethernet switch port number * @tx_errors: transmit errors * @rx_errors: receive errors + * @rsvd0: reserved bytes * @tx_smac_filt: smac filter errors + * @rsvd1: reserved bytes + * @rsvd2: reserved bytes + * @rsvd3: reserved bytes * @tx_dlid_zero: transmit packets with invalid dlid + * @rsvd4: reserved bytes * @tx_logic: other transmit errors + * @rsvd5: reserved bytes * @tx_drop_state: packet tansmission in non-forward port state * @rx_bad_veswid: received packet with invalid vesw id + * @rsvd6: reserved bytes * @rx_runt: received ethernet packet with length < 64 bytes * @rx_oversize: received ethernet packet with length > MTU size + * @rsvd7: reserved bytes * @rx_eth_down: received packets when interface is down * @rx_drop_state: received packets in non-forwarding port state * @rx_logic: other receive errors + * @rsvd8: reserved bytes + * @rsvd9: reserved bytes * * All the above are counters of corresponding error conditions. */ @@ -447,6 +467,7 @@ struct opa_veswport_iface_macs { * struct opa_vnic_vema_mad - Generic VEMA MAD * @mad_hdr: Generic MAD header * @rmpp_hdr: RMPP header for vendor specific MADs + * @reserved: reserved bytes * @oui: Unique org identifier * @data: MAD data */ @@ -467,6 +488,7 @@ struct opa_vnic_vema_mad { * @trap_num: Trap number * @toggle_count: Notice toggle bit and count value * @issuer_lid: Trap issuer's lid + * @reserved: reserved bytes * @issuer_gid: Issuer GID (only if Report method) * @raw_data: Trap message body */ @@ -487,6 +509,7 @@ struct opa_vnic_notice_attr { * struct opa_vnic_vema_mad_trap - Generic VEMA MAD Trap * @mad_hdr: Generic MAD header * @rmpp_hdr: RMPP header for vendor specific MADs + * @reserved: reserved bytes * @oui: Unique org identifier * @notice: Notice structure */ diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c index 564388a85603f5cb782994a86a6925a964426209..776e89231c52f77a5096d46b2286c0f2377e2458 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c @@ -12,6 +12,7 @@ #include #include +#include #include "rtrs-clt.h" #include "rtrs-log.h" @@ -23,6 +24,12 @@ * leads to "false positives" failed reconnect attempts */ #define RTRS_RECONNECT_BACKOFF 1000 +/* + * Wait for additional random time between 0 and 8 seconds + * before starting to reconnect to avoid clients reconnecting + * all at once in case of a major network outage + */ +#define RTRS_RECONNECT_SEED 8 MODULE_DESCRIPTION("RDMA Transport Client"); MODULE_LICENSE("GPL"); @@ -306,7 +313,8 @@ static void rtrs_rdma_error_recovery(struct rtrs_clt_con *con) */ delay_ms = clt->reconnect_delay_sec * 1000; queue_delayed_work(rtrs_wq, &sess->reconnect_dwork, - msecs_to_jiffies(delay_ms)); + msecs_to_jiffies(delay_ms + + prandom_u32() % RTRS_RECONNECT_SEED)); } else { /* * Error can happen just on establishing new connection, @@ -2503,7 +2511,9 @@ reconnect_again: sess->stats->reconnects.fail_cnt++; delay_ms = clt->reconnect_delay_sec * 1000; queue_delayed_work(rtrs_wq, &sess->reconnect_dwork, - msecs_to_jiffies(delay_ms)); + msecs_to_jiffies(delay_ms + + prandom_u32() % + RTRS_RECONNECT_SEED)); } } @@ -2972,7 +2982,7 @@ static int __init rtrs_client_init(void) pr_err("Failed to create rtrs-client dev class\n"); return PTR_ERR(rtrs_clt_dev_class); } - rtrs_wq = alloc_workqueue("rtrs_client_wq", WQ_MEM_RECLAIM, 0); + rtrs_wq = alloc_workqueue("rtrs_client_wq", 0, 0); if (!rtrs_wq) { class_destroy(rtrs_clt_dev_class); return -ENOMEM; diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c index 0d9241f5d9e68406a2e9b36aedc23cad08a0939e..a219bd1bdbc26525b3144356c1bc76080e67a273 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -2150,7 +2150,7 @@ static int __init rtrs_server_init(void) err = PTR_ERR(rtrs_dev_class); goto out_chunk_pool; } - rtrs_wq = alloc_workqueue("rtrs_server_wq", WQ_MEM_RECLAIM, 0); + rtrs_wq = alloc_workqueue("rtrs_server_wq", 0, 0); if (!rtrs_wq) { err = -ENOMEM; goto out_dev_class; diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index ef7fcd3e8e1553e629c86614cbfda93791541632..0065eb17ae36b49ebb9097cee09ff7688f3fbf8c 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -869,7 +869,7 @@ static int srpt_zerolength_write(struct srpt_rdma_ch *ch) static void srpt_zerolength_write_done(struct ib_cq *cq, struct ib_wc *wc) { - struct srpt_rdma_ch *ch = cq->cq_context; + struct srpt_rdma_ch *ch = wc->qp->qp_context; pr_debug("%s-%d wc->status %d\n", ch->sess_name, ch->qp->qp_num, wc->status); @@ -1322,7 +1322,7 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx) */ static void srpt_rdma_read_done(struct ib_cq *cq, struct ib_wc *wc) { - struct srpt_rdma_ch *ch = cq->cq_context; + struct srpt_rdma_ch *ch = wc->qp->qp_context; struct srpt_send_ioctx *ioctx = container_of(wc->wr_cqe, struct srpt_send_ioctx, rdma_cqe); @@ -1683,7 +1683,7 @@ push: static void srpt_recv_done(struct ib_cq *cq, struct ib_wc *wc) { - struct srpt_rdma_ch *ch = cq->cq_context; + struct srpt_rdma_ch *ch = wc->qp->qp_context; struct srpt_recv_ioctx *ioctx = container_of(wc->wr_cqe, struct srpt_recv_ioctx, ioctx.cqe); @@ -1744,7 +1744,7 @@ static void srpt_process_wait_list(struct srpt_rdma_ch *ch) */ static void srpt_send_done(struct ib_cq *cq, struct ib_wc *wc) { - struct srpt_rdma_ch *ch = cq->cq_context; + struct srpt_rdma_ch *ch = wc->qp->qp_context; struct srpt_send_ioctx *ioctx = container_of(wc->wr_cqe, struct srpt_send_ioctx, ioctx.cqe); enum srpt_command_state state; @@ -1791,7 +1791,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) goto out; retry: - ch->cq = ib_alloc_cq_any(sdev->device, ch, ch->rq_size + sq_size, + ch->cq = ib_cq_pool_get(sdev->device, ch->rq_size + sq_size, -1, IB_POLL_WORKQUEUE); if (IS_ERR(ch->cq)) { ret = PTR_ERR(ch->cq); @@ -1799,6 +1799,7 @@ retry: ch->rq_size + sq_size, ret); goto out; } + ch->cq_size = ch->rq_size + sq_size; qp_init->qp_context = (void *)ch; qp_init->event_handler @@ -1843,7 +1844,7 @@ retry: if (retry) { pr_debug("failed to create queue pair with sq_size = %d (%d) - retrying\n", sq_size, ret); - ib_free_cq(ch->cq); + ib_cq_pool_put(ch->cq, ch->cq_size); sq_size = max(sq_size / 2, MIN_SRPT_SQ_SIZE); goto retry; } else { @@ -1869,14 +1870,14 @@ out: err_destroy_cq: ch->qp = NULL; - ib_free_cq(ch->cq); + ib_cq_pool_put(ch->cq, ch->cq_size); goto out; } static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch) { ib_destroy_qp(ch->qp); - ib_free_cq(ch->cq); + ib_cq_pool_put(ch->cq, ch->cq_size); } /** @@ -2156,9 +2157,6 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev, WARN_ON_ONCE(irqs_disabled()); - if (WARN_ON(!sdev || !req)) - return -EINVAL; - it_iu_len = be32_to_cpu(req->req_it_iu_len); pr_info("Received SRP_LOGIN_REQ with i_port_id %pI6, t_port_id %pI6 and it_iu_len %d on port %d (guid=%pI6); pkey %#04x\n", diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h index f31c349d07a1205e98432a6b76121797e55d1bda..41435a699b53e81b5bb7daa860b8c6f62c4c0316 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.h +++ b/drivers/infiniband/ulp/srpt/ib_srpt.h @@ -300,6 +300,7 @@ struct srpt_rdma_ch { } rdma_cm; }; struct ib_cq *cq; + u32 cq_size; struct ib_cqe zw_cqe; struct rcu_head rcu; struct kref kref; diff --git a/drivers/input/touchscreen/tsc2007_iio.c b/drivers/input/touchscreen/tsc2007_iio.c index 3b0e3fa87d4cbe9e13e1f0b473f3fb606cffbfeb..752eb7fe5da3af8d0972a46eeff4583af840fb79 100644 --- a/drivers/input/touchscreen/tsc2007_iio.c +++ b/drivers/input/touchscreen/tsc2007_iio.c @@ -119,7 +119,6 @@ int tsc2007_iio_configure(struct tsc2007 *ts) iio->ts = ts; indio_dev->name = "tsc2007"; - indio_dev->dev.parent = &ts->client->dev; indio_dev->info = &tsc2007_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = tsc2007_iio_channel; diff --git a/drivers/most/Kconfig b/drivers/most/Kconfig index 58d7999170a71eed5468b430fcdc9c024bbd1f91..60fc0820dad38455fd09013295a428b17f996281 100644 --- a/drivers/most/Kconfig +++ b/drivers/most/Kconfig @@ -13,3 +13,14 @@ menuconfig MOST module will be called most_core. If in doubt, say N here. + +if MOST +config MOST_USB_HDM + tristate "USB" + depends on USB + help + Say Y here if you want to connect via USB to network transceiver. + + To compile this driver as a module, choose M here: the + module will be called most_usb. +endif diff --git a/drivers/most/Makefile b/drivers/most/Makefile index e810cd3a47eef87e615fc86335ac16dfbbdbfa9e..6a3cb905628865611566120d1c129162a352cc03 100644 --- a/drivers/most/Makefile +++ b/drivers/most/Makefile @@ -2,3 +2,5 @@ obj-$(CONFIG_MOST) += most_core.o most_core-y := core.o \ configfs.o + +obj-$(CONFIG_MOST_USB_HDM) += most_usb.o diff --git a/drivers/most/core.c b/drivers/most/core.c index f781c46cd4af9afc2458a1fe0d53c95bbbb8abfb..353ab277cbc6bc0c05b49c5a9c32d595690085b8 100644 --- a/drivers/most/core.c +++ b/drivers/most/core.c @@ -1283,10 +1283,8 @@ int most_register_interface(struct most_interface *iface) struct most_channel *c; if (!iface || !iface->enqueue || !iface->configure || - !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { - dev_err(iface->dev, "Bad interface or channel overflow\n"); + !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) return -EINVAL; - } id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); if (id < 0) { diff --git a/drivers/staging/most/usb/usb.c b/drivers/most/most_usb.c similarity index 100% rename from drivers/staging/most/usb/usb.c rename to drivers/most/most_usb.c diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c index 3de8a5e83b6c7f73ac3868d2550bfef45f7fd073..e3510e9b21f3ceed337f92ede334d50a9efd7c7c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c @@ -92,6 +92,14 @@ int cxgb4_thermal_init(struct adapter *adap) ch_thermal->tzdev = NULL; return ret; } + + ret = thermal_zone_device_enable(ch_thermal->tzdev); + if (ret) { + dev_err(adap->pdev_dev, "Failed to enable thermal zone\n"); + thermal_zone_device_unregister(adap->ch_thermal.tzdev); + return ret; + } + return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c index 42198e64a7f49b03de260c24aff91c491c0cb0fb..8db4b5f0f963b30028e94c40690e988334eb8fc6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c @@ -299,11 +299,18 @@ void mlx5_fill_page_array(struct mlx5_frag_buf *buf, __be64 *pas) } EXPORT_SYMBOL_GPL(mlx5_fill_page_array); -void mlx5_fill_page_frag_array(struct mlx5_frag_buf *buf, __be64 *pas) +void mlx5_fill_page_frag_array_perm(struct mlx5_frag_buf *buf, __be64 *pas, u8 perm) { int i; + WARN_ON(perm & 0xfc); for (i = 0; i < buf->npages; i++) - pas[i] = cpu_to_be64(buf->frags[i].map); + pas[i] = cpu_to_be64(buf->frags[i].map | perm); +} +EXPORT_SYMBOL_GPL(mlx5_fill_page_frag_array_perm); + +void mlx5_fill_page_frag_array(struct mlx5_frag_buf *buf, __be64 *pas) +{ + mlx5_fill_page_frag_array_perm(buf, pas, 0); } EXPORT_SYMBOL_GPL(mlx5_fill_page_frag_array); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 7e70a8178a46235882941806d67da5b24bb5aa84..9ccec5f8b92a78cd3efe6d884f499e335888c583 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -1577,6 +1577,7 @@ static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg, static bool counter_is_valid(u32 action) { return (action & (MLX5_FLOW_CONTEXT_ACTION_DROP | + MLX5_FLOW_CONTEXT_ACTION_ALLOW | MLX5_FLOW_CONTEXT_ACTION_FWD_DEST)); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 5763965d5ef3358e73526999854a1c09b71424b9..97b5fcb1f406448f3789d9d0047911d763ecf7ed 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -226,13 +226,20 @@ void mlx5i_uninit_underlay_qp(struct mlx5e_priv *priv) int mlx5i_create_underlay_qp(struct mlx5e_priv *priv) { + unsigned char *dev_addr = priv->netdev->dev_addr; u32 out[MLX5_ST_SZ_DW(create_qp_out)] = {}; u32 in[MLX5_ST_SZ_DW(create_qp_in)] = {}; struct mlx5i_priv *ipriv = priv->ppriv; void *addr_path; + int qpn = 0; int ret = 0; void *qpc; + if (MLX5_CAP_GEN(priv->mdev, mkey_by_name)) { + qpn = (dev_addr[1] << 16) + (dev_addr[2] << 8) + dev_addr[3]; + MLX5_SET(create_qp_in, in, input_qpn, qpn); + } + qpc = MLX5_ADDR_OF(create_qp_in, in, qpc); MLX5_SET(qpc, qpc, st, MLX5_QP_ST_UD); MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index e32d46c337011bd8cbc4ba76553b57fe5af513f8..ce43e3feccd932de0f77ff9386a336d3d3a22689 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -557,6 +557,9 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx) if (MLX5_CAP_GEN_MAX(dev, release_all_pages)) MLX5_SET(cmd_hca_cap, set_hca_cap, release_all_pages, 1); + if (MLX5_CAP_GEN_MAX(dev, mkey_by_name)) + MLX5_SET(cmd_hca_cap, set_hca_cap, mkey_by_name, 1); + return set_caps(dev, set_ctx, MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index 05f8d5a92862f490424e98180f11fe31aa84297e..8fa286ccdd6bb281a834bc135593487878930403 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -98,7 +98,6 @@ struct mlxsw_thermal_module { struct mlxsw_thermal *parent; struct thermal_zone_device *tzdev; struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; - enum thermal_device_mode mode; int module; /* Module or gearbox number */ }; @@ -110,7 +109,6 @@ struct mlxsw_thermal { struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX]; u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; - enum thermal_device_mode mode; struct mlxsw_thermal_module *tz_module_arr; u8 tz_module_num; struct mlxsw_thermal_module *tz_gearbox_arr; @@ -277,36 +275,6 @@ static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev, return 0; } -static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev, - enum thermal_device_mode *mode) -{ - struct mlxsw_thermal *thermal = tzdev->devdata; - - *mode = thermal->mode; - - return 0; -} - -static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev, - enum thermal_device_mode mode) -{ - struct mlxsw_thermal *thermal = tzdev->devdata; - - mutex_lock(&tzdev->lock); - - if (mode == THERMAL_DEVICE_ENABLED) - tzdev->polling_delay = thermal->polling_delay; - else - tzdev->polling_delay = 0; - - mutex_unlock(&tzdev->lock); - - thermal->mode = mode; - thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED); - - return 0; -} - static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev, int *p_temp) { @@ -406,8 +374,6 @@ static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev, static struct thermal_zone_device_ops mlxsw_thermal_ops = { .bind = mlxsw_thermal_bind, .unbind = mlxsw_thermal_unbind, - .get_mode = mlxsw_thermal_get_mode, - .set_mode = mlxsw_thermal_set_mode, .get_temp = mlxsw_thermal_get_temp, .get_trip_type = mlxsw_thermal_get_trip_type, .get_trip_temp = mlxsw_thermal_get_trip_temp, @@ -465,37 +431,6 @@ static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev, return err; } -static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev, - enum thermal_device_mode *mode) -{ - struct mlxsw_thermal_module *tz = tzdev->devdata; - - *mode = tz->mode; - - return 0; -} - -static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev, - enum thermal_device_mode mode) -{ - struct mlxsw_thermal_module *tz = tzdev->devdata; - struct mlxsw_thermal *thermal = tz->parent; - - mutex_lock(&tzdev->lock); - - if (mode == THERMAL_DEVICE_ENABLED) - tzdev->polling_delay = thermal->polling_delay; - else - tzdev->polling_delay = 0; - - mutex_unlock(&tzdev->lock); - - tz->mode = mode; - thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED); - - return 0; -} - static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, int *p_temp) { @@ -611,8 +546,6 @@ static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev, static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { .bind = mlxsw_thermal_module_bind, .unbind = mlxsw_thermal_module_unbind, - .get_mode = mlxsw_thermal_module_mode_get, - .set_mode = mlxsw_thermal_module_mode_set, .get_temp = mlxsw_thermal_module_temp_get, .get_trip_type = mlxsw_thermal_module_trip_type_get, .get_trip_temp = mlxsw_thermal_module_trip_temp_get, @@ -650,8 +583,6 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = { .bind = mlxsw_thermal_module_bind, .unbind = mlxsw_thermal_module_unbind, - .get_mode = mlxsw_thermal_module_mode_get, - .set_mode = mlxsw_thermal_module_mode_set, .get_temp = mlxsw_thermal_gearbox_temp_get, .get_trip_type = mlxsw_thermal_module_trip_type_get, .get_trip_temp = mlxsw_thermal_module_trip_temp_get, @@ -780,8 +711,11 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) return err; } - module_tz->mode = THERMAL_DEVICE_ENABLED; - return 0; + err = thermal_zone_device_enable(module_tz->tzdev); + if (err) + thermal_zone_device_unregister(module_tz->tzdev); + + return err; } static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev) @@ -884,6 +818,7 @@ static int mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) { char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME]; + int ret; snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d", gearbox_tz->module + 1); @@ -896,8 +831,11 @@ mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) if (IS_ERR(gearbox_tz->tzdev)) return PTR_ERR(gearbox_tz->tzdev); - gearbox_tz->mode = THERMAL_DEVICE_ENABLED; - return 0; + ret = thermal_zone_device_enable(gearbox_tz->tzdev); + if (ret) + thermal_zone_device_unregister(gearbox_tz->tzdev); + + return ret; } static void @@ -1065,10 +1003,15 @@ int mlxsw_thermal_init(struct mlxsw_core *core, if (err) goto err_unreg_modules_tzdev; - thermal->mode = THERMAL_DEVICE_ENABLED; + err = thermal_zone_device_enable(thermal->tzdev); + if (err) + goto err_unreg_gearboxes; + *p_thermal = thermal; return 0; +err_unreg_gearboxes: + mlxsw_thermal_gearboxes_fini(thermal); err_unreg_modules_tzdev: mlxsw_thermal_modules_fini(thermal); err_unreg_tzdev: diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index 418e59b7c6719d5c7bb9d51d2606edeecfef0727..0c95663bf9edcf26195facde3f351b5af40e05d5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c @@ -733,7 +733,7 @@ static struct thermal_zone_device_ops tzone_ops = { static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) { - int i; + int i, ret; char name[16]; static atomic_t counter = ATOMIC_INIT(0); @@ -759,6 +759,13 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) return; } + ret = thermal_zone_device_enable(mvm->tz_device.tzone); + if (ret) { + IWL_DEBUG_TEMP(mvm, "Failed to enable thermal zone\n"); + thermal_zone_device_unregister(mvm->tz_device.tzone); + return; + } + /* 0 is a valid temperature, * so initialize the array with S16_MIN which invalid temperature */ diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index a7a0b2e0ceb936599941b573431fb7c75970b7c1..44b6bfbd32dff8e09263a521eda7f0573c6fb1e7 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -397,39 +397,24 @@ static inline void acerhdf_revert_to_bios_mode(void) { acerhdf_change_fanstate(ACERHDF_FAN_AUTO); kernelmode = 0; - if (thz_dev) - thz_dev->polling_delay = 0; + pr_notice("kernel mode fan control OFF\n"); } static inline void acerhdf_enable_kernelmode(void) { kernelmode = 1; - thz_dev->polling_delay = interval*1000; - thermal_zone_device_update(thz_dev, THERMAL_EVENT_UNSPECIFIED); pr_notice("kernel mode fan control ON\n"); } -static int acerhdf_get_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode *mode) -{ - if (verbose) - pr_notice("kernel mode fan control %d\n", kernelmode); - - *mode = (kernelmode) ? THERMAL_DEVICE_ENABLED - : THERMAL_DEVICE_DISABLED; - - return 0; -} - /* * set operation mode; * enabled: the thermal layer of the kernel takes care about * the temperature and the fan. * disabled: the BIOS takes control of the fan. */ -static int acerhdf_set_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode mode) +static int acerhdf_change_mode(struct thermal_zone_device *thermal, + enum thermal_device_mode mode) { if (mode == THERMAL_DEVICE_DISABLED && kernelmode) acerhdf_revert_to_bios_mode(); @@ -488,8 +473,7 @@ static struct thermal_zone_device_ops acerhdf_dev_ops = { .bind = acerhdf_bind, .unbind = acerhdf_unbind, .get_temp = acerhdf_get_ec_temp, - .get_mode = acerhdf_get_mode, - .set_mode = acerhdf_set_mode, + .change_mode = acerhdf_change_mode, .get_trip_type = acerhdf_get_trip_type, .get_trip_hyst = acerhdf_get_trip_hyst, .get_trip_temp = acerhdf_get_trip_temp, @@ -733,6 +717,8 @@ static void acerhdf_unregister_platform(void) static int __init acerhdf_register_thermal(void) { + int ret; + cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL, &acerhdf_cooling_ops); @@ -746,6 +732,13 @@ static int __init acerhdf_register_thermal(void) if (IS_ERR(thz_dev)) return -EINVAL; + if (kernelmode) + ret = thermal_zone_device_enable(thz_dev); + else + ret = thermal_zone_device_disable(thz_dev); + if (ret) + return ret; + if (strcmp(thz_dev->governor->name, acerhdf_zone_params.governor_name)) { pr_err("Didn't get thermal governor %s, perhaps not compiled into thermal subsystem.\n", diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c index f402e2e74a38392e9abf1eae8debc3630dcc828c..f12f4e7bd971c14e2a737c1a1fe61435a1f23ee4 100644 --- a/drivers/platform/x86/intel_mid_thermal.c +++ b/drivers/platform/x86/intel_mid_thermal.c @@ -493,6 +493,12 @@ static int mid_thermal_probe(struct platform_device *pdev) ret = PTR_ERR(pinfo->tzd[i]); goto err; } + ret = thermal_zone_device_enable(pinfo->tzd[i]); + if (ret) { + kfree(td_info); + thermal_zone_device_unregister(pinfo->tzd[i]); + goto err; + } } pinfo->pdev = pdev; diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 1ddab5a6dead6ddf0bc6e821ba0988b51758e4c6..36fff00af9ebd482d2dce7b10e25281767c6d188 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -3114,7 +3114,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) toshiba_accelerometer_available(dev); if (dev->accelerometer_supported) { - dev->indio_dev = iio_device_alloc(sizeof(*dev)); + dev->indio_dev = iio_device_alloc(&acpi_dev->dev, sizeof(*dev)); if (!dev->indio_dev) { pr_err("Unable to allocate iio device\n"); goto iio_error; @@ -3124,7 +3124,6 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) dev->indio_dev->info = &toshiba_iio_accel_info; dev->indio_dev->name = "Toshiba accelerometer"; - dev->indio_dev->dev.parent = &acpi_dev->dev; dev->indio_dev->modes = INDIO_DIRECT_MODE; dev->indio_dev->channels = toshiba_iio_accel_channels; dev->indio_dev->num_channels = diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 02b37fe6061c08ee0b9ad97ccc8ff228f12d6fd2..90e56736d4794f6cdf68e9aa387857465bf9ae9c 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -939,7 +939,7 @@ static struct thermal_zone_device_ops psy_tzd_ops = { static int psy_register_thermal(struct power_supply *psy) { - int i; + int i, ret; if (psy->desc->no_thermal) return 0; @@ -949,7 +949,12 @@ static int psy_register_thermal(struct power_supply *psy) if (psy->desc->properties[i] == POWER_SUPPLY_PROP_TEMP) { psy->tzd = thermal_zone_device_register(psy->desc->name, 0, 0, psy, &psy_tzd_ops, NULL, 0, 0); - return PTR_ERR_OR_ZERO(psy->tzd); + if (IS_ERR(psy->tzd)) + return PTR_ERR(psy->tzd); + ret = thermal_zone_device_enable(psy->tzd); + if (ret) + thermal_zone_device_unregister(psy->tzd); + return ret; } } return 0; diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 49eda141ea431f8a92afe70786fc165e24b9372e..d9fd0a41da64ad8cc7bce39e4ba256df7d36b7a7 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -124,13 +124,12 @@ static void zfcp_ccw_remove(struct ccw_device *cdev) return; write_lock_irq(&adapter->port_list_lock); - list_for_each_entry_safe(port, p, &adapter->port_list, list) { + list_for_each_entry(port, &adapter->port_list, list) { write_lock(&port->unit_list_lock); - list_for_each_entry_safe(unit, u, &port->unit_list, list) - list_move(&unit->list, &unit_remove_lh); + list_splice_init(&port->unit_list, &unit_remove_lh); write_unlock(&port->unit_list_lock); - list_move(&port->list, &port_remove_lh); } + list_splice_init(&adapter->port_list, &port_remove_lh); write_unlock_irq(&adapter->port_list_lock); zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */ diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 79f6e8fb03cab3c646ebb6ff941a9b5731dd1a64..59e662df5774f867876e3a35a698824d332120f1 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -68,7 +68,7 @@ static void zfcp_erp_action_ready(struct zfcp_erp_action *act) { struct zfcp_adapter *adapter = act->adapter; - list_move(&act->list, &act->adapter->erp_ready_head); + list_move(&act->list, &adapter->erp_ready_head); zfcp_dbf_rec_run("erardy1", act); wake_up(&adapter->erp_ready_wq); zfcp_dbf_rec_run("erardy2", act); diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index b018b61bd168edc580d24326f6c5d214dea4fa37..d24cafe02708fa941346510c6fd8aac21f1110e3 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -48,7 +48,7 @@ unsigned int zfcp_fc_port_scan_backoff(void) { if (!port_scan_backoff) return 0; - return get_random_int() % port_scan_backoff; + return prandom_u32_max(port_scan_backoff); } static void zfcp_fc_port_scan_time(struct zfcp_adapter *adapter) diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 3a7f3374d10a34d65f507f6db01dd5a2acd4579d..e78d65bd46b167437abaf27d9ea252c057835021 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -246,7 +246,7 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio) } /** - * zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO + * zfcp_qdio_send - send req to QDIO * @qdio: pointer to struct zfcp_qdio * @q_req: pointer to struct zfcp_qdio_req * Returns: 0 on success, error otherwise @@ -260,17 +260,20 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) zfcp_qdio_account(qdio); spin_unlock(&qdio->stat_lock); + atomic_sub(sbal_number, &qdio->req_q_free); + retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, q_req->sbal_first, sbal_number); if (unlikely(retval)) { + /* Failed to submit the IO, roll back our modifications. */ + atomic_add(sbal_number, &qdio->req_q_free); zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first, sbal_number); return retval; } /* account for transferred buffers */ - atomic_sub(sbal_number, &qdio->req_q_free); qdio->req_q_idx += sbal_number; qdio->req_q_idx %= QDIO_MAX_BUFFERS_PER_Q; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index e9ff4cd5fbe90e8981086bd9052fbb236147c1ee..701b61ec76eed44d2ee16736aef6ba09ab5d3eaf 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1154,6 +1154,7 @@ source "drivers/scsi/qedf/Kconfig" config SCSI_LPFC tristate "Emulex LightPulse Fibre Channel Support" depends on PCI && SCSI + depends on CPU_FREQ depends on SCSI_FC_ATTRS depends on NVME_TARGET_FC || NVME_TARGET_FC=n depends on NVME_FC || NVME_FC=n @@ -1469,14 +1470,19 @@ config SCSI_SUNESP module will be called sun_esp. config ZFCP - tristate "FCP host bus adapter driver for IBM eServer zSeries" + tristate "FCP host bus adapter driver for IBM mainframes" depends on S390 && QDIO && SCSI depends on SCSI_FC_ATTRS help - If you want to access SCSI devices attached to your IBM eServer - zSeries by means of Fibre Channel interfaces say Y. - For details please refer to the documentation provided by IBM at - + If you want to access SCSI devices attached to your IBM mainframe by + means of Fibre Channel Protocol host bus adapters say Y. + + Supported HBAs include different models of the FICON Express and FCP + Express I/O cards. + + For a more complete list, and for more details about setup and + operation refer to the IBM publication "Device Drivers, Features, and + Commands", SC33-8411. This driver is also available as a module. This module will be called zfcp. If you want to compile it as a module, say M here diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 2b868f8db8ffe06737eea5d9a314f4798da4ca54..769af4ca9ca97e675c48e6a15750132b1969cf56 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -350,7 +350,8 @@ static inline int aac_valid_context(struct scsi_cmnd *scsicmd, /** * aac_get_config_status - check the adapter configuration - * @common: adapter to query + * @dev: aac driver data + * @commit_flag: force sending CT_COMMIT_CONFIG * * Query config status, and commit the configuration if needed. */ @@ -442,7 +443,7 @@ static void aac_expose_phy_device(struct scsi_cmnd *scsicmd) /** * aac_get_containers - list containers - * @common: adapter to probe + * @dev: aac driver data * * Make a list of all containers on this controller */ @@ -561,7 +562,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr) scsicmd->scsi_done(scsicmd); } -/** +/* * aac_get_container_name - get container name, none blocking. */ static int aac_get_container_name(struct scsi_cmnd * scsicmd) @@ -786,8 +787,7 @@ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(stru /** * aac_probe_container - query a logical volume - * @dev: device to query - * @cid: container identifier + * @scsicmd: the scsi command block * * Queries the controller about the given volume. The volume information * is updated in the struct fsa_dev_info structure rather than returned. @@ -1098,7 +1098,7 @@ static void get_container_serial_callback(void *context, struct fib * fibptr) scsicmd->scsi_done(scsicmd); } -/** +/* * aac_get_container_serial - get container serial, none blocking. */ static int aac_get_container_serial(struct scsi_cmnd * scsicmd) @@ -1952,8 +1952,6 @@ free_identify_resp: /** * aac_set_safw_attr_all_targets- update current hba map with data from FW * @dev: aac_dev structure - * @phys_luns: FW information from report phys luns - * @rescan: Indicates scan type * * Update our hba map with the information gathered from the FW */ @@ -3391,15 +3389,12 @@ int aac_dev_ioctl(struct aac_dev *dev, unsigned int cmd, void __user *arg) } /** - * * aac_srb_callback * @context: the context set in the fib - here it is scsi cmd * @fibptr: pointer to the fib * * Handles the completion of a scsi command to a non dasd device - * */ - static void aac_srb_callback(void *context, struct fib * fibptr) { struct aac_srb_reply *srbreply; @@ -3684,13 +3679,11 @@ static void hba_resp_task_failure(struct aac_dev *dev, } /** - * * aac_hba_callback * @context: the context set in the fib - here it is scsi cmd * @fibptr: pointer to the fib * * Handles the completion of a native HBA scsi command - * */ void aac_hba_callback(void *context, struct fib *fibptr) { @@ -3749,14 +3742,12 @@ out: } /** - * * aac_send_srb_fib * @scsicmd: the scsi command block * * This routine will form a FIB and fill in the aac_srb from the * scsicmd passed in. */ - static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) { struct fib* cmd_fibcontext; @@ -3792,7 +3783,6 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) } /** - * * aac_send_hba_fib * @scsicmd: the scsi command block * diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 34e65dea992e4d0c4c57471cf29d4d52f1707278..59e82a832042f038718ea00b4d4438b9e66b3755 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -32,6 +32,8 @@ #include "aacraid.h" +# define AAC_DEBUG_PREAMBLE KERN_INFO +# define AAC_DEBUG_POSTAMBLE /** * ioctl_send_fib - send a FIB from userspace * @dev: adapter is being processed @@ -40,9 +42,6 @@ * This routine sends a fib to the adapter on behalf of a user level * program. */ -# define AAC_DEBUG_PREAMBLE KERN_INFO -# define AAC_DEBUG_POSTAMBLE - static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) { struct hw_fib * kfib; @@ -158,11 +157,12 @@ cleanup: /** * open_getadapter_fib - Get the next fib + * @dev: adapter is being processed + * @arg: arguments to the open call * * This routine will get the next Fib, if available, from the AdapterFibContext * passed in from the user. */ - static int open_getadapter_fib(struct aac_dev * dev, void __user *arg) { struct aac_fib_context * fibctx; @@ -234,7 +234,6 @@ static int open_getadapter_fib(struct aac_dev * dev, void __user *arg) * This routine will get the next Fib, if available, from the AdapterFibContext * passed in from the user. */ - static int next_getadapter_fib(struct aac_dev * dev, void __user *arg) { struct fib_ioctl f; @@ -455,11 +454,10 @@ static int check_revision(struct aac_dev *dev, void __user *arg) /** - * * aac_send_raw_scb - * + * @dev: adapter is being processed + * @arg: arguments to the send call */ - static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) { struct fib* srbfib; diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 8ee4e1abe568d1f2f738e2d52063a7086beec854..adbdc3b7c7a706e0151c698f84c73251157a05e8 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -214,6 +214,7 @@ int aac_fib_setup(struct aac_dev * dev) /** * aac_fib_alloc_tag-allocate a fib using tags * @dev: Adapter to allocate the fib for + * @scmd: SCSI command * * Allocate a fib from the adapter fib pool using tags * from the blk layer. @@ -405,8 +406,8 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr * aac_queue_get - get the next free QE * @dev: Adapter * @index: Returned index - * @priority: Priority of fib - * @fib: Fib to associate with the queue entry + * @qid: Queue number + * @hw_fib: Fib to associate with the queue entry * @wait: Wait if queue full * @fibptr: Driver fib object to go with fib * @nonotify: Don't notify the adapter @@ -934,7 +935,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) /** * aac_fib_complete - fib completion handler - * @fib: FIB to complete + * @fibptr: FIB to complete * * Will do all necessary work to complete a FIB. */ @@ -1049,6 +1050,7 @@ static void aac_handle_aif_bu(struct aac_dev *dev, struct aac_aifcmd *aifcmd) } } +#define AIF_SNIFF_TIMEOUT (500*HZ) /** * aac_handle_aif - Handle a message from the firmware * @dev: Which adapter this fib is from @@ -1057,8 +1059,6 @@ static void aac_handle_aif_bu(struct aac_dev *dev, struct aac_aifcmd *aifcmd) * This routine handles a driver notify fib from the adapter and * dispatches it to the appropriate routine for handling. */ - -#define AIF_SNIFF_TIMEOUT (500*HZ) static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) { struct hw_fib * hw_fib = fibptr->hw_fib_va; @@ -2416,7 +2416,7 @@ out: /** * aac_command_thread - command processing thread - * @dev: Adapter to monitor + * @data: Adapter to monitor * * Waits on the commandready event in it's queue. When the event gets set * it will pull FIBs off it's queue. It will continue to pull FIBs off diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index a557aa629827ef32badf2e2b8303b8979819630b..fbe334c59f376cf34aaaf5f45febca390206bab5 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -99,10 +99,11 @@ unsigned int aac_response_normal(struct aac_queue * q) } if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) { - if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected)) + if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected)) { FIB_COUNTER_INCREMENT(aac_config.NoResponseRecved); - else + } else { FIB_COUNTER_INCREMENT(aac_config.AsyncRecved); + } /* * NOTE: we cannot touch the fib after this * call, because it may have been deallocated. @@ -229,7 +230,6 @@ static void aac_aif_callback(void *context, struct fib * fibptr) struct fib *fibctx; struct aac_dev *dev; struct aac_aifcmd *cmd; - int status; fibctx = (struct fib *)context; BUG_ON(fibptr == NULL); @@ -249,7 +249,7 @@ static void aac_aif_callback(void *context, struct fib * fibptr) cmd = (struct aac_aifcmd *) fib_data(fibctx); cmd->command = cpu_to_le32(AifReqEvent); - status = aac_fib_send(AifRequest, + aac_fib_send(AifRequest, fibctx, sizeof(struct hw_fib)-sizeof(struct aac_fibhdr), FsaNormal, @@ -258,7 +258,7 @@ static void aac_aif_callback(void *context, struct fib * fibptr) } -/** +/* * aac_intr_normal - Handle command replies * @dev: Device * @index: completion reference @@ -403,12 +403,13 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif, if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) { if (hwfib->header.XferState & cpu_to_le32( - NoResponseExpected)) + NoResponseExpected)) { FIB_COUNTER_INCREMENT( aac_config.NoResponseRecved); - else + } else { FIB_COUNTER_INCREMENT( aac_config.AsyncRecved); + } start_callback = 1; } else { unsigned long flagv; diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index a308e86a97f191f7abd2f9ba49317a56d29083ef..f043e378652c16a870aa08b09b7ad37e8b424168 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -230,8 +230,8 @@ static struct aac_driver_ident aac_drivers[] = { /** * aac_queuecommand - queue a SCSI command + * @shost: Scsi host to queue command on * @cmd: SCSI command to queue - * @done: Function to call on command completion * * Queues a command for execution by the associated Host Adapter. * @@ -363,9 +363,10 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, param->cylinders = cap_to_cyls(capacity, param->heads * param->sectors); if (num < 4 && end_sec == param->sectors) { - if (param->cylinders != saved_cylinders) + if (param->cylinders != saved_cylinders) { dprintk((KERN_DEBUG "Adopting geometry: heads=%d, sectors=%d from partition table %d.\n", param->heads, param->sectors, num)); + } } else if (end_head > 0 || end_sec > 0) { dprintk((KERN_DEBUG "Strange geometry: heads=%d, sectors=%d in partition table %d.\n", end_head + 1, end_sec, num)); @@ -1159,7 +1160,6 @@ static int aac_cfg_open(struct inode *inode, struct file *file) /** * aac_cfg_ioctl - AAC configuration request - * @inode: inode of device * @file: file handle * @cmd: ioctl command code * @arg: argument diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c index b5d6b24d6dbda7a25d1308d93bb3eade5711c00a..4745a99fba8ce8322a49d82ca4b952f47ef9552a 100644 --- a/drivers/scsi/aacraid/nark.c +++ b/drivers/scsi/aacraid/nark.c @@ -24,6 +24,7 @@ /** * aac_nark_ioremap + * @dev: device to ioremap * @size: mapping resize request * */ diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 5f2cede4d47762339cf1004470053897e6ef2ce8..8ebc67e541af03324e88cb9b4d890da39bc75411 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -57,6 +57,7 @@ static int aac_rkt_select_comm(struct aac_dev *dev, int comm) /** * aac_rkt_ioremap + * @dev: device to ioremap * @size: mapping resize request * */ @@ -77,8 +78,8 @@ static int aac_rkt_ioremap(struct aac_dev * dev, u32 size) * aac_rkt_init - initialize an i960 based AAC card * @dev: device to configure * - * Allocate and set up resources for the i960 based AAC variants. The - * device_interface in the commregion will be allocated and linked + * Allocate and set up resources for the i960 based AAC variants. The + * device_interface in the commregion will be allocated and linked * to the comm region. */ diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 3dea348bd25d2a42e97cfd960853127453b97e47..cdccf9abcdc402da01d5bfac8a5c79c90324a4f7 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -144,7 +144,16 @@ static void aac_rx_enable_interrupt_message(struct aac_dev *dev) * @dev: Adapter * @command: Command to execute * @p1: first parameter - * @ret: adapter status + * @p2: second parameter + * @p3: third parameter + * @p4: forth parameter + * @p5: fifth parameter + * @p6: sixth parameter + * @status: adapter status + * @r1: first return value + * @r2: second return value + * @r3: third return value + * @r4: forth return value * * This routine will send a synchronous command to the adapter and wait * for its completion. @@ -443,6 +452,7 @@ static int aac_rx_deliver_message(struct fib * fib) /** * aac_rx_ioremap + * @dev: adapter * @size: mapping resize request * */ diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index aa5d7638cade2240eaf169add843507b5e860a1a..c9a1dad2f563605fdcac44b72b5e6e2c9807ffcc 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c @@ -135,13 +135,21 @@ static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event) * @dev: Adapter * @command: Command to execute * @p1: first parameter + * @p2: second parameter + * @p3: third parameter + * @p4: forth parameter + * @p5: fifth parameter + * @p6: sixth parameter * @ret: adapter status + * @r1: first return value + * @r2: second return value + * @r3: third return value + * @r4: forth return value * - * This routine will send a synchronous command to the adapter and wait + * This routine will send a synchronous command to the adapter and wait * for its completion. */ - -static int sa_sync_cmd(struct aac_dev *dev, u32 command, +static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *ret, u32 *r1, u32 *r2, u32 *r3, u32 *r4) { @@ -283,6 +291,7 @@ static int aac_sa_check_health(struct aac_dev *dev) /** * aac_sa_ioremap + * @dev: device to ioremap * @size: mapping resize request * */ @@ -300,8 +309,8 @@ static int aac_sa_ioremap(struct aac_dev * dev, u32 size) * aac_sa_init - initialize an ARM based AAC card * @dev: device to configure * - * Allocate and set up resources for the ARM based AAC variants. The - * device_interface in the commregion will be allocated and linked + * Allocate and set up resources for the ARM based AAC variants. The + * device_interface in the commregion will be allocated and linked * to the comm region. */ diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 787ec9baebb0b8d2cc03e40c6c7234cc01c20ae3..11ef58204e96f179227c166433eb4932ed7dbafa 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -191,7 +191,16 @@ static void aac_src_enable_interrupt_message(struct aac_dev *dev) * @dev: Adapter * @command: Command to execute * @p1: first parameter - * @ret: adapter status + * @p2: second parameter + * @p3: third parameter + * @p4: forth parameter + * @p5: fifth parameter + * @p6: sixth parameter + * @status: adapter status + * @r1: first return value + * @r2: second return valu + * @r3: third return value + * @r4: forth return value * * This routine will send a synchronous command to the adapter and wait * for its completion. @@ -602,6 +611,7 @@ static int aac_src_deliver_message(struct fib *fib) /** * aac_src_ioremap + * @dev: device ioremap * @size: mapping resize request * */ @@ -632,6 +642,7 @@ static int aac_src_ioremap(struct aac_dev *dev, u32 size) /** * aac_srcv_ioremap + * @dev: device ioremap * @size: mapping resize request * */ diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 90f97df1c42a402bd1b5d43bd456bbdb8ba6913c..d8e19afa7a14071aafc7ea44d5fd6913f7436a41 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -2030,8 +2030,7 @@ static void datai_run(struct Scsi_Host *shpnt) fifodata, GETPORT(FIFOSTAT)); SETPORT(DMACNTRL0, ENDMA|_8BIT); while(fifodata>0) { - int data; - data=GETPORT(DATAPORT); + GETPORT(DATAPORT); fifodata--; DATA_LEN++; } diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index e4a09b93d00cec7002fb5ca279ed87b4efe9ec73..c912d29b8bdf7bc302753792a1d859d611649391 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -1735,10 +1735,8 @@ ahd_dump_sglist(struct scb *scb) sg_list = (struct ahd_dma64_seg*)scb->sg_list; for (i = 0; i < scb->sg_count; i++) { uint64_t addr; - uint32_t len; addr = ahd_le64toh(sg_list[i].addr); - len = ahd_le32toh(sg_list[i].len); printk("sg[%d] - Addr 0x%x%x : Length %d%s\n", i, (uint32_t)((addr >> 32) & 0xFFFFFFFF), @@ -1906,9 +1904,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) { struct ahd_devinfo devinfo; struct scb *scb; - struct ahd_initiator_tinfo *targ_info; - struct ahd_tmode_tstate *tstate; - struct ahd_transinfo *tinfo; u_int scbid; /* @@ -1936,12 +1931,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) SCB_GET_LUN(scb), SCB_GET_CHANNEL(ahd, scb), ROLE_INITIATOR); - targ_info = ahd_fetch_transinfo(ahd, - devinfo.channel, - devinfo.our_scsiid, - devinfo.target, - &tstate); - tinfo = &targ_info->curr; ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, AHD_TRANS_ACTIVE, /*paused*/TRUE); ahd_set_syncrate(ahd, &devinfo, /*period*/0, @@ -2669,7 +2658,6 @@ ahd_handle_transmission_error(struct ahd_softc *ahd) struct scb *scb; u_int scbid; u_int lqistat1; - u_int lqistat2; u_int msg_out; u_int curphase; u_int lastphase; @@ -2680,7 +2668,7 @@ ahd_handle_transmission_error(struct ahd_softc *ahd) scb = NULL; ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); lqistat1 = ahd_inb(ahd, LQISTAT1) & ~(LQIPHASE_LQ|LQIPHASE_NLQ); - lqistat2 = ahd_inb(ahd, LQISTAT2); + ahd_inb(ahd, LQISTAT2); if ((lqistat1 & (LQICRCI_NLQ|LQICRCI_LQ)) == 0 && (ahd->bugs & AHD_NLQICRC_DELAYED_BUG) != 0) { u_int lqistate; @@ -4218,13 +4206,11 @@ ahd_update_pending_scbs(struct ahd_softc *ahd) pending_scb_count = 0; LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { struct ahd_devinfo devinfo; - struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; ahd_scb_devinfo(ahd, &devinfo, pending_scb); - tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, - devinfo.our_scsiid, - devinfo.target, &tstate); + ahd_fetch_transinfo(ahd, devinfo.channel, devinfo.our_scsiid, + devinfo.target, &tstate); if ((tstate->auto_negotiate & devinfo.target_mask) == 0 && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) { pending_scb->flags &= ~SCB_AUTO_NEGOTIATE; diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index dc4fe334efd016fe2611585147f06d1966321bab..d019e3f2bb9b3c038dedb981ead9fca0cb167d40 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -700,9 +700,6 @@ ahd_linux_slave_alloc(struct scsi_device *sdev) static int ahd_linux_slave_configure(struct scsi_device *sdev) { - struct ahd_softc *ahd; - - ahd = *((struct ahd_softc **)sdev->host->hostdata); if (bootverbose) sdev_printk(KERN_INFO, sdev, "Slave Configure\n"); @@ -778,16 +775,13 @@ ahd_linux_dev_reset(struct scsi_cmnd *cmd) struct scb *reset_scb; u_int cdb_byte; int retval = SUCCESS; - int paused; - int wait; struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; unsigned long flags; DECLARE_COMPLETION_ONSTACK(done); reset_scb = NULL; - paused = FALSE; - wait = FALSE; + ahd = *(struct ahd_softc **)cmd->device->host->hostdata; scmd_printk(KERN_INFO, cmd, @@ -1793,10 +1787,12 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) */ cmd->sense_buffer[0] = 0; if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) { +#ifdef AHD_REPORT_UNDERFLOWS uint32_t amount_xferred; amount_xferred = ahd_get_transfer_length(scb) - ahd_get_residual(scb); +#endif if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) { @@ -2147,7 +2143,7 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) u_int last_phase; u_int saved_scsiid; u_int cdb_byte; - int retval; + int retval = SUCCESS; int was_paused; int paused; int wait; @@ -2185,8 +2181,7 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) * so we must not still own the command. */ scmd_printk(KERN_INFO, cmd, "Is not an active device\n"); - retval = SUCCESS; - goto no_cmd; + goto done; } /* @@ -2199,7 +2194,7 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) if (pending_scb == NULL) { scmd_printk(KERN_INFO, cmd, "Command not found\n"); - goto no_cmd; + goto done; } if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) { @@ -2207,7 +2202,7 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) * We can't queue two recovery actions using the same SCB */ retval = FAILED; - goto done; + goto done; } /* @@ -2222,7 +2217,7 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) if ((pending_scb->flags & SCB_ACTIVE) == 0) { scmd_printk(KERN_INFO, cmd, "Command already completed\n"); - goto no_cmd; + goto done; } printk("%s: At time of recovery, card was %spaused\n", @@ -2239,7 +2234,6 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", ahd_name(ahd), cmd->device->channel, cmd->device->id, (u8)cmd->device->lun); - retval = SUCCESS; goto done; } @@ -2336,17 +2330,10 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) } else { scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n"); retval = FAILED; - goto done; } -no_cmd: - /* - * Our assumption is that if we don't have the command, no - * recovery action was required, so we return success. Again, - * the semantics of the mid-layer recovery engine are not - * well defined, so this may change in time. - */ - retval = SUCCESS; + + ahd_restore_modes(ahd, saved_modes); done: if (paused) ahd_unpause(ahd); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 2edfa0594f1830cb0142286f5032bf0a61438463..e7ccb8b80fc190adee9dcf4c7bb24cee1d7e175a 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -564,8 +564,6 @@ ahc_linux_target_alloc(struct scsi_target *starget) struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget); unsigned short scsirate; struct ahc_devinfo devinfo; - struct ahc_initiator_tinfo *tinfo; - struct ahc_tmode_tstate *tstate; char channel = starget->channel + 'A'; unsigned int our_id = ahc->our_id; unsigned int target_offset; @@ -612,9 +610,6 @@ ahc_linux_target_alloc(struct scsi_target *starget) spi_max_offset(starget) = 0; spi_min_period(starget) = ahc_find_period(ahc, scsirate, maxsync); - - tinfo = ahc_fetch_transinfo(ahc, channel, ahc->our_id, - starget->id, &tstate); } ahc_compile_devinfo(&devinfo, our_id, starget->id, CAM_LUN_WILDCARD, channel, @@ -671,10 +666,6 @@ ahc_linux_slave_alloc(struct scsi_device *sdev) static int ahc_linux_slave_configure(struct scsi_device *sdev) { - struct ahc_softc *ahc; - - ahc = *((struct ahc_softc **)sdev->host->hostdata); - if (bootverbose) sdev_printk(KERN_INFO, sdev, "Slave Configure\n"); @@ -1601,7 +1592,6 @@ ahc_send_async(struct ahc_softc *ahc, char channel, case AC_TRANSFER_NEG: { struct scsi_target *starget; - struct ahc_linux_target *targ; struct ahc_initiator_tinfo *tinfo; struct ahc_tmode_tstate *tstate; int target_offset; @@ -1635,7 +1625,6 @@ ahc_send_async(struct ahc_softc *ahc, char channel, starget = ahc->platform_data->starget[target_offset]; if (starget == NULL) break; - targ = scsi_transport_target_data(starget); target_ppr_options = (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) @@ -1722,10 +1711,12 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) */ cmd->sense_buffer[0] = 0; if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) { +#ifdef AHC_REPORT_UNDERFLOWS uint32_t amount_xferred; amount_xferred = ahc_get_transfer_length(scb) - ahc_get_residual(scb); +#endif if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) { #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MISC) != 0) { diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c index 604a5331f639b16752585cff9908e5256f36a6e9..73506a459bf86be5e4705e07c7ec32322f000595 100644 --- a/drivers/scsi/aic94xx/aic94xx_dev.c +++ b/drivers/scsi/aic94xx/aic94xx_dev.c @@ -236,7 +236,7 @@ static int asd_init_sata_pm_table_ddb(struct domain_device *dev) /** * asd_init_sata_pm_port_ddb -- SATA Port Multiplier Port - * dev: pointer to domain device + * @dev: pointer to domain device * * For SATA Port Multiplier Ports we need to allocate one SATA Port * Multiplier Port DDB and depending on whether the target on it @@ -281,7 +281,7 @@ static int asd_init_initiator_ddb(struct domain_device *dev) /** * asd_init_sata_pm_ddb -- SATA Port Multiplier - * dev: pointer to domain device + * @dev: pointer to domain device * * For STP and direct-attached SATA Port Multipliers we need * one target port DDB entry and one SATA PM table DDB entry. diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index c5a46c59d4f806e1f48d9b7ad2d5d8573617896e..9256ab7b2522740707b8535eed399b61fb30d3d6 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c @@ -575,7 +575,7 @@ static int asd_extend_cmdctx(struct asd_ha_struct *asd_ha) /** * asd_init_ctxmem -- initialize context memory - * asd_ha: pointer to host adapter structure + * @asd_ha: pointer to host adapter structure * * This function sets the maximum number of SCBs and * DDBs which can be used by the sequencer. This is normally @@ -1146,7 +1146,6 @@ static void asd_swap_head_scb(struct asd_ha_struct *asd_ha, /** * asd_start_timers -- (add and) start timers of SCBs * @list: pointer to struct list_head of the scbs - * @to: timeout in jiffies * * If an SCB in the @list has no timer function, assign the default * one, then start the timer of the SCB. This function is diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index bef47f38dd0dbc3bc0a1a7faac414cb24e331a8a..a195bfe9eccc073e126dff8b3455a41a171bf72b 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -530,7 +530,7 @@ static int asd_create_ha_caches(struct asd_ha_struct *asd_ha) return 0; } -/** +/* * asd_free_edbs -- free empty data buffers * asd_ha: pointer to host adapter structure */ diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 4a80ec08f0c968c26d0599659b30c38b1da1fd0f..c264b4b56970b1a8050a5def47c37a2d77364aa3 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -123,8 +123,8 @@ static unsigned ord_phy(struct asd_ha_struct *asd_ha, struct asd_phy *phy) /** * asd_get_attached_sas_addr -- extract/generate attached SAS address - * phy: pointer to asd_phy - * sas_addr: pointer to buffer where the SAS address is to be written + * @phy: pointer to asd_phy + * @sas_addr: pointer to buffer where the SAS address is to be written * * This function extracts the SAS address from an IDENTIFY frame * received. If OOB is SATA, then a SAS address is generated from the @@ -847,7 +847,7 @@ void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id, /** * asd_ascb_timedout -- called when a pending SCB's timer has expired - * @data: unsigned long, a pointer to the ascb in question + * @t: Timer context used to fetch the SCB * * This is the default timeout function which does the most necessary. * Upper layers can implement their own timeout function, say to free diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index 11853ec29d87a33d069950e467c8c3e978f4efcd..c0f685c86851b8901c38209b23d4b452b4c80310 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c @@ -582,6 +582,7 @@ static void asd_init_cseq_scratch(struct asd_ha_struct *asd_ha) /** * asd_init_lseq_mip -- initialize LSEQ Mode independent pages 0-3 * @asd_ha: pointer to host adapter structure + * @lseq: link sequencer */ static void asd_init_lseq_mip(struct asd_ha_struct *asd_ha, u8 lseq) { @@ -669,6 +670,7 @@ static void asd_init_lseq_mip(struct asd_ha_struct *asd_ha, u8 lseq) /** * asd_init_lseq_mdp -- initialize LSEQ mode dependent pages. * @asd_ha: pointer to host adapter structure + * @lseq: link sequencer */ static void asd_init_lseq_mdp(struct asd_ha_struct *asd_ha, int lseq) { @@ -953,6 +955,7 @@ static void asd_init_cseq_cio(struct asd_ha_struct *asd_ha) /** * asd_init_lseq_cio -- initialize LmSEQ CIO registers * @asd_ha: pointer to host adapter structure + * @lseq: link sequencer */ static void asd_init_lseq_cio(struct asd_ha_struct *asd_ha, int lseq) { @@ -1345,7 +1348,8 @@ int asd_start_seqs(struct asd_ha_struct *asd_ha) /** * asd_update_port_links -- update port_map_by_links and phy_is_up - * @sas_phy: pointer to the phy which has been added to a port + * @asd_ha: pointer to host adapter structure + * @phy: pointer to the phy which has been added to a port * * 1) When a link reset has completed and we got BYTES DMAED with a * valid frame we call this function for that phy, to indicate that diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c index f814026f26fa7a7dba69c9e9d49e11a85159eeb0..1fcee65193a33e0245c10599681bc75a1ef59ded 100644 --- a/drivers/scsi/aic94xx/aic94xx_tmf.c +++ b/drivers/scsi/aic94xx/aic94xx_tmf.c @@ -673,7 +673,7 @@ int asd_lu_reset(struct domain_device *dev, u8 *lun) /** * asd_query_task -- send a QUERY TASK TMF to an I_T_L_Q nexus - * task: pointer to sas_task struct of interest + * @task: pointer to sas_task struct of interest * * Returns: TMF_RESP_FUNC_COMPLETE if the task is not in the task set, * or TMF_RESP_FUNC_SUCC if the task is in the task set. diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 30914c8f29cc214ef682b5d31cdc0514f8275675..fa562a085600ded315af1e20442e2372ff4d31e6 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -283,11 +283,10 @@ static bool arcmsr_remap_pciregion(struct AdapterControlBlock *acb) } case ACB_ADAPTER_TYPE_D: { void __iomem *mem_base0; - unsigned long addr, range, flags; + unsigned long addr, range; addr = (unsigned long)pci_resource_start(pdev, 0); range = pci_resource_len(pdev, 0); - flags = pci_resource_flags(pdev, 0); mem_base0 = ioremap(addr, range); if (!mem_base0) { pr_notice("arcmsr%d: memory mapping region fail\n", @@ -1067,12 +1066,11 @@ static void arcmsr_free_irq(struct pci_dev *pdev, static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) { - uint32_t intmask_org; struct Scsi_Host *host = pci_get_drvdata(pdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata; - intmask_org = arcmsr_disable_outbound_ints(acb); + arcmsr_disable_outbound_ints(acb); arcmsr_free_irq(pdev, acb); del_timer_sync(&acb->eternal_timer); if (set_date_time) @@ -1407,7 +1405,7 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) struct ARCMSR_CDB *pARCMSR_CDB; bool error; struct CommandControlBlock *pCCB; - unsigned long ccb_cdb_phy, cdb_phy_hipart; + unsigned long ccb_cdb_phy; switch (acb->adapter_type) { @@ -1489,8 +1487,6 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) ((toggle ^ 0x4000) + 1); doneq_index = pmu->doneq_index; spin_unlock_irqrestore(&acb->doneq_lock, flags); - cdb_phy_hipart = pmu->done_qbuffer[doneq_index & - 0xFFF].addressHigh; addressLow = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow; ccb_cdb_phy = (addressLow & 0xFFFFFFF0); @@ -2445,7 +2441,7 @@ static void arcmsr_hbaD_postqueue_isr(struct AdapterControlBlock *acb) struct MessageUnit_D *pmu; struct ARCMSR_CDB *arcmsr_cdb; struct CommandControlBlock *ccb; - unsigned long flags, ccb_cdb_phy, cdb_phy_hipart; + unsigned long flags, ccb_cdb_phy; spin_lock_irqsave(&acb->doneq_lock, flags); pmu = acb->pmuD; @@ -2459,8 +2455,6 @@ static void arcmsr_hbaD_postqueue_isr(struct AdapterControlBlock *acb) pmu->doneq_index = index_stripped ? (index_stripped | toggle) : ((toggle ^ 0x4000) + 1); doneq_index = pmu->doneq_index; - cdb_phy_hipart = pmu->done_qbuffer[doneq_index & - 0xFFF].addressHigh; addressLow = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow; ccb_cdb_phy = (addressLow & 0xFFFFFFF0); @@ -3495,7 +3489,7 @@ static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb, bool error; uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb; int rtn, doneq_index, index_stripped, outbound_write_pointer, toggle; - unsigned long flags, ccb_cdb_phy, cdb_phy_hipart; + unsigned long flags, ccb_cdb_phy; struct ARCMSR_CDB *arcmsr_cdb; struct CommandControlBlock *pCCB; struct MessageUnit_D *pmu = acb->pmuD; @@ -3527,8 +3521,6 @@ polling_hbaD_ccb_retry: ((toggle ^ 0x4000) + 1); doneq_index = pmu->doneq_index; spin_unlock_irqrestore(&acb->doneq_lock, flags); - cdb_phy_hipart = pmu->done_qbuffer[doneq_index & - 0xFFF].addressHigh; flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow; ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0); if (acb->cdb_phyadd_hipart) diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index 65691c21f133d413645f11b02c969cd603810b45..29294f0ef8a9a69e5e48b3e260ed34e4e9873419 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -450,7 +450,7 @@ static int cumanascsi2_probe(struct expansion_card *ec, if (info->info.scsi.dma != NO_DMA) free_dma(info->info.scsi.dma); - free_irq(ec->irq, host); + free_irq(ec->irq, info); out_release: fas216_release(host); diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index 6e204a2e0c8d70c512d345466e47a0a26ea6af03..591ae2a6dd74f63bf8e000407b797cf7af5a5004 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -571,7 +571,7 @@ static int eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id) if (info->info.scsi.dma != NO_DMA) free_dma(info->info.scsi.dma); - free_irq(ec->irq, host); + free_irq(ec->irq, info); out_remove: fas216_remove(host); diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index 772a13e5fd91632dbe9a0ecd3f92e4c2acb54143..d99ef014528e3e61dfaf4d454d98703337ef8111 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -378,7 +378,7 @@ static int powertecscsi_probe(struct expansion_card *ec, if (info->info.scsi.dma != NO_DMA) free_dma(info->info.scsi.dma); - free_irq(ec->irq, host); + free_irq(ec->irq, info); out_release: fas216_release(host); diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 2058d50d62e1210fab298d326e42e79a1f08413c..93da6344424dd7e53d7a03a5d4736828be9c3f53 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -27,6 +27,7 @@ extern struct iscsi_transport beiscsi_iscsi_transport; /** * beiscsi_session_create - creates a new iscsi session + * @ep: pointer to iscsi ep * @cmds_max: max commands supported * @qdepth: max queue depth supported * @initial_cmdsn: initial iscsi CMDSN @@ -164,6 +165,7 @@ beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid) * @cls_session: pointer to iscsi cls session * @cls_conn: pointer to iscsi cls conn * @transport_fd: EP handle(64 bit) + * @is_leading: indicate if this is the session leading connection (MCS) * * This function binds the TCP Conn with iSCSI Connection and Session. */ @@ -992,7 +994,7 @@ static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) /** * beiscsi_free_ep - free endpoint - * @ep: pointer to iscsi endpoint structure + * @beiscsi_ep: pointer to device endpoint struct */ static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) { @@ -1027,9 +1029,10 @@ static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) /** * beiscsi_open_conn - Ask FW to open a TCP connection - * @ep: endpoint to be used + * @ep: pointer to device endpoint struct * @src_addr: The source IP address * @dst_addr: The Destination IP address + * @non_blocking: blocking or non-blocking call * * Asks the FW to open a TCP connection */ @@ -1123,7 +1126,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, /** * beiscsi_ep_connect - Ask chip to create TCP Conn - * @scsi_host: Pointer to scsi_host structure + * @shost: Pointer to scsi_host structure * @dst_addr: The IP address of Target * @non_blocking: blocking or non-blocking call * @@ -1228,7 +1231,7 @@ static void beiscsi_flush_cq(struct beiscsi_hba *phba) /** * beiscsi_conn_close - Invalidate and upload connection - * @ep: The iscsi endpoint + * @beiscsi_ep: pointer to device endpoint struct * * Returns 0 on success, -1 on failure. */ diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 9b81cfbbc5c532d7e2a164805ed40efbdccb7ff9..8dc2e0824ad78261ed450602f6a0e84766b9fad6 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -977,7 +977,7 @@ beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context, * alloc_wrb_handle - To allocate a wrb handle * @phba: The hba pointer * @cid: The cid to use for allocation - * @pwrb_context: ptr to ptr to wrb context + * @pcontext: ptr to ptr to wrb context * * This happens under session_lock until submission to chip */ @@ -1394,7 +1394,7 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, spin_unlock_bh(&session->back_lock); } -/** +/* * ASYNC PDUs include * a. Unsolicited NOP-In (target initiated NOP-In) * b. ASYNC Messages diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index a2d69b287c7bbc47552173f01fc6418fc3b122ce..96d6e384b2b259b630dc2ec2a98caa91672338b7 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -97,6 +97,7 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, /** * mgmt_open_connection()- Establish a TCP CXN + * @phba: driver priv structure * @dst_addr: Destination Address * @beiscsi_ep: ptr to device endpoint struct * @nonemb_cmd: ptr to memory allocated for command @@ -209,7 +210,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, return tag; } -/* +/** * beiscsi_exec_nemb_cmd()- execute non-embedded MBX cmd * @phba: driver priv structure * @nonemb_cmd: DMA address of the MBX command to be issued diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index fb4c469bd89fcbf504b3a90310442c17b50f88d1..6846ca8f7313c379b03983f4c532f631bc0b2a40 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -1237,7 +1237,7 @@ bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl) complete(&bfad->disable_comp); } -/** +/* * configure queue registers from firmware response */ static void diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 766f2b5ed2ab45cf1eda37da550f29097d7c64dc..29f99561dfc3ad39d55075b84377d2e1ebf208e0 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -2335,9 +2335,7 @@ bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun) { struct bfa_lun_mask_s *lunm_list; - struct bfa_rport_s *rp = NULL; struct bfa_fcs_lport_s *port = NULL; - struct bfa_fcs_rport_s *rp_fcs; int i; /* in min cfg lunm_list could be NULL but no commands should run. */ @@ -2353,12 +2351,8 @@ bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn, port = bfa_fcs_lookup_port( &((struct bfad_s *)bfa->bfad)->bfa_fcs, vf_id, *pwwn); - if (port) { + if (port) *pwwn = port->port_cfg.pwwn; - rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn); - if (rp_fcs) - rp = rp_fcs->bfa_rport; - } } lunm_list = bfa_get_lun_mask_list(bfa); @@ -3818,7 +3812,7 @@ bfa_iotag_attach(struct bfa_fcp_mod_s *fcp) } -/** +/* * To send config req, first try to use throttle value from flash * If 0, then use driver parameter * We need to use min(flash_val, drv_val) because diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index fc294e1950a6260beb15a3176a76efd80704e1a5..143c35bd668c2626157dae76add4e0d92f9a1b67 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -2240,15 +2240,12 @@ bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport, struct bfa_fcxp_s *fcxp; struct fchs_s fchs; struct bfa_fcs_lport_s *port = rport->port; - struct fc_adisc_s *adisc; bfa_trc(port->fcs, rx_fchs->s_id); bfa_trc(port->fcs, rx_fchs->d_id); rport->stats.adisc_rcvd++; - adisc = (struct fc_adisc_s *) (rx_fchs + 1); - /* * Accept if the itnim for this rport is online. * Else reject the ADISC. diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 93471d7c61d05d840caf40acff379906058861d4..dd5821dfcac2d68585d3a4276bfdada0b943228e 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -701,7 +701,7 @@ static void bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf) { struct bfi_ioc_image_hdr_s fwhdr; - u32 r32, fwstate, pgnum, pgoff, loff = 0; + u32 r32, fwstate, pgnum, loff = 0; int i; /* @@ -731,7 +731,6 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf) * Clear fwver hdr */ pgnum = PSS_SMEM_PGNUM(iocpf->ioc->ioc_regs.smem_pg0, loff); - pgoff = PSS_SMEM_PGOFF(loff); writel(pgnum, iocpf->ioc->ioc_regs.host_page_num_fn); for (i = 0; i < sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32); i++) { @@ -1440,13 +1439,12 @@ bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc) void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr) { - u32 pgnum, pgoff; + u32 pgnum; u32 loff = 0; int i; u32 *fwsig = (u32 *) fwhdr; pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff); - pgoff = PSS_SMEM_PGOFF(loff); writel(pgnum, ioc->ioc_regs.host_page_num_fn); for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32)); @@ -1662,7 +1660,7 @@ bfa_status_t bfa_ioc_fwsig_invalidate(struct bfa_ioc_s *ioc) { - u32 pgnum, pgoff; + u32 pgnum; u32 loff = 0; enum bfi_ioc_state ioc_fwstate; @@ -1671,7 +1669,6 @@ bfa_ioc_fwsig_invalidate(struct bfa_ioc_s *ioc) return BFA_STATUS_ADAPTER_ENABLED; pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff); - pgoff = PSS_SMEM_PGOFF(loff); writel(pgnum, ioc->ioc_regs.host_page_num_fn); bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, BFA_IOC_FW_INV_SIGN); @@ -1863,7 +1860,7 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env) { u32 *fwimg; - u32 pgnum, pgoff; + u32 pgnum; u32 loff = 0; u32 chunkno = 0; u32 i; @@ -1892,8 +1889,6 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff); - pgoff = PSS_SMEM_PGOFF(loff); - writel(pgnum, ioc->ioc_regs.host_page_num_fn); for (i = 0; i < fwimg_size; i++) { @@ -4763,11 +4758,9 @@ bfa_diag_memtest_done(void *cbarg) struct bfa_ioc_s *ioc = diag->ioc; struct bfa_diag_memtest_result *res = diag->result; u32 loff = BFI_BOOT_MEMTEST_RES_ADDR; - u32 pgnum, pgoff, i; + u32 pgnum, i; pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff); - pgoff = PSS_SMEM_PGOFF(loff); - writel(pgnum, ioc->ioc_regs.host_page_num_fn); for (i = 0; i < (sizeof(struct bfa_diag_memtest_result) / @@ -5026,7 +5019,7 @@ diag_portbeacon_comp(struct bfa_diag_s *diag) /* * Diag hmbox handler */ -void +static void bfa_diag_intr(void *diagarg, struct bfi_mbmsg_s *msg) { struct bfa_diag_s *diag = diagarg; @@ -6649,8 +6642,8 @@ enum bfa_flash_cmd { BFA_FLASH_READ_STATUS = 0x05, /* read status */ }; -/** - * @brief hardware error definition +/* + * Hardware error definition */ enum bfa_flash_err { BFA_FLASH_NOT_PRESENT = -1, /*!< flash not present */ @@ -6664,8 +6657,8 @@ enum bfa_flash_err { BFA_FLASH_ERR_LEN = -9, /*!< invalid length */ }; -/** - * @brief flash command register data structure +/* + * Flash command register data structure */ union bfa_flash_cmd_reg_u { struct { @@ -6688,8 +6681,8 @@ union bfa_flash_cmd_reg_u { u32 i; }; -/** - * @brief flash device status register data structure +/* + * Flash device status register data structure */ union bfa_flash_dev_status_reg_u { struct { @@ -6714,8 +6707,8 @@ union bfa_flash_dev_status_reg_u { u32 i; }; -/** - * @brief flash address register data structure +/* + * Flash address register data structure */ union bfa_flash_addr_reg_u { struct { @@ -6730,7 +6723,7 @@ union bfa_flash_addr_reg_u { u32 i; }; -/** +/* * dg flash_raw_private Flash raw private functions */ static void @@ -6771,7 +6764,7 @@ bfa_flash_cmd_act_check(void __iomem *pci_bar) return 0; } -/** +/* * @brief * Flush FLI data fifo. * @@ -6784,7 +6777,6 @@ static u32 bfa_flash_fifo_flush(void __iomem *pci_bar) { u32 i; - u32 t; union bfa_flash_dev_status_reg_u dev_status; dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG); @@ -6794,7 +6786,7 @@ bfa_flash_fifo_flush(void __iomem *pci_bar) /* fifo counter in terms of words */ for (i = 0; i < dev_status.r.fifo_cnt; i++) - t = readl(pci_bar + FLI_RDDATA_REG); + readl(pci_bar + FLI_RDDATA_REG); /* * Check the device status. It may take some time. @@ -6811,7 +6803,7 @@ bfa_flash_fifo_flush(void __iomem *pci_bar) return 0; } -/** +/* * @brief * Read flash status. * @@ -6856,7 +6848,7 @@ bfa_flash_status_read(void __iomem *pci_bar) return ret_status; } -/** +/* * @brief * Start flash read operation. * @@ -6902,7 +6894,7 @@ bfa_flash_read_start(void __iomem *pci_bar, u32 offset, u32 len, return 0; } -/** +/* * @brief * Check flash read operation. * @@ -6918,7 +6910,8 @@ bfa_flash_read_check(void __iomem *pci_bar) return 0; } -/** + +/* * @brief * End flash read operation. * @@ -6944,7 +6937,7 @@ bfa_flash_read_end(void __iomem *pci_bar, u32 len, char *buf) bfa_flash_fifo_flush(pci_bar); } -/** +/* * @brief * Perform flash raw read. * @@ -6970,7 +6963,7 @@ bfa_raw_sem_get(void __iomem *bar) } -bfa_status_t +static bfa_status_t bfa_flash_sem_get(void __iomem *bar) { u32 n = FLASH_BLOCKING_OP_MAX; @@ -6983,7 +6976,7 @@ bfa_flash_sem_get(void __iomem *bar) return BFA_STATUS_OK; } -void +static void bfa_flash_sem_put(void __iomem *bar) { writel(0, (bar + FLASH_SEM_LOCK_REG)); diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 6fd3383ee5381d413974494f8d3c82f94de55421..fb748291676b6738115a87ef2559bc1ffad985e7 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -496,7 +496,7 @@ bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc) return BFA_FALSE; } -/** +/* * Called from bfa_ioc_attach() to map asic specific calls. */ static void @@ -517,7 +517,7 @@ bfa_ioc_set_ctx_hwif(struct bfa_ioc_s *ioc, struct bfa_ioc_hwif_s *hwif) hwif->ioc_get_alt_fwstate = bfa_ioc_ct_get_alt_ioc_fwstate; } -/** +/* * Called from bfa_ioc_attach() to map asic specific calls. */ void @@ -532,7 +532,7 @@ bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc) ioc->ioc_hwif = &hwif_ct; } -/** +/* * Called from bfa_ioc_attach() to map asic specific calls. */ void diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c index 4511ec865f06a03e79b1d47921fba513ba09dca3..cfe2c9c336bfd7b2a3fba48bce72c55ed42e5f8d 100644 --- a/drivers/scsi/bfa/bfa_port.c +++ b/drivers/scsi/bfa/bfa_port.c @@ -756,7 +756,7 @@ bfa_cee_reset_stats(struct bfa_cee_s *cee, * @return void */ -void +static void bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m) { union bfi_cee_i2h_msg_u *msg; @@ -792,7 +792,7 @@ bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m) * @return void */ -void +static void bfa_cee_notify(void *arg, enum bfa_ioc_event_e event) { struct bfa_cee_s *cee = (struct bfa_cee_s *) arg; diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 0b7d2e8f4a66954dfc31303f023b597565d5aac2..1e266c1ef7938f01a8c449845062f578294e645c 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -2718,7 +2718,7 @@ bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport, case BFA_FCPORT_SM_DPORTDISABLE: case BFA_FCPORT_SM_ENABLE: case BFA_FCPORT_SM_START: - /** + /* * Ignore event for a port that is ddport */ break; @@ -3839,7 +3839,7 @@ bfa_fcport_get_topology(struct bfa_s *bfa) return fcport->topology; } -/** +/* * Get config topology. */ enum bfa_port_topology diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 412dbe125e10c2f8919918fe0b2a1551bff5c575..fc515424ca88dbc16e3315f2de7f5d0f957718b4 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -15,7 +15,7 @@ BFA_TRC_FILE(LDRV, BSG); -int +static int bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -38,7 +38,7 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -146,7 +146,7 @@ bfad_iocmd_ioc_get_stats(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_ioc_get_fwstats(struct bfad_s *bfad, void *cmd, unsigned int payload_len) { @@ -176,7 +176,7 @@ out: return 0; } -int +static int bfad_iocmd_ioc_reset_stats(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -194,7 +194,7 @@ bfad_iocmd_ioc_reset_stats(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) return 0; } -int +static int bfad_iocmd_ioc_set_name(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) { struct bfa_bsg_ioc_name_s *iocmd = (struct bfa_bsg_ioc_name_s *) cmd; @@ -208,7 +208,7 @@ bfad_iocmd_ioc_set_name(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) return 0; } -int +static int bfad_iocmd_iocfc_get_attr(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_iocfc_attr_s *iocmd = (struct bfa_bsg_iocfc_attr_s *)cmd; @@ -219,7 +219,7 @@ bfad_iocmd_iocfc_get_attr(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_ioc_fw_sig_inv(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -231,7 +231,7 @@ bfad_iocmd_ioc_fw_sig_inv(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_iocfc_set_intr(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_iocfc_intr_s *iocmd = (struct bfa_bsg_iocfc_intr_s *)cmd; @@ -244,7 +244,7 @@ bfad_iocmd_iocfc_set_intr(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_port_enable(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -265,7 +265,7 @@ bfad_iocmd_port_enable(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_port_disable(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -315,7 +315,7 @@ bfad_iocmd_port_get_attr(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_port_get_stats(struct bfad_s *bfad, void *cmd, unsigned int payload_len) { @@ -349,7 +349,7 @@ out: return 0; } -int +static int bfad_iocmd_port_reset_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -370,7 +370,7 @@ bfad_iocmd_port_reset_stats(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_set_port_cfg(struct bfad_s *bfad, void *iocmd, unsigned int v_cmd) { struct bfa_bsg_port_cfg_s *cmd = (struct bfa_bsg_port_cfg_s *)iocmd; @@ -390,7 +390,7 @@ bfad_iocmd_set_port_cfg(struct bfad_s *bfad, void *iocmd, unsigned int v_cmd) return 0; } -int +static int bfad_iocmd_port_cfg_maxfrsize(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_port_cfg_maxfrsize_s *iocmd = @@ -404,7 +404,7 @@ bfad_iocmd_port_cfg_maxfrsize(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_port_cfg_bbcr(struct bfad_s *bfad, unsigned int cmd, void *pcmd) { struct bfa_bsg_bbcr_enable_s *iocmd = @@ -427,7 +427,7 @@ bfad_iocmd_port_cfg_bbcr(struct bfad_s *bfad, unsigned int cmd, void *pcmd) return 0; } -int +static int bfad_iocmd_port_get_bbcr_attr(struct bfad_s *bfad, void *pcmd) { struct bfa_bsg_bbcr_attr_s *iocmd = (struct bfa_bsg_bbcr_attr_s *) pcmd; @@ -465,7 +465,7 @@ out: return 0; } -int +static int bfad_iocmd_lport_get_stats(struct bfad_s *bfad, void *cmd) { struct bfa_fcs_lport_s *fcs_port; @@ -489,7 +489,7 @@ out: return 0; } -int +static int bfad_iocmd_lport_reset_stats(struct bfad_s *bfad, void *cmd) { struct bfa_fcs_lport_s *fcs_port; @@ -523,7 +523,7 @@ out: return 0; } -int +static int bfad_iocmd_lport_get_iostats(struct bfad_s *bfad, void *cmd) { struct bfa_fcs_lport_s *fcs_port; @@ -548,7 +548,7 @@ out: return 0; } -int +static int bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd, unsigned int payload_len) { @@ -590,7 +590,7 @@ out: return 0; } -int +static int bfad_iocmd_rport_get_attr(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_rport_attr_s *iocmd = (struct bfa_bsg_rport_attr_s *)cmd; @@ -676,7 +676,7 @@ out: return 0; } -int +static int bfad_iocmd_rport_get_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_rport_stats_s *iocmd = @@ -717,7 +717,7 @@ out: return 0; } -int +static int bfad_iocmd_rport_clr_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_rport_reset_stats_s *iocmd = @@ -753,7 +753,7 @@ out: return 0; } -int +static int bfad_iocmd_rport_set_speed(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_rport_set_speed_s *iocmd = @@ -789,7 +789,7 @@ out: return 0; } -int +static int bfad_iocmd_vport_get_attr(struct bfad_s *bfad, void *cmd) { struct bfa_fcs_vport_s *fcs_vport; @@ -812,7 +812,7 @@ out: return 0; } -int +static int bfad_iocmd_vport_get_stats(struct bfad_s *bfad, void *cmd) { struct bfa_fcs_vport_s *fcs_vport; @@ -840,7 +840,7 @@ out: return 0; } -int +static int bfad_iocmd_vport_clr_stats(struct bfad_s *bfad, void *cmd) { struct bfa_fcs_vport_s *fcs_vport; @@ -907,7 +907,7 @@ out: return 0; } -int +static int bfad_iocmd_qos_set_bw(struct bfad_s *bfad, void *pcmd) { struct bfa_bsg_qos_bw_s *iocmd = (struct bfa_bsg_qos_bw_s *)pcmd; @@ -920,7 +920,7 @@ bfad_iocmd_qos_set_bw(struct bfad_s *bfad, void *pcmd) return 0; } -int +static int bfad_iocmd_ratelim(struct bfad_s *bfad, unsigned int cmd, void *pcmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; @@ -949,7 +949,7 @@ bfad_iocmd_ratelim(struct bfad_s *bfad, unsigned int cmd, void *pcmd) return 0; } -int +static int bfad_iocmd_ratelim_speed(struct bfad_s *bfad, unsigned int cmd, void *pcmd) { struct bfa_bsg_trl_speed_s *iocmd = (struct bfa_bsg_trl_speed_s *)pcmd; @@ -978,7 +978,7 @@ bfad_iocmd_ratelim_speed(struct bfad_s *bfad, unsigned int cmd, void *pcmd) return 0; } -int +static int bfad_iocmd_cfg_fcpim(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fcpim_s *iocmd = (struct bfa_bsg_fcpim_s *)cmd; @@ -991,7 +991,7 @@ bfad_iocmd_cfg_fcpim(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fcpim_get_modstats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fcpim_modstats_s *iocmd = @@ -1013,7 +1013,7 @@ bfad_iocmd_fcpim_get_modstats(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fcpim_clr_modstats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fcpim_modstatsclr_s *iocmd = @@ -1035,7 +1035,7 @@ bfad_iocmd_fcpim_clr_modstats(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fcpim_get_del_itn_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fcpim_del_itn_stats_s *iocmd = @@ -1160,7 +1160,7 @@ bfad_iocmd_itnim_get_itnstats(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fcport_enable(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -1173,7 +1173,7 @@ bfad_iocmd_fcport_enable(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fcport_disable(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -1186,7 +1186,7 @@ bfad_iocmd_fcport_disable(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_ioc_get_pcifn_cfg(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_pcifn_cfg_s *iocmd = (struct bfa_bsg_pcifn_cfg_s *)cmd; @@ -1208,7 +1208,7 @@ out: return 0; } -int +static int bfad_iocmd_pcifn_create(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd; @@ -1231,7 +1231,7 @@ out: return 0; } -int +static int bfad_iocmd_pcifn_delete(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd; @@ -1253,7 +1253,7 @@ out: return 0; } -int +static int bfad_iocmd_pcifn_bw(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd; @@ -1277,7 +1277,7 @@ out: return 0; } -int +static int bfad_iocmd_adapter_cfg_mode(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_adapter_cfg_mode_s *iocmd = @@ -1300,7 +1300,7 @@ out: return 0; } -int +static int bfad_iocmd_port_cfg_mode(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_port_cfg_mode_s *iocmd = @@ -1324,7 +1324,7 @@ out: return 0; } -int +static int bfad_iocmd_ablk_optrom(struct bfad_s *bfad, unsigned int cmd, void *pcmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; @@ -1350,7 +1350,7 @@ out: return 0; } -int +static int bfad_iocmd_faa_query(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_faa_attr_s *iocmd = (struct bfa_bsg_faa_attr_s *)cmd; @@ -1373,7 +1373,7 @@ out: return 0; } -int +static int bfad_iocmd_cee_attr(struct bfad_s *bfad, void *cmd, unsigned int payload_len) { struct bfa_bsg_cee_attr_s *iocmd = @@ -1409,7 +1409,7 @@ out: return 0; } -int +static int bfad_iocmd_cee_get_stats(struct bfad_s *bfad, void *cmd, unsigned int payload_len) { @@ -1446,7 +1446,7 @@ out: return 0; } -int +static int bfad_iocmd_cee_reset_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -1460,7 +1460,7 @@ bfad_iocmd_cee_reset_stats(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_sfp_media(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_sfp_media_s *iocmd = (struct bfa_bsg_sfp_media_s *)cmd; @@ -1482,7 +1482,7 @@ out: return 0; } -int +static int bfad_iocmd_sfp_speed(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_sfp_speed_s *iocmd = (struct bfa_bsg_sfp_speed_s *)cmd; @@ -1503,7 +1503,7 @@ out: return 0; } -int +static int bfad_iocmd_flash_get_attr(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_flash_attr_s *iocmd = @@ -1524,7 +1524,7 @@ out: return 0; } -int +static int bfad_iocmd_flash_erase_part(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd; @@ -1544,7 +1544,7 @@ out: return 0; } -int +static int bfad_iocmd_flash_update_part(struct bfad_s *bfad, void *cmd, unsigned int payload_len) { @@ -1576,7 +1576,7 @@ out: return 0; } -int +static int bfad_iocmd_flash_read_part(struct bfad_s *bfad, void *cmd, unsigned int payload_len) { @@ -1608,7 +1608,7 @@ out: return 0; } -int +static int bfad_iocmd_diag_temp(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_diag_get_temp_s *iocmd = @@ -1630,7 +1630,7 @@ out: return 0; } -int +static int bfad_iocmd_diag_memtest(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_diag_memtest_s *iocmd = @@ -1653,7 +1653,7 @@ out: return 0; } -int +static int bfad_iocmd_diag_loopback(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_diag_loopback_s *iocmd = @@ -1676,7 +1676,7 @@ out: return 0; } -int +static int bfad_iocmd_diag_fwping(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_diag_fwping_s *iocmd = @@ -1700,7 +1700,7 @@ out: return 0; } -int +static int bfad_iocmd_diag_queuetest(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_diag_qtest_s *iocmd = (struct bfa_bsg_diag_qtest_s *)cmd; @@ -1721,7 +1721,7 @@ out: return 0; } -int +static int bfad_iocmd_diag_sfp(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_sfp_show_s *iocmd = @@ -1744,7 +1744,7 @@ out: return 0; } -int +static int bfad_iocmd_diag_led(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_diag_led_s *iocmd = (struct bfa_bsg_diag_led_s *)cmd; @@ -1757,7 +1757,7 @@ bfad_iocmd_diag_led(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_diag_beacon_lport(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_diag_beacon_s *iocmd = @@ -1772,7 +1772,7 @@ bfad_iocmd_diag_beacon_lport(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_diag_lb_stat_s *iocmd = @@ -1787,7 +1787,7 @@ bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_diag_dport_enable(struct bfad_s *bfad, void *pcmd) { struct bfa_bsg_dport_enable_s *iocmd = @@ -1809,7 +1809,7 @@ bfad_iocmd_diag_dport_enable(struct bfad_s *bfad, void *pcmd) return 0; } -int +static int bfad_iocmd_diag_dport_disable(struct bfad_s *bfad, void *pcmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; @@ -1829,7 +1829,7 @@ bfad_iocmd_diag_dport_disable(struct bfad_s *bfad, void *pcmd) return 0; } -int +static int bfad_iocmd_diag_dport_start(struct bfad_s *bfad, void *pcmd) { struct bfa_bsg_dport_enable_s *iocmd = @@ -1854,7 +1854,7 @@ bfad_iocmd_diag_dport_start(struct bfad_s *bfad, void *pcmd) return 0; } -int +static int bfad_iocmd_diag_dport_show(struct bfad_s *bfad, void *pcmd) { struct bfa_bsg_diag_dport_show_s *iocmd = @@ -1869,7 +1869,7 @@ bfad_iocmd_diag_dport_show(struct bfad_s *bfad, void *pcmd) } -int +static int bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_phy_attr_s *iocmd = @@ -1890,7 +1890,7 @@ out: return 0; } -int +static int bfad_iocmd_phy_get_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_phy_stats_s *iocmd = @@ -1911,7 +1911,7 @@ out: return 0; } -int +static int bfad_iocmd_phy_read(struct bfad_s *bfad, void *cmd, unsigned int payload_len) { struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd; @@ -1943,7 +1943,7 @@ out: return 0; } -int +static int bfad_iocmd_vhba_query(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_vhba_attr_s *iocmd = @@ -1962,7 +1962,7 @@ bfad_iocmd_vhba_query(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_phy_update(struct bfad_s *bfad, void *cmd, unsigned int payload_len) { struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd; @@ -1992,7 +1992,7 @@ out: return 0; } -int +static int bfad_iocmd_porglog_get(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_debug_s *iocmd = (struct bfa_bsg_debug_s *)cmd; @@ -2012,7 +2012,7 @@ out: } #define BFA_DEBUG_FW_CORE_CHUNK_SZ 0x4000U /* 16K chunks for FW dump */ -int +static int bfad_iocmd_debug_fw_core(struct bfad_s *bfad, void *cmd, unsigned int payload_len) { @@ -2046,7 +2046,7 @@ out: return 0; } -int +static int bfad_iocmd_debug_ctl(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -2067,7 +2067,7 @@ bfad_iocmd_debug_ctl(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) return 0; } -int +static int bfad_iocmd_porglog_ctl(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_portlogctl_s *iocmd = (struct bfa_bsg_portlogctl_s *)cmd; @@ -2081,7 +2081,7 @@ bfad_iocmd_porglog_ctl(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fcpim_cfg_profile(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) { struct bfa_bsg_fcpim_profile_s *iocmd = @@ -2125,7 +2125,7 @@ bfad_iocmd_itnim_get_ioprofile(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fcport_get_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fcport_stats_s *iocmd = @@ -2150,7 +2150,7 @@ out: return 0; } -int +static int bfad_iocmd_fcport_reset_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -2174,7 +2174,7 @@ out: return 0; } -int +static int bfad_iocmd_boot_cfg(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_boot_s *iocmd = (struct bfa_bsg_boot_s *)cmd; @@ -2196,7 +2196,7 @@ out: return 0; } -int +static int bfad_iocmd_boot_query(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_boot_s *iocmd = (struct bfa_bsg_boot_s *)cmd; @@ -2218,7 +2218,7 @@ out: return 0; } -int +static int bfad_iocmd_preboot_query(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_preboot_s *iocmd = (struct bfa_bsg_preboot_s *)cmd; @@ -2237,7 +2237,7 @@ bfad_iocmd_preboot_query(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_ethboot_cfg(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_ethboot_s *iocmd = (struct bfa_bsg_ethboot_s *)cmd; @@ -2260,7 +2260,7 @@ out: return 0; } -int +static int bfad_iocmd_ethboot_query(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_ethboot_s *iocmd = (struct bfa_bsg_ethboot_s *)cmd; @@ -2283,7 +2283,7 @@ out: return 0; } -int +static int bfad_iocmd_cfg_trunk(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -2323,7 +2323,7 @@ bfad_iocmd_cfg_trunk(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) return 0; } -int +static int bfad_iocmd_trunk_get_attr(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_trunk_attr_s *iocmd = (struct bfa_bsg_trunk_attr_s *)cmd; @@ -2346,7 +2346,7 @@ bfad_iocmd_trunk_get_attr(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_qos(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -2374,7 +2374,7 @@ bfad_iocmd_qos(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) return 0; } -int +static int bfad_iocmd_qos_get_attr(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_qos_attr_s *iocmd = (struct bfa_bsg_qos_attr_s *)cmd; @@ -2400,7 +2400,7 @@ bfad_iocmd_qos_get_attr(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_qos_get_vc_attr(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_qos_vc_attr_s *iocmd = @@ -2432,7 +2432,7 @@ bfad_iocmd_qos_get_vc_attr(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fcport_stats_s *iocmd = @@ -2464,7 +2464,7 @@ out: return 0; } -int +static int bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; @@ -2495,7 +2495,7 @@ out: return 0; } -int +static int bfad_iocmd_vf_get_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_vf_stats_s *iocmd = @@ -2518,7 +2518,7 @@ out: return 0; } -int +static int bfad_iocmd_vf_clr_stats(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_vf_reset_stats_s *iocmd = @@ -2555,7 +2555,7 @@ bfad_iocmd_lunmask_reset_lunscan_mode(struct bfad_s *bfad, int lunmask_cfg) bfad_reset_sdev_bflags(vport->drv_port.im_port, lunmask_cfg); } -int +static int bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; @@ -2578,7 +2578,7 @@ bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd) return 0; } -int +static int bfad_iocmd_fcpim_lunmask_query(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fcpim_lunmask_query_s *iocmd = @@ -2592,7 +2592,7 @@ bfad_iocmd_fcpim_lunmask_query(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fcpim_cfg_lunmask(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) { struct bfa_bsg_fcpim_lunmask_s *iocmd = @@ -2611,7 +2611,7 @@ bfad_iocmd_fcpim_cfg_lunmask(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) return 0; } -int +static int bfad_iocmd_fcpim_throttle_query(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fcpim_throttle_s *iocmd = @@ -2626,7 +2626,7 @@ bfad_iocmd_fcpim_throttle_query(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fcpim_throttle_set(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fcpim_throttle_s *iocmd = @@ -2641,7 +2641,7 @@ bfad_iocmd_fcpim_throttle_set(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_tfru_read(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_tfru_s *iocmd = @@ -2663,7 +2663,7 @@ bfad_iocmd_tfru_read(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_tfru_write(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_tfru_s *iocmd = @@ -2685,7 +2685,7 @@ bfad_iocmd_tfru_write(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fruvpd_read(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fruvpd_s *iocmd = @@ -2707,7 +2707,7 @@ bfad_iocmd_fruvpd_read(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fruvpd_update(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fruvpd_s *iocmd = @@ -2729,7 +2729,7 @@ bfad_iocmd_fruvpd_update(struct bfad_s *bfad, void *cmd) return 0; } -int +static int bfad_iocmd_fruvpd_get_max_size(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_fruvpd_max_size_s *iocmd = @@ -3177,7 +3177,7 @@ out: } /* FC passthru call backs */ -u64 +static u64 bfad_fcxp_get_req_sgaddr_cb(void *bfad_fcxp, int sgeid) { struct bfad_fcxp *drv_fcxp = bfad_fcxp; @@ -3189,7 +3189,7 @@ bfad_fcxp_get_req_sgaddr_cb(void *bfad_fcxp, int sgeid) return addr; } -u32 +static u32 bfad_fcxp_get_req_sglen_cb(void *bfad_fcxp, int sgeid) { struct bfad_fcxp *drv_fcxp = bfad_fcxp; @@ -3199,7 +3199,7 @@ bfad_fcxp_get_req_sglen_cb(void *bfad_fcxp, int sgeid) return sge->sg_len; } -u64 +static u64 bfad_fcxp_get_rsp_sgaddr_cb(void *bfad_fcxp, int sgeid) { struct bfad_fcxp *drv_fcxp = bfad_fcxp; @@ -3211,7 +3211,7 @@ bfad_fcxp_get_rsp_sgaddr_cb(void *bfad_fcxp, int sgeid) return addr; } -u32 +static u32 bfad_fcxp_get_rsp_sglen_cb(void *bfad_fcxp, int sgeid) { struct bfad_fcxp *drv_fcxp = bfad_fcxp; @@ -3221,7 +3221,7 @@ bfad_fcxp_get_rsp_sglen_cb(void *bfad_fcxp, int sgeid) return sge->sg_len; } -void +static void bfad_send_fcpt_cb(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg, bfa_status_t req_status, u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs) @@ -3236,7 +3236,7 @@ bfad_send_fcpt_cb(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg, complete(&drv_fcxp->comp); } -struct bfad_buf_info * +static struct bfad_buf_info * bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf, uint32_t payload_len, uint32_t *num_sgles) { @@ -3280,7 +3280,7 @@ out_free_mem: return NULL; } -void +static void bfad_fcxp_free_mem(struct bfad_s *bfad, struct bfad_buf_info *buf_base, uint32_t num_sgles) { @@ -3298,7 +3298,7 @@ bfad_fcxp_free_mem(struct bfad_s *bfad, struct bfad_buf_info *buf_base, } } -int +static int bfad_fcxp_bsg_send(struct bsg_job *job, struct bfad_fcxp *drv_fcxp, bfa_bsg_fcpt_t *bsg_fcpt) { @@ -3338,7 +3338,7 @@ bfad_fcxp_bsg_send(struct bsg_job *job, struct bfad_fcxp *drv_fcxp, return BFA_STATUS_OK; } -int +static int bfad_im_bsg_els_ct_request(struct bsg_job *job) { struct bfa_bsg_data *bsg_data; diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 0e33324e16f51e465bdd41447804795eed16636b..5cdeeb3539fdcc08f752303111759ecc996ce09f 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -1071,9 +1071,8 @@ static int bnx2fc_fip_recv(struct sk_buff *skb, struct net_device *dev, /** * bnx2fc_update_src_mac - Update Ethernet MAC filters. * - * @fip: FCoE controller. - * @old: Unicast MAC address to delete if the MAC is non-zero. - * @new: Unicast MAC address to add. + * @lport: The local port + * @addr: Location of data to copy * * Remove any previously-set unicast MAC filter. * Add secondary FCoE MAC address filter for our OUI. @@ -1659,8 +1658,7 @@ static void __bnx2fc_destroy(struct bnx2fc_interface *interface) /** * bnx2fc_destroy - Destroy a bnx2fc FCoE interface * - * @buffer: The name of the Ethernet interface to be destroyed - * @kp: The associated kernel parameter + * @netdev: The net device that the FCoE interface is on * * Called from sysfs. * @@ -2101,7 +2099,7 @@ static int __bnx2fc_disable(struct fcoe_ctlr *ctlr) return 0; } -/** +/* * Deperecated: Use bnx2fc_enabled() */ static int bnx2fc_disable(struct net_device *netdev) @@ -2229,7 +2227,7 @@ done: return 0; } -/** +/* * Deprecated: Use bnx2fc_enabled() */ static int bnx2fc_enable(struct net_device *netdev) @@ -2523,7 +2521,7 @@ static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device /** * bnx2fc_ulp_exit - shuts down adapter instance and frees all resources * - * @dev cnic device handle + * @dev: cnic device handle */ static void bnx2fc_ulp_exit(struct cnic_dev *dev) { @@ -2956,7 +2954,7 @@ static struct device_attribute *bnx2fc_host_attrs[] = { NULL, }; -/** +/* * scsi_host_template structure used while registering with SCSI-ml */ static struct scsi_host_template bnx2fc_shost_template = { @@ -2989,7 +2987,7 @@ static struct libfc_function_template bnx2fc_libfc_fcn_templ = { .rport_event_callback = bnx2fc_rport_event_handler, }; -/** +/* * bnx2fc_cnic_cb - global template of bnx2fc - cnic driver interface * structure carrying callback function pointers */ diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index 1f7c58b4c53518a53868e59cafe508f62d2fb392..e72d7bb7f4f42f3e6cb465d28fbc6424cc616985 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c @@ -485,7 +485,7 @@ int bnx2fc_send_session_disable_req(struct fcoe_port *port, /** * bnx2fc_send_session_destroy_req - initiates FCoE Session destroy * - * @port: port structure pointer + * @hba: adapter structure pointer * @tgt: bnx2fc_rport structure pointer */ int bnx2fc_send_session_destroy_req(struct bnx2fc_hba *hba, @@ -635,7 +635,6 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe) struct bnx2fc_cmd *io_req = NULL; struct bnx2fc_interface *interface = tgt->port->priv; struct bnx2fc_hba *hba = interface->hba; - int task_idx, index; int rc = 0; u64 err_warn_bit_map; u8 err_warn = 0xff; @@ -701,15 +700,12 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe) BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x\n", err_entry->data.tx_buf_off, err_entry->data.rx_buf_off); - if (xid > hba->max_xid) { BNX2FC_TGT_DBG(tgt, "xid(0x%x) out of FW range\n", xid); goto ret_err_rqe; } - task_idx = xid / BNX2FC_TASKS_PER_PAGE; - index = xid % BNX2FC_TASKS_PER_PAGE; io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid]; if (!io_req) @@ -833,8 +829,6 @@ ret_err_rqe: } BNX2FC_TGT_DBG(tgt, "warn = 0x%x\n", err_warn); - task_idx = xid / BNX2FC_TASKS_PER_PAGE; - index = xid % BNX2FC_TASKS_PER_PAGE; io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid]; if (!io_req) goto ret_warn_rqe; @@ -1008,7 +1002,6 @@ static bool bnx2fc_pending_work(struct bnx2fc_rport *tgt, unsigned int wqe) unsigned char *rq_data = NULL; unsigned char rq_data_buff[BNX2FC_RQ_BUF_SZ]; int task_idx, index; - unsigned char *dummy; u16 xid; u8 num_rq; int i; @@ -1038,7 +1031,7 @@ static bool bnx2fc_pending_work(struct bnx2fc_rport *tgt, unsigned int wqe) if (num_rq > 1) { /* We do not need extra sense data */ for (i = 1; i < num_rq; i++) - dummy = bnx2fc_get_next_rqe(tgt, 1); + bnx2fc_get_next_rqe(tgt, 1); } if (rq_data) @@ -1341,8 +1334,8 @@ static void bnx2fc_init_failure(struct bnx2fc_hba *hba, u32 err_code) /** * bnx2fc_indicae_kcqe - process KCQE * - * @hba: adapter structure pointer - * @kcqe: kcqe pointer + * @context: adapter structure pointer + * @kcq: kcqe pointer * @num_cqe: Number of completion queue elements * * Generic KCQ event handler @@ -1510,7 +1503,6 @@ void bnx2fc_init_seq_cleanup_task(struct bnx2fc_cmd *seq_clnp_req, u64 phys_addr = (u64)orig_io_req->bd_tbl->bd_tbl_dma; u32 orig_offset = offset; int bd_count; - int orig_task_idx, index; int i; memset(task, 0, sizeof(struct fcoe_task_ctx_entry)); @@ -1560,8 +1552,6 @@ void bnx2fc_init_seq_cleanup_task(struct bnx2fc_cmd *seq_clnp_req, offset; /* adjusted offset */ task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_idx = i; } else { - orig_task_idx = orig_xid / BNX2FC_TASKS_PER_PAGE; - index = orig_xid % BNX2FC_TASKS_PER_PAGE; /* Multiple SGEs were used for this IO */ sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl; @@ -2089,11 +2079,7 @@ static int bnx2fc_allocate_hash_table(struct bnx2fc_hba *hba) pbl = hba->hash_tbl_pbl; i = 0; while (*pbl && *(pbl + 1)) { - u32 lo; - u32 hi; - lo = *pbl; ++pbl; - hi = *pbl; ++pbl; ++i; } diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c index 50384b4a817c8fa75b0644a3ff6045efddc43d48..a3e2a38aabf2ff91a6f29fe6458925943ab23f57 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c +++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c @@ -431,7 +431,7 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt, return 0; } -/** +/* * This event_callback is called after successful completion of libfc * initiated target login. bnx2fc can proceed with initiating the session * establishment. @@ -656,9 +656,8 @@ static void bnx2fc_free_conn_id(struct bnx2fc_hba *hba, u32 conn_id) spin_unlock_bh(&hba->hba_lock); } -/** - *bnx2fc_alloc_session_resc - Allocate qp resources for the session - * +/* + * bnx2fc_alloc_session_resc - Allocate qp resources for the session */ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba, struct bnx2fc_rport *tgt) diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index e53ebc5eff85e3f7d211862cdecbd7ed3f5820ed..bad396e5c601449db65ee05040fd4cb088deb704 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -181,7 +181,7 @@ int bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action) /** * bnx2i_get_rq_buf - copy RQ buffer contents to driver buffer - * @conn: iscsi connection on which RQ event occurred + * @bnx2i_conn: iscsi connection on which RQ event occurred * @ptr: driver buffer to which RQ buffer contents is to * be copied * @len: length of valid data inside RQ buf @@ -223,7 +223,7 @@ static void bnx2i_ring_577xx_doorbell(struct bnx2i_conn *conn) /** * bnx2i_put_rq_buf - Replenish RQ buffer, if required ring on chip doorbell - * @conn: iscsi connection on which event to post + * @bnx2i_conn: iscsi connection on which event to post * @count: number of RQ buffer being posted to chip * * No need to ring hardware doorbell for 57710 family of devices @@ -258,7 +258,7 @@ void bnx2i_put_rq_buf(struct bnx2i_conn *bnx2i_conn, int count) /** * bnx2i_ring_sq_dbell - Ring SQ doorbell to wake-up the processing engine - * @conn: iscsi connection to which new SQ entries belong + * @bnx2i_conn: iscsi connection to which new SQ entries belong * @count: number of SQ WQEs to post * * SQ DB is updated in host memory and TX Doorbell is rung for 57710 family @@ -283,7 +283,7 @@ static void bnx2i_ring_sq_dbell(struct bnx2i_conn *bnx2i_conn, int count) /** * bnx2i_ring_dbell_update_sq_params - update SQ driver parameters - * @conn: iscsi connection to which new SQ entries belong + * @bnx2i_conn: iscsi connection to which new SQ entries belong * @count: number of SQ WQEs to post * * this routine will update SQ driver parameters and ring the doorbell @@ -320,9 +320,9 @@ static void bnx2i_ring_dbell_update_sq_params(struct bnx2i_conn *bnx2i_conn, /** * bnx2i_send_iscsi_login - post iSCSI login request MP WQE to hardware - * @conn: iscsi connection - * @cmd: driver command structure which is requesting - * a WQE to sent to chip for further processing + * @bnx2i_conn: iscsi connection + * @task: transport layer's command structure pointer which is requesting + * a WQE to sent to chip for further processing * * prepare and post an iSCSI Login request WQE to CNIC firmware */ @@ -373,7 +373,7 @@ int bnx2i_send_iscsi_login(struct bnx2i_conn *bnx2i_conn, /** * bnx2i_send_iscsi_tmf - post iSCSI task management request MP WQE to hardware - * @conn: iscsi connection + * @bnx2i_conn: iscsi connection * @mtask: driver command structure which is requesting * a WQE to sent to chip for further processing * @@ -447,7 +447,7 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn, /** * bnx2i_send_iscsi_text - post iSCSI text WQE to hardware - * @conn: iscsi connection + * @bnx2i_conn: iscsi connection * @mtask: driver command structure which is requesting * a WQE to sent to chip for further processing * @@ -495,7 +495,7 @@ int bnx2i_send_iscsi_text(struct bnx2i_conn *bnx2i_conn, /** * bnx2i_send_iscsi_scsicmd - post iSCSI scsicmd request WQE to hardware - * @conn: iscsi connection + * @bnx2i_conn: iscsi connection * @cmd: driver command structure which is requesting * a WQE to sent to chip for further processing * @@ -517,9 +517,9 @@ int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *bnx2i_conn, /** * bnx2i_send_iscsi_nopout - post iSCSI NOPOUT request WQE to hardware - * @conn: iscsi connection - * @cmd: driver command structure which is requesting - * a WQE to sent to chip for further processing + * @bnx2i_conn: iscsi connection + * @task: transport layer's command structure pointer which is + * requesting a WQE to sent to chip for further processing * @datap: payload buffer pointer * @data_len: payload data length * @unsol: indicated whether nopout pdu is unsolicited pdu or @@ -579,9 +579,9 @@ int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn, /** * bnx2i_send_iscsi_logout - post iSCSI logout request WQE to hardware - * @conn: iscsi connection - * @cmd: driver command structure which is requesting - * a WQE to sent to chip for further processing + * @bnx2i_conn: iscsi connection + * @task: transport layer's command structure pointer which is + * requesting a WQE to sent to chip for further processing * * prepare and post logout request WQE to CNIC firmware */ @@ -678,7 +678,8 @@ void bnx2i_update_iscsi_conn(struct iscsi_conn *conn) /** * bnx2i_ep_ofld_timer - post iSCSI logout request WQE to hardware - * @data: endpoint (transport handle) structure pointer + * @t: timer context used to fetch the endpoint (transport + * handle) structure pointer * * routine to handle connection offload/destroy request timeout */ @@ -1662,7 +1663,7 @@ static void bnx2i_process_nopin_local_cmpl(struct iscsi_session *session, /** * bnx2i_unsol_pdu_adjust_rq - makes adjustments to RQ after unsol pdu is recvd - * @conn: iscsi connection + * @bnx2i_conn: iscsi connection * * Firmware advances RQ producer index for every unsolicited PDU even if * payload data length is '0'. This function makes corresponding @@ -1885,7 +1886,9 @@ int bnx2i_percpu_io_thread(void *arg) /** * bnx2i_queue_scsi_cmd_resp - queue cmd completion to the percpu thread + * @session: iscsi session * @bnx2i_conn: bnx2i connection + * @cqe: pointer to newly DMA'ed CQE entry for processing * * this function is called by generic KCQ handler to queue all pending cmd * completion CQEs @@ -2466,8 +2469,9 @@ static void bnx2i_process_ofld_cmpl(struct bnx2i_hba *hba, /** * bnx2i_indicate_kcqe - process iscsi conn update completion KCQE - * @hba: adapter structure pointer - * @update_kcqe: kcqe pointer + * @context: adapter structure pointer + * @kcqe: kcqe pointer + * @num_cqe: number of kcqes to process * * Generic KCQ event handler/dispatcher */ @@ -2614,8 +2618,7 @@ static void bnx2i_cm_abort_cmpl(struct cnic_sock *cm_sk) /** * bnx2i_cm_remote_close - process received TCP FIN - * @hba: adapter structure pointer - * @update_kcqe: kcqe pointer + * @cm_sk: cnic sock structure pointer * * function callback exported via bnx2i - cnic driver interface to indicate * async TCP events such as FIN @@ -2631,8 +2634,7 @@ static void bnx2i_cm_remote_close(struct cnic_sock *cm_sk) /** * bnx2i_cm_remote_abort - process TCP RST and start conn cleanup - * @hba: adapter structure pointer - * @update_kcqe: kcqe pointer + * @cm_sk: cnic sock structure pointer * * function callback exported via bnx2i - cnic driver interface to * indicate async TCP events (RST) sent by the peer. @@ -2669,10 +2671,9 @@ static int bnx2i_send_nl_mesg(void *context, u32 msg_type, } -/** +/* * bnx2i_cnic_cb - global template of bnx2i - cnic driver interface structure * carrying callback function pointers - * */ struct cnic_ulp_ops bnx2i_cnic_cb = { .cnic_init = bnx2i_ulp_init, diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 4ebcda8d9500439941bd630f8b1187875a7beac5..6018cdd177022a2086c90a4126a1820d53070dcd 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -73,7 +73,7 @@ DEFINE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu); /** * bnx2i_identify_device - identifies NetXtreme II device type * @hba: Adapter structure pointer - * @cnic: Corresponding cnic device + * @dev: Corresponding cnic device * * This function identifies the NX2 device type and sets appropriate * queue mailbox register access method, 5709 requires driver to diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 0b28d44d3573876c21a5ce1afaf15bacc37ab596..fdd446765311a705c6d1bee24e8ded61b28d65f5 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -228,7 +228,7 @@ static void bnx2i_setup_cmd_wqe_template(struct bnx2i_cmd *cmd) /** * bnx2i_bind_conn_to_iscsi_cid - bind conn structure to 'iscsi_cid' * @hba: pointer to adapter instance - * @conn: pointer to iscsi connection + * @bnx2i_conn: pointer to iscsi connection * @iscsi_cid: iscsi context ID, range 0 - (MAX_CONN - 1) * * update iscsi cid table entry with connection pointer. This enables @@ -463,7 +463,6 @@ static int bnx2i_alloc_bdt(struct bnx2i_hba *hba, struct iscsi_session *session, * bnx2i_destroy_cmd_pool - destroys iscsi command pool and release BD table * @hba: adapter instance pointer * @session: iscsi session pointer - * @cmd: iscsi command structure */ static void bnx2i_destroy_cmd_pool(struct bnx2i_hba *hba, struct iscsi_session *session) @@ -582,8 +581,7 @@ static void bnx2i_free_mp_bdt(struct bnx2i_hba *hba) /** * bnx2i_drop_session - notifies iscsid of connection error. - * @hba: adapter instance pointer - * @session: iscsi session pointer + * @cls_session: iscsi cls session pointer * * This notifies iscsid that there is a error, so it can initiate * recovery. @@ -1277,7 +1275,8 @@ static int bnx2i_task_xmit(struct iscsi_task *task) /** * bnx2i_session_create - create a new iscsi session - * @cmds_max: max commands supported + * @ep: pointer to iscsi endpoint + * @cmds_max: user specified maximum commands * @qdepth: scsi queue depth to support * @initial_cmdsn: initial iscsi CMDSN to be used for this session * @@ -1971,7 +1970,7 @@ static int bnx2i_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) /** * bnx2i_ep_tcp_conn_active - check EP state transition - * @ep: endpoint pointer + * @bnx2i_ep: endpoint pointer * * check if underlying TCP connection is active */ @@ -2014,9 +2013,9 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep) } -/* +/** * bnx2i_hw_ep_disconnect - executes TCP connection teardown process in the hw - * @ep: TCP connection (bnx2i endpoint) handle + * @bnx2i_ep: TCP connection (bnx2i endpoint) handle * * executes TCP connection teardown process */ @@ -2171,8 +2170,8 @@ out: /** * bnx2i_nl_set_path - ISCSI_UEVENT_PATH_UPDATE user message handler - * @buf: pointer to buffer containing iscsi path message - * + * @shost: scsi host pointer + * @params: pointer to buffer containing iscsi path message */ static int bnx2i_nl_set_path(struct Scsi_Host *shost, struct iscsi_path *params) { diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c index 6d56fd60cb2b2a4f2ec514581cf29cb88110c24f..3dc790089f0fc7fc4011f4ded946fc1d0c1a5836 100644 --- a/drivers/scsi/bnx2i/bnx2i_sysfs.c +++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c @@ -30,6 +30,7 @@ static inline struct bnx2i_hba *bnx2i_dev_to_hba(struct device *dev) /** * bnx2i_show_sq_info - return(s currently configured send queue (SQ) size * @dev: device pointer + * @attr: device attribute (unused) * @buf: buffer to return current SQ size parameter * * Returns current SQ size parameter, this paramater determines the number @@ -47,6 +48,7 @@ static ssize_t bnx2i_show_sq_info(struct device *dev, /** * bnx2i_set_sq_info - update send queue (SQ) size parameter * @dev: device pointer + * @attr: device attribute (unused) * @buf: buffer to return current SQ size parameter * @count: parameter buffer size * @@ -87,6 +89,7 @@ skip_config: /** * bnx2i_show_ccell_info - returns command cell (HQ) size * @dev: device pointer + * @attr: device attribute (unused) * @buf: buffer to return current SQ size parameter * * returns per-connection TCP history queue size parameter @@ -103,6 +106,7 @@ static ssize_t bnx2i_show_ccell_info(struct device *dev, /** * bnx2i_get_link_state - set command cell (HQ) size * @dev: device pointer + * @attr: device attribute (unused) * @buf: buffer to return current SQ size parameter * @count: parameter buffer size * diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c index 950f9cdf0577f1632e58f41f0c48a30fc1dab087..98d4d39aaa572473896ec17c895a7f4254c1a6bc 100644 --- a/drivers/scsi/csiostor/csio_hw.c +++ b/drivers/scsi/csiostor/csio_hw.c @@ -306,7 +306,7 @@ csio_hw_get_vpd_params(struct csio_hw *hw, struct csio_vpd *p) uint8_t *vpd, csum; const struct t4_vpd_hdr *v; /* To get around compilation warning from strstrip */ - char *s; + char __always_unused *s; if (csio_is_valid_vpd(hw)) return 0; diff --git a/drivers/scsi/csiostor/csio_hw_t5.c b/drivers/scsi/csiostor/csio_hw_t5.c index f24def6c6fd1e4e1392f106aa2724d93f15e7d96..1df8891d37251ca61ef0e9a0640ee254e91f7158 100644 --- a/drivers/scsi/csiostor/csio_hw_t5.c +++ b/drivers/scsi/csiostor/csio_hw_t5.c @@ -148,12 +148,11 @@ csio_t5_mc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data, { int i; uint32_t mc_bist_cmd_reg, mc_bist_cmd_addr_reg, mc_bist_cmd_len_reg; - uint32_t mc_bist_status_rdata_reg, mc_bist_data_pattern_reg; + uint32_t mc_bist_data_pattern_reg; mc_bist_cmd_reg = MC_REG(MC_P_BIST_CMD_A, idx); mc_bist_cmd_addr_reg = MC_REG(MC_P_BIST_CMD_ADDR_A, idx); mc_bist_cmd_len_reg = MC_REG(MC_P_BIST_CMD_LEN_A, idx); - mc_bist_status_rdata_reg = MC_REG(MC_P_BIST_STATUS_RDATA_A, idx); mc_bist_data_pattern_reg = MC_REG(MC_P_BIST_DATA_PATTERN_A, idx); if (csio_rd_reg32(hw, mc_bist_cmd_reg) & START_BIST_F) @@ -196,7 +195,7 @@ csio_t5_edc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data, { int i; uint32_t edc_bist_cmd_reg, edc_bist_cmd_addr_reg, edc_bist_cmd_len_reg; - uint32_t edc_bist_cmd_data_pattern, edc_bist_status_rdata_reg; + uint32_t edc_bist_cmd_data_pattern; /* * These macro are missing in t4_regs.h file. @@ -208,7 +207,6 @@ csio_t5_edc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data, edc_bist_cmd_addr_reg = EDC_REG_T5(EDC_H_BIST_CMD_ADDR_A, idx); edc_bist_cmd_len_reg = EDC_REG_T5(EDC_H_BIST_CMD_LEN_A, idx); edc_bist_cmd_data_pattern = EDC_REG_T5(EDC_H_BIST_DATA_PATTERN_A, idx); - edc_bist_status_rdata_reg = EDC_REG_T5(EDC_H_BIST_STATUS_RDATA_A, idx); #undef EDC_REG_T5 #undef EDC_STRIDE_T5 diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c index 8dea7d53788a990017934ec5518d3fc6d6ee7bdb..390b07bf92b9794d0727de8e942c4d5e9eba3834 100644 --- a/drivers/scsi/csiostor/csio_init.c +++ b/drivers/scsi/csiostor/csio_init.c @@ -582,7 +582,7 @@ csio_hw_free(struct csio_hw *hw) * @hw: The HW module. * @dev: The device associated with this invocation. * @probe: Called from probe context or not? - * @os_pln: Parent lnode if any. + * @pln: Parent lnode if any. * * Allocates lnode structure via scsi_host_alloc, initializes * shost, initializes lnode module and registers with SCSI ML diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c index 74ff8adc41f77184ae336c236969e0cfb5c204ce..61cf54208451a591830c6448ba821f8ec0afe548 100644 --- a/drivers/scsi/csiostor/csio_lnode.c +++ b/drivers/scsi/csiostor/csio_lnode.c @@ -2068,10 +2068,9 @@ csio_ln_exit(struct csio_lnode *ln) ln->fcfinfo = NULL; } -/** +/* * csio_lnode_init - Initialize the members of an lnode. * @ln: lnode - * */ int csio_lnode_init(struct csio_lnode *ln, struct csio_hw *hw, diff --git a/drivers/scsi/csiostor/csio_rnode.c b/drivers/scsi/csiostor/csio_rnode.c index e9c3b045f587509ffc92d01fd91d7c455a7e47a7..713e13adf4dccce0664d581f03d03a09a64fc404 100644 --- a/drivers/scsi/csiostor/csio_rnode.c +++ b/drivers/scsi/csiostor/csio_rnode.c @@ -862,7 +862,7 @@ csio_rnode_devloss_handler(struct csio_rnode *rn) /** * csio_rnode_fwevt_handler - Event handler for firmware rnode events. * @rn: rnode - * + * @fwevt: firmware event to handle */ void csio_rnode_fwevt_handler(struct csio_rnode *rn, uint8_t fwevt) diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index ec7d01f6e2d58b03b3e1ae4d43488d0aee832f03..2b48954b6b1ef58549f0f7ff07b20546a7acca59 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c @@ -361,7 +361,7 @@ static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb, /* len includes the length of any HW ULP additions */ req->len = htonl(len); /* V_TX_ULP_SUBMODE sets both the mode and submode */ - req->flags = htonl(V_TX_ULP_SUBMODE(cxgbi_skcb_ulp_mode(skb)) | + req->flags = htonl(V_TX_ULP_SUBMODE(cxgbi_skcb_tx_ulp_mode(skb)) | V_TX_SHOVE((skb_peek(&csk->write_queue) ? 0 : 1))); req->sndseq = htonl(csk->snd_nxt); req->param = htonl(V_TX_PORT(l2t->smt_idx)); @@ -375,10 +375,8 @@ static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb, } } -/** +/* * push_tx_frames -- start transmit - * @c3cn: the offloaded connection - * @req_completion: request wr_ack or not * * Prepends TX_DATA_WR or CPL_CLOSE_CON_REQ headers to buffers waiting in a * connection's send queue and sends them on to T3. Must be called with the @@ -442,7 +440,7 @@ static int push_tx_frames(struct cxgbi_sock *csk, int req_completion) req_completion = 1; csk->wr_una_cred = 0; } - len += cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb)); + len += cxgbi_ulp_extra_len(cxgbi_skcb_tx_ulp_mode(skb)); make_tx_data_wr(csk, skb, len, req_completion); csk->snd_nxt += len; cxgbi_skcb_clear_flag(skb, SKCBF_TX_NEED_HDR); @@ -886,11 +884,6 @@ free_cpl_skbs: return -ENOMEM; } -/** - * release_offload_resources - release offload resource - * @c3cn: the offloaded iscsi tcp connection. - * Release resources held by an offload connection (TID, L2T entry, etc.) - */ static void l2t_put(struct cxgbi_sock *csk) { struct t3cdev *t3dev = (struct t3cdev *)csk->cdev->lldev; @@ -902,6 +895,10 @@ static void l2t_put(struct cxgbi_sock *csk) } } +/* + * release_offload_resources - release offload resource + * Release resources held by an offload connection (TID, L2T entry, etc.) + */ static void release_offload_resources(struct cxgbi_sock *csk) { struct t3cdev *t3dev = (struct t3cdev *)csk->cdev->lldev; diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 8ce8592f6a6492138b56a5089a6d55be88f730f7..4e82c14cb795e19a7259744b52f6ce9002013033 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -197,7 +197,10 @@ static inline bool is_ofld_imm(const struct sk_buff *skb) if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) len += sizeof(struct fw_ofld_tx_data_wr); - return len <= MAX_IMM_TX_PKT_LEN; + if (likely(cxgbi_skcb_test_flag((struct sk_buff *)skb, SKCBF_TX_ISO))) + len += sizeof(struct cpl_tx_data_iso); + + return (len <= MAX_IMM_OFLD_TX_DATA_WR_LEN); } static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, @@ -641,7 +644,10 @@ static inline int send_tx_flowc_wr(struct cxgbi_sock *csk) flowc->mnemval[8].mnemonic = 0; flowc->mnemval[8].val = 0; flowc->mnemval[8].mnemonic = FW_FLOWC_MNEM_TXDATAPLEN_MAX; - flowc->mnemval[8].val = 16384; + if (csk->cdev->skb_iso_txhdr) + flowc->mnemval[8].val = cpu_to_be32(CXGBI_MAX_ISO_DATA_IN_SKB); + else + flowc->mnemval[8].val = cpu_to_be32(16128); #ifdef CONFIG_CHELSIO_T4_DCB flowc->mnemval[9].mnemonic = FW_FLOWC_MNEM_DCBPRIO; if (vlan == CPL_L2T_VLAN_NONE) { @@ -667,38 +673,86 @@ static inline int send_tx_flowc_wr(struct cxgbi_sock *csk) return flowclen16; } -static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb, - int dlen, int len, u32 credits, int compl) +static void +cxgb4i_make_tx_iso_cpl(struct sk_buff *skb, struct cpl_tx_data_iso *cpl) +{ + struct cxgbi_iso_info *info = (struct cxgbi_iso_info *)skb->head; + u32 imm_en = !!(info->flags & CXGBI_ISO_INFO_IMM_ENABLE); + u32 fslice = !!(info->flags & CXGBI_ISO_INFO_FSLICE); + u32 lslice = !!(info->flags & CXGBI_ISO_INFO_LSLICE); + u32 pdu_type = (info->op == ISCSI_OP_SCSI_CMD) ? 0 : 1; + u32 submode = cxgbi_skcb_tx_ulp_mode(skb) & 0x3; + + cpl->op_to_scsi = cpu_to_be32(CPL_TX_DATA_ISO_OP_V(CPL_TX_DATA_ISO) | + CPL_TX_DATA_ISO_FIRST_V(fslice) | + CPL_TX_DATA_ISO_LAST_V(lslice) | + CPL_TX_DATA_ISO_CPLHDRLEN_V(0) | + CPL_TX_DATA_ISO_HDRCRC_V(submode & 1) | + CPL_TX_DATA_ISO_PLDCRC_V(((submode >> 1) & 1)) | + CPL_TX_DATA_ISO_IMMEDIATE_V(imm_en) | + CPL_TX_DATA_ISO_SCSI_V(pdu_type)); + + cpl->ahs_len = info->ahs; + cpl->mpdu = cpu_to_be16(DIV_ROUND_UP(info->mpdu, 4)); + cpl->burst_size = cpu_to_be32(info->burst_size); + cpl->len = cpu_to_be32(info->len); + cpl->reserved2_seglen_offset = + cpu_to_be32(CPL_TX_DATA_ISO_SEGLEN_OFFSET_V(info->segment_offset)); + cpl->datasn_offset = cpu_to_be32(info->datasn_offset); + cpl->buffer_offset = cpu_to_be32(info->buffer_offset); + cpl->reserved3 = cpu_to_be32(0); + log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, + "iso: flags 0x%x, op %u, ahs %u, num_pdu %u, mpdu %u, " + "burst_size %u, iso_len %u\n", + info->flags, info->op, info->ahs, info->num_pdu, + info->mpdu, info->burst_size << 2, info->len); +} + +static void +cxgb4i_make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb, int dlen, + int len, u32 credits, int compl) { + struct cxgbi_device *cdev = csk->cdev; + struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev); struct fw_ofld_tx_data_wr *req; - unsigned int submode = cxgbi_skcb_ulp_mode(skb) & 3; - unsigned int wr_ulp_mode = 0, val; - bool imm = is_ofld_imm(skb); - - req = __skb_push(skb, sizeof(*req)); - - if (imm) { - req->op_to_immdlen = htonl(FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | - FW_WR_COMPL_F | - FW_WR_IMMDLEN_V(dlen)); - req->flowid_len16 = htonl(FW_WR_FLOWID_V(csk->tid) | - FW_WR_LEN16_V(credits)); - } else { - req->op_to_immdlen = - cpu_to_be32(FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | - FW_WR_COMPL_F | - FW_WR_IMMDLEN_V(0)); - req->flowid_len16 = - cpu_to_be32(FW_WR_FLOWID_V(csk->tid) | - FW_WR_LEN16_V(credits)); + struct cpl_tx_data_iso *cpl; + u32 submode = cxgbi_skcb_tx_ulp_mode(skb) & 0x3; + u32 wr_ulp_mode = 0; + u32 hdr_size = sizeof(*req); + u32 opcode = FW_OFLD_TX_DATA_WR; + u32 immlen = 0; + u32 force = is_t5(lldi->adapter_type) ? TX_FORCE_V(!submode) : + T6_TX_FORCE_F; + + if (cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO)) { + hdr_size += sizeof(struct cpl_tx_data_iso); + opcode = FW_ISCSI_TX_DATA_WR; + immlen += sizeof(struct cpl_tx_data_iso); + submode |= 8; } + + if (is_ofld_imm(skb)) + immlen += dlen; + + req = (struct fw_ofld_tx_data_wr *)__skb_push(skb, hdr_size); + req->op_to_immdlen = cpu_to_be32(FW_WR_OP_V(opcode) | + FW_WR_COMPL_V(compl) | + FW_WR_IMMDLEN_V(immlen)); + req->flowid_len16 = cpu_to_be32(FW_WR_FLOWID_V(csk->tid) | + FW_WR_LEN16_V(credits)); + req->plen = cpu_to_be32(len); + cpl = (struct cpl_tx_data_iso *)(req + 1); + + if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO))) + cxgb4i_make_tx_iso_cpl(skb, cpl); + if (submode) wr_ulp_mode = FW_OFLD_TX_DATA_WR_ULPMODE_V(ULP2_MODE_ISCSI) | - FW_OFLD_TX_DATA_WR_ULPSUBMODE_V(submode); - val = skb_peek(&csk->write_queue) ? 0 : 1; - req->tunnel_to_proxy = htonl(wr_ulp_mode | - FW_OFLD_TX_DATA_WR_SHOVE_V(val)); - req->plen = htonl(len); + FW_OFLD_TX_DATA_WR_ULPSUBMODE_V(submode); + + req->tunnel_to_proxy = cpu_to_be32(wr_ulp_mode | force | + FW_OFLD_TX_DATA_WR_SHOVE_V(1U)); + if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT)) cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT); } @@ -716,30 +770,34 @@ static int push_tx_frames(struct cxgbi_sock *csk, int req_completion) if (unlikely(csk->state < CTP_ESTABLISHED || csk->state == CTP_CLOSE_WAIT_1 || csk->state >= CTP_ABORTING)) { log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK | - 1 << CXGBI_DBG_PDU_TX, - "csk 0x%p,%u,0x%lx,%u, in closing state.\n", - csk, csk->state, csk->flags, csk->tid); + 1 << CXGBI_DBG_PDU_TX, + "csk 0x%p,%u,0x%lx,%u, in closing state.\n", + csk, csk->state, csk->flags, csk->tid); return 0; } - while (csk->wr_cred && (skb = skb_peek(&csk->write_queue)) != NULL) { - int dlen = skb->len; - int len = skb->len; - unsigned int credits_needed; - int flowclen16 = 0; + while (csk->wr_cred && ((skb = skb_peek(&csk->write_queue)) != NULL)) { + struct cxgbi_iso_info *iso_cpl; + u32 dlen = skb->len; + u32 len = skb->len; + u32 iso_cpl_len = 0; + u32 flowclen16 = 0; + u32 credits_needed; + u32 num_pdu = 1, hdr_len; + + if (cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO)) + iso_cpl_len = sizeof(struct cpl_tx_data_iso); - skb_reset_transport_header(skb); if (is_ofld_imm(skb)) - credits_needed = DIV_ROUND_UP(dlen, 16); + credits_needed = DIV_ROUND_UP(dlen + iso_cpl_len, 16); else - credits_needed = DIV_ROUND_UP( - 8 * calc_tx_flits_ofld(skb), - 16); + credits_needed = + DIV_ROUND_UP((8 * calc_tx_flits_ofld(skb)) + + iso_cpl_len, 16); if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) - credits_needed += DIV_ROUND_UP( - sizeof(struct fw_ofld_tx_data_wr), - 16); + credits_needed += + DIV_ROUND_UP(sizeof(struct fw_ofld_tx_data_wr), 16); /* * Assumes the initial credits is large enough to support @@ -754,14 +812,19 @@ static int push_tx_frames(struct cxgbi_sock *csk, int req_completion) if (csk->wr_cred < credits_needed) { log_debug(1 << CXGBI_DBG_PDU_TX, - "csk 0x%p, skb %u/%u, wr %d < %u.\n", - csk, skb->len, skb->data_len, - credits_needed, csk->wr_cred); + "csk 0x%p, skb %u/%u, wr %d < %u.\n", + csk, skb->len, skb->data_len, + credits_needed, csk->wr_cred); + + csk->no_tx_credits++; break; } + + csk->no_tx_credits = 0; + __skb_unlink(skb, &csk->write_queue); set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id); - skb->csum = credits_needed + flowclen16; + skb->csum = (__force __wsum)(credits_needed + flowclen16); csk->wr_cred -= credits_needed; csk->wr_una_cred += credits_needed; cxgbi_sock_enqueue_wr(csk, skb); @@ -771,25 +834,42 @@ static int push_tx_frames(struct cxgbi_sock *csk, int req_completion) csk, skb->len, skb->data_len, credits_needed, csk->wr_cred, csk->wr_una_cred); + if (!req_completion && + ((csk->wr_una_cred >= (csk->wr_max_cred / 2)) || + after(csk->write_seq, (csk->snd_una + csk->snd_win / 2)))) + req_completion = 1; + if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) { - len += cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb)); - make_tx_data_wr(csk, skb, dlen, len, credits_needed, - req_completion); + u32 ulp_mode = cxgbi_skcb_tx_ulp_mode(skb); + + if (cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO)) { + iso_cpl = (struct cxgbi_iso_info *)skb->head; + num_pdu = iso_cpl->num_pdu; + hdr_len = cxgbi_skcb_tx_iscsi_hdrlen(skb); + len += (cxgbi_ulp_extra_len(ulp_mode) * num_pdu) + + (hdr_len * (num_pdu - 1)); + } else { + len += cxgbi_ulp_extra_len(ulp_mode); + } + + cxgb4i_make_tx_data_wr(csk, skb, dlen, len, + credits_needed, req_completion); csk->snd_nxt += len; cxgbi_skcb_clear_flag(skb, SKCBF_TX_NEED_HDR); } else if (cxgbi_skcb_test_flag(skb, SKCBF_TX_FLAG_COMPL) && (csk->wr_una_cred >= (csk->wr_max_cred / 2))) { struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->data; - req->wr.wr_hi |= htonl(FW_WR_COMPL_F); + + req->wr.wr_hi |= cpu_to_be32(FW_WR_COMPL_F); } + total_size += skb->truesize; t4_set_arp_err_handler(skb, csk, arp_failure_skb_discard); log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX, - "csk 0x%p,%u,0x%lx,%u, skb 0x%p, %u.\n", - csk, csk->state, csk->flags, csk->tid, skb, len); - + "csk 0x%p,%u,0x%lx,%u, skb 0x%p, %u.\n", + csk, csk->state, csk->flags, csk->tid, skb, len); cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t); } return total_size; @@ -2111,10 +2191,30 @@ static int cxgb4i_ddp_init(struct cxgbi_device *cdev) return 0; } +static bool is_memfree(struct adapter *adap) +{ + u32 io; + + io = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A); + if (is_t5(adap->params.chip)) { + if ((io & EXT_MEM0_ENABLE_F) || (io & EXT_MEM1_ENABLE_F)) + return false; + } else if (io & EXT_MEM_ENABLE_F) { + return false; + } + + return true; +} + static void *t4_uld_add(const struct cxgb4_lld_info *lldi) { struct cxgbi_device *cdev; struct port_info *pi; + struct net_device *ndev; + struct adapter *adap; + struct tid_info *t; + u32 max_cmds = CXGB4I_SCSI_HOST_QDEPTH; + u32 max_conn = CXGBI_MAX_CONN; int i, rc; cdev = cxgbi_device_register(sizeof(*lldi), lldi->nports); @@ -2154,14 +2254,40 @@ static void *t4_uld_add(const struct cxgb4_lld_info *lldi) pr_info("t4 0x%p ddp init failed %d.\n", cdev, rc); goto err_out; } + + ndev = cdev->ports[0]; + adap = netdev2adap(ndev); + if (adap) { + t = &adap->tids; + if (t->ntids <= CXGBI_MAX_CONN) + max_conn = t->ntids; + + if (is_memfree(adap)) { + cdev->flags |= CXGBI_FLAG_DEV_ISO_OFF; + max_cmds = CXGB4I_SCSI_HOST_QDEPTH >> 2; + + pr_info("%s: 0x%p, tid %u, SO adapter.\n", + ndev->name, cdev, t->ntids); + } + } else { + pr_info("%s, 0x%p, NO adapter struct.\n", ndev->name, cdev); + } + + /* ISO is enabled in T5/T6 firmware version >= 1.13.43.0 */ + if (!is_t4(lldi->adapter_type) && + (lldi->fw_vers >= 0x10d2b00) && + !(cdev->flags & CXGBI_FLAG_DEV_ISO_OFF)) + cdev->skb_iso_txhdr = sizeof(struct cpl_tx_data_iso); + rc = cxgb4i_ofld_init(cdev); if (rc) { pr_info("t4 0x%p ofld init failed.\n", cdev); goto err_out; } - rc = cxgbi_hbas_add(cdev, CXGB4I_MAX_LUN, CXGBI_MAX_CONN, - &cxgb4i_host_template, cxgb4i_stt); + cxgb4i_host_template.can_queue = max_cmds; + rc = cxgbi_hbas_add(cdev, CXGB4I_MAX_LUN, max_conn, + &cxgb4i_host_template, cxgb4i_stt); if (rc) goto err_out; diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 4bc794d2f51c96dd5da708d8c5ef10dcbd14978d..71aebaf533ea543dd4ec701aab5166036ed020bc 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -359,13 +359,15 @@ int cxgbi_hbas_add(struct cxgbi_device *cdev, u64 max_lun, shost->max_lun = max_lun; shost->max_id = max_id; shost->max_channel = 0; - shost->max_cmd_len = 16; + shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE; chba = iscsi_host_priv(shost); chba->cdev = cdev; chba->ndev = cdev->ports[i]; chba->shost = shost; + shost->can_queue = sht->can_queue - ISCSI_MGMT_CMDS_MAX; + log_debug(1 << CXGBI_DBG_DEV, "cdev 0x%p, p#%d %s: chba 0x%p.\n", cdev, i, cdev->ports[i]->name, chba); @@ -1136,82 +1138,6 @@ void cxgbi_sock_check_wr_invariants(const struct cxgbi_sock *csk) } EXPORT_SYMBOL_GPL(cxgbi_sock_check_wr_invariants); -static int cxgbi_sock_send_pdus(struct cxgbi_sock *csk, struct sk_buff *skb) -{ - struct cxgbi_device *cdev = csk->cdev; - struct sk_buff *next; - int err, copied = 0; - - spin_lock_bh(&csk->lock); - - if (csk->state != CTP_ESTABLISHED) { - log_debug(1 << CXGBI_DBG_PDU_TX, - "csk 0x%p,%u,0x%lx,%u, EAGAIN.\n", - csk, csk->state, csk->flags, csk->tid); - err = -EAGAIN; - goto out_err; - } - - if (csk->err) { - log_debug(1 << CXGBI_DBG_PDU_TX, - "csk 0x%p,%u,0x%lx,%u, EPIPE %d.\n", - csk, csk->state, csk->flags, csk->tid, csk->err); - err = -EPIPE; - goto out_err; - } - - if (csk->write_seq - csk->snd_una >= csk->snd_win) { - log_debug(1 << CXGBI_DBG_PDU_TX, - "csk 0x%p,%u,0x%lx,%u, FULL %u-%u >= %u.\n", - csk, csk->state, csk->flags, csk->tid, csk->write_seq, - csk->snd_una, csk->snd_win); - err = -ENOBUFS; - goto out_err; - } - - while (skb) { - int frags = skb_shinfo(skb)->nr_frags + - (skb->len != skb->data_len); - - if (unlikely(skb_headroom(skb) < cdev->skb_tx_rsvd)) { - pr_err("csk 0x%p, skb head %u < %u.\n", - csk, skb_headroom(skb), cdev->skb_tx_rsvd); - err = -EINVAL; - goto out_err; - } - - if (frags >= SKB_WR_LIST_SIZE) { - pr_err("csk 0x%p, frags %d, %u,%u >%u.\n", - csk, skb_shinfo(skb)->nr_frags, skb->len, - skb->data_len, (uint)(SKB_WR_LIST_SIZE)); - err = -EINVAL; - goto out_err; - } - - next = skb->next; - skb->next = NULL; - cxgbi_skcb_set_flag(skb, SKCBF_TX_NEED_HDR); - cxgbi_sock_skb_entail(csk, skb); - copied += skb->len; - csk->write_seq += skb->len + - cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb)); - skb = next; - } - - if (likely(skb_queue_len(&csk->write_queue))) - cdev->csk_push_tx_frames(csk, 1); -done: - spin_unlock_bh(&csk->lock); - return copied; - -out_err: - if (copied == 0 && err == -EPIPE) - copied = csk->err ? csk->err : -EPIPE; - else - copied = err; - goto done; -} - static inline void scmd_get_params(struct scsi_cmnd *sc, struct scatterlist **sgl, unsigned int *sgcnt, unsigned int *dlen, @@ -1284,8 +1210,6 @@ EXPORT_SYMBOL_GPL(cxgbi_ddp_set_one_ppod); * APIs interacting with open-iscsi libraries */ -static unsigned char padding[4]; - int cxgbi_ddp_ppm_setup(void **ppm_pp, struct cxgbi_device *cdev, struct cxgbi_tag_format *tformat, unsigned int iscsi_size, unsigned int llimit, @@ -1833,9 +1757,10 @@ static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt, return -EFAULT; } -static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset, - unsigned int dlen, struct page_frag *frags, - int frag_max) +static int +sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset, + unsigned int dlen, struct page_frag *frags, + int frag_max, u32 *dlimit) { unsigned int datalen = dlen; unsigned int sglen = sg->length - sgoffset; @@ -1867,6 +1792,7 @@ static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset, if (i >= frag_max) { pr_warn("too many pages %u, dlen %u.\n", frag_max, dlen); + *dlimit = dlen - datalen; return -EINVAL; } @@ -1883,38 +1809,220 @@ static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset, return i; } -int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) +static void cxgbi_task_data_sgl_check(struct iscsi_task *task) { - struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data; + struct scsi_cmnd *sc = task->sc; + struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task); + struct scatterlist *sg, *sgl = NULL; + u32 sgcnt = 0; + int i; + + tdata->flags = CXGBI_TASK_SGL_CHECKED; + if (!sc) + return; + + scmd_get_params(sc, &sgl, &sgcnt, &tdata->dlen, 0); + if (!sgl || !sgcnt) { + tdata->flags |= CXGBI_TASK_SGL_COPY; + return; + } + + for_each_sg(sgl, sg, sgcnt, i) { + if (page_count(sg_page(sg)) < 1) { + tdata->flags |= CXGBI_TASK_SGL_COPY; + return; + } + } +} + +static int +cxgbi_task_data_sgl_read(struct iscsi_task *task, u32 offset, u32 count, + u32 *dlimit) +{ + struct scsi_cmnd *sc = task->sc; + struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task); + struct scatterlist *sgl = NULL; + struct scatterlist *sg; + u32 dlen = 0; + u32 sgcnt; + int err; + + if (!sc) + return 0; + + scmd_get_params(sc, &sgl, &sgcnt, &dlen, 0); + if (!sgl || !sgcnt) + return 0; + + err = sgl_seek_offset(sgl, sgcnt, offset, &tdata->sgoffset, &sg); + if (err < 0) { + pr_warn("tpdu max, sgl %u, bad offset %u/%u.\n", + sgcnt, offset, tdata->dlen); + return err; + } + err = sgl_read_to_frags(sg, tdata->sgoffset, count, + tdata->frags, MAX_SKB_FRAGS, dlimit); + if (err < 0) { + log_debug(1 << CXGBI_DBG_ISCSI, + "sgl max limit, sgl %u, offset %u, %u/%u, dlimit %u.\n", + sgcnt, offset, count, tdata->dlen, *dlimit); + return err; + } + tdata->offset = offset; + tdata->count = count; + tdata->nr_frags = err; + tdata->total_count = count; + tdata->total_offset = offset; + + log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, + "%s: offset %u, count %u,\n" + "err %u, total_count %u, total_offset %u\n", + __func__, offset, count, err, tdata->total_count, tdata->total_offset); + + return 0; +} + +int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 op) +{ + struct iscsi_conn *conn = task->conn; + struct iscsi_session *session = task->conn->session; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct cxgbi_conn *cconn = tcp_conn->dd_data; struct cxgbi_device *cdev = cconn->chba->cdev; - struct iscsi_conn *conn = task->conn; + struct cxgbi_sock *csk = cconn->cep ? cconn->cep->csk : NULL; struct iscsi_tcp_task *tcp_task = task->dd_data; struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task); struct scsi_cmnd *sc = task->sc; - struct cxgbi_sock *csk = cconn->cep->csk; - struct net_device *ndev = cdev->ports[csk->port_id]; - int headroom = SKB_TX_ISCSI_PDU_HEADER_MAX; + u32 headroom = SKB_TX_ISCSI_PDU_HEADER_MAX; + u32 max_txdata_len = conn->max_xmit_dlength; + u32 iso_tx_rsvd = 0, local_iso_info = 0; + u32 last_tdata_offset, last_tdata_count; + int err = 0; + + if (!tcp_task) { + pr_err("task 0x%p, tcp_task 0x%p, tdata 0x%p.\n", + task, tcp_task, tdata); + return -ENOMEM; + } + if (!csk) { + pr_err("task 0x%p, csk gone.\n", task); + return -EPIPE; + } + + op &= ISCSI_OPCODE_MASK; tcp_task->dd_data = tdata; task->hdr = NULL; - if (SKB_MAX_HEAD(cdev->skb_tx_rsvd) > (512 * MAX_SKB_FRAGS) && - (opcode == ISCSI_OP_SCSI_DATA_OUT || - (opcode == ISCSI_OP_SCSI_CMD && - sc->sc_data_direction == DMA_TO_DEVICE))) - /* data could goes into skb head */ - headroom += min_t(unsigned int, - SKB_MAX_HEAD(cdev->skb_tx_rsvd), - conn->max_xmit_dlength); + last_tdata_count = tdata->count; + last_tdata_offset = tdata->offset; + + if ((op == ISCSI_OP_SCSI_DATA_OUT) || + ((op == ISCSI_OP_SCSI_CMD) && + (sc->sc_data_direction == DMA_TO_DEVICE))) { + u32 remaining_data_tosend, dlimit = 0; + u32 max_pdu_size, max_num_pdu, num_pdu; + u32 count; - tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC); + /* Preserve conn->max_xmit_dlength because it can get updated to + * ISO data size. + */ + if (task->state == ISCSI_TASK_PENDING) + tdata->max_xmit_dlength = conn->max_xmit_dlength; + + if (!tdata->offset) + cxgbi_task_data_sgl_check(task); + + remaining_data_tosend = + tdata->dlen - tdata->offset - tdata->count; + +recalculate_sgl: + max_txdata_len = tdata->max_xmit_dlength; + log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, + "tdata->dlen %u, remaining to send %u " + "conn->max_xmit_dlength %u, " + "tdata->max_xmit_dlength %u\n", + tdata->dlen, remaining_data_tosend, + conn->max_xmit_dlength, tdata->max_xmit_dlength); + + if (cdev->skb_iso_txhdr && !csk->disable_iso && + (remaining_data_tosend > tdata->max_xmit_dlength) && + !(remaining_data_tosend % 4)) { + u32 max_iso_data; + + if ((op == ISCSI_OP_SCSI_CMD) && + session->initial_r2t_en) + goto no_iso; + + max_pdu_size = tdata->max_xmit_dlength + + ISCSI_PDU_NONPAYLOAD_LEN; + max_iso_data = rounddown(CXGBI_MAX_ISO_DATA_IN_SKB, + csk->advmss); + max_num_pdu = max_iso_data / max_pdu_size; + + num_pdu = (remaining_data_tosend + + tdata->max_xmit_dlength - 1) / + tdata->max_xmit_dlength; + + if (num_pdu > max_num_pdu) + num_pdu = max_num_pdu; + + conn->max_xmit_dlength = tdata->max_xmit_dlength * num_pdu; + max_txdata_len = conn->max_xmit_dlength; + iso_tx_rsvd = cdev->skb_iso_txhdr; + local_iso_info = sizeof(struct cxgbi_iso_info); + + log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, + "max_pdu_size %u, max_num_pdu %u, " + "max_txdata %u, num_pdu %u\n", + max_pdu_size, max_num_pdu, + max_txdata_len, num_pdu); + } +no_iso: + count = min_t(u32, max_txdata_len, remaining_data_tosend); + err = cxgbi_task_data_sgl_read(task, + tdata->offset + tdata->count, + count, &dlimit); + if (unlikely(err < 0)) { + log_debug(1 << CXGBI_DBG_ISCSI, + "task 0x%p, tcp_task 0x%p, tdata 0x%p, " + "sgl err %d, count %u, dlimit %u\n", + task, tcp_task, tdata, err, count, dlimit); + if (dlimit) { + remaining_data_tosend = + rounddown(dlimit, + tdata->max_xmit_dlength); + if (!remaining_data_tosend) + remaining_data_tosend = dlimit; + + dlimit = 0; + + conn->max_xmit_dlength = remaining_data_tosend; + goto recalculate_sgl; + } + + pr_err("task 0x%p, tcp_task 0x%p, tdata 0x%p, " + "sgl err %d\n", + task, tcp_task, tdata, err); + goto ret_err; + } + + if ((tdata->flags & CXGBI_TASK_SGL_COPY) || + (tdata->nr_frags > MAX_SKB_FRAGS)) + headroom += conn->max_xmit_dlength; + } + + tdata->skb = alloc_skb(local_iso_info + cdev->skb_tx_rsvd + + iso_tx_rsvd + headroom, GFP_ATOMIC); if (!tdata->skb) { - ndev->stats.tx_dropped++; - return -ENOMEM; + tdata->count = last_tdata_count; + tdata->offset = last_tdata_offset; + err = -ENOMEM; + goto ret_err; } - skb_reserve(tdata->skb, cdev->skb_tx_rsvd); + skb_reserve(tdata->skb, local_iso_info + cdev->skb_tx_rsvd + + iso_tx_rsvd); if (task->sc) { task->hdr = (struct iscsi_hdr *)tdata->skb->data; @@ -1923,25 +2031,100 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) if (!task->hdr) { __kfree_skb(tdata->skb); tdata->skb = NULL; - ndev->stats.tx_dropped++; return -ENOMEM; } } - task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; /* BHS + AHS */ + + task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; + + if (iso_tx_rsvd) + cxgbi_skcb_set_flag(tdata->skb, SKCBF_TX_ISO); /* data_out uses scsi_cmd's itt */ - if (opcode != ISCSI_OP_SCSI_DATA_OUT) + if (op != ISCSI_OP_SCSI_DATA_OUT) task_reserve_itt(task, &task->hdr->itt); log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, - "task 0x%p, op 0x%x, skb 0x%p,%u+%u/%u, itt 0x%x.\n", - task, opcode, tdata->skb, cdev->skb_tx_rsvd, headroom, - conn->max_xmit_dlength, ntohl(task->hdr->itt)); + "task 0x%p, op 0x%x, skb 0x%p,%u+%u/%u, itt 0x%x.\n", + task, op, tdata->skb, cdev->skb_tx_rsvd, headroom, + conn->max_xmit_dlength, be32_to_cpu(task->hdr->itt)); return 0; + +ret_err: + conn->max_xmit_dlength = tdata->max_xmit_dlength; + return err; } EXPORT_SYMBOL_GPL(cxgbi_conn_alloc_pdu); +static int +cxgbi_prep_iso_info(struct iscsi_task *task, struct sk_buff *skb, + u32 count) +{ + struct cxgbi_iso_info *iso_info = (struct cxgbi_iso_info *)skb->head; + struct iscsi_r2t_info *r2t; + struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task); + struct iscsi_conn *conn = task->conn; + struct iscsi_session *session = conn->session; + struct iscsi_tcp_task *tcp_task = task->dd_data; + u32 burst_size = 0, r2t_dlength = 0, dlength; + u32 max_pdu_len = tdata->max_xmit_dlength; + u32 segment_offset = 0; + u32 num_pdu; + + if (unlikely(!cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO))) + return 0; + + memset(iso_info, 0, sizeof(struct cxgbi_iso_info)); + + if (task->hdr->opcode == ISCSI_OP_SCSI_CMD && session->imm_data_en) { + iso_info->flags |= CXGBI_ISO_INFO_IMM_ENABLE; + burst_size = count; + } + + dlength = ntoh24(task->hdr->dlength); + dlength = min(dlength, max_pdu_len); + hton24(task->hdr->dlength, dlength); + + num_pdu = (count + max_pdu_len - 1) / max_pdu_len; + + if (iscsi_task_has_unsol_data(task)) + r2t = &task->unsol_r2t; + else + r2t = tcp_task->r2t; + + if (r2t) { + log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, + "count %u, tdata->count %u, num_pdu %u," + "task->hdr_len %u, r2t->data_length %u, r2t->sent %u\n", + count, tdata->count, num_pdu, task->hdr_len, + r2t->data_length, r2t->sent); + + r2t_dlength = r2t->data_length - r2t->sent; + segment_offset = r2t->sent; + r2t->datasn += num_pdu - 1; + } + + if (!r2t || !r2t->sent) + iso_info->flags |= CXGBI_ISO_INFO_FSLICE; + + if (task->hdr->flags & ISCSI_FLAG_CMD_FINAL) + iso_info->flags |= CXGBI_ISO_INFO_LSLICE; + + task->hdr->flags &= ~ISCSI_FLAG_CMD_FINAL; + + iso_info->op = task->hdr->opcode; + iso_info->ahs = task->hdr->hlength; + iso_info->num_pdu = num_pdu; + iso_info->mpdu = max_pdu_len; + iso_info->burst_size = (burst_size + r2t_dlength) >> 2; + iso_info->len = count + task->hdr_len; + iso_info->segment_offset = segment_offset; + + cxgbi_skcb_tx_iscsi_hdrlen(skb) = task->hdr_len; + return 0; +} + static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc) { if (hcrc || dcrc) { @@ -1951,133 +2134,260 @@ static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc) submode |= 1; if (dcrc) submode |= 2; - cxgbi_skcb_ulp_mode(skb) = (ULP2_MODE_ISCSI << 4) | submode; + cxgbi_skcb_tx_ulp_mode(skb) = (ULP2_MODE_ISCSI << 4) | submode; } else - cxgbi_skcb_ulp_mode(skb) = 0; + cxgbi_skcb_tx_ulp_mode(skb) = 0; } +static struct page *rsvd_page; + int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset, unsigned int count) { struct iscsi_conn *conn = task->conn; + struct iscsi_tcp_task *tcp_task = task->dd_data; struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task); - struct sk_buff *skb = tdata->skb; - unsigned int datalen = count; - int i, padlen = iscsi_padding(count); + struct sk_buff *skb; + struct scsi_cmnd *sc = task->sc; + u32 expected_count, expected_offset; + u32 datalen = count, dlimit = 0; + u32 i, padlen = iscsi_padding(count); struct page *pg; + int err; + + if (!tcp_task || (tcp_task->dd_data != tdata)) { + pr_err("task 0x%p,0x%p, tcp_task 0x%p, tdata 0x%p/0x%p.\n", + task, task->sc, tcp_task, + tcp_task ? tcp_task->dd_data : NULL, tdata); + return -EINVAL; + } + skb = tdata->skb; log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, - "task 0x%p,0x%p, skb 0x%p, 0x%x,0x%x,0x%x, %u+%u.\n", - task, task->sc, skb, (*skb->data) & ISCSI_OPCODE_MASK, - ntohl(task->cmdsn), ntohl(task->hdr->itt), offset, count); + "task 0x%p,0x%p, skb 0x%p, 0x%x,0x%x,0x%x, %u+%u.\n", + task, task->sc, skb, (*skb->data) & ISCSI_OPCODE_MASK, + be32_to_cpu(task->cmdsn), be32_to_cpu(task->hdr->itt), offset, count); skb_put(skb, task->hdr_len); tx_skb_setmode(skb, conn->hdrdgst_en, datalen ? conn->datadgst_en : 0); - if (!count) + if (!count) { + tdata->count = count; + tdata->offset = offset; + tdata->nr_frags = 0; + tdata->total_offset = 0; + tdata->total_count = 0; + if (tdata->max_xmit_dlength) + conn->max_xmit_dlength = tdata->max_xmit_dlength; + cxgbi_skcb_clear_flag(skb, SKCBF_TX_ISO); return 0; + } - if (task->sc) { - struct scsi_data_buffer *sdb = &task->sc->sdb; - struct scatterlist *sg = NULL; - int err; + log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, + "data->total_count %u, tdata->total_offset %u\n", + tdata->total_count, tdata->total_offset); - tdata->offset = offset; - tdata->count = count; - err = sgl_seek_offset( - sdb->table.sgl, sdb->table.nents, - tdata->offset, &tdata->sgoffset, &sg); - if (err < 0) { - pr_warn("tpdu, sgl %u, bad offset %u/%u.\n", - sdb->table.nents, tdata->offset, sdb->length); - return err; - } - err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count, - tdata->frags, MAX_PDU_FRAGS); + expected_count = tdata->total_count; + expected_offset = tdata->total_offset; + + if ((count != expected_count) || + (offset != expected_offset)) { + err = cxgbi_task_data_sgl_read(task, offset, count, &dlimit); if (err < 0) { - pr_warn("tpdu, sgl %u, bad offset %u + %u.\n", - sdb->table.nents, tdata->offset, tdata->count); + pr_err("task 0x%p,0x%p, tcp_task 0x%p, tdata 0x%p/0x%p " + "dlimit %u, sgl err %d.\n", task, task->sc, + tcp_task, tcp_task ? tcp_task->dd_data : NULL, + tdata, dlimit, err); return err; } - tdata->nr_frags = err; + } + + /* Restore original value of conn->max_xmit_dlength because + * it can get updated to ISO data size. + */ + conn->max_xmit_dlength = tdata->max_xmit_dlength; + + if (sc) { + struct page_frag *frag = tdata->frags; - if (tdata->nr_frags > MAX_SKB_FRAGS || - (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) { + if ((tdata->flags & CXGBI_TASK_SGL_COPY) || + (tdata->nr_frags > MAX_SKB_FRAGS) || + (padlen && (tdata->nr_frags == + MAX_SKB_FRAGS))) { char *dst = skb->data + task->hdr_len; - struct page_frag *frag = tdata->frags; /* data fits in the skb's headroom */ for (i = 0; i < tdata->nr_frags; i++, frag++) { char *src = kmap_atomic(frag->page); - memcpy(dst, src+frag->offset, frag->size); + memcpy(dst, src + frag->offset, frag->size); dst += frag->size; kunmap_atomic(src); } + if (padlen) { memset(dst, 0, padlen); padlen = 0; } skb_put(skb, count + padlen); } else { - /* data fit into frag_list */ - for (i = 0; i < tdata->nr_frags; i++) { - __skb_fill_page_desc(skb, i, - tdata->frags[i].page, - tdata->frags[i].offset, - tdata->frags[i].size); - skb_frag_ref(skb, i); + for (i = 0; i < tdata->nr_frags; i++, frag++) { + get_page(frag->page); + skb_fill_page_desc(skb, i, frag->page, + frag->offset, frag->size); } - skb_shinfo(skb)->nr_frags = tdata->nr_frags; + skb->len += count; skb->data_len += count; skb->truesize += count; } - } else { - pg = virt_to_page(task->data); - + pg = virt_to_head_page(task->data); get_page(pg); - skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data), - count); + skb_fill_page_desc(skb, 0, pg, + task->data - (char *)page_address(pg), + count); skb->len += count; skb->data_len += count; skb->truesize += count; } if (padlen) { - i = skb_shinfo(skb)->nr_frags; + get_page(rsvd_page); skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, - virt_to_page(padding), offset_in_page(padding), - padlen); + rsvd_page, 0, padlen); skb->data_len += padlen; skb->truesize += padlen; skb->len += padlen; } + if (likely(count > tdata->max_xmit_dlength)) + cxgbi_prep_iso_info(task, skb, count); + else + cxgbi_skcb_clear_flag(skb, SKCBF_TX_ISO); + return 0; } EXPORT_SYMBOL_GPL(cxgbi_conn_init_pdu); +static int cxgbi_sock_tx_queue_up(struct cxgbi_sock *csk, struct sk_buff *skb) +{ + struct cxgbi_device *cdev = csk->cdev; + struct cxgbi_iso_info *iso_cpl; + u32 frags = skb_shinfo(skb)->nr_frags; + u32 extra_len, num_pdu, hdr_len; + u32 iso_tx_rsvd = 0; + + if (csk->state != CTP_ESTABLISHED) { + log_debug(1 << CXGBI_DBG_PDU_TX, + "csk 0x%p,%u,0x%lx,%u, EAGAIN.\n", + csk, csk->state, csk->flags, csk->tid); + return -EPIPE; + } + + if (csk->err) { + log_debug(1 << CXGBI_DBG_PDU_TX, + "csk 0x%p,%u,0x%lx,%u, EPIPE %d.\n", + csk, csk->state, csk->flags, csk->tid, csk->err); + return -EPIPE; + } + + if ((cdev->flags & CXGBI_FLAG_DEV_T3) && + before((csk->snd_win + csk->snd_una), csk->write_seq)) { + log_debug(1 << CXGBI_DBG_PDU_TX, + "csk 0x%p,%u,0x%lx,%u, FULL %u-%u >= %u.\n", + csk, csk->state, csk->flags, csk->tid, csk->write_seq, + csk->snd_una, csk->snd_win); + return -ENOBUFS; + } + + if (cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO)) + iso_tx_rsvd = cdev->skb_iso_txhdr; + + if (unlikely(skb_headroom(skb) < (cdev->skb_tx_rsvd + iso_tx_rsvd))) { + pr_err("csk 0x%p, skb head %u < %u.\n", + csk, skb_headroom(skb), cdev->skb_tx_rsvd); + return -EINVAL; + } + + if (skb->len != skb->data_len) + frags++; + + if (frags >= SKB_WR_LIST_SIZE) { + pr_err("csk 0x%p, frags %u, %u,%u >%lu.\n", + csk, skb_shinfo(skb)->nr_frags, skb->len, + skb->data_len, SKB_WR_LIST_SIZE); + return -EINVAL; + } + + cxgbi_skcb_set_flag(skb, SKCBF_TX_NEED_HDR); + skb_reset_transport_header(skb); + cxgbi_sock_skb_entail(csk, skb); + + extra_len = cxgbi_ulp_extra_len(cxgbi_skcb_tx_ulp_mode(skb)); + + if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO))) { + iso_cpl = (struct cxgbi_iso_info *)skb->head; + num_pdu = iso_cpl->num_pdu; + hdr_len = cxgbi_skcb_tx_iscsi_hdrlen(skb); + extra_len = (cxgbi_ulp_extra_len(cxgbi_skcb_tx_ulp_mode(skb)) * + num_pdu) + (hdr_len * (num_pdu - 1)); + } + + csk->write_seq += (skb->len + extra_len); + + return 0; +} + +static int cxgbi_sock_send_skb(struct cxgbi_sock *csk, struct sk_buff *skb) +{ + struct cxgbi_device *cdev = csk->cdev; + int len = skb->len; + int err; + + spin_lock_bh(&csk->lock); + err = cxgbi_sock_tx_queue_up(csk, skb); + if (err < 0) { + spin_unlock_bh(&csk->lock); + return err; + } + + if (likely(skb_queue_len(&csk->write_queue))) + cdev->csk_push_tx_frames(csk, 0); + spin_unlock_bh(&csk->lock); + return len; +} + int cxgbi_conn_xmit_pdu(struct iscsi_task *task) { struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data; struct cxgbi_conn *cconn = tcp_conn->dd_data; + struct iscsi_tcp_task *tcp_task = task->dd_data; struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task); struct cxgbi_task_tag_info *ttinfo = &tdata->ttinfo; - struct sk_buff *skb = tdata->skb; + struct sk_buff *skb; struct cxgbi_sock *csk = NULL; - unsigned int datalen; + u32 pdulen = 0; + u32 datalen; int err; + if (!tcp_task || (tcp_task->dd_data != tdata)) { + pr_err("task 0x%p,0x%p, tcp_task 0x%p, tdata 0x%p/0x%p.\n", + task, task->sc, tcp_task, + tcp_task ? tcp_task->dd_data : NULL, tdata); + return -EINVAL; + } + + skb = tdata->skb; if (!skb) { log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, - "task 0x%p\n", task); + "task 0x%p, skb NULL.\n", task); return 0; } if (cconn && cconn->cep) csk = cconn->cep->csk; + if (!csk) { log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, "task 0x%p, csk gone.\n", task); @@ -2101,13 +2411,12 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) if (!task->sc) memcpy(skb->data, task->hdr, SKB_TX_ISCSI_PDU_HEADER_MAX); - err = cxgbi_sock_send_pdus(cconn->cep->csk, skb); + err = cxgbi_sock_send_skb(csk, skb); if (err > 0) { - int pdulen = err; + pdulen += err; - log_debug(1 << CXGBI_DBG_PDU_TX, - "task 0x%p,0x%p, skb 0x%p, len %u/%u, rv %d.\n", - task, task->sc, skb, skb->len, skb->data_len, err); + log_debug(1 << CXGBI_DBG_PDU_TX, "task 0x%p,0x%p, rv %d.\n", + task, task->sc, err); if (task->conn->hdrdgst_en) pdulen += ISCSI_DIGEST_SIZE; @@ -2116,24 +2425,42 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) pdulen += ISCSI_DIGEST_SIZE; task->conn->txdata_octets += pdulen; + + if (unlikely(cxgbi_is_iso_config(csk) && cxgbi_is_iso_disabled(csk))) { + if (time_after(jiffies, csk->prev_iso_ts + HZ)) { + csk->disable_iso = false; + csk->prev_iso_ts = 0; + log_debug(1 << CXGBI_DBG_PDU_TX, + "enable iso: csk 0x%p\n", csk); + } + } + return 0; } if (err == -EAGAIN || err == -ENOBUFS) { log_debug(1 << CXGBI_DBG_PDU_TX, - "task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n", - task, skb, skb->len, skb->data_len, err); + "task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n", + task, skb, skb->len, skb->data_len, err); /* reset skb to send when we are called again */ tdata->skb = skb; + + if (cxgbi_is_iso_config(csk) && !cxgbi_is_iso_disabled(csk) && + (csk->no_tx_credits++ >= 2)) { + csk->disable_iso = true; + csk->prev_iso_ts = jiffies; + log_debug(1 << CXGBI_DBG_PDU_TX, + "disable iso:csk 0x%p, ts:%lu\n", + csk, csk->prev_iso_ts); + } + return err; } - log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, - "itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n", - task->itt, skb, skb->len, skb->data_len, err); - __kfree_skb(skb); - + log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, + "itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n", + task->itt, skb, skb->len, skb->data_len, err); iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err); iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED); return err; @@ -2145,7 +2472,7 @@ void cxgbi_cleanup_task(struct iscsi_task *task) struct iscsi_tcp_task *tcp_task = task->dd_data; struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task); - if (!tcp_task || !tdata || (tcp_task->dd_data != tdata)) { + if (!tcp_task || (tcp_task->dd_data != tdata)) { pr_info("task 0x%p,0x%p, tcp_task 0x%p, tdata 0x%p/0x%p.\n", task, task->sc, tcp_task, tcp_task ? tcp_task->dd_data : NULL, tdata); @@ -2749,12 +3076,17 @@ static int __init libcxgbi_init_module(void) BUILD_BUG_ON(sizeof_field(struct sk_buff, cb) < sizeof(struct cxgbi_skb_cb)); + rsvd_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!rsvd_page) + return -ENOMEM; + return 0; } static void __exit libcxgbi_exit_module(void) { cxgbi_device_unregister_all(0xFF); + put_page(rsvd_page); return; } diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 84b96af52655377fb8cf69f588e78b29e3ee5ca8..fc7255fefcd3bd71a0844b6f63c24b10434c382e 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -76,6 +76,14 @@ do { \ #define ULP2_MAX_PDU_PAYLOAD \ (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN) +#define CXGBI_ULP2_MAX_ISO_PAYLOAD 65535 + +#define CXGBI_MAX_ISO_DATA_IN_SKB \ + min_t(u32, MAX_SKB_FRAGS << PAGE_SHIFT, CXGBI_ULP2_MAX_ISO_PAYLOAD) + +#define cxgbi_is_iso_config(csk) ((csk)->cdev->skb_iso_txhdr) +#define cxgbi_is_iso_disabled(csk) ((csk)->disable_iso) + /* * For iscsi connections HW may inserts digest bytes into the pdu. Those digest * bytes are not sent by the host but are part of the TCP payload and therefore @@ -162,6 +170,10 @@ struct cxgbi_sock { u32 write_seq; u32 snd_win; u32 rcv_win; + + bool disable_iso; + u32 no_tx_credits; + unsigned long prev_iso_ts; }; /* @@ -203,6 +215,8 @@ struct cxgbi_skb_tx_cb { void *handle; void *arp_err_handler; struct sk_buff *wr_next; + u16 iscsi_hdr_len; + u8 ulp_mode; }; enum cxgbi_skcb_flags { @@ -218,6 +232,7 @@ enum cxgbi_skcb_flags { SKCBF_RX_HCRC_ERR, /* header digest error */ SKCBF_RX_DCRC_ERR, /* data digest error */ SKCBF_RX_PAD_ERR, /* padding byte error */ + SKCBF_TX_ISO, /* iso cpl in tx skb */ }; struct cxgbi_skb_cb { @@ -225,18 +240,18 @@ struct cxgbi_skb_cb { struct cxgbi_skb_rx_cb rx; struct cxgbi_skb_tx_cb tx; }; - unsigned char ulp_mode; unsigned long flags; unsigned int seq; }; #define CXGBI_SKB_CB(skb) ((struct cxgbi_skb_cb *)&((skb)->cb[0])) #define cxgbi_skcb_flags(skb) (CXGBI_SKB_CB(skb)->flags) -#define cxgbi_skcb_ulp_mode(skb) (CXGBI_SKB_CB(skb)->ulp_mode) #define cxgbi_skcb_tcp_seq(skb) (CXGBI_SKB_CB(skb)->seq) #define cxgbi_skcb_rx_ddigest(skb) (CXGBI_SKB_CB(skb)->rx.ddigest) #define cxgbi_skcb_rx_pdulen(skb) (CXGBI_SKB_CB(skb)->rx.pdulen) #define cxgbi_skcb_tx_wr_next(skb) (CXGBI_SKB_CB(skb)->tx.wr_next) +#define cxgbi_skcb_tx_iscsi_hdrlen(skb) (CXGBI_SKB_CB(skb)->tx.iscsi_hdr_len) +#define cxgbi_skcb_tx_ulp_mode(skb) (CXGBI_SKB_CB(skb)->tx.ulp_mode) static inline void cxgbi_skcb_set_flag(struct sk_buff *skb, enum cxgbi_skcb_flags flag) @@ -458,6 +473,7 @@ struct cxgbi_ports_map { #define CXGBI_FLAG_IPV4_SET 0x10 #define CXGBI_FLAG_USE_PPOD_OFLDQ 0x40 #define CXGBI_FLAG_DDP_OFF 0x100 +#define CXGBI_FLAG_DEV_ISO_OFF 0x400 struct cxgbi_device { struct list_head list_head; @@ -477,6 +493,7 @@ struct cxgbi_device { unsigned int pfvf; unsigned int rx_credit_thres; unsigned int skb_tx_rsvd; + u32 skb_iso_txhdr; unsigned int skb_rx_extra; /* for msg coalesced mode */ unsigned int tx_max_size; unsigned int rx_max_size; @@ -523,20 +540,41 @@ struct cxgbi_endpoint { struct cxgbi_sock *csk; }; -#define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512) struct cxgbi_task_data { +#define CXGBI_TASK_SGL_CHECKED 0x1 +#define CXGBI_TASK_SGL_COPY 0x2 + u8 flags; unsigned short nr_frags; - struct page_frag frags[MAX_PDU_FRAGS]; + struct page_frag frags[MAX_SKB_FRAGS]; struct sk_buff *skb; unsigned int dlen; unsigned int offset; unsigned int count; unsigned int sgoffset; + u32 total_count; + u32 total_offset; + u32 max_xmit_dlength; struct cxgbi_task_tag_info ttinfo; }; #define iscsi_task_cxgbi_data(task) \ ((task)->dd_data + sizeof(struct iscsi_tcp_task)) +struct cxgbi_iso_info { +#define CXGBI_ISO_INFO_FSLICE 0x1 +#define CXGBI_ISO_INFO_LSLICE 0x2 +#define CXGBI_ISO_INFO_IMM_ENABLE 0x4 + u8 flags; + u8 op; + u8 ahs; + u8 num_pdu; + u32 mpdu; + u32 burst_size; + u32 len; + u32 segment_offset; + u32 datasn_offset; + u32 buffer_offset; +}; + static inline void *cxgbi_alloc_big_mem(unsigned int size, gfp_t gfp) { diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 0497ef6a945353acf058cd92f9d0104ef1391e64..f654ad8a3d69c8431ef89a79131bda824b3446b5 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -1331,7 +1331,6 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) printk(KERN_ERR"IOP reset failed - no free memory.\n"); return -ENOMEM; } - memset(status,0,4); msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID; @@ -2784,7 +2783,6 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) pHba->name); return -ENOMEM; } - memset(status, 0, 4); writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]); writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]); @@ -2838,7 +2836,6 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name); return -ENOMEM; } - memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4); for(i = 0; i < pHba->reply_fifo_size; i++) { writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4), @@ -3073,7 +3070,6 @@ static int adpt_i2o_build_sys_table(void) printk(KERN_WARNING "SysTab Set failed. Out of memory.\n"); return -ENOMEM; } - memset(sys_tbl, 0, sys_tbl_len); sys_tbl->num_entries = hba_count; sys_tbl->version = I2OVERSION; diff --git a/drivers/scsi/esas2r/esas2r.h b/drivers/scsi/esas2r/esas2r.h index 7f43b95f4e945f04f168179f41210617c5ad52fc..e30d2f1f5368597e7351f6974e33ecd0fd01298e 100644 --- a/drivers/scsi/esas2r/esas2r.h +++ b/drivers/scsi/esas2r/esas2r.h @@ -1225,8 +1225,9 @@ static inline void esas2r_rq_init_request(struct esas2r_request *rq, /* req_table entry should be NULL at this point - if not, halt */ - if (a->req_table[LOWORD(vrq->scsi.handle)]) + if (a->req_table[LOWORD(vrq->scsi.handle)]) { esas2r_bugon(); + } /* fill in the table for this handle so we can get back to the * request. diff --git a/drivers/scsi/esas2r/esas2r_log.c b/drivers/scsi/esas2r/esas2r_log.c index 65fdf22b0ba9ad4af8a4d166955956d6f164dba3..b545798e400c492da78fecfa31372c5f7b7fa302 100644 --- a/drivers/scsi/esas2r/esas2r_log.c +++ b/drivers/scsi/esas2r/esas2r_log.c @@ -75,7 +75,7 @@ static char event_buffer[EVENT_LOG_BUFF_SIZE]; /* A lock to protect the shared buffer used for formatting messages. */ static DEFINE_SPINLOCK(event_buffer_lock); -/** +/* * translates an esas2r-defined logging event level to a kernel logging level. * * @param [in] level the esas2r-defined logging event level to translate @@ -101,7 +101,7 @@ static const char *translate_esas2r_event_level_to_kernel(const long level) } } -/** +/* * the master logging function. this function will format the message as * outlined by the formatting string, the input device information and the * substitution arguments and output the resulting string to the system log. @@ -170,7 +170,7 @@ static int esas2r_log_master(const long level, return 0; } -/** +/* * formats and logs a message to the system log. * * @param [in] level the event level of the message @@ -193,7 +193,7 @@ int esas2r_log(const long level, const char *format, ...) return retval; } -/** +/* * formats and logs a message to the system log. this message will include * device information. * @@ -221,7 +221,7 @@ int esas2r_log_dev(const long level, return retval; } -/** +/* * formats and logs a message to the system log. this message will include * device information. * diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index cb41d166e0c0feac42c6cdf98eed171f10f5d8c9..0f9274960dc6bbc32403eb2d3900165bef309da1 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -645,7 +645,7 @@ static int fcoe_lport_config(struct fc_lport *lport) return 0; } -/** +/* * fcoe_netdev_features_change - Updates the lport's offload flags based * on the LLD netdev's FCoE feature flags */ @@ -2029,7 +2029,7 @@ static int fcoe_ctlr_enabled(struct fcoe_ctlr_device *cdev) /** * fcoe_ctlr_mode() - Switch FIP mode - * @cdev: The FCoE Controller that is being modified + * @ctlr_dev: The FCoE Controller that is being modified * * When the FIP mode has been changed we need to update * the multicast addresses to ensure we get the correct @@ -2136,9 +2136,7 @@ static bool fcoe_match(struct net_device *netdev) /** * fcoe_dcb_create() - Initialize DCB attributes and hooks - * @netdev: The net_device object of the L2 link that should be queried - * @port: The fcoe_port to bind FCoE APP priority with - * @ + * @fcoe: The new FCoE interface */ static void fcoe_dcb_create(struct fcoe_interface *fcoe) { @@ -2609,7 +2607,7 @@ static void fcoe_logo_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) fc_lport_logo_resp(seq, fp, lport); } -/** +/* * fcoe_elsct_send - FCoE specific ELS handler * * This does special case handling of FIP encapsualted ELS exchanges for FCoE, diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 1791a393795daffec93ae58aefb23ee3b9131527..85c7959961cca6161c507ca43ee15662b24123e1 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -134,6 +134,7 @@ static void fcoe_ctlr_map_dest(struct fcoe_ctlr *fip) /** * fcoe_ctlr_init() - Initialize the FCoE Controller instance * @fip: The FCoE controller to initialize + * @mode: FIP mode to set */ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_mode mode) { @@ -336,7 +337,7 @@ static void fcoe_ctlr_announce(struct fcoe_ctlr *fip) printk(KERN_NOTICE "libfcoe: host%d: " "FIP Fibre-Channel Forwarder MAC %pM deselected\n", fip->lp->host->host_no, fip->dest_addr); - memset(fip->dest_addr, 0, ETH_ALEN); + eth_zero_addr(fip->dest_addr); } if (sel) { printk(KERN_INFO "libfcoe: host%d: FIP selected " @@ -587,6 +588,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, /** * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it * @fip: The FCoE controller for the ELS frame + * @lport: The local port * @dtype: The FIP descriptor type for the frame * @skb: The FCoE ELS frame including FC header but no FCoE headers * @d_id: The destination port ID. @@ -1302,7 +1304,7 @@ drop: /** * fcoe_ctlr_recv_els() - Handle an incoming link reset frame * @fip: The FCoE controller that received the frame - * @fh: The received FIP header + * @skb: The received FIP packet * * There may be multiple VN_Port descriptors. * The overall length has already been checked. @@ -1775,7 +1777,7 @@ unlock: /** * fcoe_ctlr_timeout() - FIP timeout handler - * @arg: The FCoE controller that timed out + * @t: Timer context use to obtain the controller reference */ static void fcoe_ctlr_timeout(struct timer_list *t) { @@ -1887,6 +1889,7 @@ static void fcoe_ctlr_recv_work(struct work_struct *recv_work) /** * fcoe_ctlr_recv_flogi() - Snoop pre-FIP receipt of FLOGI response * @fip: The FCoE controller + * @lport: The local port * @fp: The FC frame to snoop * * Snoop potential response to FLOGI or even incoming FLOGI. @@ -2158,7 +2161,7 @@ static struct fc_rport_operations fcoe_ctlr_vn_rport_ops = { /** * fcoe_ctlr_disc_stop_locked() - stop discovery in VN2VN mode - * @fip: The FCoE controller + * @lport: The local port * * Called with ctlr_mutex held. */ @@ -2179,7 +2182,7 @@ static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport) /** * fcoe_ctlr_disc_stop() - stop discovery in VN2VN mode - * @fip: The FCoE controller + * @lport: The local port * * Called through the local port template for discovery. * Called without the ctlr_mutex held. @@ -2195,7 +2198,7 @@ static void fcoe_ctlr_disc_stop(struct fc_lport *lport) /** * fcoe_ctlr_disc_stop_final() - stop discovery for shutdown in VN2VN mode - * @fip: The FCoE controller + * @lport: The local port * * Called through the local port template for discovery. * Called without the ctlr_mutex held. @@ -2262,7 +2265,7 @@ static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip) * fcoe_ctlr_vn_parse - parse probe request or response * @fip: The FCoE controller * @skb: incoming packet - * @rdata: buffer for resulting parsed VN entry plus fcoe_rport + * @frport: parsed FCoE rport from the probe request * * Returns non-zero error number on error. * Does not consume the packet. @@ -2793,7 +2796,7 @@ drop: * fcoe_ctlr_vlan_parse - parse vlan discovery request or response * @fip: The FCoE controller * @skb: incoming packet - * @rdata: buffer for resulting parsed VLAN entry plus fcoe_rport + * @frport: parsed FCoE rport from the probe request * * Returns non-zero error number on error. * Does not consume the packet. @@ -2892,7 +2895,6 @@ len_err: * @fip: The FCoE controller * @sub: sub-opcode for vlan notification or vn2vn vlan notification * @dest: The destination Ethernet MAC address - * @min_len: minimum size of the Ethernet payload to be sent */ static void fcoe_ctlr_vlan_send(struct fcoe_ctlr *fip, enum fip_vlan_subcode sub, @@ -2969,9 +2971,8 @@ static void fcoe_ctlr_vlan_disc_reply(struct fcoe_ctlr *fip, /** * fcoe_ctlr_vlan_recv - vlan request receive handler for VN2VN mode. - * @lport: The local port - * @fp: The received frame - * + * @fip: The FCoE controller + * @skb: The received FIP packet */ static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) { @@ -3015,9 +3016,8 @@ static void fcoe_ctlr_disc_recv(struct fc_lport *lport, struct fc_frame *fp) fc_frame_free(fp); } -/** - * fcoe_ctlr_disc_recv - start discovery for VN2VN mode. - * @fip: The FCoE controller +/* + * fcoe_ctlr_disc_start - start discovery for VN2VN mode. * * This sets a flag indicating that remote ports should be created * and started for the peers we discover. We use the disc_callback diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index a20ddc301c89e76dc0569118c1d06294b84f3940..6e187d0e71fd2e69f85e003cbd005513e20bcd56 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -382,6 +382,7 @@ EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); /** * fcoe_check_wait_queue() - Attempt to clear the transmit backlog * @lport: The local port whose backlog is to be cleared + * @skb: The received FIP packet * * This empties the wait_queue, dequeues the head of the wait_queue queue * and calls fcoe_start_io() for each packet. If all skb have been @@ -439,7 +440,7 @@ EXPORT_SYMBOL_GPL(fcoe_check_wait_queue); /** * fcoe_queue_timer() - The fcoe queue timer - * @lport: The local port + * @t: Timer context use to obtain the FCoE port * * Calls fcoe_check_wait_queue on timeout */ @@ -672,6 +673,7 @@ static void fcoe_del_netdev_mapping(struct net_device *netdev) /** * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which * it was created + * @netdev: The net device that the FCoE interface is on * * Returns : ptr to the fcoe transport that supports this netdev or NULL * if not found. diff --git a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h index 6f63fc6b0d12720325793cc451a6dedc5b85df01..93afcee207aed2198e6689dff5d15aa57958c43b 100644 --- a/drivers/scsi/fdomain.h +++ b/drivers/scsi/fdomain.h @@ -103,7 +103,7 @@ enum { #define REG_FIFO_COUNT 14 /* R: FIFO Data Count */ #ifdef CONFIG_PM_SLEEP -static const struct dev_pm_ops fdomain_pm_ops; +static const struct dev_pm_ops __maybe_unused fdomain_pm_ops; #define FDOMAIN_PM_OPS (&fdomain_pm_ops) #else #define FDOMAIN_PM_OPS NULL diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 27535c90b24830f2a1f54585e925eb8abf67384d..03b1805b106c6558b07b5efa32aaad7590a4d6f6 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -275,7 +276,7 @@ int fnic_flogi_reg_handler(struct fnic *fnic, u32 fc_id) } if (fnic->ctlr.map_dest) { - memset(gw_mac, 0xff, ETH_ALEN); + eth_broadcast_addr(gw_mac); format = FCPIO_FLOGI_REG_DEF_DEST; } else { memcpy(gw_mac, fnic->ctlr.dest_addr, ETH_ALEN); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 09a7669dad4c67ba671ed768e39e5c18f661d50a..7922a9bb1b28167b7d00a0bfefc6787a02ada621 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1258,8 +1258,10 @@ static void slot_complete_v1_hw(struct hisi_hba *hisi_hba, !(cmplt_hdr_data & CMPLT_HDR_RSPNS_XFRD_MSK)) { slot_err_v1_hw(hisi_hba, task, slot); - if (unlikely(slot->abort)) + if (unlikely(slot->abort)) { + sas_task_abort(task); return; + } goto out; } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 968d3870235359a74ed9e67c3605fb8ce52d7b94..043f47ba3600265592b6d297305d20f846f1fbee 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2404,8 +2404,10 @@ static void slot_complete_v2_hw(struct hisi_hba *hisi_hba, error_info[0], error_info[1], error_info[2], error_info[3]); - if (unlikely(slot->abort)) + if (unlikely(slot->abort)) { + sas_task_abort(task); return; + } goto out; } @@ -3300,7 +3302,7 @@ static irq_handler_t fatal_interrupts[HISI_SAS_FATAL_INT_NR] = { fatal_axi_int_v2_hw }; -/** +/* * There is a limitation in the hip06 chipset that we need * to map in all mbigen interrupts, even if they are not used. */ diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 55e2321a65bc5ff628e0c93b1dc986ca16358164..60adf5c32143d2c373821857dd0edbe0bc589a72 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2235,8 +2235,10 @@ static void slot_complete_v3_hw(struct hisi_hba *hisi_hba, dw0, dw1, complete_hdr->act, dw3, error_info[0], error_info[1], error_info[2], error_info[3]); - if (unlikely(slot->abort)) + if (unlikely(slot->abort)) { + sas_task_abort(task); return; + } goto out; } diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 7ec91c3a66cad33d179b2854a4ab7decd4ab899d..37d1c5565d90fa46a4f747c4203e54e77be48bbb 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -272,8 +272,10 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, if (shost->transportt->create_work_queue) { snprintf(shost->work_q_name, sizeof(shost->work_q_name), "scsi_wq_%d", shost->host_no); - shost->work_q = create_singlethread_workqueue( - shost->work_q_name); + shost->work_q = alloc_workqueue("%s", + WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND, + 1, shost->work_q_name); + if (!shost->work_q) { error = -EINVAL; goto out_free_shost_data; @@ -487,7 +489,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) } shost->tmf_work_q = alloc_workqueue("scsi_tmf_%d", - WQ_UNBOUND | WQ_MEM_RECLAIM, + WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 1, shost->host_no); if (!shost->tmf_work_q) { shost_printk(KERN_WARNING, shost, diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 81d0414e21175bb88a969eaa514ea373512f9017..91794a50b31fe541eb39f788cbebd4ddbaaa6a3c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -59,7 +59,7 @@ * HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' * with an optional trailing '-' followed by a byte value (0-255). */ -#define HPSA_DRIVER_VERSION "3.4.20-170" +#define HPSA_DRIVER_VERSION "3.4.20-200" #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")" #define HPSA "hpsa" @@ -2134,6 +2134,7 @@ static int hpsa_slave_alloc(struct scsi_device *sdev) } /* configure scsi device based on internal per-device structure */ +#define CTLR_TIMEOUT (120 * HZ) static int hpsa_slave_configure(struct scsi_device *sdev) { struct hpsa_scsi_dev_t *sd; @@ -2144,17 +2145,21 @@ static int hpsa_slave_configure(struct scsi_device *sdev) if (sd) { sd->was_removed = 0; + queue_depth = sd->queue_depth != 0 ? + sd->queue_depth : sdev->host->can_queue; if (sd->external) { queue_depth = EXTERNAL_QD; sdev->eh_timeout = HPSA_EH_PTRAID_TIMEOUT; blk_queue_rq_timeout(sdev->request_queue, HPSA_EH_PTRAID_TIMEOUT); - } else { - queue_depth = sd->queue_depth != 0 ? - sd->queue_depth : sdev->host->can_queue; } - } else + if (is_hba_lunid(sd->scsi3addr)) { + sdev->eh_timeout = CTLR_TIMEOUT; + blk_queue_rq_timeout(sdev->request_queue, CTLR_TIMEOUT); + } + } else { queue_depth = sdev->host->can_queue; + } scsi_change_queue_depth(sdev, queue_depth); @@ -3443,9 +3448,14 @@ static void hpsa_get_enclosure_info(struct ctlr_info *h, struct ErrorInfo *ei = NULL; struct bmic_sense_storage_box_params *bssbp = NULL; struct bmic_identify_physical_device *id_phys = NULL; - struct ext_report_lun_entry *rle = &rlep->LUN[rle_index]; + struct ext_report_lun_entry *rle; u16 bmic_device_index = 0; + if (rle_index < 0 || rle_index >= HPSA_MAX_PHYS_LUN) + return; + + rle = &rlep->LUN[rle_index]; + encl_dev->eli = hpsa_get_enclosure_logical_identifier(h, scsi3addr); @@ -4174,6 +4184,9 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, int rc; struct ext_report_lun_entry *rle; + if (rle_index < 0 || rle_index >= HPSA_MAX_PHYS_LUN) + return; + rle = &rlep->LUN[rle_index]; dev->ioaccel_handle = rle->ioaccel_handle; @@ -4198,7 +4211,12 @@ static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device, struct ReportExtendedLUNdata *rlep, int rle_index, struct bmic_identify_physical_device *id_phys) { - struct ext_report_lun_entry *rle = &rlep->LUN[rle_index]; + struct ext_report_lun_entry *rle; + + if (rle_index < 0 || rle_index >= HPSA_MAX_PHYS_LUN) + return; + + rle = &rlep->LUN[rle_index]; if ((rle->device_flags & 0x08) && this_device->ioaccel_handle) this_device->hba_ioaccel_enabled = 1; @@ -4420,7 +4438,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) /* * Skip over some devices such as a spare. */ - if (!tmpdevice->external && physical_device) { + if (phys_dev_index >= 0 && !tmpdevice->external && + physical_device) { skip_device = hpsa_skip_device(h, lunaddrbytes, &physdev_list->LUN[phys_dev_index]); if (skip_device) diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index f8c88fc7b80a050039b44e5690cbf91805b040c0..6b87d9815b358866bcb8001c2bcefbdf4d42f175 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -57,7 +57,7 @@ struct hpsa_sas_phy { bool added_to_port; }; -#define EXTERNAL_QD 7 +#define EXTERNAL_QD 128 struct hpsa_scsi_dev_t { unsigned int devtype; int bus, target, lun; /* as presented to the OS */ diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 635f6f9cffc4029173af9c2a07a3021cfb1521d3..77f4d37d5bd625b88c8e2ea9c5827851c0e57cba 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1344,7 +1344,7 @@ static void ibmvfc_map_sg_list(struct scsi_cmnd *scmd, int nseg, } /** - * ibmvfc_map_sg_data - Maps dma for a scatterlist and initializes decriptor fields + * ibmvfc_map_sg_data - Maps dma for a scatterlist and initializes descriptor fields * @scmd: struct scsi_cmnd with the scatterlist * @evt: ibmvfc event struct * @vfc_cmd: vfc_cmd that contains the memory descriptor diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 14f687e9b1f44e7a16189ce6ab91f33e92038cd6..b1f3017b6547a47dee952c333db1bf18404b62ce 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -669,7 +669,7 @@ static int map_sg_list(struct scsi_cmnd *cmd, int nseg, } /** - * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields + * map_sg_data: - Maps dma for a scatterlist and initializes descriptor fields * @cmd: struct scsi_cmnd with the scatterlist * @srp_cmd: srp_cmd that contains the memory descriptor * @dev: device for which to map dma memory diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 2519fb7aee51299fbea2a15086e20e74c878be25..1459b1467027994f1121de7c95c2d4f8b2782765 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -903,7 +903,6 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *cmd) w_ctr(ppb, 0x4); } return 0; /* Finished */ - break; default: printk("imm: Invalid scsi phase\n"); @@ -969,10 +968,8 @@ static int imm_abort(struct scsi_cmnd *cmd) case 1: /* Have not connected to interface */ dev->cur_cmd = NULL; /* Forget the problem */ return SUCCESS; - break; default: /* SCSI command sent, can not abort */ return FAILED; - break; } } diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 7d86f4ca266c86bd419c0118537fad551e8a6374..b0aa58d117cc95547d0c3f38c0cc546bf690e2db 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -670,6 +670,7 @@ static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd) /** * ipr_init_ipr_cmnd - Initialize an IPR Cmnd block * @ipr_cmd: ipr command struct + * @fast_done: fast done function call-back * * Return value: * none @@ -687,7 +688,7 @@ static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd, /** * __ipr_get_free_ipr_cmnd - Get a free IPR Cmnd block - * @ioa_cfg: ioa config struct + * @hrrq: hrr queue * * Return value: * pointer to ipr command struct @@ -737,7 +738,6 @@ struct ipr_cmnd *ipr_get_free_ipr_cmnd(struct ipr_ioa_cfg *ioa_cfg) static void ipr_mask_and_clear_interrupts(struct ipr_ioa_cfg *ioa_cfg, u32 clr_ints) { - volatile u32 int_reg; int i; /* Stop new interrupts */ @@ -757,7 +757,7 @@ static void ipr_mask_and_clear_interrupts(struct ipr_ioa_cfg *ioa_cfg, if (ioa_cfg->sis64) writel(~0, ioa_cfg->regs.clr_interrupt_reg); writel(clr_ints, ioa_cfg->regs.clr_interrupt_reg32); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); + readl(ioa_cfg->regs.sense_interrupt_reg); } /** @@ -1287,7 +1287,7 @@ static int ipr_is_same_device(struct ipr_resource_entry *res, /** * __ipr_format_res_path - Format the resource path for printing. * @res_path: resource path - * @buf: buffer + * @buffer: buffer * @len: length of buffer provided * * Return value: @@ -1310,7 +1310,7 @@ static char *__ipr_format_res_path(u8 *res_path, char *buffer, int len) * ipr_format_res_path - Format the resource path for printing. * @ioa_cfg: ioa config struct * @res_path: resource path - * @buf: buffer + * @buffer: buffer * @len: length of buffer provided * * Return value: @@ -1391,7 +1391,6 @@ static void ipr_update_res_entry(struct ipr_resource_entry *res, * ipr_clear_res_target - Clear the bit in the bit map representing the target * for the resource. * @res: resource entry struct - * @cfgtew: config table entry wrapper struct * * Return value: * none @@ -2667,7 +2666,7 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) /** * ipr_timeout - An internally generated op has timed out. - * @ipr_cmd: ipr command struct + * @t: Timer context used to fetch ipr command struct * * This function blocks host requests and initiates an * adapter reset. @@ -2700,7 +2699,7 @@ static void ipr_timeout(struct timer_list *t) /** * ipr_oper_timeout - Adapter timed out transitioning to operational - * @ipr_cmd: ipr command struct + * @t: Timer context used to fetch ipr command struct * * This function blocks host requests and initiates an * adapter reset. @@ -3484,6 +3483,7 @@ static struct bin_attribute ipr_trace_attr = { /** * ipr_show_fw_version - Show the firmware version * @dev: class device struct + * @attr: device attribute (unused) * @buf: buffer * * Return value: @@ -3518,6 +3518,7 @@ static struct device_attribute ipr_fw_version_attr = { /** * ipr_show_log_level - Show the adapter's error logging level * @dev: class device struct + * @attr: device attribute (unused) * @buf: buffer * * Return value: @@ -3540,7 +3541,9 @@ static ssize_t ipr_show_log_level(struct device *dev, /** * ipr_store_log_level - Change the adapter's error logging level * @dev: class device struct + * @attr: device attribute (unused) * @buf: buffer + * @count: buffer size * * Return value: * number of bytes printed to buffer @@ -3571,6 +3574,7 @@ static struct device_attribute ipr_log_level_attr = { /** * ipr_store_diagnostics - IOA Diagnostics interface * @dev: device struct + * @attr: device attribute (unused) * @buf: buffer * @count: buffer size * @@ -3631,7 +3635,8 @@ static struct device_attribute ipr_diagnostics_attr = { /** * ipr_show_adapter_state - Show the adapter's state - * @class_dev: device struct + * @dev: device struct + * @attr: device attribute (unused) * @buf: buffer * * Return value: @@ -3657,6 +3662,7 @@ static ssize_t ipr_show_adapter_state(struct device *dev, /** * ipr_store_adapter_state - Change adapter state * @dev: device struct + * @attr: device attribute (unused) * @buf: buffer * @count: buffer size * @@ -3708,6 +3714,7 @@ static struct device_attribute ipr_ioa_state_attr = { /** * ipr_store_reset_adapter - Reset the adapter * @dev: device struct + * @attr: device attribute (unused) * @buf: buffer * @count: buffer size * @@ -3749,6 +3756,7 @@ static int ipr_iopoll(struct irq_poll *iop, int budget); /** * ipr_show_iopoll_weight - Show ipr polling mode * @dev: class device struct + * @attr: device attribute (unused) * @buf: buffer * * Return value: @@ -3772,7 +3780,9 @@ static ssize_t ipr_show_iopoll_weight(struct device *dev, /** * ipr_store_iopoll_weight - Change the adapter's polling mode * @dev: class device struct + * @attr: device attribute (unused) * @buf: buffer + * @count: buffer size * * Return value: * number of bytes printed to buffer @@ -3871,7 +3881,7 @@ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len) /** * ipr_free_ucode_buffer - Frees a microcode download buffer - * @p_dnld: scatter/gather list pointer + * @sglist: scatter/gather list pointer * * Free a DMA'able ucode download buffer previously allocated with * ipr_alloc_ucode_buffer @@ -4059,7 +4069,8 @@ static int ipr_update_ioa_ucode(struct ipr_ioa_cfg *ioa_cfg, /** * ipr_store_update_fw - Update the firmware on the adapter - * @class_dev: device struct + * @dev: device struct + * @attr: device attribute (unused) * @buf: buffer * @count: buffer size * @@ -4139,6 +4150,7 @@ static struct device_attribute ipr_update_fw_attr = { /** * ipr_show_fw_type - Show the adapter's firmware type. * @dev: class device struct + * @attr: device attribute (unused) * @buf: buffer * * Return value: @@ -4480,7 +4492,6 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; }; * ipr_change_queue_depth - Change the device's queue depth * @sdev: scsi device struct * @qdepth: depth to set - * @reason: calling context * * Return value: * actual depth set @@ -4650,6 +4661,7 @@ static struct device_attribute ipr_resource_type_attr = { /** * ipr_show_raw_mode - Show the adapter's raw mode * @dev: class device struct + * @attr: device attribute (unused) * @buf: buffer * * Return value: @@ -4677,7 +4689,9 @@ static ssize_t ipr_show_raw_mode(struct device *dev, /** * ipr_store_raw_mode - Change the adapter's raw mode * @dev: class device struct + * @attr: device attribute (unused) * @buf: buffer + * @count: buffer size * * Return value: * number of bytes printed to buffer @@ -5060,7 +5074,7 @@ static int ipr_match_lun(struct ipr_cmnd *ipr_cmd, void *device) /** * ipr_cmnd_is_free - Check if a command is free or not - * @ipr_cmd ipr command struct + * @ipr_cmd: ipr command struct * * Returns: * true / false @@ -5096,7 +5110,7 @@ static int ipr_match_res(struct ipr_cmnd *ipr_cmd, void *resource) /** * ipr_wait_for_ops - Wait for matching commands to complete - * @ipr_cmd: ipr command struct + * @ioa_cfg: ioa config struct * @device: device to match (sdev) * @match: match function to use * @@ -5261,6 +5275,7 @@ static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg, * ipr_sata_reset - Reset the SATA port * @link: SATA link to reset * @classes: class of the attached device + * @deadline: unused * * This function issues a SATA phy reset to the affected ATA link. * @@ -5440,7 +5455,7 @@ static void ipr_bus_reset_done(struct ipr_cmnd *ipr_cmd) /** * ipr_abort_timeout - An abort task has timed out - * @ipr_cmd: ipr command struct + * @t: Timer context used to fetch ipr command struct * * This function handles when an abort task times out. If this * happens we issue a bus reset since we have resources tied @@ -5494,7 +5509,7 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd) struct ipr_ioa_cfg *ioa_cfg; struct ipr_resource_entry *res; struct ipr_cmd_pkt *cmd_pkt; - u32 ioasc, int_reg; + u32 ioasc; int i, op_found = 0; struct ipr_hrr_queue *hrrq; @@ -5517,7 +5532,7 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd) * by a still not detected EEH error. In such cases, reading a register will * trigger the EEH recovery infrastructure. */ - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); + readl(ioa_cfg->regs.sense_interrupt_reg); if (!ipr_is_gscsi(res)) return FAILED; @@ -5569,7 +5584,8 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd) /** * ipr_eh_abort - Abort a single op - * @scsi_cmd: scsi command struct + * @shost: scsi host struct + * @elapsed_time: elapsed time * * Return value: * 0 if scan in progress / 1 if scan is complete @@ -5696,6 +5712,7 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, * ipr_isr_eh - Interrupt service routine error handler * @ioa_cfg: ioa config struct * @msg: message to log + * @number: various meanings depending on the caller/message * * Return value: * none @@ -5762,7 +5779,6 @@ static int ipr_process_hrrq(struct ipr_hrr_queue *hrr_queue, int budget, static int ipr_iopoll(struct irq_poll *iop, int budget) { - struct ipr_ioa_cfg *ioa_cfg; struct ipr_hrr_queue *hrrq; struct ipr_cmnd *ipr_cmd, *temp; unsigned long hrrq_flags; @@ -5770,7 +5786,6 @@ static int ipr_iopoll(struct irq_poll *iop, int budget) LIST_HEAD(doneq); hrrq = container_of(iop, struct ipr_hrr_queue, iopoll); - ioa_cfg = hrrq->ioa_cfg; spin_lock_irqsave(hrrq->lock, hrrq_flags); completed_ops = ipr_process_hrrq(hrrq, budget, &doneq); @@ -6268,8 +6283,7 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, /** * ipr_gen_sense - Generate SCSI sense data from an IOASA - * @ioasa: IOASA - * @sense_buf: sense data buffer + * @ipr_cmd: ipr command struct * * Return value: * none @@ -6702,7 +6716,7 @@ static int ipr_ioctl(struct scsi_device *sdev, unsigned int cmd, /** * ipr_info - Get information about the card/driver - * @scsi_host: scsi host struct + * @host: scsi host struct * * Return value: * pointer to buffer with description string @@ -7592,7 +7606,7 @@ static int ipr_ioafp_mode_select_page28(struct ipr_cmnd *ipr_cmd) /** * ipr_build_mode_sense - Builds a mode sense command * @ipr_cmd: ipr command struct - * @res: resource entry struct + * @res_handle: resource entry struct * @parm: Byte 2 of mode sense command * @dma_addr: DMA address of mode sense buffer * @xfer_len: Size of DMA buffer @@ -7939,6 +7953,7 @@ static void ipr_build_ioa_service_action(struct ipr_cmnd *ipr_cmd, /** * ipr_ioafp_set_caching_parameters - Issue Set Cache parameters service * action + * @ipr_cmd: ipr command struct * * Return value: * none @@ -7975,6 +7990,10 @@ static int ipr_ioafp_set_caching_parameters(struct ipr_cmnd *ipr_cmd) /** * ipr_ioafp_inquiry - Send an Inquiry to the adapter. * @ipr_cmd: ipr command struct + * @flags: flags to send + * @page: page to inquire + * @dma_addr: DMA address + * @xfer_len: transfer data length * * This utility function sends an inquiry to the adapter. * @@ -8265,7 +8284,7 @@ static int ipr_ioafp_identify_hrrq(struct ipr_cmnd *ipr_cmd) /** * ipr_reset_timer_done - Adapter reset timer function - * @ipr_cmd: ipr command struct + * @t: Timer context used to fetch ipr command struct * * Description: This function is used in adapter reset processing * for timing events. If the reset_cmd pointer in the IOA @@ -8659,7 +8678,6 @@ static int ipr_dump_mailbox_wait(struct ipr_cmnd *ipr_cmd) static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - u32 int_reg; ENTER; ioa_cfg->pdev->state_saved = true; @@ -8675,7 +8693,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) if (ioa_cfg->sis64) { /* Set the adapter to the correct endian mode. */ writel(IPR_ENDIAN_SWAP_KEY, ioa_cfg->regs.endian_swap_reg); - int_reg = readl(ioa_cfg->regs.endian_swap_reg); + readl(ioa_cfg->regs.endian_swap_reg); } if (ioa_cfg->ioa_unit_checked) { @@ -9483,7 +9501,6 @@ static pci_ers_result_t ipr_pci_error_detected(struct pci_dev *pdev, * Description: This is the second phase of adapter initialization * This function takes care of initilizing the adapter to the point * where it can accept new commands. - * Return value: * 0 on success / -EIO on failure **/ @@ -9597,7 +9614,7 @@ static void ipr_free_irqs(struct ipr_ioa_cfg *ioa_cfg) /** * ipr_free_all_resources - Free all allocated resources for an adapter. - * @ipr_cmd: ipr command struct + * @ioa_cfg: ioa config struct * * This function frees all allocated resources for the * specified adapter. @@ -10059,7 +10076,8 @@ static int ipr_request_other_msi_irqs(struct ipr_ioa_cfg *ioa_cfg, /** * ipr_test_intr - Handle the interrupt generated in ipr_test_msi(). - * @pdev: PCI device struct + * @devp: PCI device struct + * @irq: IRQ number * * Description: Simply set the msi_received flag to 1 indicating that * Message Signaled Interrupts are supported. @@ -10085,6 +10103,7 @@ static irqreturn_t ipr_test_intr(int irq, void *devp) /** * ipr_test_msi - Test for Message Signaled Interrupt (MSI) support. + * @ioa_cfg: ioa config struct * @pdev: PCI device struct * * Description: This routine sets up and initiates a test interrupt to determine @@ -10097,7 +10116,6 @@ static irqreturn_t ipr_test_intr(int irq, void *devp) static int ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, struct pci_dev *pdev) { int rc; - volatile u32 int_reg; unsigned long lock_flags = 0; int irq = pci_irq_vector(pdev, 0); @@ -10108,7 +10126,7 @@ static int ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, struct pci_dev *pdev) ioa_cfg->msi_received = 0; ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER); writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.clr_interrupt_mask_reg32); - int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); + readl(ioa_cfg->regs.sense_interrupt_mask_reg); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); rc = request_irq(irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg); @@ -10119,7 +10137,7 @@ static int ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, struct pci_dev *pdev) dev_info(&pdev->dev, "IRQ assigned: %d\n", irq); writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.sense_interrupt_reg32); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); + readl(ioa_cfg->regs.sense_interrupt_reg); wait_event_timeout(ioa_cfg->msi_wait_q, ioa_cfg->msi_received, HZ); spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER); @@ -10530,6 +10548,8 @@ static void ipr_remove(struct pci_dev *pdev) /** * ipr_probe - Adapter hot plug add entry point + * @pdev: pci device struct + * @dev_id: pci device ID * * Return value: * 0 on success / non-zero on failure @@ -10786,6 +10806,7 @@ static struct pci_driver ipr_driver = { /** * ipr_halt_done - Shutdown prepare completion + * @ipr_cmd: ipr command struct * * Return value: * none @@ -10797,6 +10818,9 @@ static void ipr_halt_done(struct ipr_cmnd *ipr_cmd) /** * ipr_halt - Issue shutdown prepare to all adapters + * @nb: Notifier block + * @event: Notifier event + * @buf: Notifier data (unused) * * Return value: * NOTIFY_OK on success / NOTIFY_DONE on failure diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 9a0d3d729320655bbf593791b8f25ecdb6908b3e..783ee03ad9ea296525a82a457f30c8cc3cc4d40f 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1684,7 +1684,7 @@ struct ipr_dump_entry_header { struct ipr_dump_location_entry { struct ipr_dump_entry_header hdr; u8 location[20]; -}__attribute__((packed)); +}__attribute__((packed, aligned (4))); struct ipr_dump_trace_entry { struct ipr_dump_entry_header hdr; @@ -1708,7 +1708,7 @@ struct ipr_driver_dump { struct ipr_dump_location_entry location_entry; struct ipr_dump_ioa_type_entry ioa_type_entry; struct ipr_dump_trace_entry trace_entry; -}__attribute__((packed)); +}__attribute__((packed, aligned (4))); struct ipr_ioa_dump { struct ipr_dump_entry_header hdr; diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index f25672982c5f32a9563f6786d087718f445a320e..2e6077c502fc71316bbd75b1e8e927fc33f4a59c 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -2239,7 +2239,7 @@ ips_get_bios_version(ips_ha_t * ha, int intr) major = 0; minor = 0; - strncpy(ha->bios_version, " ?", 8); + memcpy(ha->bios_version, " ?", 8); if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD) { if (IPS_USE_MEMIO(ha)) { @@ -3515,11 +3515,11 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb) inquiry.Flags[1] = IPS_SCSI_INQ_WBus16 | IPS_SCSI_INQ_Sync; - strncpy(inquiry.VendorId, "IBM ", + memcpy(inquiry.VendorId, "IBM ", 8); - strncpy(inquiry.ProductId, + memcpy(inquiry.ProductId, "SERVERAID ", 16); - strncpy(inquiry.ProductRevisionLevel, + memcpy(inquiry.ProductRevisionLevel, "1.00", 4); ips_scmd_buf_write(scb->scsi_cmd, @@ -4036,9 +4036,9 @@ ips_inquiry(ips_ha_t * ha, ips_scb_t * scb) inquiry.Flags[0] = IPS_SCSI_INQ_Address16; inquiry.Flags[1] = IPS_SCSI_INQ_WBus16 | IPS_SCSI_INQ_Sync | IPS_SCSI_INQ_CmdQue; - strncpy(inquiry.VendorId, "IBM ", 8); - strncpy(inquiry.ProductId, "SERVERAID ", 16); - strncpy(inquiry.ProductRevisionLevel, "1.00", 4); + memcpy(inquiry.VendorId, "IBM ", 8); + memcpy(inquiry.ProductId, "SERVERAID ", 16); + memcpy(inquiry.ProductRevisionLevel, "1.00", 4); ips_scmd_buf_write(scb->scsi_cmd, &inquiry, sizeof (inquiry)); @@ -4697,7 +4697,6 @@ ips_init_copperhead(ips_ha_t * ha) uint8_t Isr; uint8_t Cbsp; uint8_t PostByte[IPS_MAX_POST_BYTES]; - uint8_t ConfigByte[IPS_MAX_CONFIG_BYTES]; int i, j; METHOD_TRACE("ips_init_copperhead", 1); @@ -4742,7 +4741,7 @@ ips_init_copperhead(ips_ha_t * ha) /* error occurred */ return (0); - ConfigByte[i] = inb(ha->io_addr + IPS_REG_ISPR); + inb(ha->io_addr + IPS_REG_ISPR); outb(Isr, ha->io_addr + IPS_REG_HISR); } @@ -4791,7 +4790,6 @@ ips_init_copperhead_memio(ips_ha_t * ha) uint8_t Isr = 0; uint8_t Cbsp; uint8_t PostByte[IPS_MAX_POST_BYTES]; - uint8_t ConfigByte[IPS_MAX_CONFIG_BYTES]; int i, j; METHOD_TRACE("ips_init_copperhead_memio", 1); @@ -4836,7 +4834,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) /* error occurred */ return (0); - ConfigByte[i] = readb(ha->mem_ptr + IPS_REG_ISPR); + readb(ha->mem_ptr + IPS_REG_ISPR); writeb(Isr, ha->mem_ptr + IPS_REG_HISR); } @@ -5622,10 +5620,10 @@ ips_write_driver_status(ips_ha_t * ha, int intr) /* change values (as needed) */ ha->nvram->operating_system = IPS_OS_LINUX; ha->nvram->adapter_type = ha->ad_type; - strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4); - strncpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4); - strncpy((char *) ha->nvram->bios_high, ha->bios_version, 4); - strncpy((char *) ha->nvram->bios_low, ha->bios_version + 4, 4); + memcpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4); + memcpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4); + memcpy((char *) ha->nvram->bios_high, ha->bios_version, 4); + memcpy((char *) ha->nvram->bios_low, ha->bios_version + 4, 4); ha->nvram->versioning = 0; /* Indicate the Driver Does Not Support Versioning */ @@ -6835,8 +6833,6 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr) uint32_t mem_addr; uint32_t io_len; uint32_t mem_len; - uint8_t bus; - uint8_t func; int j; int index; dma_addr_t dma_address; @@ -6856,10 +6852,6 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr) if (index >= IPS_MAX_ADAPTERS) return -1; - /* stuff that we get in dev */ - bus = pci_dev->bus->number; - func = pci_dev->devfn; - /* Init MEM/IO addresses to 0 */ mem_addr = 0; io_addr = 0; diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 343d24c7e788b8926c60318d4ad160f9ec5aba56..6561a07db18992686757adf8cfdfd6629f7d00fa 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -3444,7 +3444,7 @@ struct isci_request *isci_tmf_request_from_tag(struct isci_host *ihost, int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, struct sas_task *task, u16 tag) { - enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; + enum sci_status status; struct isci_request *ireq; unsigned long flags; int ret = 0; diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 2b865c6423e293b6e3b4a04cac83a5a4923d0e72..19721db2328390c2d5294958ac851dbf4ca94c2f 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -337,7 +337,7 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp) /** * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request - * @lport: The discovery context + * @disc: The discovery context */ static void fc_disc_gpn_ft_req(struct fc_disc *disc) { @@ -370,7 +370,7 @@ err: /** * fc_disc_gpn_ft_parse() - Parse the body of the dNS GPN_FT response. - * @lport: The local port the GPN_FT was received on + * @disc: The discovery context * @buf: The GPN_FT response buffer * @len: The size of response buffer * @@ -488,7 +488,7 @@ static void fc_disc_timeout(struct work_struct *work) * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT) * @sp: The sequence that the GPN_FT response was received on * @fp: The GPN_FT response frame - * @lp_arg: The discovery context + * @disc_arg: The discovery context * * Locking Note: This function is called without disc mutex held, and * should do all its processing with the mutex held diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 52e86665985314571878ae22b3964f2bf8e14bd7..16eb3b60ed5825ae9253cd97436c3f345553b752 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -49,6 +49,8 @@ static struct workqueue_struct *fc_exch_workqueue; * @total_exches: Total allocated exchanges * @lock: Exch pool lock * @ex_list: List of exchanges + * @left: Cache of free slot in exch array + * @right: Cache of free slot in exch array * * This structure manages per cpu exchanges in array of exchange pointers. * This array is allocated followed by struct fc_exch_pool memory for @@ -60,7 +62,6 @@ struct fc_exch_pool { u16 next_index; u16 total_exches; - /* two cache of free slot in exch array */ u16 left; u16 right; } ____cacheline_aligned_in_smp; @@ -74,6 +75,7 @@ struct fc_exch_pool { * @ep_pool: Reserved exchange pointers * @pool_max_index: Max exch array index in exch pool * @pool: Per cpu exch pool + * @lport: Local exchange port * @stats: Statistics structure * * This structure is the center for creating exchanges and sequences. @@ -702,6 +704,9 @@ int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec) /** * fc_invoke_resp() - invoke ep->resp() + * @ep: The exchange to be operated on + * @fp: The frame pointer to pass through to ->resp() + * @sp: The sequence pointer to pass through to ->resp() * * Notes: * It is assumed that after initialization finished (this means the diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index bf2cc9656e1911ac9603d83b245ae48656c4b8e2..e11d4f002bd493dc7f78d0782f330e4f6113c0ec 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -289,6 +289,7 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) /** * fc_fcp_retry_cmd() - Retry a fcp_pkt * @fsp: The FCP packet to be retried + * @status_code: The FCP status code to set * * Sets the status code to be FC_ERROR and then calls * fc_fcp_complete_locked() which in turn calls fc_io_compl(). @@ -580,7 +581,7 @@ err: /** * fc_fcp_send_data() - Send SCSI data to a target * @fsp: The FCP packet the data is on - * @sp: The sequence the data is to be sent on + * @seq: The sequence the data is to be sent on * @offset: The starting offset for this data request * @seq_blen: The burst length for this data request * @@ -1283,7 +1284,7 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp) /** * fc_lun_reset_send() - Send LUN reset command - * @data: The FCP packet that identifies the LUN to be reset + * @t: Timer context used to fetch the FSP packet */ static void fc_lun_reset_send(struct timer_list *t) { @@ -1409,7 +1410,7 @@ static void fc_fcp_cleanup(struct fc_lport *lport) /** * fc_fcp_timeout() - Handler for fcp_pkt timeouts - * @data: The FCP packet that has timed out + * @t: Timer context used to fetch the FSP packet * * If REC is supported then just issue it and return. The REC exchange will * complete or time out and recovery can continue at that point. Otherwise, @@ -1691,6 +1692,7 @@ out: /** * fc_fcp_recovery() - Handler for fcp_pkt recovery * @fsp: The FCP pkt that needs to be aborted + * @code: The FCP status code to set */ static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code) { @@ -1709,6 +1711,7 @@ static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code) * fc_fcp_srr() - Send a SRR request (Sequence Retransmission Request) * @fsp: The FCP packet the SRR is to be sent on * @r_ctl: The R_CTL field for the SRR request + * @offset: The SRR relative offset * This is called after receiving status but insufficient data, or * when expecting status but the request has timed out. */ @@ -1851,7 +1854,7 @@ static inline int fc_fcp_lport_queue_ready(struct fc_lport *lport) /** * fc_queuecommand() - The queuecommand function of the SCSI template * @shost: The Scsi_Host that the command was issued to - * @cmd: The scsi_cmnd to be executed + * @sc_cmd: The scsi_cmnd to be executed * * This is the i/o strategy routine, called by the SCSI layer. */ diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 684c5e361a286d60b85c8385a5822e259952e7f3..b84dbc316df1513473b91b5fc682bbebc0ae2567 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -405,7 +405,7 @@ static void fc_lport_recv_rlir_req(struct fc_lport *lport, struct fc_frame *fp) /** * fc_lport_recv_echo_req() - Handle received ECHO request * @lport: The local port receiving the ECHO - * @fp: ECHO request frame + * @in_fp: ECHO request frame */ static void fc_lport_recv_echo_req(struct fc_lport *lport, struct fc_frame *in_fp) @@ -440,7 +440,7 @@ static void fc_lport_recv_echo_req(struct fc_lport *lport, /** * fc_lport_recv_rnid_req() - Handle received Request Node ID data request * @lport: The local port receiving the RNID - * @fp: The RNID request frame + * @in_fp: The RNID request frame */ static void fc_lport_recv_rnid_req(struct fc_lport *lport, struct fc_frame *in_fp) @@ -1325,6 +1325,7 @@ static void fc_lport_enter_scr(struct fc_lport *lport) /** * fc_lport_enter_ns() - register some object with the name server * @lport: Fibre Channel local port to register + * @state: Local port state */ static void fc_lport_enter_ns(struct fc_lport *lport, enum fc_lport_state state) { @@ -1423,6 +1424,7 @@ err: /** * fc_lport_enter_ms() - management server commands * @lport: Fibre Channel local port to register + * @state: Local port state */ static void fc_lport_enter_ms(struct fc_lport *lport, enum fc_lport_state state) { @@ -1932,6 +1934,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, * @job: The BSG Passthrough job * @lport: The local port sending the request * @did: The destination port id + * @tov: The timeout period (in ms) */ static int fc_lport_els_request(struct bsg_job *job, struct fc_lport *lport, diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 278d15ff1c5ae26d948741c788852718de7672e2..18663a82865f99d746a2c61fb4d2a19e2e5db8e3 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -121,7 +121,7 @@ EXPORT_SYMBOL(fc_rport_lookup); /** * fc_rport_create() - Create a new remote port * @lport: The local port this remote port will be associated with - * @ids: The identifiers for the new remote port + * @port_id: The identifiers for the new remote port * * The remote port will start in the INIT state. */ @@ -1445,7 +1445,7 @@ drop: * fc_rport_logo_resp() - Handler for logout (LOGO) responses * @sp: The sequence the LOGO was on * @fp: The LOGO response frame - * @lport_arg: The local port + * @rdata_arg: The remote port */ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, void *rdata_arg) diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 5d716d38870718df5f5ea877a01e9cf577dd0ed7..1b93332daa6b38a206ced8e0393f3292ec0e7449 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -507,10 +507,23 @@ void sas_ata_end_eh(struct ata_port *ap) spin_unlock_irqrestore(&ha->lock, flags); } +static int sas_ata_prereset(struct ata_link *link, unsigned long deadline) +{ + struct ata_port *ap = link->ap; + struct domain_device *dev = ap->private_data; + struct sas_phy *local_phy = sas_get_local_phy(dev); + int res = 0; + + if (!local_phy->enabled || test_bit(SAS_DEV_GONE, &dev->state)) + res = -ENOENT; + sas_put_local_phy(local_phy); + + return res; +} + static struct ata_port_operations sas_sata_ops = { - .prereset = ata_std_prereset, + .prereset = sas_ata_prereset, .hardreset = sas_ata_hard_reset, - .postreset = ata_std_postreset, .error_handler = ata_std_error_handler, .post_internal_cmd = sas_ata_post_internal, .qc_defer = ata_std_qc_defer, diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index ab671cdd4cfb090c3797f6d18b8b2d4278e2c11d..b7d1b1ea185d773998aee67024abc054ec97da58 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -427,7 +427,7 @@ out_err: static int sas_expander_discover(struct domain_device *dev) { struct expander_device *ex = &dev->ex_dev; - int res = -ENOMEM; + int res; ex->ex_phy = kcalloc(ex->num_phys, sizeof(*ex->ex_phy), GFP_KERNEL); if (!ex->ex_phy) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index c3ceb6e5b061632adcf3f913ea1add28325cc02c..549adfaa97ce5a599eb61145cf5255e112ac8dc6 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -627,6 +627,14 @@ struct lpfc_ras_fwlog { enum ras_state state; /* RAS logging running state */ }; +#define DBG_LOG_STR_SZ 256 +#define DBG_LOG_SZ 256 + +struct dbg_log_ent { + char log[DBG_LOG_STR_SZ]; + u64 t_ns; +}; + enum lpfc_irq_chann_mode { /* Assign IRQs to all possible cpus that have hardware queues */ NORMAL_MODE, @@ -709,6 +717,9 @@ struct lpfc_hba { struct workqueue_struct *wq; struct delayed_work eq_delay_work; +#define LPFC_IDLE_STAT_DELAY 1000 + struct delayed_work idle_stat_delay_work; + struct lpfc_sli sli; uint8_t pci_dev_grp; /* lpfc PCI dev group: 0x0, 0x1, 0x2,... */ uint32_t sli_rev; /* SLI2, SLI3, or SLI4 */ @@ -1237,6 +1248,10 @@ struct lpfc_hba { struct scsi_host_template port_template; /* SCSI host template information - for all vports */ struct scsi_host_template vport_template; + atomic_t dbg_log_idx; + atomic_t dbg_log_cnt; + atomic_t dbg_log_dmping; + struct dbg_log_ent dbg_log[DBG_LOG_SZ]; }; static inline struct Scsi_Host * diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 0ea03ae93d91d7bcedb7870be83d711217b9a082..1d88fedaf3f051ac00622c5aacad62699b724200 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -2404,33 +2404,27 @@ lpfc_sli4_bsg_link_diag_test(struct bsg_job *job) union lpfc_sli4_cfg_shdr *shdr; uint32_t shdr_status, shdr_add_status; struct diag_status *diag_status_reply; - int mbxstatus, rc = 0; + int mbxstatus, rc = -ENODEV, rc1 = 0; shost = fc_bsg_to_shost(job); - if (!shost) { - rc = -ENODEV; + if (!shost) goto job_error; - } + vport = shost_priv(shost); - if (!vport) { - rc = -ENODEV; + if (!vport) goto job_error; - } + phba = vport->phba; - if (!phba) { - rc = -ENODEV; + if (!phba) goto job_error; - } - if (phba->sli_rev < LPFC_SLI_REV4) { - rc = -ENODEV; + + if (phba->sli_rev < LPFC_SLI_REV4) goto job_error; - } + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) < - LPFC_SLI_INTF_IF_TYPE_2) { - rc = -ENODEV; + LPFC_SLI_INTF_IF_TYPE_2) goto job_error; - } if (job->request_len < sizeof(struct fc_bsg_request) + sizeof(struct sli4_link_diag)) { @@ -2465,8 +2459,10 @@ lpfc_sli4_bsg_link_diag_test(struct bsg_job *job) alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE, LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE, req_len, LPFC_SLI4_MBX_EMBED); - if (alloc_len != req_len) + if (alloc_len != req_len) { + rc = -ENOMEM; goto link_diag_test_exit; + } run_link_diag_test = &pmboxq->u.mqe.un.link_diag_test; bf_set(lpfc_mbx_run_diag_test_link_num, &run_link_diag_test->u.req, @@ -2515,7 +2511,7 @@ lpfc_sli4_bsg_link_diag_test(struct bsg_job *job) diag_status_reply->shdr_add_status = shdr_add_status; link_diag_test_exit: - rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0); + rc1 = lpfc_sli4_bsg_set_link_diag_state(phba, 0); if (pmboxq) mempool_free(pmboxq, phba->mbox_mem_pool); @@ -2524,6 +2520,8 @@ link_diag_test_exit: job_error: /* make error code available to userspace */ + if (rc1 && !rc) + rc = rc1; bsg_reply->result = rc; /* complete the job back to userspace if no error */ if (rc == 0) @@ -4306,6 +4304,7 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct bsg_job *job, case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES: case COMN_OPCODE_GET_CNTL_ATTRIBUTES: case COMN_OPCODE_GET_PROFILE_CONFIG: + case COMN_OPCODE_SET_FEATURES: lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, "3106 Handled SLI_CONFIG " "subsys_comn, opcode:x%x\n", diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h index d1708133fd548a8e8f4205f2a58b1cc64afeed76..2dc71243775de4071d000f46a732527a11e7c685 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.h +++ b/drivers/scsi/lpfc/lpfc_bsg.h @@ -225,6 +225,10 @@ struct lpfc_sli_config_hdr { uint32_t reserved5; }; +#define LPFC_CSF_BOOT_DEV 0x1D +#define LPFC_CSF_QUERY 0 +#define LPFC_CSF_SAVE 1 + struct lpfc_sli_config_emb0_subsys { struct lpfc_sli_config_hdr sli_config_hdr; #define LPFC_MBX_SLI_CONFIG_MAX_MSE 19 @@ -243,6 +247,15 @@ struct lpfc_sli_config_emb0_subsys { #define FCOE_OPCODE_ADD_FCF 0x09 #define FCOE_OPCODE_SET_DPORT_MODE 0x27 #define FCOE_OPCODE_GET_DPORT_RESULTS 0x28 + uint32_t timeout; /* comn_set_feature timeout */ + uint32_t request_length; /* comn_set_feature request len */ + uint32_t version; /* comn_set_feature version */ + uint32_t csf_feature; /* comn_set_feature feature */ + uint32_t word69; /* comn_set_feature parameter len */ + uint32_t word70; /* comn_set_feature parameter val0 */ +#define lpfc_emb0_subcmnd_csf_p0_SHIFT 0 +#define lpfc_emb0_subcmnd_csf_p0_MASK 0x3 +#define lpfc_emb0_subcmnd_csf_p0_WORD word70 }; struct lpfc_sli_config_emb1_subsys { @@ -261,6 +274,7 @@ struct lpfc_sli_config_emb1_subsys { #define COMN_OPCODE_WRITE_OBJECT 0xAC #define COMN_OPCODE_READ_OBJECT_LIST 0xAD #define COMN_OPCODE_DELETE_OBJECT 0xAE +#define COMN_OPCODE_SET_FEATURES 0xBF #define COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES 0x79 #define COMN_OPCODE_GET_CNTL_ATTRIBUTES 0x20 uint32_t timeout; diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 9ee6b930a655ff0052ce3dc067769d89a57ef7a2..782f6f76f18aaf43570fece27014ac1e38366663 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -386,7 +386,7 @@ void lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp); int lpfc_link_reset(struct lpfc_vport *vport); /* Function prototypes. */ -int lpfc_check_pci_resettable(const struct lpfc_hba *phba); +int lpfc_check_pci_resettable(struct lpfc_hba *phba); const char* lpfc_info(struct Scsi_Host *); int lpfc_scan_finished(struct Scsi_Host *, unsigned long); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 69d4710d95a0498e7de576b9c00bcd58399c8a9c..dd9f2bf54edd4ba212ebe31132074c0c23353700 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -300,7 +300,7 @@ lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb) return 0; } -/** +/* * lpfc_gen_req - Build and issue a GEN_REQUEST command to the SLI Layer * @vport: pointer to a host virtual N_Port data structure. * @bmp: Pointer to BPL for SLI command @@ -394,7 +394,7 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, return 0; } -/** +/* * lpfc_ct_cmd - Build and issue a CT command * @vport: pointer to a host virtual N_Port data structure. * @inmp: Pointer to data buffer for response data. @@ -750,7 +750,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (vport->fc_flag & FC_RSCN_MODE) lpfc_els_flush_rscn(vport); lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0257 GID_FT Query error: 0x%x 0x%x\n", irsp->ulpStatus, vport->fc_ns_retry); } else { @@ -811,7 +811,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } else { /* NameServer Rsp Error */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0241 NameServer Rsp Error " "Data: x%x x%x x%x x%x\n", CTrsp->CommandResponse.bits.CmdRsp, @@ -951,7 +951,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (vport->fc_flag & FC_RSCN_MODE) lpfc_els_flush_rscn(vport); lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "4103 GID_FT Query error: 0x%x 0x%x\n", irsp->ulpStatus, vport->fc_ns_retry); } else { @@ -1012,7 +1012,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } } else { /* NameServer Rsp Error */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "4109 NameServer Rsp Error " "Data: x%x x%x x%x x%x\n", CTrsp->CommandResponse.bits.CmdRsp, @@ -1143,7 +1143,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } } } - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0267 NameServer GFF Rsp " "x%x Error (%d %d) Data: x%x x%x\n", did, irsp->ulpStatus, irsp->un.ulpWord[4], @@ -1271,7 +1271,7 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } } } else - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "3065 GFT_ID failed x%08x\n", irsp->ulpStatus); lpfc_ct_free_iocb(phba, cmdiocb); @@ -1320,7 +1320,7 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode); if (irsp->ulpStatus) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0268 NS cmd x%x Error (x%x x%x)\n", cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4]); @@ -1843,7 +1843,7 @@ ns_cmd_free_mpvirt: ns_cmd_free_mp: kfree(mp); ns_cmd_exit: - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0266 Issue NameServer Req x%x err %d Data: x%x x%x\n", cmdcode, rc, vport->fc_flag, vport->fc_rscn_id_cnt); return 1; @@ -3019,8 +3019,8 @@ int (*lpfc_fdmi_port_action[]) * lpfc_fdmi_cmd - Build and send a FDMI cmd to the specified NPort * @vport: pointer to a host virtual N_Port data structure. * @ndlp: ndlp to send FDMI cmd to (if NULL use FDMI_DID) - * cmdcode: FDMI command to send - * mask: Mask of HBA or PORT Attributes to send + * @cmdcode: FDMI command to send + * @new_mask: Mask of HBA or PORT Attributes to send * * Builds and sends a FDMI command using the CT subsystem. */ @@ -3262,7 +3262,7 @@ fdmi_cmd_exit: /** * lpfc_delayed_disc_tmo - Timeout handler for delayed discovery timer. - * @ptr - Context object of the timer. + * @t: Context object of the timer. * * This function set the WORKER_DELAYED_DISC_TMO flag and wake up * the worker thread. diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 3d670568a2760a96c56dca241cebe34cc0f9080e..85d4e4000c25f2e8dd16c624800a0be3cde03786 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -100,7 +100,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) return 0; /* Pending Link Event during Discovery */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0237 Pending Link Event during " "Discovery: State x%x\n", phba->pport->port_state); @@ -440,8 +440,9 @@ fail_free_mbox: fail: lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, - "0249 Cannot issue Register Fabric login: Err %d\n", err); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "0249 Cannot issue Register Fabric login: Err %d\n", + err); return -ENXIO; } @@ -524,8 +525,8 @@ fail: } lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, - "0289 Issue Register VFI failed: Err %d\n", rc); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "0289 Issue Register VFI failed: Err %d\n", rc); return rc; } @@ -550,7 +551,7 @@ lpfc_issue_unreg_vfi(struct lpfc_vport *vport) mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2556 UNREG_VFI mbox allocation failed" "HBA state x%x\n", phba->pport->port_state); return -ENOMEM; @@ -562,7 +563,7 @@ lpfc_issue_unreg_vfi(struct lpfc_vport *vport) rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2557 UNREG_VFI issue mbox failed rc x%x " "HBA state x%x\n", rc, phba->pport->port_state); @@ -1041,18 +1042,18 @@ stop_rr_fcf_flogi: if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT && ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == IOERR_LOOP_OPEN_FAILURE))) - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, - "2858 FLOGI failure Status:x%x/x%x " - "TMO:x%x Data x%x x%x\n", - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout, phba->hba_flag, - phba->fcf.fcf_flag); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "2858 FLOGI failure Status:x%x/x%x TMO" + ":x%x Data x%x x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout, phba->hba_flag, + phba->fcf.fcf_flag); /* Check for retry */ if (lpfc_els_retry(phba, cmdiocb, rspiocb)) goto out; - lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, + lpfc_printf_vlog(vport, KERN_WARNING, LOG_TRACE_EVENT, "0150 FLOGI failure Status:x%x/x%x " "xri x%x TMO:x%x\n", irsp->ulpStatus, irsp->un.ulpWord[4], @@ -1132,8 +1133,7 @@ stop_rr_fcf_flogi: else if (!(phba->hba_flag & HBA_FCOE_MODE)) rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp); else { - lpfc_printf_vlog(vport, KERN_ERR, - LOG_FIP | LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2831 FLOGI response with cleared Fabric " "bit fcf_index 0x%x " "Switch Name %02x%02x%02x%02x%02x%02x%02x%02x " @@ -1934,7 +1934,7 @@ lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || ndlp != rrq->ndlp) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2882 RRQ completes to NPort x%x " "with no ndlp. Data: x%x x%x x%x\n", irsp->un.elsreq64.remoteID, @@ -1957,10 +1957,11 @@ lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, (((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) && ((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) || (phba)->pport->cfg_log_verbose & LOG_ELS) - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, - "2881 RRQ failure DID:%06X Status:x%x/x%x\n", - ndlp->nlp_DID, irsp->ulpStatus, - irsp->un.ulpWord[4]); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "2881 RRQ failure DID:%06X Status:" + "x%x/x%x\n", + ndlp->nlp_DID, irsp->ulpStatus, + irsp->un.ulpWord[4]); } out: if (rrq) @@ -2010,7 +2011,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0136 PLOGI completes to NPort x%x " "with no ndlp. Data: x%x x%x x%x\n", irsp->un.elsreq64.remoteID, @@ -2059,7 +2060,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, (((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) && ((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) || (phba)->pport->cfg_log_verbose & LOG_ELS) - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2753 PLOGI failure DID:%06X Status:x%x/x%x\n", ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4]); @@ -2237,6 +2238,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, IOCB_t *irsp; struct lpfc_nodelist *ndlp; char *mode; + u32 loglevel; /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; @@ -2278,13 +2280,16 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * could be expected. */ if ((vport->fc_flag & FC_FABRIC) || - (vport->cfg_enable_fc4_type != LPFC_ENABLE_BOTH)) + (vport->cfg_enable_fc4_type != LPFC_ENABLE_BOTH)) { mode = KERN_ERR; - else + loglevel = LOG_TRACE_EVENT; + } else { mode = KERN_INFO; + loglevel = LOG_ELS; + } /* PRLI failed */ - lpfc_printf_vlog(vport, mode, LOG_ELS, + lpfc_printf_vlog(vport, mode, loglevel, "2754 PRLI failure DID:%06X Status:x%x/x%x, " "data: x%x\n", ndlp->nlp_DID, irsp->ulpStatus, @@ -2695,7 +2700,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto out; } /* ADISC failed */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2755 ADISC failure DID:%06X Status:x%x/x%x\n", ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4]); @@ -2853,7 +2858,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, */ if (irsp->ulpStatus) { /* LOGO failed */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2756 LOGO failure, No Retry DID:%06X Status:x%x/x%x\n", ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4]); @@ -3597,7 +3602,7 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) /** * lpfc_els_retry_delay - Timer function with a ndlp delayed function timer - * @ptr: holder for the pointer to the timer function associated data (ndlp). + * @t: pointer to the timer function associated data (ndlp). * * This routine is invoked by the ndlp delayed-function timer to check * whether there is any pending ELS retry event(s) with the node. If not, it @@ -3734,7 +3739,7 @@ lpfc_link_reset(struct lpfc_vport *vport) "2851 Attempt link reset\n"); mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2852 Failed to allocate mbox memory"); return 1; } @@ -3756,7 +3761,7 @@ lpfc_link_reset(struct lpfc_vport *vport) mbox->vport = vport; rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2853 Failed to issue INIT_LINK " "mbox command, rc:x%x\n", rc); mempool_free(mbox, phba->mbox_mem_pool); @@ -3860,7 +3865,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, break; case IOERR_ILLEGAL_COMMAND: - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0124 Retry illegal cmd x%x " "retry:x%x delay:x%x\n", cmd, cmdiocb->retry, delay); @@ -3970,7 +3975,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && (cmd == ELS_CMD_FDISC) && (stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){ - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0125 FDISC Failed (x%x). " "Fabric out of resources\n", stat.un.lsRjtError); @@ -4009,7 +4015,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, LSEXP_NOTHING_MORE) { vport->fc_sparam.cmn.bbRcvSizeMsb &= 0xf; retry = 1; - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0820 FLOGI Failed (x%x). " "BBCredit Not Supported\n", stat.un.lsRjtError); @@ -4022,7 +4029,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ((stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_PNAME) || (stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID)) ) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0122 FDISC Failed (x%x). " "Fabric Detected Bad WWN\n", stat.un.lsRjtError); @@ -4200,7 +4208,7 @@ out_retry: } /* No retry ELS command to remote NPORT */ if (logerr) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0137 No retry ELS command x%x to remote " "NPORT x%x: Out of Resources: Error:x%x/%x\n", cmd, did, irsp->ulpStatus, @@ -4499,7 +4507,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp = &rspiocb->iocb; if (!vport) { - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3177 ELS response failed\n"); goto out; } @@ -4605,7 +4613,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; /* ELS rsp: Cannot issue reg_login for */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0138 ELS rsp: Cannot issue reg_login for x%x " "Data: x%x x%x x%x\n", ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, @@ -4843,7 +4851,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, /** * lpfc_els_rsp_reject - Propare and issue a rjt response iocb command * @vport: pointer to a virtual N_Port data structure. - * @rejectError: + * @rejectError: reject response to issue * @oldiocb: pointer to the original lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. * @mbox: pointer to the driver internal queue element for mailbox command. @@ -6411,8 +6419,8 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lcb_context->rx_id = cmdiocb->iocb.ulpContext; lcb_context->ndlp = lpfc_nlp_get(ndlp); if (lpfc_sli4_set_beacon(vport, lcb_context, state)) { - lpfc_printf_vlog(ndlp->vport, KERN_ERR, - LOG_ELS, "0193 failed to send mail box"); + lpfc_printf_vlog(ndlp->vport, KERN_ERR, LOG_TRACE_EVENT, + "0193 failed to send mail box"); kfree(lcb_context); lpfc_nlp_put(ndlp); rjt_err = LSRJT_UNABLE_TPC; @@ -6621,7 +6629,7 @@ lpfc_send_rscn_event(struct lpfc_vport *vport, rscn_event_data = kmalloc(sizeof(struct lpfc_rscn_event_header) + payload_len, GFP_KERNEL); if (!rscn_event_data) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0147 Failed to allocate memory for RSCN event\n"); return; } @@ -6998,7 +7006,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, /* An FLOGI ELS command was received from DID in Loop Mode */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0113 An FLOGI ELS command x%x was " "received from DID x%x in Loop Mode\n", cmd, did); @@ -7879,7 +7887,7 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, /** * lpfc_els_timeout - Handler funciton to the els timer - * @ptr: holder for the timer function associated data. + * @t: timer context used to obtain the vport. * * This routine is invoked by the ELS timer after timeout. It posts the ELS * timer timeout event by setting the WORKER_ELS_TMO bit to the work port @@ -7988,7 +7996,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { cmd = &piocb->iocb; - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0127 ELS timeout Data: x%x x%x x%x " "x%x\n", els_command, remote_ID, cmd->ulpCommand, cmd->ulpIoTag); @@ -8098,7 +8106,7 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) spin_unlock_irqrestore(&phba->hbalock, iflags); } if (!list_empty(&abort_list)) - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "3387 abort list for txq not empty\n"); INIT_LIST_HEAD(&abort_list); @@ -8252,7 +8260,7 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba, * lpfc_send_els_event - Posts unsolicited els event * @vport: Pointer to vport object. * @ndlp: Pointer FC node object. - * @cmd: ELS command code. + * @payload: ELS command code type. * * This function posts an event when there is an incoming * unsolicited ELS command. @@ -8269,7 +8277,7 @@ lpfc_send_els_event(struct lpfc_vport *vport, if (*payload == ELS_CMD_LOGO) { logo_data = kmalloc(sizeof(struct lpfc_logo_event), GFP_KERNEL); if (!logo_data) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0148 Failed to allocate memory " "for LOGO event\n"); return; @@ -8279,7 +8287,7 @@ lpfc_send_els_event(struct lpfc_vport *vport, els_data = kmalloc(sizeof(struct lpfc_els_event_header), GFP_KERNEL); if (!els_data) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0149 Failed to allocate memory " "for ELS event\n"); return; @@ -8337,7 +8345,7 @@ DECLARE_ENUM2STR_LOOKUP(lpfc_get_fpin_li_event_nm, fc_fpin_li_event_types, /** * lpfc_els_rcv_fpin_li - Process an FPIN Link Integrity Event. * @vport: Pointer to vport object. - * @lnk_not: Pointer to the Link Integrity Notification Descriptor. + * @tlv: Pointer to the Link Integrity Notification Descriptor. * * This function processes a link integrity FPIN event by * logging a message @@ -8396,7 +8404,7 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, struct fc_els_fpin *fpin, break; default: dtag_nm = lpfc_get_tlv_dtag_nm(dtag); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "4678 skipped FPIN descriptor[%d]: " "tag x%x (%s)\n", desc_cnt, dtag, dtag_nm); @@ -8811,7 +8819,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, rjt_exp = LSEXP_NOTHING_MORE; /* Unknown ELS command received from NPORT */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0115 Unknown ELS command x%x " "received from NPORT x%x\n", cmd, did); if (newnode) @@ -8856,7 +8864,7 @@ lsrjt: dropit: if (vport && !(vport->load_flag & FC_UNLOADING)) - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0111 Dropping received ELS cmd " "Data: x%x x%x x%x\n", icmd->ulpStatus, icmd->un.ulpWord[4], icmd->ulpTimeout); @@ -9006,7 +9014,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) spin_lock_irq(shost->host_lock); if (vport->fc_flag & FC_DISC_DELAYED) { spin_unlock_irq(shost->host_lock); - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3334 Delay fc port discovery for %d seconds\n", phba->fc_ratov); mod_timer(&vport->delayed_disc_tmo, @@ -9024,7 +9032,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) return; } lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0251 NameServer login: no memory\n"); return; } @@ -9036,7 +9044,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) return; } lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0348 NameServer login: node freed\n"); return; } @@ -9047,7 +9055,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) if (lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0)) { lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0252 Cannot issue NameServer login\n"); return; } @@ -9084,7 +9092,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) spin_unlock_irq(shost->host_lock); if (mb->mbxStatus) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0915 Register VPI failed : Status: x%x" " upd bit: x%x \n", mb->mbxStatus, mb->un.varRegVpi.upd); @@ -9114,8 +9122,8 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - lpfc_printf_vlog(vport, - KERN_ERR, LOG_MBOX, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "2732 Failed to issue INIT_VPI" " mailbox command\n"); } else { @@ -9203,12 +9211,12 @@ lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, lpfc_nlp_put(ndlp); mempool_free(mbox, phba->mbox_mem_pool); - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0253 Register VPI: Can't send mbox\n"); goto mbox_err_exit; } } else { - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0254 Register VPI: no memory\n"); goto mbox_err_exit; } @@ -9370,7 +9378,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (lpfc_els_retry(phba, cmdiocb, rspiocb)) goto out; /* FDISC failed */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0126 FDISC failed. (x%x/x%x)\n", irsp->ulpStatus, irsp->un.ulpWord[4]); goto fdisc_failed; @@ -9492,7 +9500,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ELS_CMD_FDISC); if (!elsiocb) { lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0255 Issue FDISC: no IOCB\n"); return 1; } @@ -9546,7 +9554,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0256 Issue FDISC: Cannot send IOCB\n"); return 1; } @@ -9666,7 +9674,7 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) /** * lpfc_fabric_block_timeout - Handler function to the fabric block timer - * @ptr: holder for the timer function associated data. + * @t: timer context used to obtain the lpfc hba. * * This routine is invoked by the fabric iocb block timer after * timeout. It posts the fabric iocb block timeout event by setting the @@ -10127,8 +10135,7 @@ lpfc_sli_abts_recover_port(struct lpfc_vport *vport, "rport in state 0x%x\n", ndlp->nlp_state); return; } - lpfc_printf_log(phba, KERN_ERR, - LOG_ELS | LOG_FCP_ERROR | LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3094 Start rport recovery on shost id 0x%x " "fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x " "flags 0x%x\n", diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 4084f7f2b82162041a25ac2a83bef13c0fd74717..142a021144793c555242f5f37d58f508f9661ddd 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -155,17 +155,17 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) return; if (rport->port_name != wwn_to_u64(ndlp->nlp_portname.u.wwn)) - lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, - "6789 rport name %llx != node port name %llx", - rport->port_name, - wwn_to_u64(ndlp->nlp_portname.u.wwn)); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "6789 rport name %llx != node port name %llx", + rport->port_name, + wwn_to_u64(ndlp->nlp_portname.u.wwn)); evtp = &ndlp->dev_loss_evt; if (!list_empty(&evtp->evt_listp)) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, - "6790 rport name %llx dev_loss_evt pending", - rport->port_name); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "6790 rport name %llx dev_loss_evt pending", + rport->port_name); return; } @@ -295,7 +295,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) } if (warn_on) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0203 Devloss timeout on " "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x " "NPort x%06x Data: x%x x%x x%x\n", @@ -304,7 +304,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); } else { - lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_INFO, LOG_TRACE_EVENT, "0204 Devloss timeout on " "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x " "NPort x%06x Data: x%x x%x x%x\n", @@ -755,7 +755,7 @@ lpfc_do_work(void *p) || kthread_should_stop())); /* Signal wakeup shall terminate the worker thread */ if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0433 Wakeup on signal: rc=x%x\n", rc); break; } @@ -1092,7 +1092,7 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* Check for error */ if ((mb->mbxStatus) && (mb->mbxStatus != 0x1601)) { /* CLEAR_LA mbox error state */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0320 CLEAR_LA mbxStatus error x%x hba " "state x%x\n", mb->mbxStatus, vport->port_state); @@ -1180,7 +1180,7 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) return; out: - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0306 CONFIG_LINK mbxStatus error x%x " "HBA state x%x\n", pmb->u.mb.mbxStatus, vport->port_state); @@ -1188,7 +1188,7 @@ out: lpfc_linkdown(phba); - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0200 CONFIG_LINK bad hba state x%x\n", vport->port_state); @@ -1198,7 +1198,7 @@ out: /** * lpfc_sli4_clear_fcf_rr_bmask - * @phba pointer to the struct lpfc_hba for this port. + * @phba: pointer to the struct lpfc_hba for this port. * This fucnction resets the round robin bit mask and clears the * fcf priority list. The list deletions are done while holding the * hbalock. The ON_LIST flag and the FLOGI_FAILED flags are cleared @@ -1224,10 +1224,10 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) struct lpfc_vport *vport = mboxq->vport; if (mboxq->u.mb.mbxStatus) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, - "2017 REG_FCFI mbxStatus error x%x " - "HBA state x%x\n", - mboxq->u.mb.mbxStatus, vport->port_state); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "2017 REG_FCFI mbxStatus error x%x " + "HBA state x%x\n", mboxq->u.mb.mbxStatus, + vport->port_state); goto fail_out; } @@ -1297,7 +1297,7 @@ lpfc_fab_name_match(uint8_t *fab_name, struct fcf_record *new_fcf_record) /** * lpfc_sw_name_match - Check if the fcf switch name match. - * @fab_name: pointer to fabric name. + * @sw_name: pointer to switch name. * @new_fcf_record: pointer to fcf record. * * This routine compare the fcf record's switch name with provided @@ -1385,7 +1385,7 @@ __lpfc_update_fcf_record_pri(struct lpfc_hba *phba, uint16_t fcf_index, /** * lpfc_copy_fcf_record - Copy fcf information to lpfc_hba. - * @fcf: pointer to driver fcf record. + * @fcf_rec: pointer to driver fcf record. * @new_fcf_record: pointer to fcf record. * * This routine copies the FCF information from the FCF @@ -1848,7 +1848,7 @@ lpfc_sli4_fcf_rec_mbox_parse(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, */ lpfc_sli4_mbx_sge_get(mboxq, 0, &sge); if (unlikely(!mboxq->sge_array)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2524 Failed to get the non-embedded SGE " "virtual address\n"); return NULL; @@ -1864,11 +1864,12 @@ lpfc_sli4_fcf_rec_mbox_parse(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, if (shdr_status || shdr_add_status) { if (shdr_status == STATUS_FCF_TABLE_EMPTY || if_type == LPFC_SLI_INTF_IF_TYPE_2) - lpfc_printf_log(phba, KERN_ERR, LOG_FIP, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "2726 READ_FCF_RECORD Indicates empty " "FCF table.\n"); else - lpfc_printf_log(phba, KERN_ERR, LOG_FIP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2521 READ_FCF_RECORD mailbox failed " "with status x%x add_status x%x, " "mbx\n", shdr_status, shdr_add_status); @@ -1952,7 +1953,7 @@ lpfc_sli4_log_fcf_record_info(struct lpfc_hba *phba, } /** - lpfc_sli4_fcf_record_match - testing new FCF record for matching existing FCF + * lpfc_sli4_fcf_record_match - testing new FCF record for matching existing FCF * @phba: pointer to lpfc hba data structure. * @fcf_rec: pointer to an existing FCF record. * @new_fcf_record: pointer to a new FCF record. @@ -2066,7 +2067,7 @@ stop_flogi_current_fcf: /** * lpfc_sli4_fcf_pri_list_del * @phba: pointer to lpfc hba data structure. - * @fcf_index the index of the fcf record to delete + * @fcf_index: the index of the fcf record to delete * This routine checks the on list flag of the fcf_index to be deleted. * If it is one the list then it is removed from the list, and the flag * is cleared. This routine grab the hbalock before removing the fcf @@ -2096,7 +2097,7 @@ static void lpfc_sli4_fcf_pri_list_del(struct lpfc_hba *phba, /** * lpfc_sli4_set_fcf_flogi_fail * @phba: pointer to lpfc hba data structure. - * @fcf_index the index of the fcf record to update + * @fcf_index: the index of the fcf record to update * This routine acquires the hbalock and then set the LPFC_FCF_FLOGI_FAILED * flag so the the round robin slection for the particular priority level * will try a different fcf record that does not have this bit set. @@ -2116,7 +2117,8 @@ lpfc_sli4_set_fcf_flogi_fail(struct lpfc_hba *phba, uint16_t fcf_index) /** * lpfc_sli4_fcf_pri_list_add * @phba: pointer to lpfc hba data structure. - * @fcf_index the index of the fcf record to add + * @fcf_index: the index of the fcf record to add + * @new_fcf_record: pointer to a new FCF record. * This routine checks the priority of the fcf_index to be added. * If it is a lower priority than the current head of the fcf_pri list * then it is added to the list in the right order. @@ -2246,7 +2248,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) new_fcf_record = lpfc_sli4_fcf_rec_mbox_parse(phba, mboxq, &next_fcf_index); if (!new_fcf_record) { - lpfc_printf_log(phba, KERN_ERR, LOG_FIP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2765 Mailbox command READ_FCF_RECORD " "failed to retrieve a FCF record.\n"); /* Let next new FCF event trigger fast failover */ @@ -2290,7 +2292,8 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) new_fcf_record, LPFC_FCOE_IGNORE_VID)) { if (bf_get(lpfc_fcf_record_fcf_index, new_fcf_record) != phba->fcf.current_rec.fcf_indx) { - lpfc_printf_log(phba, KERN_ERR, LOG_FIP, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "2862 FCF (x%x) matches property " "of in-use FCF (x%x)\n", bf_get(lpfc_fcf_record_fcf_index, @@ -2360,7 +2363,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) phba->pport->fc_flag); goto out; } else - lpfc_printf_log(phba, KERN_ERR, LOG_FIP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2863 New FCF (x%x) matches " "property of in-use FCF (x%x)\n", bf_get(lpfc_fcf_record_fcf_index, @@ -2774,10 +2777,9 @@ lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != LPFC_SLI_INTF_IF_TYPE_0) && mboxq->u.mb.mbxStatus != MBX_VFI_IN_USE) { - lpfc_printf_vlog(vport, KERN_ERR, - LOG_MBOX, - "2891 Init VFI mailbox failed 0x%x\n", - mboxq->u.mb.mbxStatus); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "2891 Init VFI mailbox failed 0x%x\n", + mboxq->u.mb.mbxStatus); mempool_free(mboxq, phba->mbox_mem_pool); lpfc_vport_set_state(vport, FC_VPORT_FAILED); return; @@ -2805,7 +2807,7 @@ lpfc_issue_init_vfi(struct lpfc_vport *vport) mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) { lpfc_printf_vlog(vport, KERN_ERR, - LOG_MBOX, "2892 Failed to allocate " + LOG_TRACE_EVENT, "2892 Failed to allocate " "init_vfi mailbox\n"); return; } @@ -2813,8 +2815,8 @@ lpfc_issue_init_vfi(struct lpfc_vport *vport) mboxq->mbox_cmpl = lpfc_init_vfi_cmpl; rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - lpfc_printf_vlog(vport, KERN_ERR, - LOG_MBOX, "2893 Failed to issue init_vfi mailbox\n"); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "2893 Failed to issue init_vfi mailbox\n"); mempool_free(mboxq, vport->phba->mbox_mem_pool); } } @@ -2834,10 +2836,9 @@ lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) struct Scsi_Host *shost = lpfc_shost_from_vport(vport); if (mboxq->u.mb.mbxStatus) { - lpfc_printf_vlog(vport, KERN_ERR, - LOG_MBOX, - "2609 Init VPI mailbox failed 0x%x\n", - mboxq->u.mb.mbxStatus); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "2609 Init VPI mailbox failed 0x%x\n", + mboxq->u.mb.mbxStatus); mempool_free(mboxq, phba->mbox_mem_pool); lpfc_vport_set_state(vport, FC_VPORT_FAILED); return; @@ -2851,7 +2852,7 @@ lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) ndlp = lpfc_findnode_did(vport, Fabric_DID); if (!ndlp) lpfc_printf_vlog(vport, KERN_ERR, - LOG_DISCOVERY, + LOG_TRACE_EVENT, "2731 Cannot find fabric " "controller node\n"); else @@ -2864,7 +2865,7 @@ lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) lpfc_initial_fdisc(vport); else { lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2606 No NPIV Fabric support\n"); } mempool_free(mboxq, phba->mbox_mem_pool); @@ -2887,8 +2888,7 @@ lpfc_issue_init_vpi(struct lpfc_vport *vport) if ((vport->port_type != LPFC_PHYSICAL_PORT) && (!vport->vpi)) { vpi = lpfc_alloc_vpi(vport->phba); if (!vpi) { - lpfc_printf_vlog(vport, KERN_ERR, - LOG_MBOX, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "3303 Failed to obtain vport vpi\n"); lpfc_vport_set_state(vport, FC_VPORT_FAILED); return; @@ -2899,7 +2899,7 @@ lpfc_issue_init_vpi(struct lpfc_vport *vport) mboxq = mempool_alloc(vport->phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) { lpfc_printf_vlog(vport, KERN_ERR, - LOG_MBOX, "2607 Failed to allocate " + LOG_TRACE_EVENT, "2607 Failed to allocate " "init_vpi mailbox\n"); return; } @@ -2908,8 +2908,8 @@ lpfc_issue_init_vpi(struct lpfc_vport *vport) mboxq->mbox_cmpl = lpfc_init_vpi_cmpl; rc = lpfc_sli_issue_mbox(vport->phba, mboxq, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - lpfc_printf_vlog(vport, KERN_ERR, - LOG_MBOX, "2608 Failed to issue init_vpi mailbox\n"); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "2608 Failed to issue init_vpi mailbox\n"); mempool_free(mboxq, vport->phba->mbox_mem_pool); } } @@ -2953,7 +2953,7 @@ lpfc_start_fdiscs(struct lpfc_hba *phba) lpfc_vport_set_state(vports[i], FC_VPORT_NO_FABRIC_SUPP); lpfc_printf_vlog(vports[i], KERN_ERR, - LOG_ELS, + LOG_TRACE_EVENT, "0259 No NPIV " "Fabric support\n"); } @@ -2977,10 +2977,10 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != LPFC_SLI_INTF_IF_TYPE_0) && mboxq->u.mb.mbxStatus != MBX_VFI_IN_USE) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, - "2018 REG_VFI mbxStatus error x%x " - "HBA state x%x\n", - mboxq->u.mb.mbxStatus, vport->port_state); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "2018 REG_VFI mbxStatus error x%x " + "HBA state x%x\n", + mboxq->u.mb.mbxStatus, vport->port_state); if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { /* FLOGI failed, use loop map to make discovery list */ lpfc_disc_list_loopmap(vport); @@ -3067,7 +3067,7 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* Check for error */ if (mb->mbxStatus) { /* READ_SPARAM mbox error state */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0319 READ_SPARAM mbxStatus error x%x " "hba state x%x>\n", mb->mbxStatus, vport->port_state); @@ -3286,7 +3286,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) GFP_KERNEL); if (unlikely(!fcf_record)) { lpfc_printf_log(phba, KERN_ERR, - LOG_MBOX | LOG_SLI, + LOG_TRACE_EVENT, "2554 Could not allocate memory for " "fcf record\n"); rc = -ENODEV; @@ -3298,7 +3298,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) rc = lpfc_sli4_add_fcf_record(phba, fcf_record); if (unlikely(rc)) { lpfc_printf_log(phba, KERN_ERR, - LOG_MBOX | LOG_SLI, + LOG_TRACE_EVENT, "2013 Could not manually add FCF " "record 0, status %d\n", rc); rc = -ENODEV; @@ -3344,7 +3344,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) return; out: lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0263 Discovery Mailbox error: state: 0x%x : x%px x%px\n", vport->port_state, sparam_mbox, cfglink_mbox); lpfc_issue_clear_la(phba, vport); @@ -3617,7 +3617,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) break; /* If VPI is busy, reset the HBA */ case 0x9700: - lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2798 Unreg_vpi failed vpi 0x%x, mb status = 0x%x\n", vport->vpi, mb->mbxStatus); if (!(phba->pport->load_flag & FC_UNLOADING)) @@ -3655,7 +3655,7 @@ lpfc_mbx_unreg_vpi(struct lpfc_vport *vport) mbox->mbox_cmpl = lpfc_mbx_cmpl_unreg_vpi; rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1800 Could not issue unreg_vpi\n"); mempool_free(mbox, phba->mbox_mem_pool); vport->unreg_vpi_cmpl = VPORT_ERROR; @@ -3742,7 +3742,7 @@ lpfc_create_static_vport(struct lpfc_hba *phba) pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmb) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0542 lpfc_create_static_vport failed to" " allocate mailbox memory\n"); return; @@ -3752,7 +3752,7 @@ lpfc_create_static_vport(struct lpfc_hba *phba) vport_info = kzalloc(sizeof(struct static_vport_info), GFP_KERNEL); if (!vport_info) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0543 lpfc_create_static_vport failed to" " allocate vport_info\n"); mempool_free(pmb, phba->mbox_mem_pool); @@ -3813,11 +3813,12 @@ lpfc_create_static_vport(struct lpfc_hba *phba) if ((le32_to_cpu(vport_info->signature) != VPORT_INFO_SIG) || ((le32_to_cpu(vport_info->rev) & VPORT_INFO_REV_MASK) != VPORT_INFO_REV)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0545 lpfc_create_static_vport bad" - " information header 0x%x 0x%x\n", - le32_to_cpu(vport_info->signature), - le32_to_cpu(vport_info->rev) & VPORT_INFO_REV_MASK); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0545 lpfc_create_static_vport bad" + " information header 0x%x 0x%x\n", + le32_to_cpu(vport_info->signature), + le32_to_cpu(vport_info->rev) & + VPORT_INFO_REV_MASK); goto out; } @@ -3881,7 +3882,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) pmb->ctx_buf = NULL; if (mb->mbxStatus) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0258 Register Fabric login error: 0x%x\n", mb->mbxStatus); lpfc_mbuf_free(phba, mp->virt, mp->phys); @@ -3954,7 +3955,8 @@ lpfc_issue_gidft(struct lpfc_vport *vport) /* Cannot issue NameServer FCP Query, so finish up * discovery */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0604 %s FC TYPE %x %s\n", "Failed to issue GID_FT to ", FC_TYPE_FCP, @@ -3970,7 +3972,8 @@ lpfc_issue_gidft(struct lpfc_vport *vport) /* Cannot issue NameServer NVME Query, so finish up * discovery */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0605 %s FC_TYPE %x %s %d\n", "Failed to issue GID_FT to ", FC_TYPE_NVME, @@ -4002,7 +4005,7 @@ lpfc_issue_gidpt(struct lpfc_vport *vport) /* Cannot issue NameServer FCP Query, so finish up * discovery */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0606 %s Port TYPE %x %s\n", "Failed to issue GID_PT to ", GID_PT_N_PORT, @@ -4032,7 +4035,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) vport->gidft_inp = 0; if (mb->mbxStatus) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0260 Register NameServer error: 0x%x\n", mb->mbxStatus); @@ -4344,7 +4347,7 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, GFP_KERNEL); if (!ndlp->lat_data) - lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0286 lpfc_nlp_state_cleanup failed to " "allocate statistical data buffer DID " "0x%x\n", ndlp->nlp_DID); @@ -5013,8 +5016,8 @@ lpfc_unreg_hba_rpis(struct lpfc_hba *phba) vports = lpfc_create_vport_work_array(phba); if (!vports) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "2884 Vport array allocation failed \n"); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2884 Vport array allocation failed \n"); return; } for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { @@ -5057,9 +5060,10 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport) mempool_free(mbox, phba->mbox_mem_pool); if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED)) - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT, - "1836 Could not issue " - "unreg_login(all_rpis) status %d\n", rc); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "1836 Could not issue " + "unreg_login(all_rpis) status %d\n", + rc); } } @@ -5086,7 +5090,7 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport) mempool_free(mbox, phba->mbox_mem_pool); if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED)) - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1815 Could not issue " "unreg_did (default rpis) status %d\n", rc); @@ -5907,7 +5911,8 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) case LPFC_FLOGI: /* port_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */ /* Initial FLOGI timeout */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0222 Initial %s timeout\n", vport->vpi ? "FDISC" : "FLOGI"); @@ -5925,7 +5930,8 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) case LPFC_FABRIC_CFG_LINK: /* hba_state is identically LPFC_FABRIC_CFG_LINK while waiting for NameServer login */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0223 Timeout while waiting for " "NameServer login\n"); /* Next look for NameServer ndlp */ @@ -5938,7 +5944,8 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) case LPFC_NS_QRY: /* Check for wait for NameServer Rsp timeout */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0224 NameServer Query timeout " "Data: x%x x%x\n", vport->fc_ns_retry, LPFC_MAX_NS_RETRY); @@ -5971,7 +5978,8 @@ restart_disc: /* Setup and issue mailbox INITIALIZE LINK command */ initlinkmbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!initlinkmbox) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0206 Device Discovery " "completion error\n"); phba->link_state = LPFC_HBA_ERROR; @@ -5993,7 +6001,8 @@ restart_disc: case LPFC_DISC_AUTH: /* Node Authentication timeout */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0227 Node Authentication timeout\n"); lpfc_disc_flush_list(vport); @@ -6013,7 +6022,8 @@ restart_disc: case LPFC_VPORT_READY: if (vport->fc_flag & FC_RSCN_MODE) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0231 RSCN timeout Data: x%x " "x%x\n", vport->fc_ns_retry, LPFC_MAX_NS_RETRY); @@ -6027,7 +6037,8 @@ restart_disc: break; default: - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0273 Unexpected discovery timeout, " "vport State x%x\n", vport->port_state); break; @@ -6036,7 +6047,8 @@ restart_disc: switch (phba->link_state) { case LPFC_CLEAR_LA: /* CLEAR LA timeout */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0228 CLEAR LA timeout\n"); clrlaerr = 1; break; @@ -6050,7 +6062,8 @@ restart_disc: case LPFC_INIT_MBX_CMDS: case LPFC_LINK_DOWN: case LPFC_HBA_ERROR: - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0230 Unexpected timeout, hba link " "state x%x\n", phba->link_state); clrlaerr = 1; @@ -6241,9 +6254,9 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) } if (i >= phba->max_vpi) { - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "2936 Could not find Vport mapped " - "to vpi %d\n", vpi); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2936 Could not find Vport mapped " + "to vpi %d\n", vpi); return NULL; } } @@ -6547,10 +6560,10 @@ lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) struct Scsi_Host *shost = lpfc_shost_from_vport(vport); if (mboxq->u.mb.mbxStatus) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, - "2555 UNREG_VFI mbxStatus error x%x " - "HBA state x%x\n", - mboxq->u.mb.mbxStatus, vport->port_state); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2555 UNREG_VFI mbxStatus error x%x " + "HBA state x%x\n", + mboxq->u.mb.mbxStatus, vport->port_state); } spin_lock_irq(shost->host_lock); phba->pport->fc_flag &= ~FC_VFI_REGISTERED; @@ -6572,10 +6585,10 @@ lpfc_unregister_fcfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) struct lpfc_vport *vport = mboxq->vport; if (mboxq->u.mb.mbxStatus) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, - "2550 UNREG_FCFI mbxStatus error x%x " - "HBA state x%x\n", - mboxq->u.mb.mbxStatus, vport->port_state); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2550 UNREG_FCFI mbxStatus error x%x " + "HBA state x%x\n", + mboxq->u.mb.mbxStatus, vport->port_state); } mempool_free(mboxq, phba->mbox_mem_pool); return; @@ -6664,7 +6677,7 @@ lpfc_sli4_unregister_fcf(struct lpfc_hba *phba) mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2551 UNREG_FCFI mbox allocation failed" "HBA state x%x\n", phba->pport->port_state); return -ENOMEM; @@ -6675,7 +6688,7 @@ lpfc_sli4_unregister_fcf(struct lpfc_hba *phba) rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2552 Unregister FCFI command failed rc x%x " "HBA state x%x\n", rc, phba->pport->port_state); @@ -6699,7 +6712,7 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba) /* Preparation for unregistering fcf */ rc = lpfc_unregister_fcf_prep(phba); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2748 Failed to prepare for unregistering " "HBA's FCF record: rc=%d\n", rc); return; @@ -6735,7 +6748,7 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag &= ~FCF_INIT_DISC; spin_unlock_irq(&phba->hbalock); - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2553 lpfc_unregister_unused_fcf failed " "to read FCF record HBA state x%x\n", phba->pport->port_state); @@ -6757,7 +6770,7 @@ lpfc_unregister_fcf(struct lpfc_hba *phba) /* Preparation for unregistering fcf */ rc = lpfc_unregister_fcf_prep(phba); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2749 Failed to prepare for unregistering " "HBA's FCF record: rc=%d\n", rc); return; @@ -6844,9 +6857,9 @@ lpfc_read_fcf_conn_tbl(struct lpfc_hba *phba, conn_entry = kzalloc(sizeof(struct lpfc_fcf_conn_entry), GFP_KERNEL); if (!conn_entry) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2566 Failed to allocate connection" - " table entry\n"); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2566 Failed to allocate connection" + " table entry\n"); return; } @@ -6990,7 +7003,7 @@ lpfc_parse_fcoe_conf(struct lpfc_hba *phba, /* Check the region signature first */ if (memcmp(buff, LPFC_REGION23_SIGNATURE, 4)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2567 Config region 23 has bad signature\n"); return; } @@ -6999,8 +7012,8 @@ lpfc_parse_fcoe_conf(struct lpfc_hba *phba, /* Check the data structure version */ if (buff[offset] != LPFC_REGION23_VERSION) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2568 Config region 23 has bad version\n"); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2568 Config region 23 has bad version\n"); return; } offset += 4; diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 6dfff03765471c7cfd24ca26fde059deaaf83f22..c4ba8273a63fbea46f49b45a92dd85c3a55e444c 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -650,6 +650,9 @@ struct lpfc_register { #define lpfc_sliport_status_oti_SHIFT 29 #define lpfc_sliport_status_oti_MASK 0x1 #define lpfc_sliport_status_oti_WORD word0 +#define lpfc_sliport_status_dip_SHIFT 25 +#define lpfc_sliport_status_dip_MASK 0x1 +#define lpfc_sliport_status_dip_WORD word0 #define lpfc_sliport_status_rn_SHIFT 24 #define lpfc_sliport_status_rn_MASK 0x1 #define lpfc_sliport_status_rn_WORD word0 @@ -3531,7 +3534,7 @@ struct lpfc_sli4_parameters { }; #define LPFC_SET_UE_RECOVERY 0x10 -#define LPFC_SET_MDS_DIAGS 0x11 +#define LPFC_SET_MDS_DIAGS 0x12 #define LPFC_SET_DUAL_DUMP 0x1e struct lpfc_mbx_set_feature { struct mbox_header header; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 6637f84a3d1bccd02d6cfa226b8d5d469e3758a9..c4a7e82d3ff2449a6f7decfa3e03e88fbc64732a 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -153,7 +153,7 @@ lpfc_config_port_prep(struct lpfc_hba *phba) rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0324 Config Port initialization " "error, mbxCmd x%x READ_NVPARM, " "mbxStatus x%x\n", @@ -177,7 +177,7 @@ lpfc_config_port_prep(struct lpfc_hba *phba) lpfc_read_rev(phba, pmb); rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0439 Adapter failed to init, mbxCmd x%x " "READ_REV, mbxStatus x%x\n", mb->mbxCommand, mb->mbxStatus); @@ -192,7 +192,7 @@ lpfc_config_port_prep(struct lpfc_hba *phba) */ if (mb->un.varRdRev.rr == 0) { vp->rev.rBit = 0; - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0440 Adapter failed to init, READ_REV has " "missing revision information.\n"); mempool_free(pmb, phba->mbox_mem_pool); @@ -253,13 +253,15 @@ lpfc_config_port_prep(struct lpfc_hba *phba) */ if (mb->un.varDmp.word_cnt == 0) break; - if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset) - mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset; + + i = mb->un.varDmp.word_cnt * sizeof(uint32_t); + if (offset + i > DMP_VPD_SIZE) + i = DMP_VPD_SIZE - offset; lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET, - lpfc_vpd_data + offset, - mb->un.varDmp.word_cnt); - offset += mb->un.varDmp.word_cnt; - } while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE); + lpfc_vpd_data + offset, i); + offset += i; + } while (offset < DMP_VPD_SIZE); + lpfc_parse_vpd(phba, lpfc_vpd_data, offset); kfree(lpfc_vpd_data); @@ -442,7 +444,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) pmb->vport = vport; if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0448 Adapter failed init, mbxCmd x%x " "READ_SPARM mbxStatus x%x\n", mb->mbxCommand, mb->mbxStatus); @@ -496,7 +498,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) lpfc_read_config(phba, pmb); pmb->vport = vport; if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0453 Adapter failed to init, mbxCmd x%x " "READ_CONFIG, mbxStatus x%x\n", mb->mbxCommand, mb->mbxStatus); @@ -545,7 +547,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) } rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0352 Config MSI mailbox command " "failed, mbxCmd x%x, mbxStatus x%x\n", pmb->u.mb.mbxCommand, @@ -596,17 +598,15 @@ lpfc_config_port_post(struct lpfc_hba *phba) jiffies + msecs_to_jiffies(1000 * phba->eratt_poll_interval)); if (phba->hba_flag & LINK_DISABLED) { - lpfc_printf_log(phba, - KERN_ERR, LOG_INIT, - "2598 Adapter Link is disabled.\n"); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2598 Adapter Link is disabled.\n"); lpfc_down_link(phba, pmb); pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); if ((rc != MBX_SUCCESS) && (rc != MBX_BUSY)) { - lpfc_printf_log(phba, - KERN_ERR, LOG_INIT, - "2599 Adapter failed to issue DOWN_LINK" - " mbox command rc 0x%x\n", rc); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2599 Adapter failed to issue DOWN_LINK" + " mbox command rc 0x%x\n", rc); mempool_free(pmb, phba->mbox_mem_pool); return -EIO; @@ -630,9 +630,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - lpfc_printf_log(phba, - KERN_ERR, - LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0456 Adapter failed to issue " "ASYNCEVT_ENABLE mbox status x%x\n", rc); @@ -652,7 +650,8 @@ lpfc_config_port_post(struct lpfc_hba *phba) rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0435 Adapter failed " + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0435 Adapter failed " "to get Option ROM version status x%x\n", rc); mempool_free(pmb, phba->mbox_mem_pool); } @@ -730,10 +729,10 @@ lpfc_hba_init_link_fc_topology(struct lpfc_hba *phba, uint32_t fc_topology, ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_64G) && !(phba->lmt & LMT_64Gb))) { /* Reset link speed to auto */ - lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, - "1302 Invalid speed for this board:%d " - "Reset link speed to auto.\n", - phba->cfg_link_speed); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "1302 Invalid speed for this board:%d " + "Reset link speed to auto.\n", + phba->cfg_link_speed); phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO; } lpfc_init_link(phba, pmb, fc_topology, phba->cfg_link_speed); @@ -742,10 +741,10 @@ lpfc_hba_init_link_fc_topology(struct lpfc_hba *phba, uint32_t fc_topology, lpfc_set_loopback_flag(phba); rc = lpfc_sli_issue_mbox(phba, pmb, flag); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0498 Adapter failed to init, mbxCmd x%x " - "INIT_LINK, mbxStatus x%x\n", - mb->mbxCommand, mb->mbxStatus); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0498 Adapter failed to init, mbxCmd x%x " + "INIT_LINK, mbxStatus x%x\n", + mb->mbxCommand, mb->mbxStatus); if (phba->sli_rev <= LPFC_SLI_REV3) { /* Clear all interrupt enable conditions */ writel(0, phba->HCregaddr); @@ -791,17 +790,15 @@ lpfc_hba_down_link(struct lpfc_hba *phba, uint32_t flag) return -ENOMEM; } - lpfc_printf_log(phba, - KERN_ERR, LOG_INIT, - "0491 Adapter Link is disabled.\n"); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0491 Adapter Link is disabled.\n"); lpfc_down_link(phba, pmb); pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; rc = lpfc_sli_issue_mbox(phba, pmb, flag); if ((rc != MBX_SUCCESS) && (rc != MBX_BUSY)) { - lpfc_printf_log(phba, - KERN_ERR, LOG_INIT, - "2522 Adapter failed to issue DOWN_LINK" - " mbox command rc 0x%x\n", rc); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2522 Adapter failed to issue DOWN_LINK" + " mbox command rc 0x%x\n", rc); mempool_free(pmb, phba->mbox_mem_pool); return -EIO; @@ -996,7 +993,6 @@ lpfc_hba_clean_txcmplq(struct lpfc_hba *phba) /** * lpfc_hba_down_post_s3 - Perform lpfc uninitialization after HBA reset - int i; * @phba: pointer to lpfc HBA data structure. * * This routine will do uninitialization after the HBA is reset when bring @@ -1124,7 +1120,7 @@ lpfc_hba_down_post(struct lpfc_hba *phba) /** * lpfc_hb_timeout - The HBA-timer timeout handler - * @ptr: unsigned long holds the pointer to lpfc hba data structure. + * @t: timer context used to obtain the pointer to lpfc hba data structure. * * This is the HBA-timer timeout handler registered to the lpfc driver. When * this timer fires, a HBA timeout event shall be posted to the lpfc driver @@ -1158,7 +1154,7 @@ lpfc_hb_timeout(struct timer_list *t) /** * lpfc_rrq_timeout - The RRQ-timer timeout handler - * @ptr: unsigned long holds the pointer to lpfc hba data structure. + * @t: timer context used to obtain the pointer to lpfc hba data structure. * * This is the RRQ-timer timeout handler registered to the lpfc driver. When * this timer fires, a RRQ timeout event shall be posted to the lpfc driver @@ -1222,6 +1218,75 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) return; } +/* + * lpfc_idle_stat_delay_work - idle_stat tracking + * + * This routine tracks per-cq idle_stat and determines polling decisions. + * + * Return codes: + * None + **/ +static void +lpfc_idle_stat_delay_work(struct work_struct *work) +{ + struct lpfc_hba *phba = container_of(to_delayed_work(work), + struct lpfc_hba, + idle_stat_delay_work); + struct lpfc_queue *cq; + struct lpfc_sli4_hdw_queue *hdwq; + struct lpfc_idle_stat *idle_stat; + u32 i, idle_percent; + u64 wall, wall_idle, diff_wall, diff_idle, busy_time; + + if (phba->pport->load_flag & FC_UNLOADING) + return; + + if (phba->link_state == LPFC_HBA_ERROR || + phba->pport->fc_flag & FC_OFFLINE_MODE) + goto requeue; + + for_each_present_cpu(i) { + hdwq = &phba->sli4_hba.hdwq[phba->sli4_hba.cpu_map[i].hdwq]; + cq = hdwq->io_cq; + + /* Skip if we've already handled this cq's primary CPU */ + if (cq->chann != i) + continue; + + idle_stat = &phba->sli4_hba.idle_stat[i]; + + /* get_cpu_idle_time returns values as running counters. Thus, + * to know the amount for this period, the prior counter values + * need to be subtracted from the current counter values. + * From there, the idle time stat can be calculated as a + * percentage of 100 - the sum of the other consumption times. + */ + wall_idle = get_cpu_idle_time(i, &wall, 1); + diff_idle = wall_idle - idle_stat->prev_idle; + diff_wall = wall - idle_stat->prev_wall; + + if (diff_wall <= diff_idle) + busy_time = 0; + else + busy_time = diff_wall - diff_idle; + + idle_percent = div64_u64(100 * busy_time, diff_wall); + idle_percent = 100 - idle_percent; + + if (idle_percent < 15) + cq->poll_mode = LPFC_QUEUE_WORK; + else + cq->poll_mode = LPFC_IRQ_POLL; + + idle_stat->prev_idle = wall_idle; + idle_stat->prev_wall = wall; + } + +requeue: + schedule_delayed_work(&phba->idle_stat_delay_work, + msecs_to_jiffies(LPFC_IDLE_STAT_DELAY)); +} + static void lpfc_hb_eq_delay_work(struct work_struct *work) { @@ -1538,11 +1603,11 @@ lpfc_handle_deferred_eratt(struct lpfc_hba *phba) return; } - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0479 Deferred Adapter Hardware Error " - "Data: x%x x%x x%x\n", - phba->work_hs, - phba->work_status[0], phba->work_status[1]); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0479 Deferred Adapter Hardware Error " + "Data: x%x x%x x%x\n", + phba->work_hs, phba->work_status[0], + phba->work_status[1]); spin_lock_irq(&phba->hbalock); psli->sli_flag &= ~LPFC_SLI_ACTIVE; @@ -1693,7 +1758,7 @@ lpfc_handle_eratt_s3(struct lpfc_hba *phba) temp_event_data.event_code = LPFC_CRIT_TEMP; temp_event_data.data = (uint32_t)temperature; - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0406 Adapter maximum temperature exceeded " "(%ld), taking this port offline " "Data: x%x x%x x%x\n", @@ -1717,7 +1782,7 @@ lpfc_handle_eratt_s3(struct lpfc_hba *phba) * failure is a value other than FFER6. Do not call the offline * twice. This is the adapter hardware error path. */ - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0457 Adapter Hardware Error " "Data: x%x x%x x%x\n", phba->work_hs, @@ -1738,7 +1803,7 @@ lpfc_handle_eratt_s3(struct lpfc_hba *phba) * lpfc_sli4_port_sta_fn_reset - The SLI4 function reset due to port status reg * @phba: pointer to lpfc hba data structure. * @mbx_action: flag for mailbox shutdown action. - * + * @en_rn_msg: send reset/port recovery message. * This routine is invoked to perform an SLI4 port PCI function reset in * response to port status register polling attention. It waits for port * status register (ERR, RDY, RN) bits before proceeding with function reset. @@ -1765,7 +1830,7 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action, /* need reset: attempt for port recovery */ if (en_rn_msg) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2887 Reset Needed: Attempting Port " "Recovery...\n"); lpfc_offline_prep(phba, mbx_action); @@ -1775,14 +1840,14 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action, lpfc_sli4_disable_intr(phba); rc = lpfc_sli_brdrestart(phba); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6309 Failed to restart board\n"); return rc; } /* request and enable interrupt */ intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode); if (intr_mode == LPFC_INTR_ERROR) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3175 Failed to enable interrupt\n"); return -EIO; } @@ -1821,7 +1886,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) * we cannot communicate with the pci card anyway. */ if (pci_channel_offline(phba->pcidev)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3166 pci channel is offline\n"); lpfc_sli4_offline_eratt(phba); return; @@ -1844,7 +1909,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) lpfc_sli4_offline_eratt(phba); return; } - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "7623 Checking UE recoverable"); for (i = 0; i < phba->sli4_hba.ue_to_sr / 1000; i++) { @@ -1861,7 +1926,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) msleep(1000); } - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "4827 smphr_port_status x%x : Waited %dSec", smphr_port_status, i); @@ -1879,14 +1944,14 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) LPFC_MBX_NO_WAIT, en_rn_msg); if (rc == 0) return; - lpfc_printf_log(phba, - KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "4215 Failed to recover UE"); break; } } } - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "7624 Firmware not ready: Failing UE recovery," " waited %dSec", i); phba->link_state = LPFC_HBA_ERROR; @@ -1899,7 +1964,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) &portstat_reg.word0); /* consider PCI bus read error as pci_channel_offline */ if (pci_rd_rc1 == -EIO) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3151 PCI bus read access failure: x%x\n", readl(phba->sli4_hba.u.if_type2.STATUSregaddr)); lpfc_sli4_offline_eratt(phba); @@ -1908,10 +1973,10 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) reg_err1 = readl(phba->sli4_hba.u.if_type2.ERR1regaddr); reg_err2 = readl(phba->sli4_hba.u.if_type2.ERR2regaddr); if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2889 Port Overtemperature event, " - "taking port offline Data: x%x x%x\n", - reg_err1, reg_err2); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2889 Port Overtemperature event, " + "taking port offline Data: x%x x%x\n", + reg_err1, reg_err2); phba->sfp_alarm |= LPFC_TRANSGRESSION_HIGH_TEMPERATURE; temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT; @@ -1933,17 +1998,17 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) } if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 && reg_err2 == SLIPORT_ERR2_REG_FW_RESTART) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3143 Port Down: Firmware Update " "Detected\n"); en_rn_msg = false; } else if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 && reg_err2 == SLIPORT_ERR2_REG_FORCED_DUMP) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3144 Port Down: Debug Dump\n"); else if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 && reg_err2 == SLIPORT_ERR2_REG_FUNC_PROVISON) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3145 Port Down: Provisioning\n"); /* If resets are disabled then leave the HBA alone and return */ @@ -1962,7 +2027,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) break; } /* fall through for not able to recover */ - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3152 Unrecoverable error\n"); phba->link_state = LPFC_HBA_ERROR; break; @@ -2080,8 +2145,8 @@ lpfc_handle_latt_err_exit: lpfc_linkdown(phba); phba->link_state = LPFC_HBA_ERROR; - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "0300 LATT: Cannot issue READ_LA: Data:%d\n", rc); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0300 LATT: Cannot issue READ_LA: Data:%d\n", rc); return; } @@ -2830,12 +2895,13 @@ lpfc_cleanup(struct lpfc_vport *vport) */ while (!list_empty(&vport->fc_nodes)) { if (i++ > 3000) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0233 Nodelist not empty\n"); list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { lpfc_printf_vlog(ndlp->vport, KERN_ERR, - LOG_NODE, + LOG_TRACE_EVENT, "0282 did:x%x ndlp:x%px " "usgmap:x%x refcnt:%d\n", ndlp->nlp_DID, (void *)ndlp, @@ -2922,6 +2988,7 @@ lpfc_stop_hba_timers(struct lpfc_hba *phba) if (phba->pport) lpfc_stop_vport_timers(phba->pport); cancel_delayed_work_sync(&phba->eq_delay_work); + cancel_delayed_work_sync(&phba->idle_stat_delay_work); del_timer_sync(&phba->sli.mbox_tmo); del_timer_sync(&phba->fabric_block_timer); del_timer_sync(&phba->eratt_poll); @@ -2942,7 +3009,7 @@ lpfc_stop_hba_timers(struct lpfc_hba *phba) lpfc_sli4_stop_fcf_redisc_wait_timer(phba); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0297 Invalid device group (x%x)\n", phba->pci_dev_grp); break; @@ -2953,6 +3020,7 @@ lpfc_stop_hba_timers(struct lpfc_hba *phba) /** * lpfc_block_mgmt_io - Mark a HBA's management interface as blocked * @phba: pointer to lpfc hba data structure. + * @mbx_action: flag for mailbox no wait action. * * This routine marks a HBA's management interface as blocked. Once the HBA's * management interface is marked as blocked, all the user space access to @@ -2989,10 +3057,10 @@ lpfc_block_mgmt_io(struct lpfc_hba *phba, int mbx_action) /* Check active mailbox complete status every 2ms */ msleep(2); if (time_after(jiffies, timeout)) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "2813 Mgmt IO is Blocked %x " - "- mbox cmd %x still active\n", - phba->sli.sli_flag, actcmd); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2813 Mgmt IO is Blocked %x " + "- mbox cmd %x still active\n", + phba->sli.sli_flag, actcmd); break; } } @@ -3337,7 +3405,7 @@ lpfc_online(struct lpfc_hba *phba) !phba->nvmet_support) { error = lpfc_nvme_create_localport(phba->pport); if (error) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6132 NVME restore reg failed " "on nvmei error x%x\n", error); } @@ -3403,6 +3471,7 @@ lpfc_unblock_mgmt_io(struct lpfc_hba * phba) /** * lpfc_offline_prep - Prepare a HBA to be brought offline * @phba: pointer to lpfc hba data structure. + * @mbx_action: flag for mailbox shutdown action. * * This routine is invoked to prepare a HBA to be brought offline. It performs * unregistration login to all the nodes on all vports and flushes the mailbox @@ -3677,7 +3746,8 @@ lpfc_sli4_els_sgl_update(struct lpfc_hba *phba) sglq_entry = kzalloc(sizeof(struct lpfc_sglq), GFP_KERNEL); if (sglq_entry == NULL) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "2562 Failure to allocate an " "ELS sgl entry:%d\n", i); rc = -ENOMEM; @@ -3688,7 +3758,8 @@ lpfc_sli4_els_sgl_update(struct lpfc_hba *phba) &sglq_entry->phys); if (sglq_entry->virt == NULL) { kfree(sglq_entry); - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "2563 Failure to allocate an " "ELS mbuf:%d\n", i); rc = -ENOMEM; @@ -3743,7 +3814,8 @@ lpfc_sli4_els_sgl_update(struct lpfc_hba *phba) &phba->sli4_hba.lpfc_els_sgl_list, list) { lxri = lpfc_sli4_next_xritag(phba); if (lxri == NO_XRI) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "2400 Failed to allocate xri for " "ELS sgl\n"); rc = -ENOMEM; @@ -3798,7 +3870,8 @@ lpfc_sli4_nvmet_sgl_update(struct lpfc_hba *phba) sglq_entry = kzalloc(sizeof(struct lpfc_sglq), GFP_KERNEL); if (sglq_entry == NULL) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "6303 Failure to allocate an " "NVMET sgl entry:%d\n", i); rc = -ENOMEM; @@ -3809,7 +3882,8 @@ lpfc_sli4_nvmet_sgl_update(struct lpfc_hba *phba) &sglq_entry->phys); if (sglq_entry->virt == NULL) { kfree(sglq_entry); - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "6304 Failure to allocate an " "NVMET buf:%d\n", i); rc = -ENOMEM; @@ -3865,7 +3939,8 @@ lpfc_sli4_nvmet_sgl_update(struct lpfc_hba *phba) &phba->sli4_hba.lpfc_nvmet_sgl_list, list) { lxri = lpfc_sli4_next_xritag(phba); if (lxri == NO_XRI) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "6307 Failed to allocate xri for " "NVMET sgl\n"); rc = -ENOMEM; @@ -4039,7 +4114,8 @@ lpfc_sli4_io_sgl_update(struct lpfc_hba *phba) &io_sgl_list, list) { lxri = lpfc_sli4_next_xritag(phba); if (lxri == NO_XRI) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "6075 Failed to allocate xri for " "nvme buffer\n"); rc = -ENOMEM; @@ -4058,8 +4134,8 @@ out_free_mem: /** * lpfc_new_io_buf - IO buffer allocator for HBA with SLI4 IF spec - * @vport: The virtual port for which this call being executed. - * @num_to_allocate: The requested number of buffers to allocate. + * @phba: Pointer to lpfc hba data structure. + * @num_to_alloc: The requested number of buffers to allocate. * * This routine allocates nvme buffers for device with SLI-4 interface spec, * the nvme buffer contains all the necessary information needed to initiate @@ -4109,7 +4185,8 @@ lpfc_new_io_buf(struct lpfc_hba *phba, int num_to_alloc) if ((phba->sli3_options & LPFC_SLI3_BG_ENABLED) && (((unsigned long)(lpfc_ncmd->data) & (unsigned long)(SLI4_PAGE_SIZE - 1)) != 0)) { - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "3369 Memory alignment err: " "addr=%lx\n", (unsigned long)lpfc_ncmd->data); @@ -4138,7 +4215,7 @@ lpfc_new_io_buf(struct lpfc_hba *phba, int num_to_alloc) dma_pool_free(phba->lpfc_sg_dma_buf_pool, lpfc_ncmd->data, lpfc_ncmd->dma_handle); kfree(lpfc_ncmd); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6121 Failed to allocate IOTAG for" " XRI:0x%x\n", lxri); lpfc_sli4_free_xri(phba, lxri); @@ -4189,7 +4266,7 @@ lpfc_get_wwpn(struct lpfc_hba *phba) lpfc_read_nv(phba, mboxq); rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6019 Mailbox failed , mbxCmd x%x " "READ_NV, mbxStatus x%x\n", bf_get(lpfc_mqe_command, &mboxq->u.mqe), @@ -4249,7 +4326,8 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) for (i = 0; i < lpfc_no_hba_reset_cnt; i++) { if (wwn == lpfc_no_hba_reset[i]) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "6020 Setting use_no_reset port=%llx\n", wwn); use_no_reset_hba = true; @@ -4646,7 +4724,7 @@ lpfc_fcf_redisc_wait_start_timer(struct lpfc_hba *phba) /** * lpfc_sli4_fcf_redisc_wait_tmo - FCF table rediscover wait timeout - * @ptr: Map to lpfc_hba data structure pointer. + * @t: Timer context used to obtain the pointer to lpfc hba data structure. * * This routine is invoked when waiting for FCF table rediscover has been * timed out. If new FCF record(s) has (have) been discovered during the @@ -4694,7 +4772,7 @@ lpfc_sli4_parse_latt_fault(struct lpfc_hba *phba, case LPFC_ASYNC_LINK_FAULT_LR_LRR: break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0398 Unknown link fault code: x%x\n", bf_get(lpfc_acqe_link_fault, acqe_link)); break; @@ -4730,7 +4808,7 @@ lpfc_sli4_parse_latt_type(struct lpfc_hba *phba, att_type = LPFC_ATT_LINK_UP; break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0399 Invalid link attention type: x%x\n", bf_get(lpfc_acqe_link_status, acqe_link)); att_type = LPFC_ATT_RESERVED; @@ -4902,19 +4980,19 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba, phba->fcoe_eventtag = acqe_link->event_tag; pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmb) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0395 The mboxq allocation failed\n"); return; } mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); if (!mp) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0396 The lpfc_dmabuf allocation failed\n"); goto out_free_pmb; } mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); if (!mp->virt) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0397 The mbuf allocation failed\n"); goto out_free_dmabuf; } @@ -5013,7 +5091,6 @@ out_free_pmb: * lpfc_async_link_speed_to_read_top - Parse async evt link speed code to read * topology. * @phba: pointer to lpfc hba data structure. - * @evt_code: asynchronous event code. * @speed_code: asynchronous event link speed code. * * This routine is to parse the giving SLI4 async event link speed code into @@ -5115,7 +5192,7 @@ lpfc_update_trunk_link_status(struct lpfc_hba *phba, phba->trunk_link.link3.fault = port_fault & 0x8 ? err : 0; } - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2910 Async FC Trunking Event - Speed:%d\n" "\tLogical speed:%d " "port0: %s port1: %s port2: %s port3: %s\n", @@ -5125,7 +5202,7 @@ lpfc_update_trunk_link_status(struct lpfc_hba *phba, trunk_link_status(2), trunk_link_status(3)); if (port_fault) - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3202 trunk error:0x%x (%s) seen on port0:%s " /* * SLI-4: We have only 0xA error codes @@ -5159,7 +5236,7 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc) if (bf_get(lpfc_trailer_type, acqe_fc) != LPFC_FC_LA_EVENT_TYPE_FC_LINK) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2895 Non FC link Event detected.(%d)\n", bf_get(lpfc_trailer_type, acqe_fc)); return; @@ -5207,19 +5284,19 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc) phba->sli4_hba.link_state.fault); pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmb) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2897 The mboxq allocation failed\n"); return; } mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); if (!mp) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2898 The lpfc_dmabuf allocation failed\n"); goto out_free_pmb; } mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); if (!mp->virt) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2899 The mbuf allocation failed\n"); goto out_free_dmabuf; } @@ -5291,7 +5368,7 @@ out_free_pmb: /** * lpfc_sli4_async_sli_evt - Process the asynchronous SLI link event * @phba: pointer to lpfc hba data structure. - * @acqe_fc: pointer to the async SLI completion queue entry. + * @acqe_sli: pointer to the async SLI completion queue entry. * * This routine is to handle the SLI4 asynchronous SLI events. **/ @@ -5386,7 +5463,7 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli) &misconfigured->theEvent); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3296 " "LPFC_SLI_EVENT_TYPE_MISCONFIGURED " "event: Invalid link %d", @@ -5438,7 +5515,8 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli) rc = lpfc_sli4_read_config(phba); if (rc) { phba->lmt = 0; - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "3194 Unable to retrieve supported " "speeds, rc = 0x%x\n", rc); } @@ -5546,7 +5624,7 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport) /** * lpfc_sli4_perform_all_vport_cvl - Perform clear virtual link on all vports - * @vport: pointer to lpfc hba data structure. + * @phba: pointer to lpfc hba data structure. * * This routine is to perform Clear Virtual Link (CVL) on all vports in * response to a FCF dead event. @@ -5567,7 +5645,7 @@ lpfc_sli4_perform_all_vport_cvl(struct lpfc_hba *phba) /** * lpfc_sli4_async_fip_evt - Process the asynchronous FCoE FIP event * @phba: pointer to lpfc hba data structure. - * @acqe_link: pointer to the async fcoe completion queue entry. + * @acqe_fip: pointer to the async fcoe completion queue entry. * * This routine is to handle the SLI4 asynchronous fcoe event. **/ @@ -5590,8 +5668,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, case LPFC_FIP_EVENT_TYPE_NEW_FCF: case LPFC_FIP_EVENT_TYPE_FCF_PARAM_MOD: if (event_type == LPFC_FIP_EVENT_TYPE_NEW_FCF) - lpfc_printf_log(phba, KERN_ERR, LOG_FIP | - LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2546 New FCF event, evt_tag:x%x, " "index:x%x\n", acqe_fip->event_tag, @@ -5644,23 +5721,24 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); if (rc) - lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2547 Issue FCF scan read FCF mailbox " "command failed (x%x)\n", rc); break; case LPFC_FIP_EVENT_TYPE_FCF_TABLE_FULL: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "2548 FCF Table full count 0x%x tag 0x%x\n", - bf_get(lpfc_acqe_fip_fcf_count, acqe_fip), - acqe_fip->event_tag); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2548 FCF Table full count 0x%x tag 0x%x\n", + bf_get(lpfc_acqe_fip_fcf_count, acqe_fip), + acqe_fip->event_tag); break; case LPFC_FIP_EVENT_TYPE_FCF_DEAD: phba->fcoe_cvl_eventtag = acqe_fip->event_tag; - lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, - "2549 FCF (x%x) disconnected from network, " - "tag:x%x\n", acqe_fip->index, acqe_fip->event_tag); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2549 FCF (x%x) disconnected from network, " + "tag:x%x\n", acqe_fip->index, + acqe_fip->event_tag); /* * If we are in the middle of FCF failover process, clear * the corresponding FCF bit in the roundrobin bitmap. @@ -5697,7 +5775,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, rc = lpfc_sli4_redisc_fcf_table(phba); if (rc) { lpfc_printf_log(phba, KERN_ERR, LOG_FIP | - LOG_DISCOVERY, + LOG_TRACE_EVENT, "2772 Issue FCF rediscover mailbox " "command failed, fail through to FCF " "dead event\n"); @@ -5721,7 +5799,8 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, break; case LPFC_FIP_EVENT_TYPE_CVL: phba->fcoe_cvl_eventtag = acqe_fip->event_tag; - lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "2718 Clear Virtual Link Received for VPI 0x%x" " tag 0x%x\n", acqe_fip->index, acqe_fip->event_tag); @@ -5788,7 +5867,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, rc = lpfc_sli4_redisc_fcf_table(phba); if (rc) { lpfc_printf_log(phba, KERN_ERR, LOG_FIP | - LOG_DISCOVERY, + LOG_TRACE_EVENT, "2774 Issue FCF rediscover " "mailbox command failed, " "through to CVL event\n"); @@ -5809,9 +5888,9 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, } break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "0288 Unknown FCoE event type 0x%x event tag " - "0x%x\n", event_type, acqe_fip->event_tag); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0288 Unknown FCoE event type 0x%x event tag " + "0x%x\n", event_type, acqe_fip->event_tag); break; } } @@ -5819,7 +5898,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, /** * lpfc_sli4_async_dcbx_evt - Process the asynchronous dcbx event * @phba: pointer to lpfc hba data structure. - * @acqe_link: pointer to the async dcbx completion queue entry. + * @acqe_dcbx: pointer to the async dcbx completion queue entry. * * This routine is to handle the SLI4 asynchronous dcbx event. **/ @@ -5828,7 +5907,7 @@ lpfc_sli4_async_dcbx_evt(struct lpfc_hba *phba, struct lpfc_acqe_dcbx *acqe_dcbx) { phba->fc_eventTag = acqe_dcbx->event_tag; - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0290 The SLI4 DCBX asynchronous event is not " "handled yet\n"); } @@ -5836,7 +5915,7 @@ lpfc_sli4_async_dcbx_evt(struct lpfc_hba *phba, /** * lpfc_sli4_async_grp5_evt - Process the asynchronous group5 event * @phba: pointer to lpfc hba data structure. - * @acqe_link: pointer to the async grp5 completion queue entry. + * @acqe_grp5: pointer to the async grp5 completion queue entry. * * This routine is to handle the SLI4 asynchronous grp5 event. A grp5 event * is an asynchronous notified of a logical link speed change. The Port @@ -5905,7 +5984,8 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *phba) lpfc_sli4_async_sli_evt(phba, &cq_event->cqe.acqe_sli); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "1804 Invalid asynchronous event code: " "x%x\n", bf_get(lpfc_trailer_code, &cq_event->cqe.mcqe_cmpl)); @@ -5941,7 +6021,7 @@ void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *phba) "2777 Start post-quiescent FCF table scan\n"); rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); if (rc) - lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2747 Issue FCF scan read FCF mailbox " "command failed 0x%x\n", rc); } @@ -6012,7 +6092,7 @@ static void lpfc_log_intr_mode(struct lpfc_hba *phba, uint32_t intr_mode) "0480 Enabled MSI-X interrupt mode.\n"); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0482 Illegal interrupt mode.\n"); break; } @@ -6060,7 +6140,7 @@ lpfc_enable_pci_dev(struct lpfc_hba *phba) out_disable_device: pci_disable_device(pdev); out_error: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1401 Failed to enable pci device\n"); return -ENODEV; } @@ -6161,7 +6241,7 @@ lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *phba, int nr_vfn) max_nr_vfn = lpfc_sli_sriov_nr_virtfn_get(phba); if (nr_vfn > max_nr_vfn) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3057 Requested vfs (%d) greater than " "supported vfs (%d)", nr_vfn, max_nr_vfn); return -EINVAL; @@ -6200,6 +6280,9 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba) * Driver resources common to all SLI revisions */ atomic_set(&phba->fast_event_count, 0); + atomic_set(&phba->dbg_log_idx, 0); + atomic_set(&phba->dbg_log_cnt, 0); + atomic_set(&phba->dbg_log_dmping, 0); spin_lock_init(&phba->hbalock); /* Initialize ndlp management spinlock */ @@ -6253,6 +6336,9 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba) INIT_DELAYED_WORK(&phba->eq_delay_work, lpfc_hb_eq_delay_work); + INIT_DELAYED_WORK(&phba->idle_stat_delay_work, + lpfc_idle_stat_delay_work); + return 0; } @@ -6624,7 +6710,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) lpfc_read_nv(phba, mboxq); rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "6016 Mailbox failed , mbxCmd x%x " "READ_NV, mbxStatus x%x\n", bf_get(lpfc_mqe_command, &mboxq->u.mqe), @@ -6653,11 +6740,13 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) phba->nvmet_support = 1; /* a match */ - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "6017 NVME Target %016llx\n", wwn); #else - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "6021 Can't enable NVME Target." " NVME_TARGET_FC infrastructure" " is not in kernel\n"); @@ -6717,9 +6806,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) &phba->sli4_hba.sli_intf); if (phba->sli4_hba.extents_in_use && phba->sli4_hba.rpi_hdrs_in_use) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2999 Unsupported SLI4 Parameters " - "Extents and RPI headers enabled.\n"); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2999 Unsupported SLI4 Parameters " + "Extents and RPI headers enabled.\n"); if (if_type == LPFC_SLI_INTF_IF_TYPE_0 && if_fam == LPFC_SLI_INTF_FAMILY_BE2) { mempool_free(mboxq, phba->mbox_mem_pool); @@ -6879,13 +6968,13 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) /* Allocate and initialize active sgl array */ rc = lpfc_init_active_sgl_array(phba); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1430 Failed to initialize sgl list.\n"); goto out_destroy_cq_event_pool; } rc = lpfc_sli4_init_rpi_hdrs(phba); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1432 Failed to initialize rpi headers.\n"); goto out_free_active_sgl; } @@ -6895,7 +6984,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) phba->fcf.fcf_rr_bmask = kcalloc(longs, sizeof(unsigned long), GFP_KERNEL); if (!phba->fcf.fcf_rr_bmask) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2759 Failed allocate memory for FCF round " "robin failover bmask\n"); rc = -ENOMEM; @@ -6906,7 +6995,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) sizeof(struct lpfc_hba_eq_hdl), GFP_KERNEL); if (!phba->sli4_hba.hba_eq_hdl) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2572 Failed allocate memory for " "fast-path per-EQ handle array\n"); rc = -ENOMEM; @@ -6917,7 +7006,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) sizeof(struct lpfc_vector_map_info), GFP_KERNEL); if (!phba->sli4_hba.cpu_map) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3327 Failed allocate memory for msi-x " "interrupt vector mapping\n"); rc = -ENOMEM; @@ -6926,19 +7015,29 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) phba->sli4_hba.eq_info = alloc_percpu(struct lpfc_eq_intr_info); if (!phba->sli4_hba.eq_info) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3321 Failed allocation for per_cpu stats\n"); rc = -ENOMEM; goto out_free_hba_cpu_map; } + phba->sli4_hba.idle_stat = kcalloc(phba->sli4_hba.num_possible_cpu, + sizeof(*phba->sli4_hba.idle_stat), + GFP_KERNEL); + if (!phba->sli4_hba.idle_stat) { + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "3390 Failed allocation for idle_stat\n"); + rc = -ENOMEM; + goto out_free_hba_eq_info; + } + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS phba->sli4_hba.c_stat = alloc_percpu(struct lpfc_hdwq_stat); if (!phba->sli4_hba.c_stat) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3332 Failed allocating per cpu hdwq stats\n"); rc = -ENOMEM; - goto out_free_hba_eq_info; + goto out_free_hba_idle_stat; } #endif @@ -6962,9 +7061,11 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) return 0; #ifdef CONFIG_SCSI_LPFC_DEBUG_FS +out_free_hba_idle_stat: + kfree(phba->sli4_hba.idle_stat); +#endif out_free_hba_eq_info: free_percpu(phba->sli4_hba.eq_info); -#endif out_free_hba_cpu_map: kfree(phba->sli4_hba.cpu_map); out_free_hba_eq_hdl: @@ -7006,6 +7107,7 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba) #ifdef CONFIG_SCSI_LPFC_DEBUG_FS free_percpu(phba->sli4_hba.c_stat); #endif + kfree(phba->sli4_hba.idle_stat); /* Free memory allocated for msi-x interrupt vector to CPU mapping */ kfree(phba->sli4_hba.cpu_map); @@ -7080,7 +7182,7 @@ lpfc_init_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) phba->lpfc_stop_port = lpfc_stop_port_s4; break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1431 Invalid HBA PCI-device group: 0x%x\n", dev_grp); return -ENODEV; @@ -7164,6 +7266,7 @@ lpfc_free_iocb_list(struct lpfc_hba *phba) /** * lpfc_init_iocb_list - Allocate and initialize iocb list. * @phba: pointer to lpfc hba data structure. + * @iocb_count: number of requested iocbs * * This routine is invoked to allocate and initizlize the driver's IOCB * list and set up the IOCB tag array accordingly. @@ -7375,7 +7478,7 @@ lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *phba) rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); if (!rpi_hdr) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0391 Error during rpi post operation\n"); lpfc_sli4_remove_rpis(phba); rc = -ENODEV; @@ -7687,7 +7790,7 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost) if (phba->cfg_prot_mask && phba->cfg_prot_guard) { if ((old_mask != phba->cfg_prot_mask) || (old_guard != phba->cfg_prot_guard)) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1475 Registering BlockGuard with the " "SCSI layer: mask %d guard %d\n", phba->cfg_prot_mask, @@ -7696,7 +7799,7 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost) scsi_host_set_prot(shost, phba->cfg_prot_mask); scsi_host_set_guard(shost, phba->cfg_prot_guard); } else - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1479 Not Registering BlockGuard with the SCSI " "layer, Bad protection parameters: %d %d\n", old_mask, old_guard); @@ -7927,7 +8030,7 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba) * other register reads as the data may not be valid. Just exit. */ if (port_error) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1408 Port Failed POST - portsmphr=0x%x, " "perr=x%x, sfi=x%x, nip=x%x, ipc=x%x, scr1=x%x, " "scr2=x%x, hscratch=x%x, pstatus=x%x\n", @@ -7976,7 +8079,8 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba) readl(phba->sli4_hba.u.if_type0.UERRHIregaddr); if ((~phba->sli4_hba.ue_mask_lo & uerrlo_reg.word0) || (~phba->sli4_hba.ue_mask_hi & uerrhi_reg.word0)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "1422 Unrecoverable Error " "Detected during POST " "uerr_lo_reg=0x%x, " @@ -8003,7 +8107,7 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba) phba->work_status[1] = readl(phba->sli4_hba.u.if_type2. ERR2regaddr); - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2888 Unrecoverable port error " "following POST: port status reg " "0x%x, port_smphr reg 0x%x, " @@ -8116,6 +8220,7 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type) /** * lpfc_sli4_bar1_register_memmap - Set up SLI4 BAR1 register memory map. * @phba: pointer to lpfc hba data structure. + * @if_type: sli if type to operate on. * * This routine is invoked to set up SLI4 BAR1 register memory map. **/ @@ -8297,20 +8402,19 @@ static const char * const lpfc_topo_to_str[] = { "P2P then Loop", }; +#define LINK_FLAGS_DEF 0x0 +#define LINK_FLAGS_P2P 0x1 +#define LINK_FLAGS_LOOP 0x2 /** * lpfc_map_topology - Map the topology read from READ_CONFIG * @phba: pointer to lpfc hba data structure. - * @rdconf: pointer to read config data + * @rd_config: pointer to read config data * * This routine is invoked to map the topology values as read * from the read config mailbox command. If the persistent * topology feature is supported, the firmware will provide the * saved topology information to be used in INIT_LINK - * **/ -#define LINK_FLAGS_DEF 0x0 -#define LINK_FLAGS_P2P 0x1 -#define LINK_FLAGS_LOOP 0x2 static void lpfc_map_topology(struct lpfc_hba *phba, struct lpfc_mbx_read_config *rd_config) { @@ -8397,7 +8501,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmb) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2011 Unable to allocate memory for issuing " "SLI_CONFIG_SPECIAL mailbox command\n"); return -ENOMEM; @@ -8407,11 +8511,11 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "2012 Mailbox failed , mbxCmd x%x " - "READ_CONFIG, mbxStatus x%x\n", - bf_get(lpfc_mqe_command, &pmb->u.mqe), - bf_get(lpfc_mqe_status, &pmb->u.mqe)); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2012 Mailbox failed , mbxCmd x%x " + "READ_CONFIG, mbxStatus x%x\n", + bf_get(lpfc_mqe_command, &pmb->u.mqe), + bf_get(lpfc_mqe_status, &pmb->u.mqe)); rc = -EIO; } else { rd_config = &pmb->u.mqe.un.rd_config; @@ -8521,7 +8625,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) /* Check to see if there is enough for NVME */ if ((phba->cfg_irq_chann > qmin) || (phba->cfg_hdw_queue > qmin)) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2005 Reducing Queues: " "WQ %d CQ %d EQ %d: min %d: " "IRQ %d HDWQ %d\n", @@ -8587,7 +8691,8 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) LPFC_USER_LINK_SPEED_AUTO; break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "0047 Unrecognized link " "speed : %d\n", forced_link_speed); @@ -8624,7 +8729,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (rc2 || shdr_status || shdr_add_status) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3026 Mailbox failed , mbxCmd x%x " "GET_FUNCTION_CONFIG, mbxStatus x%x\n", bf_get(lpfc_mqe_command, &pmb->u.mqe), @@ -8661,7 +8766,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) "vf_number:%d\n", phba->sli4_hba.iov.pf_number, phba->sli4_hba.iov.vf_number); else - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3028 GET_FUNCTION_CONFIG: failed to find " "Resource Descriptor:x%x\n", LPFC_RSRC_DESC_TYPE_FCFCOE); @@ -8698,7 +8803,7 @@ lpfc_setup_endian_order(struct lpfc_hba *phba) mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0492 Unable to allocate memory for " "issuing SLI_CONFIG_SPECIAL mailbox " "command\n"); @@ -8713,7 +8818,7 @@ lpfc_setup_endian_order(struct lpfc_hba *phba) memcpy(&mboxq->u.mqe, &endian_mb_data, sizeof(endian_mb_data)); rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0493 SLI_CONFIG_SPECIAL mailbox " "failed with status x%x\n", rc); @@ -8793,8 +8898,9 @@ lpfc_alloc_io_wq_cq(struct lpfc_hba *phba, int idx) phba->sli4_hba.cq_esize, phba->sli4_hba.cq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0499 Failed allocate fast-path IO CQ (%d)\n", idx); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0499 Failed allocate fast-path IO CQ (%d)\n", + idx); return 1; } qdesc->qe_valid = 1; @@ -8816,7 +8922,7 @@ lpfc_alloc_io_wq_cq(struct lpfc_hba *phba, int idx) phba->sli4_hba.wq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0503 Failed allocate fast-path IO WQ (%d)\n", idx); return 1; @@ -8872,7 +8978,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->cfg_hdw_queue, sizeof(struct lpfc_sli4_hdw_queue), GFP_KERNEL); if (!phba->sli4_hba.hdwq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6427 Failed allocate memory for " "fast-path Hardware Queue array\n"); goto out_error; @@ -8904,7 +9010,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) sizeof(struct lpfc_queue *), GFP_KERNEL); if (!phba->sli4_hba.nvmet_cqset) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3121 Fail allocate memory for " "fast-path CQ set array\n"); goto out_error; @@ -8914,7 +9020,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) sizeof(struct lpfc_queue *), GFP_KERNEL); if (!phba->sli4_hba.nvmet_mrq_hdr) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3122 Fail allocate memory for " "fast-path RQ set hdr array\n"); goto out_error; @@ -8924,7 +9030,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) sizeof(struct lpfc_queue *), GFP_KERNEL); if (!phba->sli4_hba.nvmet_mrq_data) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3124 Fail allocate memory for " "fast-path RQ set data array\n"); goto out_error; @@ -8952,7 +9058,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.eq_esize, phba->sli4_hba.eq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0497 Failed allocate EQ (%d)\n", cpup->hdwq); goto out_error; @@ -9006,7 +9112,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.cq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3142 Failed allocate NVME " "CQ Set (%d)\n", idx); goto out_error; @@ -9028,7 +9134,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.cq_esize, phba->sli4_hba.cq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0500 Failed allocate slow-path mailbox CQ\n"); goto out_error; } @@ -9040,7 +9146,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.cq_esize, phba->sli4_hba.cq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0501 Failed allocate slow-path ELS CQ\n"); goto out_error; } @@ -9059,7 +9165,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.mq_esize, phba->sli4_hba.mq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0505 Failed allocate slow-path MQ\n"); goto out_error; } @@ -9075,7 +9181,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.wq_esize, phba->sli4_hba.wq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0504 Failed allocate slow-path ELS WQ\n"); goto out_error; } @@ -9089,7 +9195,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.cq_esize, phba->sli4_hba.cq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6079 Failed allocate NVME LS CQ\n"); goto out_error; } @@ -9102,7 +9208,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.wq_esize, phba->sli4_hba.wq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6080 Failed allocate NVME LS WQ\n"); goto out_error; } @@ -9120,7 +9226,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.rq_esize, phba->sli4_hba.rq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0506 Failed allocate receive HRQ\n"); goto out_error; } @@ -9131,7 +9237,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.rq_esize, phba->sli4_hba.rq_ecount, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0507 Failed allocate receive DRQ\n"); goto out_error; } @@ -9149,7 +9255,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) LPFC_NVMET_RQE_DEF_COUNT, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3146 Failed allocate " "receive HRQ\n"); goto out_error; @@ -9162,7 +9268,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) GFP_KERNEL, cpu_to_node(cpu)); if (qdesc->rqbp == NULL) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6131 Failed allocate " "Header RQBP\n"); goto out_error; @@ -9178,7 +9284,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) LPFC_NVMET_RQE_DEF_COUNT, cpu); if (!qdesc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3156 Failed allocate " "receive DRQ\n"); goto out_error; @@ -9369,7 +9475,7 @@ lpfc_create_wq_cq(struct lpfc_hba *phba, struct lpfc_queue *eq, int rc; if (!eq || !cq || !wq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6085 Fast-path %s (%d) not allocated\n", ((eq) ? ((cq) ? "WQ" : "CQ") : "EQ"), qidx); return -ENOMEM; @@ -9379,9 +9485,9 @@ lpfc_create_wq_cq(struct lpfc_hba *phba, struct lpfc_queue *eq, rc = lpfc_cq_create(phba, cq, eq, (qtype == LPFC_MBOX) ? LPFC_MCQ : LPFC_WCQ, qtype); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "6086 Failed setup of CQ (%d), rc = 0x%x\n", - qidx, (uint32_t)rc); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "6086 Failed setup of CQ (%d), rc = 0x%x\n", + qidx, (uint32_t)rc); return rc; } @@ -9397,7 +9503,7 @@ lpfc_create_wq_cq(struct lpfc_hba *phba, struct lpfc_queue *eq, /* create the wq */ rc = lpfc_wq_create(phba, wq, cq, qtype); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "4618 Fail setup fastpath WQ (%d), rc = 0x%x\n", qidx, (uint32_t)rc); /* no need to tear down cq - caller will do so */ @@ -9415,9 +9521,9 @@ lpfc_create_wq_cq(struct lpfc_hba *phba, struct lpfc_queue *eq, } else { rc = lpfc_mq_create(phba, wq, cq, LPFC_MBOX); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0539 Failed setup of slow-path MQ: " - "rc = 0x%x\n", rc); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0539 Failed setup of slow-path MQ: " + "rc = 0x%x\n", rc); /* no need to tear down cq - caller will do so */ return rc; } @@ -9490,7 +9596,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) /* Check for dual-ULP support */ mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3249 Unable to allocate memory for " "QUERY_FW_CFG mailbox command\n"); return -ENOMEM; @@ -9508,7 +9614,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3250 QUERY_FW_CFG mailbox failed with status " "x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -9539,7 +9645,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) /* Set up HBA event queue */ if (!qp) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3147 Fast-path EQs not allocated\n"); rc = -ENOMEM; goto out_error; @@ -9563,7 +9669,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) rc = lpfc_eq_create(phba, qp[cpup->hdwq].hba_eq, phba->cfg_fcp_imax); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0523 Failed setup of fast-path" " EQ (%d), rc = 0x%x\n", cpup->eq, (uint32_t)rc); @@ -9595,7 +9701,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) qidx, LPFC_IO); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0535 Failed to setup fastpath " "IO WQ/CQ (%d), rc = 0x%x\n", qidx, (uint32_t)rc); @@ -9610,7 +9716,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) /* Set up slow-path MBOX CQ/MQ */ if (!phba->sli4_hba.mbx_cq || !phba->sli4_hba.mbx_wq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0528 %s not allocated\n", phba->sli4_hba.mbx_cq ? "Mailbox WQ" : "Mailbox CQ"); @@ -9623,14 +9729,14 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) phba->sli4_hba.mbx_wq, NULL, 0, LPFC_MBOX); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0529 Failed setup of mailbox WQ/CQ: rc = 0x%x\n", (uint32_t)rc); goto out_destroy; } if (phba->nvmet_support) { if (!phba->sli4_hba.nvmet_cqset) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3165 Fast-path NVME CQ Set " "array not allocated\n"); rc = -ENOMEM; @@ -9642,7 +9748,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) qp, LPFC_WCQ, LPFC_NVMET); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3164 Failed setup of NVME CQ " "Set, rc = 0x%x\n", (uint32_t)rc); @@ -9654,7 +9760,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) qp[0].hba_eq, LPFC_WCQ, LPFC_NVMET); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6089 Failed setup NVMET CQ: " "rc = 0x%x\n", (uint32_t)rc); goto out_destroy; @@ -9671,7 +9777,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) /* Set up slow-path ELS WQ/CQ */ if (!phba->sli4_hba.els_cq || !phba->sli4_hba.els_wq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0530 ELS %s not allocated\n", phba->sli4_hba.els_cq ? "WQ" : "CQ"); rc = -ENOMEM; @@ -9682,7 +9788,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) phba->sli4_hba.els_wq, NULL, 0, LPFC_ELS); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0525 Failed setup of ELS WQ/CQ: rc = 0x%x\n", (uint32_t)rc); goto out_destroy; @@ -9695,7 +9801,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { /* Set up NVME LS Complete Queue */ if (!phba->sli4_hba.nvmels_cq || !phba->sli4_hba.nvmels_wq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6091 LS %s not allocated\n", phba->sli4_hba.nvmels_cq ? "WQ" : "CQ"); rc = -ENOMEM; @@ -9706,7 +9812,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) phba->sli4_hba.nvmels_wq, NULL, 0, LPFC_NVME_LS); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0526 Failed setup of NVVME LS WQ/CQ: " "rc = 0x%x\n", (uint32_t)rc); goto out_destroy; @@ -9726,7 +9832,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) if ((!phba->sli4_hba.nvmet_cqset) || (!phba->sli4_hba.nvmet_mrq_hdr) || (!phba->sli4_hba.nvmet_mrq_data)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6130 MRQ CQ Queues not " "allocated\n"); rc = -ENOMEM; @@ -9739,7 +9845,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) phba->sli4_hba.nvmet_cqset, LPFC_NVMET); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6098 Failed setup of NVMET " "MRQ: rc = 0x%x\n", (uint32_t)rc); @@ -9753,7 +9859,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) phba->sli4_hba.nvmet_cqset[0], LPFC_NVMET); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6057 Failed setup of NVMET " "Receive Queue: rc = 0x%x\n", (uint32_t)rc); @@ -9772,7 +9878,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) } if (!phba->sli4_hba.hdr_rq || !phba->sli4_hba.dat_rq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0540 Receive Queue not allocated\n"); rc = -ENOMEM; goto out_destroy; @@ -9781,7 +9887,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) rc = lpfc_rq_create(phba, phba->sli4_hba.hdr_rq, phba->sli4_hba.dat_rq, phba->sli4_hba.els_cq, LPFC_USOL); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0541 Failed setup of Receive Queue: " "rc = 0x%x\n", (uint32_t)rc); goto out_destroy; @@ -9809,7 +9915,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) phba->sli4_hba.cq_lookup = kcalloc((phba->sli4_hba.cq_max + 1), sizeof(struct lpfc_queue *), GFP_KERNEL); if (!phba->sli4_hba.cq_lookup) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0549 Failed setup of CQ Lookup table: " "size 0x%x\n", phba->sli4_hba.cq_max); rc = -ENOMEM; @@ -10109,7 +10215,7 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0494 Unable to allocate memory for " "issuing SLI_FUNCTION_RESET mailbox " "command\n"); @@ -10129,7 +10235,7 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) if (rc != MBX_TIMEOUT) mempool_free(mboxq, phba->mbox_mem_pool); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0495 SLI_FUNCTION_RESET mailbox " "failed with status x%x add_status x%x," " mbx status x%x\n", @@ -10161,7 +10267,7 @@ wait: phba->sli4_hba.u.if_type2.ERR1regaddr); phba->work_status[1] = readl( phba->sli4_hba.u.if_type2.ERR2regaddr); - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2890 Port not ready, port status reg " "0x%x error 1=0x%x, error 2=0x%x\n", reg_data.word0, @@ -10203,7 +10309,7 @@ wait: out: /* Catch the not-ready port failure after a port reset. */ if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3317 HBA not functional: IP Reset Failed " "try: echo fw_reset > board_mode\n"); rc = -ENODEV; @@ -10253,7 +10359,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) /* There is no SLI3 failback for SLI4 devices. */ if (bf_get(lpfc_sli_intf_valid, &phba->sli4_hba.sli_intf) != LPFC_SLI_INTF_VALID) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2894 SLI_INTF reg contents invalid " "sli_intf reg 0x%x\n", phba->sli4_hba.sli_intf.word0); @@ -10528,7 +10634,7 @@ lpfc_sli_enable_msix(struct lpfc_hba *phba) if (!pmb) { rc = -ENOMEM; - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0474 Unable to allocate memory for issuing " "MBOX_CONFIG_MSI command\n"); goto mem_fail_out; @@ -10611,6 +10717,7 @@ lpfc_sli_enable_msi(struct lpfc_hba *phba) /** * lpfc_sli_enable_intr - Enable device interrupt to SLI-3 device. * @phba: pointer to lpfc hba data structure. + * @cfg_mode: Interrupt configuration mode (INTx, MSI or MSI-X). * * This routine is invoked to enable device interrupt and associate driver's * interrupt handler(s) to interrupt vector(s) to device with SLI-3 interface @@ -11008,7 +11115,7 @@ found_any: /* 1 to 1, the first LPFC_CPU_FIRST_IRQ cpus to a unique hdwq */ cpup->hdwq = idx; idx++; - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "3333 Set Affinity: CPU %d (phys %d core %d): " "hdwq %d eq %d flg x%x\n", cpu, cpup->phys_id, cpup->core_id, @@ -11086,7 +11193,7 @@ found_any: start_cpu = first_cpu; cpup->hdwq = new_cpup->hdwq; logit: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "3335 Set Affinity: CPU %d (phys %d core %d): " "hdwq %d eq %d flg x%x\n", cpu, cpup->phys_id, cpup->core_id, @@ -11128,7 +11235,7 @@ found_any: * * @phba: pointer to lpfc hba data structure. * @cpu: cpu going offline - * @eqlist: + * @eqlist: eq list to append to */ static int lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu, @@ -11417,9 +11524,9 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba) char *name; const struct cpumask *aff_mask = NULL; unsigned int cpu = 0, cpu_cnt = 0, cpu_select = nr_cpu_ids; + struct lpfc_vector_map_info *cpup; struct lpfc_hba_eq_hdl *eqhdl; const struct cpumask *maskp; - bool first; unsigned int flags = PCI_IRQ_MSIX; /* Set up MSI-X multi-message vectors */ @@ -11492,24 +11599,34 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba) } else { maskp = pci_irq_get_affinity(phba->pcidev, index); - first = true; /* Loop through all CPUs associated with vector index */ for_each_cpu_and(cpu, maskp, cpu_present_mask) { + cpup = &phba->sli4_hba.cpu_map[cpu]; + /* If this is the first CPU thats assigned to * this vector, set LPFC_CPU_FIRST_IRQ. + * + * With certain platforms its possible that irq + * vectors are affinitized to all the cpu's. + * This can result in each cpu_map.eq to be set + * to the last vector, resulting in overwrite + * of all the previous cpu_map.eq. Ensure that + * each vector receives a place in cpu_map. + * Later call to lpfc_cpu_affinity_check will + * ensure we are nicely balanced out. */ + if (cpup->eq != LPFC_VECTOR_MAP_EMPTY) + continue; lpfc_assign_eq_map_info(phba, index, - first ? - LPFC_CPU_FIRST_IRQ : 0, + LPFC_CPU_FIRST_IRQ, cpu); - if (first) - first = false; + break; } } } if (vectors != phba->cfg_irq_chann) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3238 Reducing IO channels to match number of " "MSI-X vectors, requested %d got %d\n", phba->cfg_irq_chann, vectors); @@ -11593,6 +11710,7 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba) /** * lpfc_sli4_enable_intr - Enable device interrupt to SLI-4 device * @phba: pointer to lpfc hba data structure. + * @cfg_mode: Interrupt configuration mode (INTx, MSI or MSI-X). * * This routine is invoked to enable device interrupt and associate driver's * interrupt handler(s) to interrupt vector(s) to device with SLI-4 @@ -11782,17 +11900,17 @@ lpfc_sli4_xri_exchange_busy_wait(struct lpfc_hba *phba) while (!els_xri_cmpl || !io_xri_cmpl || !nvmet_xri_cmpl) { if (wait_time > LPFC_XRI_EXCH_BUSY_WAIT_TMO) { if (!nvmet_xri_cmpl) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6424 NVMET XRI exchange busy " "wait time: %d seconds.\n", wait_time/1000); if (!io_xri_cmpl) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6100 IO XRI exchange busy " "wait time: %d seconds.\n", wait_time/1000); if (!els_xri_cmpl) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2878 ELS XRI exchange busy " "wait time: %d seconds.\n", wait_time/1000); @@ -12287,14 +12405,14 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid) /* Configure and enable interrupt */ intr_mode = lpfc_sli_enable_intr(phba, cfg_mode); if (intr_mode == LPFC_INTR_ERROR) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0431 Failed to enable interrupt.\n"); error = -ENODEV; goto out_free_sysfs_attr; } /* SLI-3 HBA setup */ if (lpfc_sli_hba_setup(phba)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1477 Failed to set up hba\n"); error = -ENODEV; goto out_remove_device; @@ -12552,7 +12670,7 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev) /* Configure and enable interrupt */ intr_mode = lpfc_sli_enable_intr(phba, phba->intr_mode); if (intr_mode == LPFC_INTR_ERROR) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0430 PM resume Failed to enable interrupt\n"); return -EIO; } else @@ -12578,7 +12696,7 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev) static void lpfc_sli_prep_dev_for_recover(struct lpfc_hba *phba) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2723 PCI channel I/O abort preparing for recovery\n"); /* @@ -12599,7 +12717,7 @@ lpfc_sli_prep_dev_for_recover(struct lpfc_hba *phba) static void lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2710 PCI channel disable preparing for reset\n"); /* Block any management I/Os to the device */ @@ -12630,7 +12748,7 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba) static void lpfc_sli_prep_dev_for_perm_failure(struct lpfc_hba *phba) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2711 PCI channel permanent disable for failure\n"); /* Block all SCSI devices' I/Os on the host */ lpfc_scsi_dev_block(phba); @@ -12681,7 +12799,7 @@ lpfc_io_error_detected_s3(struct pci_dev *pdev, pci_channel_state_t state) return PCI_ERS_RESULT_DISCONNECT; default: /* Unknown state, prepare and request slot reset */ - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0472 Unknown PCI error state: x%x\n", state); lpfc_sli_prep_dev_for_reset(phba); return PCI_ERS_RESULT_NEED_RESET; @@ -12739,7 +12857,7 @@ lpfc_io_slot_reset_s3(struct pci_dev *pdev) /* Configure and enable interrupt */ intr_mode = lpfc_sli_enable_intr(phba, phba->intr_mode); if (intr_mode == LPFC_INTR_ERROR) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0427 Cannot re-enable interrupt after " "slot reset.\n"); return PCI_ERS_RESULT_DISCONNECT; @@ -12842,7 +12960,7 @@ lpfc_log_write_firmware_error(struct lpfc_hba *phba, uint32_t offset, magic_number != MAGIC_NUMBER_G6) || (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC && magic_number != MAGIC_NUMBER_G7)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3030 This firmware version is not supported on" " this HBA model. Device:%x Magic:%x Type:%x " "ID:%x Size %d %zd\n", @@ -12850,7 +12968,7 @@ lpfc_log_write_firmware_error(struct lpfc_hba *phba, uint32_t offset, fsize, fw->size); rc = -EINVAL; } else if (offset == ADD_STATUS_FW_DOWNLOAD_HW_DISABLED) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3021 Firmware downloads have been prohibited " "by a system configuration setting on " "Device:%x Magic:%x Type:%x ID:%x Size %d " @@ -12859,7 +12977,7 @@ lpfc_log_write_firmware_error(struct lpfc_hba *phba, uint32_t offset, fsize, fw->size); rc = -EACCES; } else { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3022 FW Download failed. Add Status x%x " "Device:%x Magic:%x Type:%x ID:%x Size %d " "%zd\n", @@ -12874,7 +12992,6 @@ lpfc_log_write_firmware_error(struct lpfc_hba *phba, uint32_t offset, * lpfc_write_firmware - attempt to write a firmware image to the port * @fw: pointer to firmware image returned from request_firmware. * @context: pointer to firmware image returned from request_firmware. - * @ret: return value this routine provides to the caller. * **/ static void @@ -12904,7 +13021,7 @@ lpfc_write_firmware(const struct firmware *fw, void *context) INIT_LIST_HEAD(&dma_buffer_list); lpfc_decode_firmware_rev(phba, fwrev, 1); if (strncmp(fwrev, image->revision, strnlen(image->revision, 16))) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3023 Updating Firmware, Current Version:%s " "New Version:%s\n", fwrev, image->revision); @@ -12954,7 +13071,7 @@ lpfc_write_firmware(const struct firmware *fw, void *context) } rc = offset; } else - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3029 Skipped Firmware update, Current " "Version:%s New Version:%s\n", fwrev, image->revision); @@ -12969,16 +13086,17 @@ release_out: release_firmware(fw); out: if (rc < 0) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3062 Firmware update error, status %d.\n", rc); else - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3024 Firmware update success: size %d.\n", rc); } /** * lpfc_sli4_request_firmware_update - Request linux generic firmware upgrade * @phba: pointer to lpfc hba data structure. + * @fw_upgrade: which firmware to update. * * This routine is called to perform Linux generic firmware upgrade on device * that supports such feature. @@ -13101,7 +13219,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) /* Configure and enable interrupt */ intr_mode = lpfc_sli4_enable_intr(phba, cfg_mode); if (intr_mode == LPFC_INTR_ERROR) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0426 Failed to enable interrupt.\n"); error = -ENODEV; goto out_unset_driver_resource; @@ -13136,7 +13254,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) /* Set up SLI-4 HBA */ if (lpfc_sli4_hba_setup(phba)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1421 Failed to set up hba\n"); error = -ENODEV; goto out_free_sysfs_attr; @@ -13161,7 +13279,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) */ error = lpfc_nvme_create_localport(vport); if (error) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6004 NVME registration " "failed, error x%x\n", error); @@ -13395,7 +13513,7 @@ lpfc_pci_resume_one_s4(struct pci_dev *pdev) /* Configure and enable interrupt */ intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode); if (intr_mode == LPFC_INTR_ERROR) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0294 PM resume Failed to enable interrupt\n"); return -EIO; } else @@ -13421,7 +13539,7 @@ lpfc_pci_resume_one_s4(struct pci_dev *pdev) static void lpfc_sli4_prep_dev_for_recover(struct lpfc_hba *phba) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2828 PCI channel I/O abort preparing for recovery\n"); /* * There may be errored I/Os through HBA, abort all I/Os on txcmplq @@ -13441,7 +13559,7 @@ lpfc_sli4_prep_dev_for_recover(struct lpfc_hba *phba) static void lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2826 PCI channel disable preparing for reset\n"); /* Block any management I/Os to the device */ @@ -13473,7 +13591,7 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba) static void lpfc_sli4_prep_dev_for_perm_failure(struct lpfc_hba *phba) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2827 PCI channel permanent disable for failure\n"); /* Block all SCSI devices' I/Os on the host */ @@ -13523,7 +13641,7 @@ lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state) return PCI_ERS_RESULT_DISCONNECT; default: /* Unknown state, prepare and request slot reset */ - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2825 Unknown PCI error state: x%x\n", state); lpfc_sli4_prep_dev_for_reset(phba); return PCI_ERS_RESULT_NEED_RESET; @@ -13581,7 +13699,7 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev) /* Configure and enable interrupt */ intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode); if (intr_mode == LPFC_INTR_ERROR) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2824 Cannot re-enable interrupt after " "slot reset.\n"); return PCI_ERS_RESULT_DISCONNECT; @@ -13686,7 +13804,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev) lpfc_pci_remove_one_s4(pdev); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1424 Invalid PCI device group: 0x%x\n", phba->pci_dev_grp); break; @@ -13723,7 +13841,7 @@ lpfc_pci_suspend_one(struct pci_dev *pdev, pm_message_t msg) rc = lpfc_pci_suspend_one_s4(pdev, msg); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1425 Invalid PCI device group: 0x%x\n", phba->pci_dev_grp); break; @@ -13759,7 +13877,7 @@ lpfc_pci_resume_one(struct pci_dev *pdev) rc = lpfc_pci_resume_one_s4(pdev); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1426 Invalid PCI device group: 0x%x\n", phba->pci_dev_grp); break; @@ -13797,7 +13915,7 @@ lpfc_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) rc = lpfc_io_error_detected_s4(pdev, state); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1427 Invalid PCI device group: 0x%x\n", phba->pci_dev_grp); break; @@ -13834,7 +13952,7 @@ lpfc_io_slot_reset(struct pci_dev *pdev) rc = lpfc_io_slot_reset_s4(pdev); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1428 Invalid PCI device group: 0x%x\n", phba->pci_dev_grp); break; @@ -13866,7 +13984,7 @@ lpfc_io_resume(struct pci_dev *pdev) lpfc_io_resume_s4(pdev); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1429 Invalid PCI device group: 0x%x\n", phba->pci_dev_grp); break; @@ -13974,8 +14092,8 @@ lpfc_init(void) { int error = 0; - printk(LPFC_MODULE_DESC "\n"); - printk(LPFC_COPYRIGHT "\n"); + pr_info(LPFC_MODULE_DESC "\n"); + pr_info(LPFC_COPYRIGHT "\n"); error = misc_register(&lpfc_mgmt_dev); if (error) @@ -14022,6 +14140,85 @@ cpuhp_failure: return error; } +void lpfc_dmp_dbg(struct lpfc_hba *phba) +{ + unsigned int start_idx; + unsigned int dbg_cnt; + unsigned int temp_idx; + int i; + int j = 0; + unsigned long rem_nsec; + + if (phba->cfg_log_verbose) + return; + + if (atomic_cmpxchg(&phba->dbg_log_dmping, 0, 1) != 0) + return; + + start_idx = (unsigned int)atomic_read(&phba->dbg_log_idx) % DBG_LOG_SZ; + dbg_cnt = (unsigned int)atomic_read(&phba->dbg_log_cnt); + temp_idx = start_idx; + if (dbg_cnt >= DBG_LOG_SZ) { + dbg_cnt = DBG_LOG_SZ; + temp_idx -= 1; + } else { + if ((start_idx + dbg_cnt) > (DBG_LOG_SZ - 1)) { + temp_idx = (start_idx + dbg_cnt) % DBG_LOG_SZ; + } else { + if (start_idx < dbg_cnt) + start_idx = DBG_LOG_SZ - (dbg_cnt - start_idx); + else + start_idx -= dbg_cnt; + } + } + dev_info(&phba->pcidev->dev, "start %d end %d cnt %d\n", + start_idx, temp_idx, dbg_cnt); + + for (i = 0; i < dbg_cnt; i++) { + if ((start_idx + i) < DBG_LOG_SZ) + temp_idx = (start_idx + i) % DBG_LOG_SZ; + else + temp_idx = j++; + rem_nsec = do_div(phba->dbg_log[temp_idx].t_ns, NSEC_PER_SEC); + dev_info(&phba->pcidev->dev, "%d: [%5lu.%06lu] %s", + temp_idx, + (unsigned long)phba->dbg_log[temp_idx].t_ns, + rem_nsec / 1000, + phba->dbg_log[temp_idx].log); + } + atomic_set(&phba->dbg_log_cnt, 0); + atomic_set(&phba->dbg_log_dmping, 0); +} + +__printf(2, 3) +void lpfc_dbg_print(struct lpfc_hba *phba, const char *fmt, ...) +{ + unsigned int idx; + va_list args; + int dbg_dmping = atomic_read(&phba->dbg_log_dmping); + struct va_format vaf; + + + va_start(args, fmt); + if (unlikely(dbg_dmping)) { + vaf.fmt = fmt; + vaf.va = &args; + dev_info(&phba->pcidev->dev, "%pV", &vaf); + va_end(args); + return; + } + idx = (unsigned int)atomic_fetch_add(1, &phba->dbg_log_idx) % + DBG_LOG_SZ; + + atomic_inc(&phba->dbg_log_cnt); + + vscnprintf(phba->dbg_log[idx].log, + sizeof(phba->dbg_log[idx].log), fmt, args); + va_end(args); + + phba->dbg_log[idx].t_ns = local_clock(); +} + /** * lpfc_exit - lpfc module removal routine * diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index 148d02a27b58f6443561328d32bea42ce92d1793..5660a872946258ad696ccc335e51f6408f7ffc72 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h @@ -44,7 +44,11 @@ #define LOG_NVME_DISC 0x00200000 /* NVME Discovery/Connect events. */ #define LOG_NVME_ABTS 0x00400000 /* NVME ABTS events. */ #define LOG_NVME_IOERR 0x00800000 /* NVME IO Error events. */ -#define LOG_ALL_MSG 0xffffffff /* LOG all messages */ +#define LOG_TRACE_EVENT 0x80000000 /* Dmp the DBG log on this err */ +#define LOG_ALL_MSG 0x7fffffff /* LOG all messages */ + +void lpfc_dmp_dbg(struct lpfc_hba *phba); +void lpfc_dbg_print(struct lpfc_hba *phba, const char *fmt, ...); /* generate message by verbose log setting or severity */ #define lpfc_vlog_msg(vport, level, mask, fmt, arg...) \ @@ -65,9 +69,15 @@ do { \ #define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \ do { \ - { if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '3')) \ + { if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '3')) { \ + if ((mask) & LOG_TRACE_EVENT) \ + lpfc_dmp_dbg((vport)->phba); \ dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \ - fmt, (vport)->phba->brd_no, vport->vpi, ##arg); } \ + fmt, (vport)->phba->brd_no, vport->vpi, ##arg); \ + } else if (!(vport)->cfg_log_verbose) \ + lpfc_dbg_print((vport)->phba, "%d:(%d):" fmt, \ + (vport)->phba->brd_no, (vport)->vpi, ##arg); \ + } \ } while (0) #define lpfc_printf_log(phba, level, mask, fmt, arg...) \ @@ -75,8 +85,12 @@ do { \ { uint32_t log_verbose = (phba)->pport ? \ (phba)->pport->cfg_log_verbose : \ (phba)->cfg_log_verbose; \ - if (((mask) & log_verbose) || (level[1] <= '3')) \ + if (((mask) & log_verbose) || (level[1] <= '3')) { \ + if ((mask) & LOG_TRACE_EVENT) \ + lpfc_dmp_dbg(phba); \ dev_printk(level, &((phba)->pcidev)->dev, "%d:" \ - fmt, phba->brd_no, ##arg); \ + fmt, phba->brd_no, ##arg); \ + } else if (!(phba)->cfg_log_verbose)\ + lpfc_dbg_print(phba, "%d:" fmt, phba->brd_no, ##arg); \ } \ } while (0) diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index e34e0f11bfdd5aae62357860e66a97454009b459..3414ffcb26fed84394b0a63a3cc54aeaacfda24c 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -868,9 +868,7 @@ lpfc_sli4_unreg_all_rpis(struct lpfc_vport *vport) /** * lpfc_reg_vpi - Prepare a mailbox command for registering vport identifier - * @phba: pointer to lpfc hba data structure. - * @vpi: virtual N_Port identifier. - * @sid: Fibre Channel S_ID (N_Port_ID assigned to a virtual N_Port). + * @vport: pointer to a vport object. * @pmb: pointer to the driver internal queue element for mailbox command. * * The registration vport identifier mailbox command is used to activate a @@ -1199,7 +1197,7 @@ lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id, /** * lpfc_config_ring - Prepare a mailbox command for configuring an IOCB ring * @phba: pointer to lpfc hba data structure. - * @ring: + * @ring: ring number/index * @pmb: pointer to the driver internal queue element for mailbox command. * * The configure ring mailbox command is used to configure an IOCB ring. This @@ -1613,7 +1611,7 @@ lpfc_mbox_dev_check(struct lpfc_hba *phba) /** * lpfc_mbox_tmo_val - Retrieve mailbox command timeout value * @phba: pointer to lpfc hba data structure. - * @cmd: mailbox command code. + * @mboxq: pointer to the driver internal queue element for mailbox command. * * This routine retrieves the proper timeout value according to the mailbox * command code. @@ -1700,6 +1698,7 @@ lpfc_sli4_mbx_sge_set(struct lpfcMboxq *mbox, uint32_t sgentry, * lpfc_sli4_mbx_sge_get - Get a sge entry from non-embedded mailbox command * @mbox: pointer to lpfc mbox command. * @sgentry: sge entry index. + * @sge: pointer to lpfc mailbox sge to load into. * * This routine gets an entry from the non-embedded mailbox command at the sge * index location. @@ -1767,6 +1766,7 @@ lpfc_sli4_mbox_cmd_free(struct lpfc_hba *phba, struct lpfcMboxq *mbox) * @subsystem: The sli4 config sub mailbox subsystem. * @opcode: The sli4 config sub mailbox command opcode. * @length: Length of the sli4 config mailbox command (including sub-header). + * @emb: True if embedded mbox command should be setup. * * This routine sets up the header fields of SLI4 specific mailbox command * for sending IOCTL command. @@ -2012,6 +2012,7 @@ lpfc_sli_config_mbox_opcode_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) /** * lpfc_sli4_mbx_read_fcf_rec - Allocate and construct read fcf mbox cmd * @phba: pointer to lpfc hba data structure. + * @mboxq: pointer to lpfc mbox command. * @fcf_index: index to fcf table. * * This routine routine allocates and constructs non-embedded mailbox command @@ -2068,6 +2069,7 @@ lpfc_sli4_mbx_read_fcf_rec(struct lpfc_hba *phba, /** * lpfc_request_features: Configure SLI4 REQUEST_FEATURES mailbox + * @phba: pointer to lpfc hba data structure. * @mboxq: pointer to lpfc mbox command. * * This routine sets up the mailbox for an SLI4 REQUEST_FEATURES diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 726f6619230fda193a434323a800cc552d7ed383..27ff67e9edae72ac4f61c178296f2a3c3104f559 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -45,6 +45,7 @@ #define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */ #define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */ #define LPFC_DEVICE_DATA_POOL_SIZE 64 /* max elements in device data pool */ +#define LPFC_RRQ_POOL_SIZE 256 /* max elements in non-DMA pool */ int lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *phba) { @@ -67,6 +68,7 @@ lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *phba) { /** * lpfc_mem_alloc - create and allocate all PCI and memory pools * @phba: HBA to allocate pools for + * @align: alignment requirement for blocks; must be a power of two * * Description: Creates and allocates PCI pools lpfc_mbuf_pool, * lpfc_hrb_pool. Creates and allocates kmalloc-backed mempools @@ -121,7 +123,7 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) if (phba->sli_rev == LPFC_SLI_REV4) { phba->rrq_pool = - mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, + mempool_create_kmalloc_pool(LPFC_RRQ_POOL_SIZE, sizeof(struct lpfc_node_rrq)); if (!phba->rrq_pool) goto fail_free_nlp_mem_pool; diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index d8501bd959e717a09dd809963f32a3f7d4aa396e..e4c710fe02451f317d13d08218ba04c908f150b0 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -152,7 +152,7 @@ lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name)); return 1; bad_service_param: - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0207 Device %x " "(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent " "invalid service parameters. Ignoring device.\n", @@ -301,7 +301,7 @@ lpfc_defer_pt2pt_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *link_mbox) /* Check for CONFIG_LINK error */ if (mb->mbxStatus) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "4575 CONFIG_LINK fails pt2pt discovery: %x\n", mb->mbxStatus); mempool_free(login_mbox, phba->mbox_mem_pool); @@ -316,7 +316,7 @@ lpfc_defer_pt2pt_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *link_mbox) rc = lpfc_els_rsp_acc(link_mbox->vport, ELS_CMD_PLOGI, save_iocb, ndlp, login_mbox); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "4576 PLOGI ACC fails pt2pt discovery: %x\n", rc); mempool_free(login_mbox, phba->mbox_mem_pool); @@ -361,7 +361,7 @@ lpfc_defer_acc_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_sli4_unreg_rpi_cmpl_clr(phba, pmb); if (!piocb) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY | LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "4578 PLOGI ACC fail\n"); if (mbox) mempool_free(mbox, phba->mbox_mem_pool); @@ -370,7 +370,7 @@ lpfc_defer_acc_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) rc = lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, piocb, ndlp, mbox); if (rc) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY | LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "4579 PLOGI ACC fail %x\n", rc); if (mbox) mempool_free(mbox, phba->mbox_mem_pool); @@ -405,7 +405,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lp = (uint32_t *) pcmd->virt; sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); if (wwn_to_u64(sp->portName.u.wwn) == 0) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0140 PLOGI Reject: invalid nname\n"); stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_PNAME; @@ -414,7 +414,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, return 0; } if (wwn_to_u64(sp->nodeName.u.wwn) == 0) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0141 PLOGI Reject: invalid pname\n"); stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_NNAME; @@ -481,7 +481,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } if (nlp_portwwn != 0 && nlp_portwwn != wwn_to_u64(sp->portName.u.wwn)) - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0143 PLOGI recv'd from DID: x%x " "WWPN changed: old %llx new %llx\n", ndlp->nlp_DID, @@ -689,7 +689,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, return 1; out: if (defer_acc) - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "4577 discovery failure: %p %p %p\n", save_iocb, link_mbox, login_mbox); kfree(save_iocb); @@ -797,11 +797,17 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp, NULL); } out: - /* If we are authenticated, move to the proper state */ - if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET)) - lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE); - else - lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); + /* If we are authenticated, move to the proper state. + * It is possible an ADISC arrived and the remote nport + * is already in MAPPED or UNMAPPED state. Catch this + * condition and don't set the nlp_state again because + * it causes an unnecessary transport unregister/register. + */ + if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET)) { + if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) + lpfc_nlp_set_state(vport, ndlp, + NLP_STE_MAPPED_NODE); + } return 1; } @@ -1062,6 +1068,7 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) * lpfc_release_rpi - Release a RPI by issuing unreg_login mailbox cmd. * @phba : Pointer to lpfc_hba structure. * @vport: Pointer to lpfc_vport structure. + * @ndlp: Pointer to lpfc_nodelist structure. * @rpi : rpi to be release. * * This function will send a unreg_login mailbox command to the firmware @@ -1091,8 +1098,8 @@ lpfc_release_rpi(struct lpfc_hba *phba, struct lpfc_vport *vport, pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmb) - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, - "2796 mailbox memory allocation failed \n"); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "2796 mailbox memory allocation failed \n"); else { lpfc_unreg_login(phba, vport->vpi, rpi, pmb); pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; @@ -1130,7 +1137,7 @@ lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, rpi = pmb->u.mb.un.varWords[0]; lpfc_release_rpi(phba, vport, ndlp, rpi); } - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0271 Illegal State Transition: node x%x " "event x%x, state x%x Data: x%x x%x\n", ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi, @@ -1148,11 +1155,11 @@ lpfc_cmpl_plogi_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, * to stop it. */ if (!(ndlp->nlp_flag & NLP_RCV_PLOGI)) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, - "0272 Illegal State Transition: node x%x " - "event x%x, state x%x Data: x%x x%x\n", - ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi, - ndlp->nlp_flag); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "0272 Illegal State Transition: node x%x " + "event x%x, state x%x Data: x%x x%x\n", + ndlp->nlp_DID, evt, ndlp->nlp_state, + ndlp->nlp_rpi, ndlp->nlp_flag); } return ndlp->nlp_state; } @@ -1372,7 +1379,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, if ((ndlp->nlp_DID != FDMI_DID) && (wwn_to_u64(sp->portName.u.wwn) == 0 || wwn_to_u64(sp->nodeName.u.wwn) == 0)) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0142 PLOGI RSP: Invalid WWN.\n"); goto out; } @@ -1434,7 +1441,8 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, } else { mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0133 PLOGI: no memory " "for config_link " "Data: x%x x%x x%x x%x\n", @@ -1459,7 +1467,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0018 PLOGI: no memory for reg_login " "Data: x%x x%x x%x x%x\n", ndlp->nlp_DID, ndlp->nlp_state, @@ -1499,7 +1507,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, kfree(mp); mempool_free(mbox, phba->mbox_mem_pool); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0134 PLOGI: cannot issue reg_login " "Data: x%x x%x x%x x%x\n", ndlp->nlp_DID, ndlp->nlp_state, @@ -1507,7 +1515,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, } else { mempool_free(mbox, phba->mbox_mem_pool); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0135 PLOGI: cannot format reg_login " "Data: x%x x%x x%x x%x\n", ndlp->nlp_DID, ndlp->nlp_state, @@ -1518,7 +1526,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, out: if (ndlp->nlp_DID == NameServer_DID) { lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0261 Cannot Register NameServer login\n"); } @@ -1940,8 +1948,8 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, if (mb->mbxStatus) { /* RegLogin failed */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, - "0246 RegLogin failed Data: x%x x%x x%x x%x " + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "0246 RegLogin failed Data: x%x x%x x%x x%x " "x%x\n", did, mb->mbxStatus, vport->port_state, mb->un.varRegLogin.vpi, diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index b16c087ba27209a9c69515438e0e498a6a40be18..e5be334d6a119e15ed0f794e138e9655c309e227 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -234,8 +234,10 @@ lpfc_nvme_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt) /** * lpfc_nvme_create_queue - + * @pnvme_lport: Transport localport that LS is to be issued from * @lpfc_pnvme: Pointer to the driver's nvme instance data * @qidx: An cpu index used to affinitize IO queues and MSIX vectors. + * @qsize: Size of the queue in bytes * @handle: An opaque driver handle used in follow-up calls. * * Driver registers this routine to preallocate and initialize any @@ -292,7 +294,7 @@ lpfc_nvme_create_queue(struct nvme_fc_local_port *pnvme_lport, /** * lpfc_nvme_delete_queue - - * @lpfc_pnvme: Pointer to the driver's nvme instance data + * @pnvme_lport: Transport localport that LS is to be issued from * @qidx: An cpu index used to affinitize IO queues and MSIX vectors. * @handle: An opaque driver handle from lpfc_nvme_create_queue * @@ -498,7 +500,7 @@ __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, if (pnvme_lsreq->done) pnvme_lsreq->done(pnvme_lsreq, status); else - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6046 NVMEx cmpl without done call back? " "Data %px DID %x Xri: %x status %x\n", pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0, @@ -647,7 +649,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, rc = lpfc_sli4_issue_wqe(phba, &phba->sli4_hba.hdwq[0], genwqe); if (rc) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC | LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6045 Issue GEN REQ WQE to NPORT x%x " "Data: x%x x%x rc x%x\n", ndlp->nlp_DID, genwqe->iotag, @@ -672,6 +674,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, * @vport: The local port issuing the LS * @ndlp: The remote port to send the LS to * @pnvme_lsreq: Pointer to LS request structure from the transport + * @gen_req_cmp: Completion call-back * * Routine validates the ndlp, builds buffers and sends a GEN_REQUEST * WQE to perform the LS operation. @@ -693,8 +696,7 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, uint16_t ntype, nstate; if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { - lpfc_printf_vlog(vport, KERN_ERR, - LOG_NVME_DISC | LOG_NODE | LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6051 NVMEx LS REQ: Bad NDLP x%px, Failing " "LS Req\n", ndlp); @@ -705,8 +707,7 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, nstate = ndlp->nlp_state; if ((ntype & NLP_NVME_TARGET && nstate != NLP_STE_MAPPED_NODE) || (ntype & NLP_NVME_INITIATOR && nstate != NLP_STE_UNMAPPED_NODE)) { - lpfc_printf_vlog(vport, KERN_ERR, - LOG_NVME_DISC | LOG_NODE | LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6088 NVMEx LS REQ: Fail DID x%06x not " "ready for IO. Type x%x, State x%x\n", ndlp->nlp_DID, ntype, nstate); @@ -727,9 +728,7 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, bmp = kmalloc(sizeof(*bmp), GFP_KERNEL); if (!bmp) { - - lpfc_printf_vlog(vport, KERN_ERR, - LOG_NVME_DISC | LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6044 NVMEx LS REQ: Could not alloc LS buf " "for DID %x\n", ndlp->nlp_DID); @@ -738,8 +737,7 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, bmp->virt = lpfc_mbuf_alloc(vport->phba, MEM_PRI, &(bmp->phys)); if (!bmp->virt) { - lpfc_printf_vlog(vport, KERN_ERR, - LOG_NVME_DISC | LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6042 NVMEx LS REQ: Could not alloc mbuf " "for DID %x\n", ndlp->nlp_DID); @@ -774,8 +772,7 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, pnvme_lsreq, gen_req_cmp, ndlp, 2, LPFC_NVME_LS_TIMEOUT, 0); if (ret != WQE_SUCCESS) { - lpfc_printf_vlog(vport, KERN_ERR, - LOG_NVME_DISC | LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6052 NVMEx REQ: EXIT. issue ls wqe failed " "lsreq x%px Status %x DID %x\n", pnvme_lsreq, ret, ndlp->nlp_DID); @@ -789,9 +786,9 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /** * lpfc_nvme_ls_req - Issue an NVME Link Service request - * @lpfc_nvme_lport: Transport localport that LS is to be issued from. - * @lpfc_nvme_rport: Transport remoteport that LS is to be sent to. - * @pnvme_lsreq - the transport nvme_ls_req structure for the LS + * @pnvme_lport: Transport localport that LS is to be issued from. + * @nvme_rport: Transport remoteport that LS is to be sent to. + * @pnvme_lsreq: the transport nvme_ls_req structure for the LS * * Driver registers this routine to handle any link service request * from the nvme_fc transport to a remote nvme-aware port. @@ -853,9 +850,7 @@ __lpfc_nvme_ls_abort(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, bool foundit = false; if (!ndlp) { - lpfc_printf_log(phba, KERN_ERR, - LOG_NVME_DISC | LOG_NODE | - LOG_NVME_IOERR | LOG_NVME_ABTS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6049 NVMEx LS REQ Abort: Bad NDLP x%px DID " "x%06x, Failing LS Req\n", ndlp, ndlp ? ndlp->nlp_DID : 0); @@ -931,9 +926,9 @@ lpfc_nvme_xmt_ls_rsp(struct nvme_fc_local_port *localport, /** * lpfc_nvme_ls_abort - Abort a prior NVME LS request - * @lpfc_nvme_lport: Transport localport that LS is to be issued from. - * @lpfc_nvme_rport: Transport remoteport that LS is to be sent to. - * @pnvme_lsreq - the transport nvme_ls_req structure for the LS + * @pnvme_lport: Transport localport that LS is to be issued from. + * @pnvme_rport: Transport remoteport that LS is to be sent to. + * @pnvme_lsreq: the transport nvme_ls_req structure for the LS * * Driver registers this routine to abort a NVME LS request that is * in progress (from the transports perspective). @@ -1063,11 +1058,8 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, } -/** +/* * lpfc_nvme_io_cmd_wqe_cmpl - Complete an NVME-over-FCP IO - * @lpfc_pnvme: Pointer to the driver's nvme instance data - * @lpfc_nvme_lport: Pointer to the driver's local port data - * @lpfc_nvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq * * Driver registers this routine as it io request handler. This * routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq @@ -1099,8 +1091,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, /* Sanity check on return of outstanding command */ if (!lpfc_ncmd) { - lpfc_printf_vlog(vport, KERN_ERR, - LOG_NODE | LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6071 Null lpfc_ncmd pointer. No " "release, skip completion\n"); return; @@ -1111,7 +1102,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, if (!lpfc_ncmd->nvmeCmd) { spin_unlock(&lpfc_ncmd->buf_lock); - lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6066 Missing cmpl ptrs: lpfc_ncmd x%px, " "nvmeCmd x%px\n", lpfc_ncmd, lpfc_ncmd->nvmeCmd); @@ -1144,7 +1135,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, */ ndlp = lpfc_ncmd->ndlp; if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6062 Ignoring NVME cmpl. No ndlp\n"); goto out_err; } @@ -1215,7 +1206,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, /* Sanity check */ if (nCmd->rcv_rsplen == LPFC_NVME_ERSP_LEN) break; - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6081 NVME Completion Protocol Error: " "xri %x status x%x result x%x " "placed x%x\n", @@ -1300,11 +1291,10 @@ out_err: /** * lpfc_nvme_prep_io_cmd - Issue an NVME-over-FCP IO - * @lpfc_pnvme: Pointer to the driver's nvme instance data - * @lpfc_nvme_lport: Pointer to the driver's local port data - * @lpfc_nvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq - * @lpfc_nvme_fcreq: IO request from nvme fc to driver. - * @hw_queue_handle: Driver-returned handle in lpfc_nvme_create_queue + * @vport: pointer to a host virtual N_Port data structure + * @lpfcn_cmd: Pointer to lpfc scsi command + * @pnode: pointer to a node-list data structure + * @cstat: pointer to the control status structure * * Driver registers this routine as it io request handler. This * routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq @@ -1409,11 +1399,8 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, /** * lpfc_nvme_prep_io_dma - Issue an NVME-over-FCP IO - * @lpfc_pnvme: Pointer to the driver's nvme instance data - * @lpfc_nvme_lport: Pointer to the driver's local port data - * @lpfc_nvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq - * @lpfc_nvme_fcreq: IO request from nvme fc to driver. - * @hw_queue_handle: Driver-returned handle in lpfc_nvme_create_queue + * @vport: pointer to a host virtual N_Port data structure + * @lpfcn_cmd: Pointer to lpfc scsi command * * Driver registers this routine as it io request handler. This * routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq @@ -1459,7 +1446,7 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, first_data_sgl = sgl; lpfc_ncmd->seg_cnt = nCmd->sg_cnt; if (lpfc_ncmd->seg_cnt > lpfc_nvme_template.max_sgl_segments) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6058 Too many sg segments from " "NVME Transport. Max %d, " "nvmeIO sg_cnt %d\n", @@ -1482,7 +1469,7 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, j = 2; for (i = 0; i < nseg; i++) { if (data_sg == NULL) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6059 dptr err %d, nseg %d\n", i, nseg); lpfc_ncmd->seg_cnt = 0; @@ -1583,7 +1570,7 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, * and sg_cnt must zero. */ if (nCmd->payload_length != 0) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6063 NVME DMA Prep Err: sg_cnt %d " "payload_length x%x\n", nCmd->sg_cnt, nCmd->payload_length); @@ -1946,7 +1933,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, /* driver queued commands are in process of being flushed */ if (phba->hba_flag & HBA_IOQ_FLUSH) { spin_unlock_irqrestore(&phba->hbalock, flags); - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6139 Driver in reset cleanup - flushing " "NVME Req now. hba_flag x%x\n", phba->hba_flag); @@ -1956,13 +1943,13 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, lpfc_nbuf = freqpriv->nvme_buf; if (!lpfc_nbuf) { spin_unlock_irqrestore(&phba->hbalock, flags); - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6140 NVME IO req has no matching lpfc nvme " "io buffer. Skipping abort req.\n"); return; } else if (!lpfc_nbuf->nvmeCmd) { spin_unlock_irqrestore(&phba->hbalock, flags); - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6141 lpfc NVME IO req has no nvme_fcreq " "io buffer. Skipping abort req.\n"); return; @@ -1980,7 +1967,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, * has not seen it yet. */ if (lpfc_nbuf->nvmeCmd != pnvme_fcreq) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6143 NVME req mismatch: " "lpfc_nbuf x%px nvmeCmd x%px, " "pnvme_fcreq x%px. Skipping Abort xri x%x\n", @@ -1991,7 +1978,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, /* Don't abort IOs no longer on the pending queue. */ if (!(nvmereq_wqe->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6142 NVME IO req x%px not queued - skipping " "abort req xri x%x\n", pnvme_fcreq, nvmereq_wqe->sli4_xritag); @@ -2005,7 +1992,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, /* Outstanding abort is in progress */ if (nvmereq_wqe->iocb_flag & LPFC_DRIVER_ABORTED) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6144 Outstanding NVME I/O Abort Request " "still pending on nvme_fcreq x%px, " "lpfc_ncmd %px xri x%x\n", @@ -2016,7 +2003,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, abts_buf = __lpfc_sli_get_iocbq(phba); if (!abts_buf) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6136 No available abort wqes. Skipping " "Abts req for nvme_fcreq x%px xri x%x\n", pnvme_fcreq, nvmereq_wqe->sli4_xritag); @@ -2037,7 +2024,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, spin_unlock(&lpfc_nbuf->buf_lock); spin_unlock_irqrestore(&phba->hbalock, flags); if (ret_val) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6137 Failed abts issue_wqe with status x%x " "for nvme_fcreq x%px.\n", ret_val, pnvme_fcreq); @@ -2310,7 +2297,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, if (pring->txcmplq_cnt) pending += pring->txcmplq_cnt; } - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6176 Lport x%px Localport x%px wait " "timed out. Pending %d. Renewing.\n", lport, vport->localport, pending); @@ -2432,6 +2419,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) struct nvme_fc_remote_port *remote_port; struct nvme_fc_port_info rpinfo; struct lpfc_nodelist *prev_ndlp = NULL; + struct fc_rport *srport = ndlp->rport; lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NVME_DISC, "6006 Register NVME PORT. DID x%06x nlptype x%x\n", @@ -2461,6 +2449,10 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn); rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn); + if (srport) + rpinfo.dev_loss_tmo = srport->dev_loss_tmo; + else + rpinfo.dev_loss_tmo = vport->cfg_devloss_tmo; spin_lock_irq(&vport->phba->hbalock); oldrport = lpfc_ndlp_get_nrport(ndlp); @@ -2528,7 +2520,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ndlp, prev_ndlp); } else { lpfc_printf_vlog(vport, KERN_ERR, - LOG_NVME_DISC | LOG_NODE, + LOG_TRACE_EVENT, "6031 RemotePort Registration failed " "err: %d, DID x%06x\n", ret, ndlp->nlp_DID); @@ -2574,7 +2566,7 @@ lpfc_nvme_rescan_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ndlp->nlp_state == NLP_STE_MAPPED_NODE) { nvme_fc_rescan_remoteport(remoteport); - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6172 NVME rescanned DID x%06x " "port_state x%x\n", ndlp->nlp_DID, remoteport->port_state); @@ -2657,7 +2649,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ret = nvme_fc_unregister_remoteport(remoteport); if (ret != 0) { lpfc_nlp_put(ndlp); - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6167 NVME unregister failed %d " "port_state x%x\n", ret, remoteport->port_state); @@ -2667,7 +2659,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) input_err: #endif - lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6168 State error: lport x%px, rport x%px FCID x%06x\n", vport->localport, ndlp->rport, ndlp->nlp_DID); } @@ -2752,7 +2744,7 @@ lpfc_nvme_wait_for_io_drain(struct lpfc_hba *phba) * dump a message. Something is wrong. */ if ((wait_cnt % 1000) == 0) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6178 NVME IO not empty, " "cnt %d\n", wait_cnt); } diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 88760416a8cbd3143b8d1a53d296d618fab4117a..a4430aeeb04a8fa345ac94227c367a30424d05b0 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -303,7 +303,7 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, result = wcqe->parameter; if (axchg->state != LPFC_NVME_STE_LS_RSP || axchg->entry_cnt != 2) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC | LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6410 NVMEx LS cmpl state mismatch IO x%x: " "%d %d\n", axchg->oxid, axchg->state, axchg->entry_cnt); @@ -395,7 +395,7 @@ lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf) unsigned long iflag; if (ctxp->state == LPFC_NVME_STE_FREE) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6411 NVMET free, already free IO x%x: %d %d\n", ctxp->oxid, ctxp->state, ctxp->entry_cnt); } @@ -474,7 +474,7 @@ lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf) if (!queue_work(phba->wq, &ctx_buf->defer_work)) { atomic_inc(&tgtp->rcv_fcp_cmd_drop); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6181 Unable to queue deferred work " "for oxid x%x. " "FCP Drop IO [x%x x%x x%x]\n", @@ -879,7 +879,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg, "6023 NVMEx LS rsp oxid x%x\n", axchg->oxid); if (axchg->state != LPFC_NVME_STE_LS_RCV || axchg->entry_cnt != 1) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC | LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6412 NVMEx LS rsp state mismatch " "oxid x%x: %d %d\n", axchg->oxid, axchg->state, axchg->entry_cnt); @@ -891,8 +891,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg, nvmewqeq = lpfc_nvmet_prep_ls_wqe(phba, axchg, ls_rsp->rspdma, ls_rsp->rsplen); if (nvmewqeq == NULL) { - lpfc_printf_log(phba, KERN_ERR, - LOG_NVME_DISC | LOG_NVME_IOERR | LOG_NVME_ABTS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6150 NVMEx LS Drop Rsp x%x: Prep\n", axchg->oxid); rc = -ENOMEM; @@ -936,8 +935,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg, return 0; } - lpfc_printf_log(phba, KERN_ERR, - LOG_NVME_DISC | LOG_NVME_IOERR | LOG_NVME_ABTS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6151 NVMEx LS RSP x%x: failed to transmit %d\n", axchg->oxid, rc); @@ -1058,7 +1056,7 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport, if ((ctxp->flag & LPFC_NVME_ABTS_RCV) || (ctxp->state == LPFC_NVME_STE_ABORT)) { atomic_inc(&lpfc_nvmep->xmt_fcp_drop); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6102 IO oxid x%x aborted\n", ctxp->oxid); rc = -ENXIO; @@ -1068,7 +1066,7 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport, nvmewqeq = lpfc_nvmet_prep_fcp_wqe(phba, ctxp); if (nvmewqeq == NULL) { atomic_inc(&lpfc_nvmep->xmt_fcp_drop); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6152 FCP Drop IO x%x: Prep\n", ctxp->oxid); rc = -ENXIO; @@ -1116,7 +1114,7 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport, /* Give back resources */ atomic_inc(&lpfc_nvmep->xmt_fcp_drop); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6153 FCP Drop IO x%x: Issue: %d\n", ctxp->oxid, rc); @@ -1216,7 +1214,7 @@ lpfc_nvmet_xmt_fcp_release(struct nvmet_fc_target_port *tgtport, ctxp->flag, ctxp->oxid); else if (ctxp->state != LPFC_NVME_STE_DONE && ctxp->state != LPFC_NVME_STE_ABORT) - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6413 NVMET release bad state %d %d oxid x%x\n", ctxp->state, ctxp->entry_cnt, ctxp->oxid); @@ -1395,7 +1393,7 @@ lpfc_nvmet_discovery_event(struct nvmet_fc_target_port *tgtport) phba = tgtp->phba; rc = lpfc_issue_els_rscn(phba->pport, 0); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6420 NVMET subsystem change: Notification %s\n", (rc) ? "Failed" : "Sent"); } @@ -1493,7 +1491,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba) phba->sli4_hba.num_possible_cpu * phba->cfg_nvmet_mrq, sizeof(struct lpfc_nvmet_ctx_info), GFP_KERNEL); if (!phba->sli4_hba.nvmet_ctx_info) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6419 Failed allocate memory for " "nvmet context lists\n"); return -ENOMEM; @@ -1551,7 +1549,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba) for (i = 0; i < phba->sli4_hba.nvmet_xri_cnt; i++) { ctx_buf = kzalloc(sizeof(*ctx_buf), GFP_KERNEL); if (!ctx_buf) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6404 Ran out of memory for NVMET\n"); return -ENOMEM; } @@ -1560,7 +1558,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba) GFP_KERNEL); if (!ctx_buf->context) { kfree(ctx_buf); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6405 Ran out of NVMET " "context memory\n"); return -ENOMEM; @@ -1572,7 +1570,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba) if (!ctx_buf->iocbq) { kfree(ctx_buf->context); kfree(ctx_buf); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6406 Ran out of NVMET iocb/WQEs\n"); return -ENOMEM; } @@ -1591,7 +1589,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba) lpfc_sli_release_iocbq(phba, ctx_buf->iocbq); kfree(ctx_buf->context); kfree(ctx_buf); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6407 Ran out of NVMET XRIs\n"); return -ENOMEM; } @@ -1670,7 +1668,7 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba) error = -ENOENT; #endif if (error) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6025 Cannot register NVME targetport x%x: " "portnm %llx nodenm %llx segs %d qs %d\n", error, @@ -2114,7 +2112,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba) nvmet_fc_unregister_targetport(phba->targetport); if (!wait_for_completion_timeout(tgtp->tport_unreg_cmp, msecs_to_jiffies(LPFC_NVMET_WAIT_TMO))) - lpfc_printf_log(phba, KERN_ERR, LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6179 Unreg targetport x%px timeout " "reached.\n", phba->targetport); lpfc_nvmet_cleanup_io_context(phba); @@ -2187,7 +2185,7 @@ lpfc_nvmet_process_rcv_fcp_req(struct lpfc_nvmet_ctxbuf *ctx_buf) unsigned long iflags; if (!nvmebuf) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6159 process_rcv_fcp_req, nvmebuf is NULL, " "oxid: x%x flg: x%x state: x%x\n", ctxp->oxid, ctxp->flag, ctxp->state); @@ -2200,7 +2198,7 @@ lpfc_nvmet_process_rcv_fcp_req(struct lpfc_nvmet_ctxbuf *ctx_buf) } if (ctxp->flag & LPFC_NVME_ABTS_RCV) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6324 IO oxid x%x aborted\n", ctxp->oxid); return; @@ -2264,7 +2262,7 @@ lpfc_nvmet_process_rcv_fcp_req(struct lpfc_nvmet_ctxbuf *ctx_buf) } ctxp->flag &= ~LPFC_NVME_TNOTIFY; atomic_inc(&tgtp->rcv_fcp_cmd_drop); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2582 FCP Drop IO x%x: err x%x: x%x x%x x%x\n", ctxp->oxid, rc, atomic_read(&tgtp->rcv_fcp_cmd_in), @@ -2383,7 +2381,7 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba, ctx_buf = NULL; if (!nvmebuf || !phba->targetport) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6157 NVMET FCP Drop IO\n"); if (nvmebuf) lpfc_rq_buf_free(phba, &nvmebuf->hbuf); @@ -2456,7 +2454,7 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba, list_add_tail(&ctxp->list, &phba->sli4_hba.t_active_ctx_list); spin_unlock_irqrestore(&phba->sli4_hba.t_active_list_lock, iflag); if (ctxp->state != LPFC_NVME_STE_FREE) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6414 NVMET Context corrupt %d %d oxid x%x\n", ctxp->state, ctxp->entry_cnt, ctxp->oxid); } @@ -2498,7 +2496,7 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba, if (!queue_work(phba->wq, &ctx_buf->defer_work)) { atomic_inc(&tgtp->rcv_fcp_cmd_drop); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6325 Unable to queue work for oxid x%x. " "FCP Drop IO [x%x x%x x%x]\n", ctxp->oxid, @@ -2535,7 +2533,7 @@ lpfc_nvmet_unsol_fcp_event(struct lpfc_hba *phba, uint8_t cqflag) { if (!nvmebuf) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3167 NVMET FCP Drop IO\n"); return; } @@ -2581,7 +2579,7 @@ lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba, union lpfc_wqe128 *wqe; if (!lpfc_is_link_up(phba)) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6104 NVMET prep LS wqe: link err: " "NPORT x%x oxid:x%x ste %d\n", ctxp->sid, ctxp->oxid, ctxp->state); @@ -2591,7 +2589,7 @@ lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba, /* Allocate buffer for command wqe */ nvmewqe = lpfc_sli_get_iocbq(phba); if (nvmewqe == NULL) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6105 NVMET prep LS wqe: No WQE: " "NPORT x%x oxid x%x ste %d\n", ctxp->sid, ctxp->oxid, ctxp->state); @@ -2602,7 +2600,7 @@ lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba, if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6106 NVMET prep LS wqe: No ndlp: " "NPORT x%x oxid x%x ste %d\n", ctxp->sid, ctxp->oxid, ctxp->state); @@ -2711,7 +2709,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, int xc = 1; if (!lpfc_is_link_up(phba)) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6107 NVMET prep FCP wqe: link err:" "NPORT x%x oxid x%x ste %d\n", ctxp->sid, ctxp->oxid, ctxp->state); @@ -2722,7 +2720,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6108 NVMET prep FCP wqe: no ndlp: " "NPORT x%x oxid x%x ste %d\n", ctxp->sid, ctxp->oxid, ctxp->state); @@ -2730,7 +2728,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, } if (rsp->sg_cnt > lpfc_tgttemplate.max_sgl_segments) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6109 NVMET prep FCP wqe: seg cnt err: " "NPORT x%x oxid x%x ste %d cnt %d\n", ctxp->sid, ctxp->oxid, ctxp->state, @@ -2745,7 +2743,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, /* Allocate buffer for command wqe */ nvmewqe = ctxp->ctxbuf->iocbq; if (nvmewqe == NULL) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6110 NVMET prep FCP wqe: No " "WQE: NPORT x%x oxid x%x ste %d\n", ctxp->sid, ctxp->oxid, ctxp->state); @@ -2763,7 +2761,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, (ctxp->state == LPFC_NVME_STE_DATA)) { wqe = &nvmewqe->wqe; } else { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6111 Wrong state NVMET FCP: %d cnt %d\n", ctxp->state, ctxp->entry_cnt); return NULL; @@ -3136,7 +3134,7 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, /* Sanity check */ if (ctxp->state != LPFC_NVME_STE_ABORT) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6112 ABTS Wrong state:%d oxid x%x\n", ctxp->state, ctxp->oxid); } @@ -3210,7 +3208,7 @@ lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, result, wcqe->word3); if (!ctxp) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6415 NVMET LS Abort No ctx: WCQE: " "%08x %08x %08x %08x\n", wcqe->word0, wcqe->total_data_placed, @@ -3221,7 +3219,7 @@ lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, } if (ctxp->state != LPFC_NVME_STE_LS_ABORT) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6416 NVMET LS abort cmpl state mismatch: " "oxid x%x: %d %d\n", ctxp->oxid, ctxp->state, ctxp->entry_cnt); @@ -3256,7 +3254,7 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba, (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) { if (tgtp) atomic_inc(&tgtp->xmt_abort_rsp_error); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6134 Drop ABTS - wrong NDLP state x%x.\n", (ndlp) ? ndlp->nlp_state : NLP_STE_MAX_STATE); @@ -3353,7 +3351,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) { atomic_inc(&tgtp->xmt_abort_rsp_error); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6160 Drop ABORT - wrong NDLP state x%x.\n", (ndlp) ? ndlp->nlp_state : NLP_STE_MAX_STATE); @@ -3369,7 +3367,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, spin_lock_irqsave(&ctxp->ctxlock, flags); if (!ctxp->abort_wqeq) { atomic_inc(&tgtp->xmt_abort_rsp_error); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6161 ABORT failed: No wqeqs: " "xri: x%x\n", ctxp->oxid); /* No failure to an ABTS request. */ @@ -3396,7 +3394,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, if (phba->hba_flag & HBA_IOQ_FLUSH) { spin_unlock_irqrestore(&phba->hbalock, flags); atomic_inc(&tgtp->xmt_abort_rsp_error); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6163 Driver in reset cleanup - flushing " "NVME Req now. hba_flag x%x oxid x%x\n", phba->hba_flag, ctxp->oxid); @@ -3411,7 +3409,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, if (abts_wqeq->iocb_flag & LPFC_DRIVER_ABORTED) { spin_unlock_irqrestore(&phba->hbalock, flags); atomic_inc(&tgtp->xmt_abort_rsp_error); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6164 Outstanding NVME I/O Abort Request " "still pending on oxid x%x\n", ctxp->oxid); @@ -3449,7 +3447,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, ctxp->flag &= ~LPFC_NVME_ABORT_OP; spin_unlock_irqrestore(&ctxp->ctxlock, flags); lpfc_sli_release_iocbq(phba, abts_wqeq); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6166 Failed ABORT issue_wqe with status x%x " "for oxid x%x.\n", rc, ctxp->oxid); @@ -3474,7 +3472,7 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba, } if (ctxp->state == LPFC_NVME_STE_FREE) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6417 NVMET ABORT ctx freed %d %d oxid x%x\n", ctxp->state, ctxp->entry_cnt, ctxp->oxid); rc = WQE_BUSY; @@ -3512,7 +3510,7 @@ aerr: spin_unlock_irqrestore(&ctxp->ctxlock, flags); atomic_inc(&tgtp->xmt_abort_rsp_error); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6135 Failed to Issue ABTS for oxid x%x. Status x%x " "(%x)\n", ctxp->oxid, rc, released); @@ -3544,7 +3542,7 @@ lpfc_nvme_unsol_ls_issue_abort(struct lpfc_hba *phba, ctxp->state = LPFC_NVME_STE_LS_ABORT; ctxp->entry_cnt++; } else { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6418 NVMET LS abort state mismatch " "IO x%x: %d %d\n", ctxp->oxid, ctxp->state, ctxp->entry_cnt); @@ -3558,7 +3556,7 @@ lpfc_nvme_unsol_ls_issue_abort(struct lpfc_hba *phba, /* Issue ABTS for this WQE based on iotag */ ctxp->wqeq = lpfc_sli_get_iocbq(phba); if (!ctxp->wqeq) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6068 Abort failed: No wqeqs: " "xri: x%x\n", xri); /* No failure to an ABTS request. */ @@ -3590,7 +3588,7 @@ out: abts_wqeq->context2 = NULL; abts_wqeq->context3 = NULL; lpfc_sli_release_iocbq(phba, abts_wqeq); - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6056 Failed to Issue ABTS. Status x%x\n", rc); return 1; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index ad62fb3f3a54d5615d2cb1c8a9703579013302cd..5e802c8b22a99229ed1ae072b3c79011723caa1f 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -867,11 +867,11 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) lpfc_cmd->seg_cnt = nseg; if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9064 BLKGRD: %s: Too many sg segments from " - "dma_map_sg. Config %d, seg_cnt %d\n", - __func__, phba->cfg_sg_seg_cnt, - lpfc_cmd->seg_cnt); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "9064 BLKGRD: %s: Too many sg segments" + " from dma_map_sg. Config %d, seg_cnt" + " %d\n", __func__, phba->cfg_sg_seg_cnt, + lpfc_cmd->seg_cnt); WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt); lpfc_cmd->seg_cnt = 0; scsi_dma_unmap(scsi_cmnd); @@ -1061,7 +1061,8 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, * inserted in middle of the IO. */ - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "9076 BLKGRD: Injecting reftag error: " "write lba x%lx + x%x oldrefTag x%x\n", (unsigned long)lba, blockoff, @@ -1111,7 +1112,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, } rc = BG_ERR_TGT | BG_ERR_CHECK; - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9078 BLKGRD: Injecting reftag error: " "write lba x%lx\n", (unsigned long)lba); break; @@ -1132,7 +1133,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, } rc = BG_ERR_INIT; - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9077 BLKGRD: Injecting reftag error: " "write lba x%lx\n", (unsigned long)lba); break; @@ -1159,7 +1160,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, } rc = BG_ERR_INIT; - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9079 BLKGRD: Injecting reftag error: " "read lba x%lx\n", (unsigned long)lba); break; @@ -1181,7 +1182,8 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, * inserted in middle of the IO. */ - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, "9080 BLKGRD: Injecting apptag error: " "write lba x%lx + x%x oldappTag x%x\n", (unsigned long)lba, blockoff, @@ -1230,7 +1232,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, } rc = BG_ERR_TGT | BG_ERR_CHECK; - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0813 BLKGRD: Injecting apptag error: " "write lba x%lx\n", (unsigned long)lba); break; @@ -1251,7 +1253,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, } rc = BG_ERR_INIT; - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0812 BLKGRD: Injecting apptag error: " "write lba x%lx\n", (unsigned long)lba); break; @@ -1278,7 +1280,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, } rc = BG_ERR_INIT; - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0814 BLKGRD: Injecting apptag error: " "read lba x%lx\n", (unsigned long)lba); break; @@ -1313,7 +1315,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, rc |= BG_ERR_TGT | BG_ERR_SWAP; /* Signals the caller to swap CRC->CSUM */ - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0817 BLKGRD: Injecting guard error: " "write lba x%lx\n", (unsigned long)lba); break; @@ -1335,7 +1337,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, rc = BG_ERR_INIT | BG_ERR_SWAP; /* Signals the caller to swap CRC->CSUM */ - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0816 BLKGRD: Injecting guard error: " "write lba x%lx\n", (unsigned long)lba); break; @@ -1363,7 +1365,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, rc = BG_ERR_INIT | BG_ERR_SWAP; /* Signals the caller to swap CRC->CSUM */ - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0818 BLKGRD: Injecting guard error: " "read lba x%lx\n", (unsigned long)lba); } @@ -1413,7 +1415,7 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc, case SCSI_PROT_NORMAL: default: - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9063 BLKGRD: Bad op/guard:%d/IP combination\n", scsi_get_prot_op(sc)); ret = 1; @@ -1442,7 +1444,7 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc, case SCSI_PROT_NORMAL: default: - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9075 BLKGRD: Bad op/guard:%d/CRC combination\n", scsi_get_prot_op(sc)); ret = 1; @@ -1728,7 +1730,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, sgde = scsi_sglist(sc); if (!sgpe || !sgde) { - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9020 Invalid s/g entry: data=x%px prot=x%px\n", sgpe, sgde); return 0; @@ -1840,7 +1842,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, return num_bde + 1; if (!sgde) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9065 BLKGRD:%s Invalid data segment\n", __func__); return 0; @@ -1903,8 +1905,8 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, reftag += protgrp_blks; } else { /* if we're here, we have a bug */ - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9054 BLKGRD: bug in %s\n", __func__); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "9054 BLKGRD: bug in %s\n", __func__); } } while (!alldone); @@ -2154,7 +2156,7 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, sgde = scsi_sglist(sc); if (!sgpe || !sgde) { - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9082 Invalid s/g entry: data=x%px prot=x%px\n", sgpe, sgde); return 0; @@ -2307,7 +2309,7 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, return num_sge + 1; if (!sgde) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9086 BLKGRD:%s Invalid data segment\n", __func__); return 0; @@ -2412,8 +2414,8 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, reftag += protgrp_blks; } else { /* if we're here, we have a bug */ - lpfc_printf_log(phba, KERN_ERR, LOG_BG, - "9085 BLKGRD: bug in %s\n", __func__); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "9085 BLKGRD: bug in %s\n", __func__); } } while (!alldone); @@ -2453,7 +2455,7 @@ lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc) break; default: if (phba) - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9021 Unsupported protection op:%d\n", op); break; @@ -2617,7 +2619,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, scsi_dma_unmap(scsi_cmnd); lpfc_cmd->seg_cnt = 0; - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9022 Unexpected protection group %i\n", prot_group_type); return 2; @@ -2661,7 +2663,7 @@ err: scsi_prot_sg_count(scsi_cmnd), scsi_cmnd->sc_data_direction); - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9023 Cannot setup S/G List for HBA" "IO segs %d/%d BPL %d SCSI %d: %d %d\n", lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt, @@ -3085,11 +3087,12 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) lpfc_cmd->seg_cnt = nseg; if (!phba->cfg_xpsgl && lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9074 BLKGRD:" - " %s: Too many sg segments from " - "dma_map_sg. Config %d, seg_cnt %d\n", - __func__, phba->cfg_sg_seg_cnt, - lpfc_cmd->seg_cnt); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "9074 BLKGRD:" + " %s: Too many sg segments from " + "dma_map_sg. Config %d, seg_cnt %d\n", + __func__, phba->cfg_sg_seg_cnt, + lpfc_cmd->seg_cnt); WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt); lpfc_cmd->seg_cnt = 0; scsi_dma_unmap(scsi_cmnd); @@ -3366,7 +3369,7 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, scsi_dma_unmap(scsi_cmnd); lpfc_cmd->seg_cnt = 0; - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9083 Unexpected protection group %i\n", prot_group_type); return 2; @@ -3422,7 +3425,7 @@ err: scsi_prot_sg_count(scsi_cmnd), scsi_cmnd->sc_data_direction); - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9084 Cannot setup S/G List for HBA" "IO segs %d/%d SGL %d SCSI %d: %d %d\n", lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt, @@ -3632,17 +3635,17 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, if (resp_info & RSP_LEN_VALID) { rsplen = be32_to_cpu(fcprsp->rspRspLen); if (rsplen != 0 && rsplen != 4 && rsplen != 8) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "2719 Invalid response length: " - "tgt x%x lun x%llx cmnd x%x rsplen x%x\n", - cmnd->device->id, - cmnd->device->lun, cmnd->cmnd[0], - rsplen); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "2719 Invalid response length: " + "tgt x%x lun x%llx cmnd x%x rsplen " + "x%x\n", cmnd->device->id, + cmnd->device->lun, cmnd->cmnd[0], + rsplen); host_status = DID_ERROR; goto out; } if (fcprsp->rspInfo3 != RSP_NO_FAILURE) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2757 Protocol failure detected during " "processing of FCP I/O op: " "tgt x%x lun x%llx cmnd x%x rspInfo3 x%x\n", @@ -3812,7 +3815,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, /* Sanity check on return of outstanding command */ cmd = lpfc_cmd->pCmd; if (!cmd || !phba) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2621 IO completion: Not an active IO\n"); spin_unlock(&lpfc_cmd->buf_lock); return; @@ -4277,7 +4280,7 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4; break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1418 Invalid HBA PCI-device group: 0x%x\n", dev_grp); return -ENODEV; @@ -4324,7 +4327,7 @@ lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba, * 0, successful */ int -lpfc_check_pci_resettable(const struct lpfc_hba *phba) +lpfc_check_pci_resettable(struct lpfc_hba *phba) { const struct pci_dev *pdev = phba->pcidev; struct pci_dev *ptr = NULL; @@ -4528,7 +4531,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) if ((scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) && (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED))) { - lpfc_printf_log(phba, KERN_ERR, LOG_BG, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "9058 BLKGRD: ERROR: rcvd protected cmd:%02x" " op:%02x str=%s without registering for" " BlockGuard - Rejecting command\n", @@ -4887,7 +4890,7 @@ wait_for_cmpl: if (lpfc_cmd->pCmd == cmnd) { ret = FAILED; - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0748 abort handler timed out waiting " "for aborting I/O (xri:x%x) to complete: " "ret %#x, ID %d, LUN %llu\n", @@ -5080,7 +5083,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, (iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) { if (status != IOCB_SUCCESS || iocbqrsp->iocb.ulpStatus != IOSTAT_FCP_RSP_ERROR) - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0727 TMF %s to TGT %d LUN %llu " "failed (%d, %d) iocb_flag x%x\n", lpfc_taskmgmt_name(task_mgmt_cmd), @@ -5195,7 +5198,7 @@ lpfc_reset_flush_io_context(struct lpfc_vport *vport, uint16_t tgt_id, cnt = lpfc_sli_sum_iocb(vport, tgt_id, lun_id, context); } if (cnt) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0724 I/O flush failure for context %s : cnt x%x\n", ((context == LPFC_CTX_LUN) ? "LUN" : ((context == LPFC_CTX_TGT) ? "TGT" : @@ -5231,7 +5234,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) rdata = lpfc_rport_data_from_scsi_device(cmnd->device); if (!rdata || !rdata->pnode) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0798 Device Reset rdata failure: rdata x%px\n", rdata); return FAILED; @@ -5243,7 +5246,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) status = lpfc_chk_tgt_mapped(vport, cmnd); if (status == FAILED) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0721 Device Reset rport failure: rdata x%px\n", rdata); return FAILED; } @@ -5260,7 +5263,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id, FCP_LUN_RESET); - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0713 SCSI layer issued Device Reset (%d, %llu) " "return x%x\n", tgt_id, lun_id, status); @@ -5302,7 +5305,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) rdata = lpfc_rport_data_from_scsi_device(cmnd->device); if (!rdata || !rdata->pnode) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0799 Target Reset rdata failure: rdata x%px\n", rdata); return FAILED; @@ -5314,7 +5317,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) status = lpfc_chk_tgt_mapped(vport, cmnd); if (status == FAILED) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0722 Target Reset rport failure: rdata x%px\n", rdata); if (pnode) { spin_lock_irq(shost->host_lock); @@ -5339,7 +5342,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id, FCP_TARGET_RESET); - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0723 SCSI layer issued Target Reset (%d, %llu) " "return x%x\n", tgt_id, lun_id, status); @@ -5420,7 +5423,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) i, 0, FCP_TARGET_RESET); if (status != SUCCESS) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0700 Bus Reset on target %d failed\n", i); ret = FAILED; @@ -5437,7 +5440,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) if (status != SUCCESS) ret = FAILED; - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0714 SCSI layer issued Bus Reset Data: x%x\n", ret); return ret; } @@ -5466,7 +5469,7 @@ lpfc_host_reset_handler(struct scsi_cmnd *cmnd) struct lpfc_hba *phba = vport->phba; int rc, ret = SUCCESS; - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "3172 SCSI layer issued Host Reset Data:\n"); lpfc_offline_prep(phba, LPFC_MBX_WAIT); @@ -5483,7 +5486,7 @@ lpfc_host_reset_handler(struct scsi_cmnd *cmnd) return ret; error: - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "3323 Failed host reset\n"); lpfc_unblock_mgmt_io(phba); return FAILED; @@ -5594,7 +5597,7 @@ lpfc_slave_alloc(struct scsi_device *sdev) } num_allocated = lpfc_new_scsi_buf_s3(vport, num_to_alloc); if (num_to_alloc != num_allocated) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0708 Allocation request of %d " "command buffers did not succeed. " "Allocated %d buffers.\n", diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 25653baba36755607e2adb3da5083129bd3c720d..8582b51b061318b90544526a01a6e901cb3809eb 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef CONFIG_X86 #include #endif @@ -242,7 +243,7 @@ lpfc_sli4_wq_release(struct lpfc_queue *q, uint32_t index) /** * lpfc_sli4_mq_put - Put a Mailbox Queue Entry on an Mailbox Queue * @q: The Mailbox Queue to operate on. - * @wqe: The Mailbox Queue Entry to put on the Work queue. + * @mqe: The Mailbox Queue Entry to put on the Work queue. * * This routine will copy the contents of @mqe to the next available entry on * the @q. This function will then ring the Work Queue Doorbell to signal the @@ -656,10 +657,8 @@ lpfc_sli4_if6_write_cq_db(struct lpfc_hba *phba, struct lpfc_queue *q, writel(doorbell.word0, q->phba->sli4_hba.CQDBregaddr); } -/** +/* * lpfc_sli4_rq_put - Put a Receive Buffer Queue Entry on a Receive Queue - * @q: The Header Receive Queue to operate on. - * @wqe: The Receive Queue Entry to put on the Receive queue. * * This routine will copy the contents of @wqe to the next available entry on * the @q. This function will then ring the Receive Queue Doorbell to signal the @@ -722,9 +721,8 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq, return hq_put_index; } -/** +/* * lpfc_sli4_rq_release - Updates internal hba index for RQ - * @q: The Header Receive Queue to operate on. * * This routine will update the HBA index of a queue to reflect consumption of * one Receive Queue Entry by the HBA. When the HBA indicates that it has @@ -1008,7 +1006,7 @@ lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap. * @phba: Pointer to HBA context object. * @ndlp: Targets nodelist pointer for this exchange. - * @xritag the xri in the bitmap to test. + * @xritag: the xri in the bitmap to test. * * This function returns: * 0 = rrq not active for this xri @@ -1079,7 +1077,7 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, goto out; spin_unlock_irqrestore(&phba->hbalock, iflags); - rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL); + rrq = mempool_alloc(phba->rrq_pool, GFP_ATOMIC); if (!rrq) { lpfc_printf_log(phba, KERN_INFO, LOG_SLI, "3155 Unable to allocate RRQ xri:0x%x rxid:0x%x" @@ -1118,7 +1116,7 @@ out: /** * __lpfc_sli_get_els_sglq - Allocates an iocb object from sgl pool * @phba: Pointer to HBA context object. - * @piocb: Pointer to the iocbq. + * @piocbq: Pointer to the iocbq. * * The driver calls this function with either the nvme ls ring lock * or the fc els ring lock held depending on the iocb usage. This function @@ -1194,7 +1192,7 @@ __lpfc_sli_get_els_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) /** * __lpfc_sli_get_nvmet_sglq - Allocates an iocb object from sgl pool * @phba: Pointer to HBA context object. - * @piocb: Pointer to the iocbq. + * @piocbq: Pointer to the iocbq. * * This function is called with the sgl_list lock held. This function * gets a new driver sglq object from the sglq list. If the @@ -1491,6 +1489,7 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) case DSSCMD_IWRITE64_CX: case DSSCMD_IREAD64_CR: case DSSCMD_IREAD64_CX: + case CMD_SEND_FRAME: type = LPFC_SOL_IOCB; break; case CMD_ABORT_XRI_CN: @@ -1565,7 +1564,7 @@ lpfc_sli_ring_map(struct lpfc_hba *phba) lpfc_config_ring(phba, i, pmb); rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0446 Adapter failed to init (%d), " "mbxCmd x%x CFG_RING, mbxStatus x%x, " "ring %d\n", @@ -1674,7 +1673,7 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring) pring->sli.sli3.local_getidx = le32_to_cpu(pgp->cmdGetInx); if (unlikely(pring->sli.sli3.local_getidx >= max_cmd_idx)) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0315 Ring %d issue: portCmdGet %d " "is bigger than cmd ring %d\n", pring->ringno, @@ -1960,8 +1959,7 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno) hbqp->local_hbqGetIdx = getidx; if (unlikely(hbqp->local_hbqGetIdx >= hbqp->entry_count)) { - lpfc_printf_log(phba, KERN_ERR, - LOG_SLI | LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1802 HBQ %d: local_hbqGetIdx " "%u is > than hbqp->entry_count %u\n", hbqno, hbqp->local_hbqGetIdx, @@ -2229,10 +2227,8 @@ lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno) lpfc_hbq_defs[qno]->init_count); } -/** +/* * lpfc_sli_hbqbuf_get - Remove the first hbq off of an hbq list - * @phba: Pointer to HBA context object. - * @hbqno: HBQ number. * * This function removes the first hbq buffer on an hbq list and returns a * pointer to that buffer. If it finds no buffers on the list it returns NULL. @@ -2251,7 +2247,7 @@ lpfc_sli_hbqbuf_get(struct list_head *rb_list) /** * lpfc_sli_rqbuf_get - Remove the first dma buffer off of an RQ list * @phba: Pointer to HBA context object. - * @hbqno: HBQ number. + * @hrq: HBQ number. * * This function removes the first RQ buffer on an RQ buffer list and returns a * pointer to that buffer. If it finds no buffers on the list it returns NULL. @@ -2300,7 +2296,7 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) } } spin_unlock_irq(&phba->hbalock); - lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1803 Bad hbq tag. Data: x%x x%x\n", tag, phba->hbqs[tag >> 16].buffer_count); return NULL; @@ -2554,7 +2550,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* Check security permission status on INIT_LINK mailbox command */ if ((pmb->u.mb.mbxCommand == MBX_INIT_LINK) && (pmb->u.mb.mbxStatus == MBXERR_SEC_NO_PERMISSION)) - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2860 SLI authentication is required " "for INIT_LINK but has not done yet\n"); @@ -2690,7 +2686,7 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) if (lpfc_sli_chk_mbx_command(pmbox->mbxCommand) == MBX_SHUTDOWN) { /* Unknown mailbox command compl */ - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "(%d):0323 Unknown Mailbox command " "x%x (x%x/x%x) Cmpl\n", pmb->vport ? pmb->vport->vpi : @@ -2848,7 +2844,7 @@ lpfc_nvme_unsol_ls_handler(struct lpfc_hba *phba, struct lpfc_iocbq *piocb) } if (unlikely(failwhy)) { - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC | LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6154 Drop NVME LS: SID %06X OXID x%X: %s\n", sid, oxid, failwhy); goto out_fail; @@ -2888,7 +2884,7 @@ lpfc_nvme_unsol_ls_handler(struct lpfc_hba *phba, struct lpfc_iocbq *piocb) if (!ret) return; - lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC | LOG_NVME_IOERR, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6155 Drop NVME LS from DID %06X: SID %06X OXID x%X " "NVMe%s handler failed %d\n", did, sid, oxid, @@ -3171,7 +3167,7 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, } spin_unlock_irqrestore(temp_lock, iflag); - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0317 iotag x%x is out of " "range: max iotag x%x wd0 x%x\n", iotag, phba->sli.last_iotag, @@ -3218,7 +3214,7 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba, } spin_unlock_irqrestore(temp_lock, iflag); - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0372 iotag x%x lookup error: max iotag (x%x) " "iocb_flag x%x\n", iotag, phba->sli.last_iotag, @@ -3394,7 +3390,7 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) * Ring handler: portRspPut is bigger than * rsp ring */ - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0312 Ring %d handler: portRspPut %d " "is bigger than rsp ring %d\n", pring->ringno, le32_to_cpu(pgp->rspPutInx), @@ -3416,7 +3412,7 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) /** * lpfc_poll_eratt - Error attention polling timer timeout handler - * @ptr: Pointer to address of HBA context object. + * @t: Context to fetch pointer to address of HBA context object from. * * This function is invoked by the Error Attention polling timer when the * timer times out. It will check the SLI Error Attention register for @@ -3613,7 +3609,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, phba->brd_no, adaptermsg); } else { /* Unknown IOCB command */ - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0334 Unknown IOCB command " "Data: x%x, x%x x%x x%x x%x\n", type, irsp->ulpCommand, @@ -3811,7 +3807,7 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, phba->brd_no, adaptermsg); } else { /* Unknown IOCB command */ - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0335 Unknown IOCB " "command Data: x%x " "x%x x%x x%x\n", @@ -3891,7 +3887,7 @@ lpfc_sli_handle_slow_ring_event_s3(struct lpfc_hba *phba, * Ring handler: portRspPut is bigger than * rsp ring */ - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0303 Ring %d handler: portRspPut %d " "is bigger than rsp ring %d\n", pring->ringno, portRspPut, portRspMax); @@ -4102,7 +4098,6 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) /** * lpfc_sli_abort_fcp_rings - Abort all iocbs in all FCP rings * @phba: Pointer to HBA context object. - * @pring: Pointer to driver SLI ring object. * * This function aborts all iocbs in FCP rings and frees all the iocb * objects in txq. This function issues an abort iocb for all the iocb commands @@ -4263,7 +4258,7 @@ lpfc_sli_brdready_s3(struct lpfc_hba *phba, uint32_t mask) /* Check to see if any errors occurred during init */ if ((status & HS_FFERM) || (i >= 20)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2751 Adapter failed to restart, " "status reg x%x, FW Data: A8 x%x AC x%x\n", status, @@ -4485,7 +4480,7 @@ lpfc_sli_brdkill(struct lpfc_hba *phba) if (retval != MBX_SUCCESS) { if (retval != MBX_BUSY) mempool_free(pmb, phba->mbox_mem_pool); - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2752 KILL_BOARD command failed retval %d\n", retval); spin_lock_irq(&phba->hbalock); @@ -4837,7 +4832,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) if (i++ >= 200) { /* Adapter failed to init, timeout, status reg */ - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0436 Adapter failed to init, " "timeout, status reg x%x, " "FW Data: A8 x%x AC x%x\n", status, @@ -4852,7 +4847,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) /* ERROR: During chipset initialization */ /* Adapter failed to init, chipset, status reg */ - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0437 Adapter failed to init, " "chipset, status reg x%x, " "FW Data: A8 x%x AC x%x\n", status, @@ -4883,7 +4878,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) if (status & HS_FFERM) { /* ERROR: During chipset initialization */ /* Adapter failed to init, chipset, status reg */ - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0438 Adapter failed to init, chipset, " "status reg x%x, " "FW Data: A8 x%x AC x%x\n", status, @@ -5106,7 +5101,7 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) LPFC_SLI3_CRP_ENABLED | LPFC_SLI3_DSS_ENABLED); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0442 Adapter failed to init, mbxCmd x%x " "CONFIG_PORT, mbxStatus x%x Data: x%x\n", pmb->u.mb.mbxCommand, pmb->u.mb.mbxStatus, 0); @@ -5156,7 +5151,7 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) if (pmb->u.mb.un.varCfgPort.gbg == 0) { phba->cfg_enable_bg = 0; phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED; - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0443 Adapter did not grant " "BlockGuard\n"); } @@ -5195,7 +5190,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) switch (phba->cfg_sli_mode) { case 2: if (phba->cfg_enable_npiv) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1824 NPIV enabled: Override sli_mode " "parameter (%d) to auto (0).\n", phba->cfg_sli_mode); @@ -5207,7 +5202,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) case 3: break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1819 Unrecognized sli_mode parameter: %d.\n", phba->cfg_sli_mode); @@ -5218,7 +5213,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) rc = lpfc_sli_config_port(phba, mode); if (rc && phba->cfg_sli_mode == 3) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1820 Unable to select SLI-3. " "Not supported by adapter.\n"); if (rc && mode != 2) @@ -5312,7 +5307,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) lpfc_sli_hba_setup_error: phba->link_state = LPFC_HBA_ERROR; - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0445 Firmware initialization failed\n"); return rc; } @@ -5320,7 +5315,7 @@ lpfc_sli_hba_setup_error: /** * lpfc_sli4_read_fcoe_params - Read fcoe params from conf region * @phba: Pointer to HBA context object. - * @mboxq: mailbox pointer. + * * This function issue a dump mailbox command to read config region * 23 and parse the records in the region and populate driver * data structure. @@ -5509,7 +5504,7 @@ lpfc_sli4_get_ctl_attr(struct lpfc_hba *phba) LPFC_SLI4_MBX_NEMBED); if (alloclen < reqlen) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3084 Allocated DMA memory size (%d) is " "less than the requested DMA memory size " "(%d)\n", alloclen, reqlen); @@ -5769,7 +5764,7 @@ lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type, rsrc_info = &mbox->u.mqe.un.rsrc_extent_info; if (bf_get(lpfc_mbox_hdr_status, &rsrc_info->header.cfg_shdr.response)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2930 Failed to get resource extents " "Status 0x%x Add'l Status 0x%x\n", bf_get(lpfc_mbox_hdr_status, @@ -5858,10 +5853,10 @@ lpfc_sli4_chk_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type) /** * lpfc_sli4_cfg_post_extnts - * @phba: Pointer to HBA context object. - * @extnt_cnt - number of available extents. - * @type - the extent type (rpi, xri, vfi, vpi). - * @emb - buffer to hold either MBX_EMBED or MBX_NEMBED operation. - * @mbox - pointer to the caller's allocated mailbox structure. + * @extnt_cnt: number of available extents. + * @type: the extent type (rpi, xri, vfi, vpi). + * @emb: buffer to hold either MBX_EMBED or MBX_NEMBED operation. + * @mbox: pointer to the caller's allocated mailbox structure. * * This function executes the extents allocation request. It also * takes care of the amount of memory needed to allocate or get the @@ -5907,7 +5902,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t extnt_cnt, LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT, req_len, *emb); if (alloc_len < req_len) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2982 Allocated DMA memory size (x%x) is " "less than the requested DMA memory " "size (x%x)\n", alloc_len, req_len); @@ -5963,7 +5958,7 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type) return -EIO; if ((rsrc_cnt == 0) || (rsrc_size == 0)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3009 No available Resource Extents " "for resource type 0x%x: Count: 0x%x, " "Size 0x%x\n", type, rsrc_cnt, @@ -6214,7 +6209,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type) dealloc_rsrc = &mbox->u.mqe.un.dealloc_rsrc_extents; if (bf_get(lpfc_mbox_hdr_status, &dealloc_rsrc->header.cfg_shdr.response)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2919 Failed to release resource extents " "for type %d - Status 0x%x Add'l Status 0x%x. " "Resource memory not released.\n", @@ -6408,7 +6403,7 @@ lpfc_sli4_ras_dma_alloc(struct lpfc_hba *phba, &ras_fwlog->lwpd.phys, GFP_KERNEL); if (!ras_fwlog->lwpd.virt) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6185 LWPD Memory Alloc Failed\n"); return -ENOMEM; @@ -6449,7 +6444,7 @@ free_mem: /** * lpfc_sli4_ras_mbox_cmpl: Completion handler for RAS MBX command * @phba: pointer to lpfc hba data structure. - * @pmboxq: pointer to the driver internal queue element for mailbox command. + * @pmb: pointer to the driver internal queue element for mailbox command. * * Completion handler for driver's RAS MBX command to the device. **/ @@ -6469,7 +6464,7 @@ lpfc_sli4_ras_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (mb->mbxStatus != MBX_SUCCESS || shdr_status) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6188 FW LOG mailbox " "completed with status x%x add_status x%x," " mbx status x%x\n", @@ -6537,7 +6532,7 @@ lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba, /* Setup Mailbox command */ mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6190 RAS MBX Alloc Failed"); rc = -ENOMEM; goto mem_free; @@ -6585,7 +6580,7 @@ lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba, rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6191 FW-Log Mailbox failed. " "status %d mbxStatus : x%x", rc, bf_get(lpfc_mqe_status, &mbox->u.mqe)); @@ -6721,7 +6716,7 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) /* RPIs. */ count = phba->sli4_hba.max_cfg_param.max_rpi; if (count <= 0) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3279 Invalid provisioning of " "rpi:%d\n", count); rc = -EINVAL; @@ -6749,7 +6744,7 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) /* VPIs. */ count = phba->sli4_hba.max_cfg_param.max_vpi; if (count <= 0) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3280 Invalid provisioning of " "vpi:%d\n", count); rc = -EINVAL; @@ -6776,7 +6771,7 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) /* XRIs. */ count = phba->sli4_hba.max_cfg_param.max_xri; if (count <= 0) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3281 Invalid provisioning of " "xri:%d\n", count); rc = -EINVAL; @@ -6805,7 +6800,7 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) /* VFIs. */ count = phba->sli4_hba.max_cfg_param.max_vfi; if (count <= 0) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3282 Invalid provisioning of " "vfi:%d\n", count); rc = -EINVAL; @@ -6899,7 +6894,7 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba) * lpfc_sli4_get_allocated_extnts - Get the port's allocated extents. * @phba: Pointer to HBA context object. * @type: The resource extent type. - * @extnt_count: buffer to hold port extent count response + * @extnt_cnt: buffer to hold port extent count response * @extnt_size: buffer to hold port extent size response. * * This function calls the port to read the host allocated extents @@ -6983,7 +6978,7 @@ lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type, LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT, req_len, emb); if (alloc_len < req_len) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2983 Allocated DMA memory size (x%x) is " "less than the requested DMA memory " "size (x%x)\n", alloc_len, req_len); @@ -7026,7 +7021,7 @@ lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type, } if (bf_get(lpfc_mbox_hdr_status, &shdr->response)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2984 Failed to read allocated resources " "for type %d - Status 0x%x Add'l Status 0x%x.\n", type, @@ -7043,7 +7038,6 @@ lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type, /** * lpfc_sli4_repost_sgl_list - Repost the buffers sgl pages as block * @phba: pointer to lpfc hba data structure. - * @pring: Pointer to driver SLI ring object. * @sgl_list: linked link of sgl buffers to post * @cnt: number of linked list buffers * @@ -7181,7 +7175,7 @@ lpfc_sli4_repost_sgl_list(struct lpfc_hba *phba, spin_unlock(&phba->sli4_hba.sgl_list_lock); spin_unlock_irq(&phba->hbalock); } else { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3161 Failure to post sgl to port.\n"); return -EIO; } @@ -7278,7 +7272,7 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq, drqe.address_hi = putPaddrHigh(rqb_buffer->dbuf.phys); rc = lpfc_sli4_rq_put(hrq, drq, &hrqe, &drqe); if (rc < 0) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6421 Cannot post to HRQ %d: %x %x %x " "DRQ %x %x\n", hrq->queue_id, @@ -7298,6 +7292,68 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq, return 1; } +/** + * lpfc_init_idle_stat_hb - Initialize idle_stat tracking + * @phba: pointer to lpfc hba data structure. + * + * This routine initializes the per-cq idle_stat to dynamically dictate + * polling decisions. + * + * Return codes: + * None + **/ +static void lpfc_init_idle_stat_hb(struct lpfc_hba *phba) +{ + int i; + struct lpfc_sli4_hdw_queue *hdwq; + struct lpfc_queue *cq; + struct lpfc_idle_stat *idle_stat; + u64 wall; + + for_each_present_cpu(i) { + hdwq = &phba->sli4_hba.hdwq[phba->sli4_hba.cpu_map[i].hdwq]; + cq = hdwq->io_cq; + + /* Skip if we've already handled this cq's primary CPU */ + if (cq->chann != i) + continue; + + idle_stat = &phba->sli4_hba.idle_stat[i]; + + idle_stat->prev_idle = get_cpu_idle_time(i, &wall, 1); + idle_stat->prev_wall = wall; + + if (phba->nvmet_support) + cq->poll_mode = LPFC_QUEUE_WORK; + else + cq->poll_mode = LPFC_IRQ_POLL; + } + + if (!phba->nvmet_support) + schedule_delayed_work(&phba->idle_stat_delay_work, + msecs_to_jiffies(LPFC_IDLE_STAT_DELAY)); +} + +static void lpfc_sli4_dip(struct lpfc_hba *phba) +{ + uint32_t if_type; + + if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); + if (if_type == LPFC_SLI_INTF_IF_TYPE_2 || + if_type == LPFC_SLI_INTF_IF_TYPE_6) { + struct lpfc_register reg_data; + + if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, + ®_data.word0)) + return; + + if (bf_get(lpfc_sliport_status_dip, ®_data)) + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2904 Firmware Dump Image Present" + " on Adapter"); + } +} + /** * lpfc_sli4_hba_setup - SLI4 device initialization PCI function * @phba: Pointer to HBA context object. @@ -7336,6 +7392,8 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) spin_unlock_irq(&phba->hbalock); } + lpfc_sli4_dip(phba); + /* * Allocate a single mailbox container for initializing the * port. @@ -7376,7 +7434,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) phba->hba_flag &= ~HBA_IOQ_FLUSH; if (phba->sli_rev != LPFC_SLI_REV4) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0376 READ_REV Error. SLI Level %d " "FCoE enabled %d\n", phba->sli_rev, phba->hba_flag & HBA_FCOE_MODE); @@ -7418,7 +7476,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) */ rc = lpfc_parse_vpd(phba, vpd, vpd_size); if (unlikely(!rc)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0377 Error %d parsing vpd. " "Using defaults.\n", rc); rc = 0; @@ -7557,7 +7615,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); dd = bf_get(lpfc_mbx_set_feature_dd, &mboxq->u.mqe.un.set_feature); if ((rc == MBX_SUCCESS) && (dd == LPFC_ENABLE_DUAL_DUMP)) - lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "6448 Dual Dump is enabled\n"); else lpfc_printf_log(phba, KERN_INFO, LOG_SLI | LOG_INIT, @@ -7575,7 +7633,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) */ rc = lpfc_sli4_alloc_resource_identifiers(phba); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2920 Failed to alloc Resource IDs " "rc = x%x\n", rc); goto out_free_mbox; @@ -7614,7 +7672,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) kfree(mp); mboxq->ctx_buf = NULL; if (unlikely(rc)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0382 READ_SPARAM command failed " "status %d, mbxStatus x%x\n", rc, bf_get(lpfc_mqe_status, mqe)); @@ -7632,7 +7690,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) /* Create all the SLI4 queues */ rc = lpfc_sli4_queue_create(phba); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3089 Failed to allocate queues\n"); rc = -ENODEV; goto out_free_mbox; @@ -7640,7 +7698,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) /* Set up all the queues to the device */ rc = lpfc_sli4_queue_setup(phba); if (unlikely(rc)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0381 Error %d during queue setup.\n ", rc); goto out_stop_timers; } @@ -7651,7 +7709,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) /* update host els xri-sgl sizes and mappings */ rc = lpfc_sli4_els_sgl_update(phba); if (unlikely(rc)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1400 Failed to update xri-sgl size and " "mapping: %d\n", rc); goto out_destroy_queue; @@ -7661,7 +7719,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) rc = lpfc_sli4_repost_sgl_list(phba, &phba->sli4_hba.lpfc_els_sgl_list, phba->sli4_hba.els_xri_cnt); if (unlikely(rc < 0)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0582 Error %d during els sgl post " "operation\n", rc); rc = -ENODEV; @@ -7673,7 +7731,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) /* update host nvmet xri-sgl sizes and mappings */ rc = lpfc_sli4_nvmet_sgl_update(phba); if (unlikely(rc)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6308 Failed to update nvmet-sgl size " "and mapping: %d\n", rc); goto out_destroy_queue; @@ -7685,7 +7743,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) &phba->sli4_hba.lpfc_nvmet_sgl_list, phba->sli4_hba.nvmet_xri_cnt); if (unlikely(rc < 0)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3117 Error %d during nvmet " "sgl post\n", rc); rc = -ENODEV; @@ -7702,7 +7760,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) /* update host common xri-sgl sizes and mappings */ rc = lpfc_sli4_io_sgl_update(phba); if (unlikely(rc)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6082 Failed to update nvme-sgl size " "and mapping: %d\n", rc); goto out_destroy_queue; @@ -7711,7 +7769,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) /* register the allocated common sgl pool to the port */ rc = lpfc_sli4_repost_io_sgl_list(phba); if (unlikely(rc)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6116 Error %d during nvme sgl post " "operation\n", rc); /* Some NVME buffers were moved to abort nvme list */ @@ -7732,7 +7790,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) cnt); rc = lpfc_init_iocb_list(phba, cnt); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1413 Failed to init iocb list.\n"); goto out_destroy_queue; } @@ -7761,7 +7819,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) /* Post the rpi header region to the device. */ rc = lpfc_sli4_post_all_rpi_hdrs(phba); if (unlikely(rc)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0393 Error %d during rpi post operation\n", rc); rc = -ENODEV; @@ -7853,6 +7911,9 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) queue_delayed_work(phba->wq, &phba->eq_delay_work, msecs_to_jiffies(LPFC_EQ_DELAY_MSECS)); + /* start per phba idle_stat_delay heartbeat */ + lpfc_init_idle_stat_hb(phba); + /* Start error attention (ERATT) polling timer */ mod_timer(&phba->eratt_poll, jiffies + msecs_to_jiffies(1000 * phba->eratt_poll_interval)); @@ -7902,12 +7963,12 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) if (!(phba->hba_flag & HBA_FCOE_MODE) && (phba->hba_flag & LINK_DISABLED)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3103 Adapter Link is disabled.\n"); lpfc_down_link(phba, mboxq); rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3104 Adapter failed to issue " "DOWN_LINK mbox cmd, rc:x%x\n", rc); goto out_io_buff_free; @@ -7940,7 +8001,7 @@ out_free_mbox: /** * lpfc_mbox_timeout - Timeout call back function for mbox timer - * @ptr: context object - pointer to hba structure. + * @t: Context to fetch pointer to hba structure from. * * This is the callback function for mailbox timer. The mailbox * timer is armed when a new mailbox command is issued and the timer @@ -8114,7 +8175,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) } /* Mbox cmd timeout */ - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0310 Mailbox command x%x timeout Data: x%x x%x x%px\n", mb->mbxCommand, phba->pport->port_state, @@ -8136,7 +8197,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) lpfc_sli_abort_fcp_rings(phba); - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0345 Resetting board due to mailbox timeout\n"); /* Reset the HBA device */ @@ -8234,7 +8295,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, spin_unlock_irqrestore(&phba->hbalock, drvr_flag); /* Mbox command cannot issue */ - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "(%d):0311 Mailbox command x%x cannot " "issue Data: x%x x%x\n", pmbox->vport ? pmbox->vport->vpi : 0, @@ -8246,7 +8307,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, if (lpfc_readl(phba->HCregaddr, &hc_copy) || !(hc_copy & HC_MBINT_ENA)) { spin_unlock_irqrestore(&phba->hbalock, drvr_flag); - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "(%d):2528 Mailbox command x%x cannot " "issue Data: x%x x%x\n", pmbox->vport ? pmbox->vport->vpi : 0, @@ -8265,7 +8326,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, spin_unlock_irqrestore(&phba->hbalock, drvr_flag); /* Mbox command cannot issue */ - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "(%d):2529 Mailbox command x%x " "cannot issue Data: x%x x%x\n", pmbox->vport ? pmbox->vport->vpi : 0, @@ -8277,7 +8338,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, if (!(psli->sli_flag & LPFC_SLI_ACTIVE)) { spin_unlock_irqrestore(&phba->hbalock, drvr_flag); /* Mbox command cannot issue */ - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "(%d):2530 Mailbox command x%x " "cannot issue Data: x%x x%x\n", pmbox->vport ? pmbox->vport->vpi : 0, @@ -8330,7 +8391,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; spin_unlock_irqrestore(&phba->hbalock, drvr_flag); /* Mbox command cannot issue */ - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "(%d):2531 Mailbox command x%x " "cannot issue Data: x%x x%x\n", pmbox->vport ? pmbox->vport->vpi : 0, @@ -8721,7 +8782,7 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) spin_lock_irqsave(&phba->hbalock, iflag); if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) { spin_unlock_irqrestore(&phba->hbalock, iflag); - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "(%d):2532 Mailbox command x%x (x%x/x%x) " "cannot issue Data: x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, @@ -8820,7 +8881,7 @@ exit: /** * lpfc_sli_issue_mbox_s4 - Issue an SLI4 mailbox command to firmware * @phba: Pointer to HBA context object. - * @pmbox: Pointer to mailbox object. + * @mboxq: Pointer to mailbox object. * @flag: Flag indicating how the mailbox need to be processed. * * This function is called by discovery code and HBA management code to submit @@ -8842,7 +8903,7 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, rc = lpfc_mbox_dev_check(phba); if (unlikely(rc)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "(%d):2544 Mailbox command x%x (x%x/x%x) " "cannot issue Data: x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, @@ -8919,7 +8980,7 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, /* Now, interrupt mode asynchronous mailbox command */ rc = lpfc_mbox_cmd_check(phba, mboxq); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "(%d):2543 Mailbox command x%x (x%x/x%x) " "cannot issue Data: x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, @@ -8987,7 +9048,7 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba) } if (unlikely(phba->sli.mbox_active)) { spin_unlock_irqrestore(&phba->hbalock, iflags); - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0384 There is pending active mailbox cmd\n"); return MBX_NOT_FINISHED; } @@ -9048,7 +9109,7 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba) /* Post the mailbox command to the port */ rc = lpfc_sli4_mq_put(phba->sli4_hba.mbx_wq, mqe); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "(%d):2533 Mailbox command x%x (x%x/x%x) " "cannot issue Data: x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, @@ -9124,7 +9185,7 @@ lpfc_mbox_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) phba->lpfc_sli_brdready = lpfc_sli_brdready_s4; break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1420 Invalid HBA PCI-device group: 0x%x\n", dev_grp); return -ENODEV; @@ -9225,8 +9286,7 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number, if (piocb->iocb_cmpl && (!piocb->vport) && (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) { - lpfc_printf_log(phba, KERN_ERR, - LOG_SLI | LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1807 IOCB x%x failed. No vport\n", piocb->iocb.ulpCommand); dump_stack(); @@ -9327,7 +9387,7 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number, /** * lpfc_sli4_bpl2sgl - Convert the bpl/bde to a sgl. * @phba: Pointer to HBA context object. - * @piocb: Pointer to command iocb. + * @piocbq: Pointer to command iocb. * @sglq: Pointer to the scatter gather queue object. * * This routine converts the bpl or bde that is in the IOCB @@ -9435,7 +9495,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, /** * lpfc_sli_iocb2wqe - Convert the IOCB to a work queue entry. * @phba: Pointer to HBA context object. - * @piocb: Pointer to command iocb. + * @iocbq: Pointer to command iocb. * @wqe: Pointer to the work queue entry. * * This routine converts the iocb command to its Work Queue Entry @@ -9521,7 +9581,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, else ndlp = (struct lpfc_nodelist *)iocbq->context1; if (!iocbq->iocb.ulpLe) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2007 Only Limited Edition cmd Format" " supported 0x%x\n", iocbq->iocb.ulpCommand); @@ -9829,7 +9889,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, /* word6 context tag copied in memcpy */ if (iocbq->iocb.ulpCt_h || iocbq->iocb.ulpCt_l) { ct = ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l); - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2015 Invalid CT %x command 0x%x\n", ct, iocbq->iocb.ulpCommand); return IOCB_ERROR; @@ -10008,7 +10068,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, case CMD_FCP_TRSP64_CX: /* Target mode rcv */ case CMD_FCP_AUTO_TRSP_CX: /* Auto target rsp */ default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2014 Invalid command 0x%x\n", iocbq->iocb.ulpCommand); return IOCB_ERROR; @@ -10129,7 +10189,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, return 0; } -/** +/* * __lpfc_sli_issue_iocb - Wrapper func of lockless version for issuing iocb * * This routine wraps the actual lockless version for issusing IOCB function @@ -10170,7 +10230,7 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) phba->__lpfc_sli_release_iocbq = __lpfc_sli_release_iocbq_s4; break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1419 Invalid HBA PCI-device group: 0x%x\n", dev_grp); return -ENODEV; @@ -10218,7 +10278,7 @@ lpfc_sli4_calc_ring(struct lpfc_hba *phba, struct lpfc_iocbq *piocb) /** * lpfc_sli_issue_iocb - Wrapper function for __lpfc_sli_issue_iocb * @phba: Pointer to HBA context object. - * @pring: Pointer to driver SLI ring object. + * @ring_number: Ring number * @piocb: Pointer to command iocb. * @flag: Flag indicating if this command can be put into txq. * @@ -10430,13 +10490,13 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT; if (evt_code == ASYNC_TEMP_WARN) { temp_event_data.event_code = LPFC_THRESHOLD_TEMP; - lpfc_printf_log(phba, KERN_ERR, LOG_TEMP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0347 Adapter is very hot, please take " "corrective action. temperature : %d Celsius\n", (uint32_t) icmd->ulpContext); } else { temp_event_data.event_code = LPFC_NORMAL_TEMP; - lpfc_printf_log(phba, KERN_ERR, LOG_TEMP, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0340 Adapter temperature is OK now. " "temperature : %d Celsius\n", (uint32_t) icmd->ulpContext); @@ -10453,7 +10513,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, break; default: iocb_w = (uint32_t *) icmd; - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0346 Ring %d handler: unexpected ASYNC_STATUS" " evt_code 0x%x\n" "W0 0x%08x W1 0x%08x W2 0x%08x W3 0x%08x\n" @@ -11127,7 +11187,7 @@ lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } spin_unlock_irq(&phba->hbalock); - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0402 Cannot find virtual addr for buffer tag on " "ring %d Data x%lx x%px x%px x%x\n", pring->ringno, (unsigned long) tag, @@ -11171,7 +11231,7 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } spin_unlock_irq(&phba->hbalock); - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0410 Cannot find virtual addr for mapped buf on " "ring %d Data x%llx x%px x%px x%x\n", pring->ringno, (unsigned long long)phys, @@ -11719,7 +11779,7 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, * @pring: Pointer to driver SLI ring object. * @tgt_id: SCSI ID of the target. * @lun_id: LUN ID of the scsi device. - * @taskmgmt_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST. + * @cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST. * * This function sends an abort command for every SCSI command * associated with the given virtual port pending on the ring @@ -11959,7 +12019,7 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba, /** * lpfc_sli_issue_iocb_wait - Synchronous function to issue iocb commands * @phba: Pointer to HBA context object.. - * @pring: Pointer to sli ring. + * @ring_number: Ring number * @piocb: Pointer to command iocb. * @prspiocbq: Pointer to response iocb. * @timeout: Timeout in number of seconds. @@ -12065,12 +12125,12 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, * completed. Not that it completed successfully. * */ } else if (timeleft == 0) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0338 IOCB wait timeout error - no " "wake response Data x%x\n", timeout); retval = IOCB_TIMEDOUT; } else { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0330 IOCB wake NOT set, " "Data x%x x%lx\n", timeout, (timeleft / jiffies)); @@ -12179,6 +12239,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, /** * lpfc_sli_mbox_sys_shutdown - shutdown mailbox command sub-system * @phba: Pointer to HBA context. + * @mbx_action: Mailbox shutdown options. * * This function is called to shutdown the driver's mailbox sub-system. * It first marks the mailbox sub-system is in a block state to prevent @@ -12332,7 +12393,7 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba) } if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) || (~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1423 HBA Unrecoverable error: " "uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, " "ue_mask_lo_reg=0x%x, " @@ -12363,7 +12424,7 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba) readl(phba->sli4_hba.u.if_type2.ERR1regaddr); phba->work_status[1] = readl(phba->sli4_hba.u.if_type2.ERR2regaddr); - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2885 Port Status Event: " "port status reg 0x%x, " "port smphr reg 0x%x, " @@ -12379,7 +12440,7 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba) break; case LPFC_SLI_INTF_IF_TYPE_1: default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2886 HBA Error Attention on unsupported " "if type %d.", if_type); return 1; @@ -12443,7 +12504,7 @@ lpfc_sli_check_eratt(struct lpfc_hba *phba) ha_copy = lpfc_sli4_eratt_read(phba); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0299 Invalid SLI revision (%d)\n", phba->sli_rev); ha_copy = 0; @@ -12676,8 +12737,7 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id) * Stray Mailbox Interrupt, mbxCommand * mbxStatus */ - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | - LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "(%d):0304 Stray Mailbox " "Interrupt mbxCommand x%x " "mbxStatus x%x\n", @@ -12737,7 +12797,7 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id) if (rc != MBX_BUSY) lpfc_printf_log(phba, KERN_ERR, - LOG_MBOX | LOG_SLI, + LOG_TRACE_EVENT, "0350 rc should have" "been MBX_BUSY\n"); if (rc != MBX_NOT_FINISHED) @@ -12766,8 +12826,9 @@ send_current_mbox: MBX_NOWAIT); } while (rc == MBX_NOT_FINISHED); if (rc != MBX_SUCCESS) - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | - LOG_SLI, "0349 rc should be " + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, + "0349 rc should be " "MBX_SUCCESS\n"); } @@ -13139,7 +13200,7 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba, /** * lpfc_sli4_els_wcqe_to_rspiocbq - Get response iocbq from els wcqe * @phba: Pointer to HBA context object. - * @wcqe: Pointer to work-queue completion queue entry. + * @irspiocbq: Pointer to work-queue completion queue entry. * * This routine handles an ELS work-queue completion event and construct * a pseudo response ELS IODBQ from the SLI4 ELS WCQE for the common @@ -13194,7 +13255,7 @@ lpfc_cq_event_setup(struct lpfc_hba *phba, void *entry, int size) /* Allocate a new internal CQ_EVENT entry */ cq_event = lpfc_sli4_cq_event_alloc(phba); if (!cq_event) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0602 Failed to alloc CQ_EVENT entry\n"); return NULL; } @@ -13207,7 +13268,7 @@ lpfc_cq_event_setup(struct lpfc_hba *phba, void *entry, int size) /** * lpfc_sli4_sp_handle_async_event - Handle an asynchronous event * @phba: Pointer to HBA context object. - * @cqe: Pointer to mailbox completion queue entry. + * @mcqe: Pointer to mailbox completion queue entry. * * This routine process a mailbox completion queue entry with asynchronous * event. @@ -13240,7 +13301,7 @@ lpfc_sli4_sp_handle_async_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe) /** * lpfc_sli4_sp_handle_mbox_event - Handle a mailbox completion event * @phba: Pointer to HBA context object. - * @cqe: Pointer to mailbox completion queue entry. + * @mcqe: Pointer to mailbox completion queue entry. * * This routine process a mailbox completion queue entry with mailbox * completion event. @@ -13269,7 +13330,7 @@ lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe) spin_lock_irqsave(&phba->hbalock, iflags); pmb = phba->sli.mbox_active; if (unlikely(!pmb)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1832 No pending MBOX command to handle\n"); spin_unlock_irqrestore(&phba->hbalock, iflags); goto out_no_mqe_complete; @@ -13318,8 +13379,9 @@ lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe) pmb->vport = vport; rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); if (rc != MBX_BUSY) - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | - LOG_SLI, "0385 rc should " + lpfc_printf_log(phba, KERN_ERR, + LOG_TRACE_EVENT, + "0385 rc should " "have been MBX_BUSY\n"); if (rc != MBX_NOT_FINISHED) goto send_current_mbox; @@ -13360,6 +13422,7 @@ out_no_mqe_complete: /** * lpfc_sli4_sp_handle_mcqe - Process a mailbox completion queue entry * @phba: Pointer to HBA context object. + * @cq: Pointer to associated CQ * @cqe: Pointer to mailbox completion queue entry. * * This routine process a mailbox completion queue entry, it invokes the @@ -13426,7 +13489,7 @@ lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, txq_cnt++; if (!list_empty(&pring->txcmplq)) txcmplq_cnt++; - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0387 NO IOCBQ data: txq_cnt=%d iocb_cnt=%d " "els_txcmplq_cnt=%d\n", txq_cnt, phba->iocb_cnt, @@ -13517,7 +13580,7 @@ lpfc_sli4_sp_handle_abort_xri_wcqe(struct lpfc_hba *phba, workposted = true; break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0603 Invalid CQ subtype %d: " "%08x %08x %08x %08x\n", cq->subtype, wcqe->word0, wcqe->parameter, @@ -13565,7 +13628,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe) status = bf_get(lpfc_rcqe_status, rcqe); switch (status) { case FC_STATUS_RQ_BUF_LEN_EXCEEDED: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2537 Receive Frame Truncated!!\n"); /* fall through */ case FC_STATUS_RQ_SUCCESS: @@ -13602,7 +13665,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe) case FC_STATUS_INSUFF_BUF_FRM_DISC: if (phba->nvmet_support) { tgtp = phba->targetport->private; - lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6402 RQE Error x%x, posted %d err_cnt " "%d: %x %x %x\n", status, hrq->RQ_buf_posted, @@ -13674,7 +13737,7 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, (struct lpfc_rcqe *)&cqevt); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0388 Not a valid WCQE code: x%x\n", bf_get(lpfc_cqe_code, &cqevt)); break; @@ -13686,6 +13749,7 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, * lpfc_sli4_sp_handle_eqe - Process a slow-path event queue entry * @phba: Pointer to HBA context object. * @eqe: Pointer to fast-path event queue entry. + * @speq: Pointer to slow-path event queue. * * This routine process a event queue entry from the slow-path event queue. * It will check the MajorCode and MinorCode to determine this is for a @@ -13701,6 +13765,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, { struct lpfc_queue *cq = NULL, *childq; uint16_t cqid; + int ret = 0; /* Get the reference to the corresponding CQ */ cqid = bf_get_le32(lpfc_eqe_resource_id, eqe); @@ -13713,7 +13778,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, } if (unlikely(!cq)) { if (phba->sli.sli_flag & LPFC_SLI_ACTIVE) - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0365 Slow-path CQ identifier " "(%d) does not exist\n", cqid); return; @@ -13722,9 +13787,14 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, /* Save EQ associated with this CQ */ cq->assoc_qp = speq; - if (!queue_work_on(cq->chann, phba->wq, &cq->spwork)) - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "0390 Cannot schedule soft IRQ " + if (is_kdump_kernel()) + ret = queue_work(phba->wq, &cq->spwork); + else + ret = queue_work_on(cq->chann, phba->wq, &cq->spwork); + + if (!ret) + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0390 Cannot schedule queue work " "for CQ eqcqid=%d, cqid=%d on CPU %d\n", cqid, cq->queue_id, raw_smp_processor_id()); } @@ -13735,6 +13805,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, * @cq: Pointer to CQ to be processed * @handler: Routine to process each cqe * @delay: Pointer to usdelay to set in case of rescheduling of the handler + * @poll_mode: Polling mode we were called from * * This routine processes completion queue entries in a CQ. While a valid * queue element is found, the handler is called. During processing checks @@ -13752,7 +13823,8 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, static bool __lpfc_sli4_process_cq(struct lpfc_hba *phba, struct lpfc_queue *cq, bool (*handler)(struct lpfc_hba *, struct lpfc_queue *, - struct lpfc_cqe *), unsigned long *delay) + struct lpfc_cqe *), unsigned long *delay, + enum lpfc_poll_mode poll_mode) { struct lpfc_cqe *cqe; bool workposted = false; @@ -13793,6 +13865,10 @@ __lpfc_sli4_process_cq(struct lpfc_hba *phba, struct lpfc_queue *cq, arm = false; } + /* Note: complete the irq_poll softirq before rearming CQ */ + if (poll_mode == LPFC_IRQ_POLL) + irq_poll_complete(&cq->iop); + /* Track the max number of CQEs processed in 1 EQ */ if (count > cq->CQ_max_cqe) cq->CQ_max_cqe = count; @@ -13835,36 +13911,42 @@ __lpfc_sli4_sp_process_cq(struct lpfc_queue *cq) struct lpfc_hba *phba = cq->phba; unsigned long delay; bool workposted = false; + int ret = 0; /* Process and rearm the CQ */ switch (cq->type) { case LPFC_MCQ: workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_sp_handle_mcqe, - &delay); + &delay, LPFC_QUEUE_WORK); break; case LPFC_WCQ: if (cq->subtype == LPFC_IO) workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe, - &delay); + &delay, LPFC_QUEUE_WORK); else workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_sp_handle_cqe, - &delay); + &delay, LPFC_QUEUE_WORK); break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0370 Invalid completion queue type (%d)\n", cq->type); return; } if (delay) { - if (!queue_delayed_work_on(cq->chann, phba->wq, - &cq->sched_spwork, delay)) - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "0394 Cannot schedule soft IRQ " + if (is_kdump_kernel()) + ret = queue_delayed_work(phba->wq, &cq->sched_spwork, + delay); + else + ret = queue_delayed_work_on(cq->chann, phba->wq, + &cq->sched_spwork, delay); + if (!ret) + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0394 Cannot schedule queue work " "for cqid=%d on CPU %d\n", cq->queue_id, cq->chann); } @@ -13933,9 +14015,9 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, IOERR_NO_RESOURCES)) phba->lpfc_rampdown_queue_depth(phba); - /* Log the error status */ + /* Log the cmpl status */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "0373 FCP CQE error: status=x%x: " + "0373 FCP CQE cmpl: status=x%x: " "CQE: %08x %08x %08x %08x\n", bf_get(lpfc_wcqe_c_status, wcqe), wcqe->word0, wcqe->total_data_placed, @@ -14029,6 +14111,7 @@ lpfc_sli4_fp_handle_rel_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, /** * lpfc_sli4_nvmet_handle_rcqe - Process a receive-queue completion queue entry * @phba: Pointer to HBA context object. + * @cq: Pointer to completion queue. * @rcqe: Pointer to receive-queue completion queue entry. * * This routine process a receive-queue completion queue entry. @@ -14073,7 +14156,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, status = bf_get(lpfc_rcqe_status, rcqe); switch (status) { case FC_STATUS_RQ_BUF_LEN_EXCEEDED: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6126 Receive Frame Truncated!!\n"); /* fall through */ case FC_STATUS_RQ_SUCCESS: @@ -14113,7 +14196,7 @@ drop: case FC_STATUS_INSUFF_BUF_FRM_DISC: if (phba->nvmet_support) { tgtp = phba->targetport->private; - lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6401 RQE Error x%x, posted %d err_cnt " "%d: %x %x %x\n", status, hrq->RQ_buf_posted, @@ -14137,7 +14220,7 @@ out: * lpfc_sli4_fp_handle_cqe - Process fast-path work queue completion entry * @phba: adapter with cq * @cq: Pointer to the completion queue. - * @eqe: Pointer to fast-path completion queue entry. + * @cqe: Pointer to fast-path completion queue entry. * * This routine process a fast-path work queue completion entry from fast-path * event queue for FCP command response completion. @@ -14187,7 +14270,7 @@ lpfc_sli4_fp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, } break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0144 Not a valid CQE code: x%x\n", bf_get(lpfc_wcqe_c_code, &wcqe)); break; @@ -14195,9 +14278,48 @@ lpfc_sli4_fp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, return workposted; } +/** + * lpfc_sli4_sched_cq_work - Schedules cq work + * @phba: Pointer to HBA context object. + * @cq: Pointer to CQ + * @cqid: CQ ID + * + * This routine checks the poll mode of the CQ corresponding to + * cq->chann, then either schedules a softirq or queue_work to complete + * cq work. + * + * queue_work path is taken if in NVMET mode, or if poll_mode is in + * LPFC_QUEUE_WORK mode. Otherwise, softirq path is taken. + * + **/ +static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba, + struct lpfc_queue *cq, uint16_t cqid) +{ + int ret = 0; + + switch (cq->poll_mode) { + case LPFC_IRQ_POLL: + irq_poll_sched(&cq->iop); + break; + case LPFC_QUEUE_WORK: + default: + if (is_kdump_kernel()) + ret = queue_work(phba->wq, &cq->irqwork); + else + ret = queue_work_on(cq->chann, phba->wq, &cq->irqwork); + if (!ret) + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0383 Cannot schedule queue work " + "for CQ eqcqid=%d, cqid=%d on CPU %d\n", + cqid, cq->queue_id, + raw_smp_processor_id()); + } +} + /** * lpfc_sli4_hba_handle_eqe - Process a fast-path event queue entry * @phba: Pointer to HBA context object. + * @eq: Pointer to the queue structure. * @eqe: Pointer to fast-path event queue entry. * * This routine process a event queue entry from the fast-path event queue. @@ -14216,7 +14338,7 @@ lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq, uint16_t cqid, id; if (unlikely(bf_get_le32(lpfc_eqe_major_code, eqe) != 0)) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0366 Not a valid completion " "event: majorcode=x%x, minorcode=x%x\n", bf_get_le32(lpfc_eqe_major_code, eqe), @@ -14259,7 +14381,7 @@ lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq, process_cq: if (unlikely(cqid != cq->queue_id)) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0368 Miss-matched fast-path completion " "queue identifier: eqcqid=%d, fcpcqid=%d\n", cqid, cq->queue_id); @@ -14273,16 +14395,13 @@ work_cq: else cq->isr_timestamp = 0; #endif - if (!queue_work_on(cq->chann, phba->wq, &cq->irqwork)) - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "0363 Cannot schedule soft IRQ " - "for CQ eqcqid=%d, cqid=%d on CPU %d\n", - cqid, cq->queue_id, raw_smp_processor_id()); + lpfc_sli4_sched_cq_work(phba, cq, cqid); } /** * __lpfc_sli4_hba_process_cq - Process a fast-path event queue entry * @cq: Pointer to CQ to be processed + * @poll_mode: Enum lpfc_poll_state to determine poll mode * * This routine calls the cq processing routine with the handler for * fast path CQEs. @@ -14296,23 +14415,30 @@ work_cq: * the delay indicates when to reschedule it. **/ static void -__lpfc_sli4_hba_process_cq(struct lpfc_queue *cq) +__lpfc_sli4_hba_process_cq(struct lpfc_queue *cq, + enum lpfc_poll_mode poll_mode) { struct lpfc_hba *phba = cq->phba; unsigned long delay; bool workposted = false; + int ret = 0; /* process and rearm the CQ */ workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe, - &delay); + &delay, poll_mode); if (delay) { - if (!queue_delayed_work_on(cq->chann, phba->wq, - &cq->sched_irqwork, delay)) - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "0367 Cannot schedule soft IRQ " - "for cqid=%d on CPU %d\n", - cq->queue_id, cq->chann); + if (is_kdump_kernel()) + ret = queue_delayed_work(phba->wq, &cq->sched_irqwork, + delay); + else + ret = queue_delayed_work_on(cq->chann, phba->wq, + &cq->sched_irqwork, delay); + if (!ret) + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0367 Cannot schedule queue work " + "for cqid=%d on CPU %d\n", + cq->queue_id, cq->chann); } /* wake up worker thread if there are works to be done */ @@ -14332,7 +14458,7 @@ lpfc_sli4_hba_process_cq(struct work_struct *work) { struct lpfc_queue *cq = container_of(work, struct lpfc_queue, irqwork); - __lpfc_sli4_hba_process_cq(cq); + __lpfc_sli4_hba_process_cq(cq, LPFC_QUEUE_WORK); } /** @@ -14347,7 +14473,7 @@ lpfc_sli4_dly_hba_process_cq(struct work_struct *work) struct lpfc_queue *cq = container_of(to_delayed_work(work), struct lpfc_queue, sched_irqwork); - __lpfc_sli4_hba_process_cq(cq); + __lpfc_sli4_hba_process_cq(cq, LPFC_QUEUE_WORK); } /** @@ -14668,7 +14794,7 @@ lpfc_sli4_queue_free(struct lpfc_queue *queue) * @phba: The HBA that this queue is being created on. * @page_size: The size of a queue page * @entry_size: The size of each queue entry for this queue. - * @entry count: The number of entries that this queue will handle. + * @entry_count: The number of entries that this queue will handle. * @cpu: The cpu that will primarily utilize this queue. * * This function allocates a queue structure and the DMAable memory used for @@ -14840,7 +14966,7 @@ lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq, mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_FCP | LOG_NVME, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6428 Failed allocating mailbox cmd buffer." " EQ delay was not set.\n"); return; @@ -14882,7 +15008,7 @@ lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq, shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2512 MODIFY_EQ_DELAY mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -14959,7 +15085,7 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax) dmult); switch (eq->entry_count) { default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0360 Unsupported EQ count. (%d)\n", eq->entry_count); if (eq->entry_count < 256) { @@ -15003,7 +15129,7 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax) shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2500 EQ_CREATE mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -15022,11 +15148,22 @@ out: return status; } +static int lpfc_cq_poll_hdler(struct irq_poll *iop, int budget) +{ + struct lpfc_queue *cq = container_of(iop, struct lpfc_queue, iop); + + __lpfc_sli4_hba_process_cq(cq, LPFC_IRQ_POLL); + + return 1; +} + /** * lpfc_cq_create - Create a Completion Queue on the HBA * @phba: HBA structure that indicates port to create a queue on. * @cq: The queue structure to use to create the completion queue. * @eq: The event queue to bind this completion queue to. + * @type: Type of queue (EQ, GCQ, MCQ, WCQ, etc). + * @subtype: Functional purpose of the queue (MBOX, IO, ELS, NVMET, etc). * * This function creates a completion queue, as detailed in @wq, on a port, * described by @phba by sending a CQ_CREATE mailbox command to the HBA. @@ -15099,7 +15236,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, } /* fall through */ default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0361 Unsupported CQ count: " "entry cnt %d sz %d pg cnt %d\n", cq->entry_count, cq->entry_size, @@ -15135,7 +15272,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2501 CQ_CREATE mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -15161,6 +15298,8 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, if (cq->queue_id > phba->sli4_hba.cq_max) phba->sli4_hba.cq_max = cq->queue_id; + + irq_poll_init(&cq->iop, LPFC_IRQ_POLL_WEIGHT, lpfc_cq_poll_hdler); out: mempool_free(mbox, phba->mbox_mem_pool); return status; @@ -15171,6 +15310,8 @@ out: * @phba: HBA structure that indicates port to create a queue on. * @cqp: The queue structure array to use to create the completion queues. * @hdwq: The hardware queue array with the EQ to bind completion queues to. + * @type: Type of queue (EQ, GCQ, MCQ, WCQ, etc). + * @subtype: Functional purpose of the queue (MBOX, IO, ELS, NVMET, etc). * * This function creates a set of completion queue, s to support MRQ * as detailed in @cqp, on a port, @@ -15220,7 +15361,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, LPFC_MBOX_OPCODE_FCOE_CQ_CREATE_SET, length, LPFC_SLI4_MBX_NEMBED); if (alloclen < length) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3098 Allocated DMA memory size (%d) is " "less than the requested DMA memory size " "(%d)\n", alloclen, length); @@ -15274,7 +15415,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, } /* fall through */ default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3118 Bad CQ count. (%d)\n", cq->entry_count); if (cq->entry_count < 256) { @@ -15392,7 +15533,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3119 CQ_CREATE_SET mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -15550,7 +15691,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq, cq->queue_id); switch (mq->entry_count) { default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0362 Unsupported MQ count. (%d)\n", mq->entry_count); if (mq->entry_count < 16) { @@ -15606,7 +15747,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq, shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2502 MQ_CREATE mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -15669,8 +15810,10 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, uint16_t pci_barset; uint8_t dpp_barset; uint32_t dpp_offset; - unsigned long pg_addr; uint8_t wq_create_version; +#ifdef CONFIG_X86 + unsigned long pg_addr; +#endif /* sanity check on queue memory */ if (!wq || !cq) @@ -15755,7 +15898,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2503 WQ_CREATE mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -15782,7 +15925,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, &wq_create->u.response); if ((wq->db_format != LPFC_DB_LIST_FORMAT) && (wq->db_format != LPFC_DB_RING_FORMAT)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3265 WQ[%d] doorbell format " "not supported: x%x\n", wq->queue_id, wq->db_format); @@ -15794,7 +15937,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, pci_barset); if (!bar_memmap_p) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3263 WQ[%d] failed to memmap " "pci barset:x%x\n", wq->queue_id, pci_barset); @@ -15804,7 +15947,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, db_offset = wq_create->u.response.doorbell_offset; if ((db_offset != LPFC_ULP0_WQ_DOORBELL) && (db_offset != LPFC_ULP1_WQ_DOORBELL)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3252 WQ[%d] doorbell offset " "not supported: x%x\n", wq->queue_id, db_offset); @@ -15828,7 +15971,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, pci_barset); if (!bar_memmap_p) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3267 WQ[%d] failed to memmap " "pci barset:x%x\n", wq->queue_id, pci_barset); @@ -15844,7 +15987,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, dpp_barset); if (!bar_memmap_p) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3268 WQ[%d] failed to memmap " "pci barset:x%x\n", wq->queue_id, dpp_barset); @@ -15860,9 +16003,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, wq->queue_id, pci_barset, db_offset, wq->dpp_id, dpp_barset, dpp_offset); +#ifdef CONFIG_X86 /* Enable combined writes for DPP aperture */ pg_addr = (unsigned long)(wq->dpp_regaddr) & PAGE_MASK; -#ifdef CONFIG_X86 rc = set_memory_wc(pg_addr, 1); if (rc) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -15902,6 +16045,7 @@ out: * @hrq: The queue structure to use to create the header receive queue. * @drq: The queue structure to use to create the data receive queue. * @cq: The completion queue to bind this work queue to. + * @subtype: The subtype of the work queue indicating its functionality. * * This function creates a receive buffer queue pair , as detailed in @hrq and * @drq, on a port, described by @phba by sending a RQ_CREATE mailbox command @@ -15968,7 +16112,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, } else { switch (hrq->entry_count) { default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2535 Unsupported RQ count. (%d)\n", hrq->entry_count); if (hrq->entry_count < 512) { @@ -16019,7 +16163,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2504 RQ_CREATE mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -16037,7 +16181,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, &rq_create->u.response); if ((hrq->db_format != LPFC_DB_LIST_FORMAT) && (hrq->db_format != LPFC_DB_RING_FORMAT)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3262 RQ [%d] doorbell format not " "supported: x%x\n", hrq->queue_id, hrq->db_format); @@ -16049,7 +16193,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, &rq_create->u.response); bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, pci_barset); if (!bar_memmap_p) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3269 RQ[%d] failed to memmap pci " "barset:x%x\n", hrq->queue_id, pci_barset); @@ -16060,7 +16204,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, db_offset = rq_create->u.response.doorbell_offset; if ((db_offset != LPFC_ULP0_RQ_DOORBELL) && (db_offset != LPFC_ULP1_RQ_DOORBELL)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3270 RQ[%d] doorbell offset not " "supported: x%x\n", hrq->queue_id, db_offset); @@ -16105,7 +16249,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, } else { switch (drq->entry_count) { default: - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2536 Unsupported RQ count. (%d)\n", drq->entry_count); if (drq->entry_count < 512) { @@ -16191,6 +16335,7 @@ out: * @hrqp: The queue structure array to use to create the header receive queues. * @drqp: The queue structure array to use to create the data receive queues. * @cqp: The completion queue array to bind these receive queues to. + * @subtype: Functional purpose of the queue (MBOX, IO, ELS, NVMET, etc). * * This function creates a receive buffer queue pair , as detailed in @hrq and * @drq, on a port, described by @phba by sending a RQ_CREATE mailbox command @@ -16242,7 +16387,7 @@ lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp, LPFC_MBOX_OPCODE_FCOE_RQ_CREATE, length, LPFC_SLI4_MBX_NEMBED); if (alloclen < length) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3099 Allocated DMA memory size (%d) is " "less than the requested DMA memory size " "(%d)\n", alloclen, length); @@ -16352,7 +16497,7 @@ lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp, shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3120 RQ_CREATE mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -16380,6 +16525,7 @@ out: /** * lpfc_eq_destroy - Destroy an event Queue on the HBA + * @phba: HBA structure that indicates port to destroy a queue on. * @eq: The queue structure associated with the queue to destroy. * * This function destroys a queue, as detailed in @eq by sending an mailbox @@ -16422,7 +16568,7 @@ lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq) shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2505 EQ_DESTROY mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -16437,6 +16583,7 @@ lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq) /** * lpfc_cq_destroy - Destroy a Completion Queue on the HBA + * @phba: HBA structure that indicates port to destroy a queue on. * @cq: The queue structure associated with the queue to destroy. * * This function destroys a queue, as detailed in @cq by sending an mailbox @@ -16477,7 +16624,7 @@ lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq) shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2506 CQ_DESTROY mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -16491,7 +16638,8 @@ lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq) /** * lpfc_mq_destroy - Destroy a Mailbox Queue on the HBA - * @qm: The queue structure associated with the queue to destroy. + * @phba: HBA structure that indicates port to destroy a queue on. + * @mq: The queue structure associated with the queue to destroy. * * This function destroys a queue, as detailed in @mq by sending an mailbox * command, specific to the type of queue, to the HBA. @@ -16531,7 +16679,7 @@ lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq) shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2507 MQ_DESTROY mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -16545,6 +16693,7 @@ lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq) /** * lpfc_wq_destroy - Destroy a Work Queue on the HBA + * @phba: HBA structure that indicates port to destroy a queue on. * @wq: The queue structure associated with the queue to destroy. * * This function destroys a queue, as detailed in @wq by sending an mailbox @@ -16584,7 +16733,7 @@ lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq) shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2508 WQ_DESTROY mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -16600,7 +16749,9 @@ lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq) /** * lpfc_rq_destroy - Destroy a Receive Queue on the HBA - * @rq: The queue structure associated with the queue to destroy. + * @phba: HBA structure that indicates port to destroy a queue on. + * @hrq: The queue structure associated with the queue to destroy. + * @drq: The queue structure associated with the queue to destroy. * * This function destroys a queue, as detailed in @rq by sending an mailbox * command, specific to the type of queue, to the HBA. @@ -16641,7 +16792,7 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq, shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2509 RQ_DESTROY mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -16657,7 +16808,7 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq, shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2510 RQ_DESTROY mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -16705,7 +16856,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, union lpfc_sli4_cfg_shdr *shdr; if (xritag == NO_XRI) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0364 Invalid param:\n"); return -EINVAL; } @@ -16746,7 +16897,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, if (rc != MBX_TIMEOUT) mempool_free(mbox, phba->mbox_mem_pool); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2511 POST_SGL mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -16793,6 +16944,7 @@ lpfc_sli4_alloc_xri(struct lpfc_hba *phba) /** * lpfc_sli4_free_xri - Release an xri for reuse. * @phba: pointer to lpfc hba data structure. + * @xri: xri to release. * * This routine is invoked to release an xri to the pool of * available rpis maintained by the driver. @@ -16808,6 +16960,7 @@ __lpfc_sli4_free_xri(struct lpfc_hba *phba, int xri) /** * lpfc_sli4_free_xri - Release an xri for reuse. * @phba: pointer to lpfc hba data structure. + * @xri: xri to release. * * This routine is invoked to release an xri to the pool of * available rpis maintained by the driver. @@ -16850,7 +17003,7 @@ lpfc_sli4_next_xritag(struct lpfc_hba *phba) * lpfc_sli4_post_sgl_list - post a block of ELS sgls to the port. * @phba: pointer to lpfc hba data structure. * @post_sgl_list: pointer to els sgl entry list. - * @count: number of els sgl entries on the list. + * @post_cnt: number of els sgl entries on the list. * * This routine is invoked to post a block of driver's sgl pages to the * HBA using non-embedded mailbox command. No Lock is held. This routine @@ -16877,7 +17030,7 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba, reqlen = post_cnt * sizeof(struct sgl_page_pairs) + sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t); if (reqlen > SLI4_PAGE_SIZE) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2559 Block sgl registration required DMA " "size (%d) great than a page\n", reqlen); return -ENOMEM; @@ -16893,7 +17046,7 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba, LPFC_SLI4_MBX_NEMBED); if (alloclen < reqlen) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0285 Allocated DMA memory size (%d) is " "less than the requested DMA memory " "size (%d)\n", alloclen, reqlen); @@ -16941,7 +17094,7 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba, if (rc != MBX_TIMEOUT) lpfc_sli4_mbox_cmd_free(phba, mbox); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2513 POST_SGL_BLOCK mailbox command failed " "status x%x add_status x%x mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -16989,7 +17142,7 @@ lpfc_sli4_post_io_sgl_block(struct lpfc_hba *phba, struct list_head *nblist, } mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6119 Failed to allocate mbox cmd memory\n"); return -ENOMEM; } @@ -17000,7 +17153,7 @@ lpfc_sli4_post_io_sgl_block(struct lpfc_hba *phba, struct list_head *nblist, reqlen, LPFC_SLI4_MBX_NEMBED); if (alloclen < reqlen) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6120 Allocated DMA memory size (%d) is " "less than the requested DMA memory " "size (%d)\n", alloclen, reqlen); @@ -17054,7 +17207,7 @@ lpfc_sli4_post_io_sgl_block(struct lpfc_hba *phba, struct list_head *nblist, if (rc != MBX_TIMEOUT) lpfc_sli4_mbox_cmd_free(phba, mbox); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6125 POST_SGL_BLOCK mailbox command failed " "status x%x add_status x%x mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -17067,6 +17220,7 @@ lpfc_sli4_post_io_sgl_block(struct lpfc_hba *phba, struct list_head *nblist, * lpfc_sli4_post_io_sgl_list - Post blocks of nvme buffer sgls from a list * @phba: pointer to lpfc hba data structure. * @post_nblist: pointer to the nvme buffer list. + * @sb_count: number of nvme buffers. * * This routine walks a list of nvme buffers that was passed in. It attempts * to construct blocks of nvme buffer sgls which contains contiguous xris and @@ -17300,6 +17454,7 @@ lpfc_fc_hdr_get_vfi(struct fc_frame_header *fc_hdr) * @phba: Pointer to the HBA structure to search for the vport on * @fc_hdr: A pointer to the FC Header data (In Big Endian Format) * @fcfi: The FC Fabric ID that the frame came from + * @did: Destination ID to match against * * This function searches the @phba for a vport that matches the content of the * @fc_hdr passed in and the @fcfi. This function uses the @fc_hdr to fetch the @@ -17437,6 +17592,7 @@ lpfc_rcv_seq_check_edtov(struct lpfc_vport *vport) /** * lpfc_fc_frame_add - Adds a frame to the vport's list of received sequences + * @vport: pointer to a vitural port * @dmabuf: pointer to a dmabuf that describes the hdr and data of the FC frame * * This function searches through the existing incomplete sequences that have @@ -17638,7 +17794,7 @@ lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba, /* Failure means BLS ABORT RSP did not get delivered to remote node*/ if (rsp_iocbq && rsp_iocbq->iocb.ulpStatus) - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3154 BLS ABORT RSP failed, data: x%x/x%x\n", rsp_iocbq->iocb.ulpStatus, rsp_iocbq->iocb.un.ulpWord[4]); @@ -17667,8 +17823,9 @@ lpfc_sli4_xri_inrange(struct lpfc_hba *phba, /** * lpfc_sli4_seq_abort_rsp - bls rsp to sequence abort - * @phba: Pointer to HBA context object. + * @vport: pointer to a vitural port. * @fc_hdr: pointer to a FC frame header. + * @aborted: was the partially assembled receive sequence successfully aborted * * This function sends a basic response to a previous unsol sequence abort * event after aborting the sequence handling. @@ -17800,7 +17957,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0); if (rc == IOCB_ERROR) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2925 Failed to issue CT ABTS RSP x%x on " "xri x%x, Data x%x\n", icmd->un.xseq64.w5.hcsw.Rctl, oxid, @@ -17820,7 +17977,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, * receive sequence is only partially assembed by the driver, it shall abort * the partially assembled frames for the sequence. Otherwise, if the * unsolicited receive sequence has been completely assembled and passed to - * the Upper Layer Protocol (UPL), it then mark the per oxid status for the + * the Upper Layer Protocol (ULP), it then mark the per oxid status for the * unsolicited sequence has been aborted. After that, it will issue a basic * accept to accept the abort. **/ @@ -17907,7 +18064,7 @@ lpfc_seq_complete(struct hbq_dmabuf *dmabuf) /** * lpfc_prep_seq - Prep sequence for ULP processing * @vport: Pointer to the vport on which this sequence was received - * @dmabuf: pointer to a dmabuf that describes the FC sequence + * @seq_dmabuf: pointer to a dmabuf that describes the FC sequence * * This function takes a sequence, described by a list of frames, and creates * a list of iocbq structures to describe the sequence. This iocbq list will be @@ -18050,7 +18207,7 @@ lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport, fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt; iocbq = lpfc_prep_seq(vport, seq_dmabuf); if (!iocbq) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2707 Ring %d handler: Failed to allocate " "iocb Rctl x%x Type x%x received\n", LPFC_ELS_RING, @@ -18061,7 +18218,7 @@ lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport, phba->sli4_hba.els_wq->pring, iocbq, fc_hdr->fh_r_ctl, fc_hdr->fh_type)) - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2540 Ring %d handler: unexpected Rctl " "x%x Type x%x received\n", LPFC_ELS_RING, @@ -18180,6 +18337,7 @@ exit: /** * lpfc_sli4_handle_received_buffer - Handle received buffers from firmware * @phba: Pointer to HBA context object. + * @dmabuf: Pointer to a dmabuf that describes the FC sequence. * * This function is called with no lock held. This function processes all * the received buffers and gives it to upper layers when a received buffer @@ -18326,7 +18484,7 @@ lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *phba) rc = lpfc_sli4_post_rpi_hdr(phba, rpi_page); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2008 Error %d posting all rpi " "headers\n", rc); rc = -EIO; @@ -18372,7 +18530,7 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) /* The port is notified of the header region via a mailbox command. */ mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2001 Unable to allocate memory for issuing " "SLI_CONFIG_SPECIAL mailbox command\n"); return -ENOMEM; @@ -18402,7 +18560,7 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) if (rc != MBX_TIMEOUT) mempool_free(mboxq, phba->mbox_mem_pool); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2514 POST_RPI_HDR mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -18492,7 +18650,7 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) if (rpi_remaining < LPFC_RPI_LOW_WATER_MARK) { rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); if (!rpi_hdr) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2002 Error Could not grow rpi " "count\n"); } else { @@ -18508,6 +18666,7 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) /** * lpfc_sli4_free_rpi - Release an rpi for reuse. * @phba: pointer to lpfc hba data structure. + * @rpi: rpi to free * * This routine is invoked to release an rpi to the pool of * available rpis maintained by the driver. @@ -18536,6 +18695,7 @@ __lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) /** * lpfc_sli4_free_rpi - Release an rpi for reuse. * @phba: pointer to lpfc hba data structure. + * @rpi: rpi to free * * This routine is invoked to release an rpi to the pool of * available rpis maintained by the driver. @@ -18565,7 +18725,9 @@ lpfc_sli4_remove_rpis(struct lpfc_hba *phba) /** * lpfc_sli4_resume_rpi - Remove the rpi bitmask region - * @phba: pointer to lpfc hba data structure. + * @ndlp: pointer to lpfc nodelist data structure. + * @cmpl: completion call-back. + * @arg: data to load as MBox 'caller buffer information' * * This routine is invoked to remove the memory region that * provided rpi via a bitmask. @@ -18594,7 +18756,7 @@ lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp, mboxq->vport = ndlp->vport; rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2010 Resume RPI Mailbox failed " "status %d, mbxStatus x%x\n", rc, bf_get(lpfc_mqe_status, &mboxq->u.mqe)); @@ -18629,7 +18791,7 @@ lpfc_sli4_init_vpi(struct lpfc_vport *vport) mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq); rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo); if (rc != MBX_SUCCESS) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2022 INIT VPI Mailbox failed " "status %d, mbxStatus x%x\n", rc, bf_get(lpfc_mqe_status, &mboxq->u.mqe)); @@ -18665,7 +18827,7 @@ lpfc_mbx_cmpl_add_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) if ((shdr_status || shdr_add_status) && (shdr_status != STATUS_FCF_IN_USE)) - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2558 ADD_FCF_RECORD mailbox failed with " "status x%x add_status x%x\n", shdr_status, shdr_add_status); @@ -18695,7 +18857,7 @@ lpfc_sli4_add_fcf_record(struct lpfc_hba *phba, struct fcf_record *fcf_record) mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2009 Failed to allocate mbox for ADD_FCF cmd\n"); return -ENOMEM; } @@ -18708,7 +18870,7 @@ lpfc_sli4_add_fcf_record(struct lpfc_hba *phba, struct fcf_record *fcf_record) LPFC_MBOX_OPCODE_FCOE_ADD_FCF, req_len, LPFC_SLI4_MBX_NEMBED); if (alloc_len < req_len) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2523 Allocated DMA memory size (x%x) is " "less than the requested DMA memory " "size (x%x)\n", alloc_len, req_len); @@ -18741,7 +18903,7 @@ lpfc_sli4_add_fcf_record(struct lpfc_hba *phba, struct fcf_record *fcf_record) mboxq->mbox_cmpl = lpfc_mbx_cmpl_add_fcf_record; rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2515 ADD_FCF_RECORD mailbox failed with " "status 0x%x\n", rc); lpfc_sli4_mbox_cmd_free(phba, mboxq); @@ -18814,7 +18976,7 @@ lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) phba->fcoe_cvl_eventtag_attn = phba->fcoe_cvl_eventtag; mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2000 Failed to allocate mbox for " "READ_FCF cmd\n"); error = -ENOMEM; @@ -18949,7 +19111,7 @@ fail_fcf_read: /** * lpfc_check_next_fcf_pri_level - * phba pointer to the lpfc_hba struct for this port. + * @phba: pointer to the lpfc_hba struct for this port. * This routine is called from the lpfc_sli4_fcf_rr_next_index_get * routine when the rr_bmask is empty. The FCF indecies are put into the * rr_bmask based on their priority level. Starting from the highest priority @@ -19114,6 +19276,7 @@ next_priority: /** * lpfc_sli4_fcf_rr_index_set - Set bmask with eligible fcf record index * @phba: pointer to lpfc hba data structure. + * @fcf_index: index into the FCF table to 'set' * * This routine sets the FCF record index in to the eligible bmask for * roundrobin failover search. It checks to make sure that the index @@ -19146,6 +19309,7 @@ lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index) /** * lpfc_sli4_fcf_rr_index_clear - Clear bmask from eligible fcf record index * @phba: pointer to lpfc hba data structure. + * @fcf_index: index into the FCF table to 'clear' * * This routine clears the FCF record index from the eligible bmask for * roundrobin failover search. It checks to make sure that the index @@ -19183,6 +19347,7 @@ lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index) /** * lpfc_mbx_cmpl_redisc_fcf_table - completion routine for rediscover FCF table * @phba: pointer to lpfc hba data structure. + * @mbox: An allocated pointer to type LPFC_MBOXQ_t * * This routine is the completion routine for the rediscover FCF table mailbox * command. If the mailbox command returned failure, it will try to stop the @@ -19257,7 +19422,7 @@ lpfc_sli4_redisc_fcf_table(struct lpfc_hba *phba) mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2745 Failed to allocate mbox for " "requesting FCF rediscover.\n"); return -ENOMEM; @@ -19325,14 +19490,14 @@ lpfc_sli_get_config_region23(struct lpfc_hba *phba, char *rgn23_data) LPFC_MBOXQ_t *pmb = NULL; MAILBOX_t *mb; uint32_t offset = 0; - int rc; + int i, rc; if (!rgn23_data) return 0; pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmb) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2600 failed to allocate mailbox memory\n"); return 0; } @@ -19355,14 +19520,14 @@ lpfc_sli_get_config_region23(struct lpfc_hba *phba, char *rgn23_data) */ if (mb->un.varDmp.word_cnt == 0) break; - if (mb->un.varDmp.word_cnt > DMP_RGN23_SIZE - offset) - mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset; + i = mb->un.varDmp.word_cnt * sizeof(uint32_t); + if (offset + i > DMP_RGN23_SIZE) + i = DMP_RGN23_SIZE - offset; lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET, - rgn23_data + offset, - mb->un.varDmp.word_cnt); - offset += mb->un.varDmp.word_cnt; - } while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE); + rgn23_data + offset, i); + offset += i; + } while (offset < DMP_RGN23_SIZE); mempool_free(pmb, phba->mbox_mem_pool); return offset; @@ -19391,7 +19556,7 @@ lpfc_sli4_get_config_region23(struct lpfc_hba *phba, char *rgn23_data) mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3105 failed to allocate mailbox memory\n"); return 0; } @@ -19455,7 +19620,7 @@ lpfc_sli_read_link_ste(struct lpfc_hba *phba) /* Check the region signature first */ if (memcmp(&rgn23_data[offset], LPFC_REGION23_SIGNATURE, 4)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2619 Config region 23 has bad signature\n"); goto out; } @@ -19463,7 +19628,7 @@ lpfc_sli_read_link_ste(struct lpfc_hba *phba) /* Check the data structure version */ if (rgn23_data[offset] != LPFC_REGION23_VERSION) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2620 Config region 23 has bad version\n"); goto out; } @@ -19640,7 +19805,7 @@ lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list, if (rc != MBX_TIMEOUT) mempool_free(mbox, phba->mbox_mem_pool); if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3025 Write Object mailbox failed with " "status x%x add_status x%x, mbx status x%x\n", shdr_status, shdr_add_status, rc); @@ -19820,7 +19985,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) piocbq = lpfc_sli_ringtx_get(phba, pring); if (!piocbq) { spin_unlock_irqrestore(&pring->ring_lock, iflags); - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2823 txq empty and txq_cnt is %d\n ", txq_cnt); break; @@ -19849,7 +20014,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) if (fail_msg) { /* Failed means we can't issue and need to cancel */ - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2822 IOCB failed %s iotag 0x%x " "xri 0x%x\n", fail_msg, @@ -19869,7 +20034,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) /** * lpfc_wqe_bpl2sgl - Convert the bpl/bde to a sgl. * @phba: Pointer to HBA context object. - * @pwqe: Pointer to command WQE. + * @pwqeq: Pointer to command WQE. * @sglq: Pointer to the scatter gather queue object. * * This routine converts the bpl or bde that is in the WQE @@ -19994,7 +20159,7 @@ lpfc_wqe_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeq, /** * lpfc_sli4_issue_wqe - Issue an SLI4 Work Queue Entry (WQE) * @phba: Pointer to HBA context object. - * @ring_number: Base sli ring number + * @qp: Pointer to HDW queue. * @pwqe: Pointer to command WQE. **/ int @@ -20276,6 +20441,7 @@ void lpfc_move_xri_pvt_to_pbl(struct lpfc_hba *phba, u32 hwqid) /** * _lpfc_move_xri_pbl_to_pvt - Move some XRIs from public to private pool * @phba: pointer to lpfc hba data structure + * @qp: pointer to HDW queue * @pbl_pool: specified public free XRI pool * @pvt_pool: specified private free XRI pool * @count: number of XRIs to move @@ -20405,7 +20571,7 @@ void lpfc_move_xri_pbl_to_pvt(struct lpfc_hba *phba, u32 hwqid, u32 count) /** * lpfc_keep_pvt_pool_above_lowwm - Keep pvt_pool above low watermark * @phba: pointer to lpfc hba data structure. - * @qp: belong to which HWQ. + * @hwqid: belong to which HWQ. * * This routine get a batch of XRIs from pbl_pool if pvt_pool is less than * low watermark. @@ -20527,6 +20693,7 @@ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd, /** * lpfc_get_io_buf_from_private_pool - Get one free IO buf from private pool * @phba: pointer to lpfc hba data structure. + * @qp: pointer to HDW queue * @pvt_pool: pointer to private pool data structure. * @ndlp: pointer to lpfc nodelist data structure. * diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 4decb53d81c362de2c2a3e9fde2eea5f45190831..a966cdeb52ee7c07f7139b9cb8e52a75677499b4 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -20,6 +20,9 @@ * included with this package. * *******************************************************************/ +#include +#include + #if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_SCSI_LPFC_DEBUG_FS) #define CONFIG_SCSI_LPFC_DEBUG_FS #endif @@ -135,6 +138,16 @@ struct lpfc_rqb { struct rqb_dmabuf *); }; +enum lpfc_poll_mode { + LPFC_QUEUE_WORK, + LPFC_IRQ_POLL +}; + +struct lpfc_idle_stat { + u64 prev_idle; + u64 prev_wall; +}; + struct lpfc_queue { struct list_head list; struct list_head wq_list; @@ -265,6 +278,10 @@ struct lpfc_queue { struct lpfc_queue *assoc_qp; struct list_head _poll_list; void **q_pgs; /* array to index entries per page */ + +#define LPFC_IRQ_POLL_WEIGHT 256 + struct irq_poll iop; + enum lpfc_poll_mode poll_mode; }; struct lpfc_sli4_link { @@ -926,6 +943,7 @@ struct lpfc_sli4_hba { #ifdef CONFIG_SCSI_LPFC_DEBUG_FS struct lpfc_hdwq_stat __percpu *c_stat; #endif + struct lpfc_idle_stat *idle_stat; uint32_t conf_trunk; #define lpfc_conf_trunk_port0_WORD conf_trunk #define lpfc_conf_trunk_port0_SHIFT 0 diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index ab0bc26c098d229392eb0426603deddb8c6a1a82..1987c66662799f50b0d9758d0c840d728f859760 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "12.8.0.1" +#define LPFC_DRIVER_VERSION "12.8.0.2" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index b7664635798006dd25881fdd751c320364ddcbdc..aa4e451d5dc1070a337aa5d37e7abc9fb8e77e38 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -145,7 +145,7 @@ lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport) rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2); if (rc != MBX_SUCCESS) { if (signal_pending(current)) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT | LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1830 Signal aborted mbxCmd x%x\n", mb->mbxCommand); lpfc_mbuf_free(phba, mp->virt, mp->phys); @@ -154,7 +154,7 @@ lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport) mempool_free(pmb, phba->mbox_mem_pool); return -EINTR; } else { - lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT | LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1818 VPort failed init, mbxCmd x%x " "READ_SPARM mbxStatus x%x, rc = x%x\n", mb->mbxCommand, mb->mbxStatus, rc); @@ -190,7 +190,7 @@ lpfc_valid_wwn_format(struct lpfc_hba *phba, struct lpfc_name *wwn, ((wwn->u.wwn[0] & 0xf) != 0 || (wwn->u.wwn[1] & 0xf) != 0))) return 1; - lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1822 Invalid %s: %02x:%02x:%02x:%02x:" "%02x:%02x:%02x:%02x\n", name_type, @@ -284,11 +284,11 @@ static void lpfc_discovery_wait(struct lpfc_vport *vport) } if (time_after(jiffies, wait_time_max)) - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, - "1835 Vport discovery quiesce failed:" - " state x%x fc_flags x%x wait msecs x%x\n", - vport->port_state, vport->fc_flag, - jiffies_to_msecs(jiffies - start_time)); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "1835 Vport discovery quiesce failed:" + " state x%x fc_flags x%x wait msecs x%x\n", + vport->port_state, vport->fc_flag, + jiffies_to_msecs(jiffies - start_time)); } int @@ -305,7 +305,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) int status; if ((phba->sli_rev < 3) || !(phba->cfg_enable_npiv)) { - lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1808 Create VPORT failed: " "NPIV is not enabled: SLImode:%d\n", phba->sli_rev); @@ -315,7 +315,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) /* NPIV is not supported if HBA has NVME Target enabled */ if (phba->nvmet_support) { - lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3189 Create VPORT failed: " "NPIV is not supported on NVME Target\n"); rc = VPORT_INVAL; @@ -324,7 +324,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) vpi = lpfc_alloc_vpi(phba); if (vpi == 0) { - lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1809 Create VPORT failed: " "Max VPORTs (%d) exceeded\n", phba->max_vpi); @@ -334,7 +334,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) /* Assign an unused board number */ if ((instance = lpfc_get_instance()) < 0) { - lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1810 Create VPORT failed: Cannot get " "instance number\n"); lpfc_free_vpi(phba, vpi); @@ -344,7 +344,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) vport = lpfc_create_port(phba, instance, &fc_vport->dev); if (!vport) { - lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1811 Create VPORT failed: vpi x%x\n", vpi); lpfc_free_vpi(phba, vpi); rc = VPORT_NORESOURCES; @@ -356,11 +356,11 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) if ((status = lpfc_vport_sparm(phba, vport))) { if (status == -EINTR) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1831 Create VPORT Interrupted.\n"); rc = VPORT_ERROR; } else { - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1813 Create VPORT failed. " "Cannot get sparam\n"); rc = VPORT_NORESOURCES; @@ -378,7 +378,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) if (!lpfc_valid_wwn_format(phba, &vport->fc_sparam.nodeName, "WWNN") || !lpfc_valid_wwn_format(phba, &vport->fc_sparam.portName, "WWPN")) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1821 Create VPORT failed. " "Invalid WWN format\n"); lpfc_free_vpi(phba, vpi); @@ -388,7 +388,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) } if (!lpfc_unique_wwpn(phba, vport)) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1823 Create VPORT failed. " "Duplicate WWN on HBA\n"); lpfc_free_vpi(phba, vpi); @@ -426,7 +426,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) (pport->fc_flag & FC_VFI_REGISTERED)) { rc = lpfc_sli4_init_vpi(vport); if (rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "1838 Failed to INIT_VPI on vpi %d " "status %d\n", vpi, rc); rc = VPORT_NORESOURCES; @@ -469,7 +469,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) lpfc_initial_fdisc(vport); } else { lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0262 No NPIV Fabric support\n"); } } else { @@ -478,8 +478,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) rc = VPORT_OK; out: - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, - "1825 Vport Created.\n"); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "1825 Vport Created.\n"); lpfc_host_attrib_init(lpfc_shost_from_vport(vport)); error_out: return rc; @@ -534,7 +534,7 @@ disable_vport(struct fc_vport *fc_vport) } lpfc_vport_set_state(vport, FC_VPORT_DISABLED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1826 Vport Disabled.\n"); return VPORT_OK; } @@ -575,7 +575,7 @@ enable_vport(struct fc_vport *fc_vport) lpfc_initial_fdisc(vport); } else { lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP); - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0264 No NPIV Fabric support\n"); } } else { @@ -583,7 +583,7 @@ enable_vport(struct fc_vport *fc_vport) } out: - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1827 Vport Enabled.\n"); return VPORT_OK; } @@ -609,7 +609,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport) bool ns_ndlp_referenced = false; if (vport->port_type == LPFC_PHYSICAL_PORT) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1812 vport_delete failed: Cannot delete " "physical host\n"); return VPORT_ERROR; @@ -618,7 +618,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport) /* If the vport is a static vport fail the deletion. */ if ((vport->vport_flag & STATIC_VPORT) && !(phba->pport->load_flag & FC_UNLOADING)) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1837 vport_delete failed: Cannot delete " "static vport.\n"); return VPORT_ERROR; @@ -642,27 +642,16 @@ lpfc_vport_delete(struct fc_vport *fc_vport) vport->port_state < LPFC_VPORT_READY) return -EAGAIN; } + /* - * This is a bit of a mess. We want to ensure the shost doesn't get - * torn down until we're done with the embedded lpfc_vport structure. - * - * Beyond holding a reference for this function, we also need a - * reference for outstanding I/O requests we schedule during delete - * processing. But once we scsi_remove_host() we can no longer obtain - * a reference through scsi_host_get(). - * - * So we take two references here. We release one reference at the - * bottom of the function -- after delinking the vport. And we - * release the other at the completion of the unreg_vpi that get's - * initiated after we've disposed of all other resources associated - * with the port. + * Take early refcount for outstanding I/O requests we schedule during + * delete processing for unreg_vpi. Always keep this before + * scsi_remove_host() as we can no longer obtain a reference through + * scsi_host_get() after scsi_host_remove as shost is set to SHOST_DEL. */ if (!scsi_host_get(shost)) return VPORT_INVAL; - if (!scsi_host_get(shost)) { - scsi_host_put(shost); - return VPORT_INVAL; - } + lpfc_free_sysfs_attr(vport); lpfc_debugfs_terminate(vport); @@ -809,15 +798,16 @@ skip_logo: if (!(vport->vpi_state & LPFC_VPI_REGISTERED) || lpfc_mbx_unreg_vpi(vport)) scsi_host_put(shost); - } else + } else { scsi_host_put(shost); + } lpfc_free_vpi(phba, vport->vpi); vport->work_port_events = 0; spin_lock_irq(&phba->port_list_lock); list_del_init(&vport->listentry); spin_unlock_irq(&phba->port_list_lock); - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "1828 Vport Deleted.\n"); scsi_host_put(shost); return VPORT_OK; @@ -838,7 +828,8 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba) if (port_iterator->load_flag & FC_UNLOADING) continue; if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) { - lpfc_printf_vlog(port_iterator, KERN_ERR, LOG_VPORT, + lpfc_printf_vlog(port_iterator, KERN_ERR, + LOG_TRACE_EVENT, "1801 Create vport work array FAILED: " "cannot do scsi_host_get\n"); continue; @@ -908,7 +899,8 @@ lpfc_alloc_bucket(struct lpfc_vport *vport) GFP_ATOMIC); if (!ndlp->lat_data) - lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, + lpfc_printf_vlog(vport, KERN_ERR, + LOG_TRACE_EVENT, "0287 lpfc_alloc_bucket failed to " "allocate statistical data buffer DID " "0x%x\n", ndlp->nlp_DID); diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index f27ffd088c8aef2cb5f97885568dc4c9793ee555..0484ee52ae8023e2be9bc06f6f47fb55999fd612 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -124,7 +124,7 @@ static int trace_level; /** * mega_setup_mailbox() - * @adapter - pointer to our soft state + * @adapter: pointer to our soft state * * Allocates a 8 byte aligned memory for the handshake mailbox. */ @@ -347,7 +347,7 @@ mega_query_adapter(adapter_t *adapter) /** * mega_runpendq() - * @adapter - pointer to our soft state + * @adapter: pointer to our soft state * * Runs through the list of pending requests. */ @@ -413,8 +413,8 @@ static DEF_SCSI_QCMD(megaraid_queue) /** * mega_allocate_scb() - * @adapter - pointer to our soft state - * @cmd - scsi command from the mid-layer + * @adapter: pointer to our soft state + * @cmd: scsi command from the mid-layer * * Allocate a SCB structure. This is the central structure for controller * commands. @@ -444,9 +444,9 @@ mega_allocate_scb(adapter_t *adapter, struct scsi_cmnd *cmd) /** * mega_get_ldrv_num() - * @adapter - pointer to our soft state - * @cmd - scsi mid layer command - * @channel - channel on the controller + * @adapter: pointer to our soft state + * @cmd: scsi mid layer command + * @channel: channel on the controller * * Calculate the logical drive number based on the information in scsi command * and the channel number. @@ -503,9 +503,9 @@ mega_get_ldrv_num(adapter_t *adapter, struct scsi_cmnd *cmd, int channel) /** * mega_build_cmd() - * @adapter - pointer to our soft state - * @cmd - Prepare using this scsi command - * @busy - busy flag if no resources + * @adapter: pointer to our soft state + * @cmd: Prepare using this scsi command + * @busy: busy flag if no resources * * Prepares a command and scatter gather list for the controller. This routine * also finds out if the commands is intended for a logical drive or a @@ -517,7 +517,6 @@ mega_get_ldrv_num(adapter_t *adapter, struct scsi_cmnd *cmd, int channel) static scb_t * mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy) { - mega_ext_passthru *epthru; mega_passthru *pthru; scb_t *scb; mbox_t *mbox; @@ -905,7 +904,7 @@ mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy) if( adapter->support_ext_cdb ) { - epthru = mega_prepare_extpassthru(adapter, scb, cmd, + mega_prepare_extpassthru(adapter, scb, cmd, channel, target); mbox->m_out.cmd = MEGA_MBOXCMD_EXTPTHRU; @@ -937,11 +936,11 @@ mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy) /** * mega_prepare_passthru() - * @adapter - pointer to our soft state - * @scb - our scsi control block - * @cmd - scsi command from the mid-layer - * @channel - actual channel on the controller - * @target - actual id on the controller. + * @adapter: pointer to our soft state + * @scb: our scsi control block + * @cmd: scsi command from the mid-layer + * @channel: actual channel on the controller + * @target: actual id on the controller. * * prepare a command for the scsi physical devices. */ @@ -1000,11 +999,11 @@ mega_prepare_passthru(adapter_t *adapter, scb_t *scb, struct scsi_cmnd *cmd, /** * mega_prepare_extpassthru() - * @adapter - pointer to our soft state - * @scb - our scsi control block - * @cmd - scsi command from the mid-layer - * @channel - actual channel on the controller - * @target - actual id on the controller. + * @adapter: pointer to our soft state + * @scb: our scsi control block + * @cmd: scsi command from the mid-layer + * @channel: actual channel on the controller + * @target: actual id on the controller. * * prepare a command for the scsi physical devices. This rountine prepares * commands for devices which can take extended CDBs (>10 bytes) @@ -1085,8 +1084,8 @@ __mega_runpendq(adapter_t *adapter) /** * issue_scb() - * @adapter - pointer to our soft state - * @scb - scsi control block + * @adapter: pointer to our soft state + * @scb: scsi control block * * Post a command to the card if the mailbox is available, otherwise return * busy. We also take the scb from the pending list if the mailbox is @@ -1166,8 +1165,8 @@ mega_busywait_mbox (adapter_t *adapter) /** * issue_scb_block() - * @adapter - pointer to our soft state - * @raw_mbox - the mailbox + * @adapter: pointer to our soft state + * @raw_mbox: the mailbox * * Issue a scb in synchronous and non-interrupt mode */ @@ -1247,8 +1246,8 @@ bug_blocked_mailbox: /** * megaraid_isr_iomapped() - * @irq - irq - * @devp - pointer to our soft state + * @irq: irq + * @devp: pointer to our soft state * * Interrupt service routine for io-mapped controllers. * Find out if our device is interrupting. If yes, acknowledge the interrupt @@ -1323,8 +1322,8 @@ megaraid_isr_iomapped(int irq, void *devp) /** * megaraid_isr_memmapped() - * @irq - irq - * @devp - pointer to our soft state + * @irq: irq + * @devp: pointer to our soft state * * Interrupt service routine for memory-mapped controllers. * Find out if our device is interrupting. If yes, acknowledge the interrupt @@ -1401,10 +1400,10 @@ megaraid_isr_memmapped(int irq, void *devp) } /** * mega_cmd_done() - * @adapter - pointer to our soft state - * @completed - array of ids of completed commands - * @nstatus - number of completed commands - * @status - status of the last command completed + * @adapter: pointer to our soft state + * @completed: array of ids of completed commands + * @nstatus: number of completed commands + * @status: status of the last command completed * * Complete the commands and call the scsi mid-layer callback hooks. */ @@ -1921,9 +1920,9 @@ megaraid_reset(struct scsi_cmnd *cmd) /** * megaraid_abort_and_reset() - * @adapter - megaraid soft state - * @cmd - scsi command to be aborted or reset - * @aor - abort or reset flag + * @adapter: megaraid soft state + * @cmd: scsi command to be aborted or reset + * @aor: abort or reset flag * * Try to locate the scsi command in the pending queue. If found and is not * issued to the controller, abort/reset it. Otherwise return failure @@ -2021,8 +2020,8 @@ free_local_pdev(struct pci_dev *pdev) /** * mega_allocate_inquiry() - * @dma_handle - handle returned for dma address - * @pdev - handle to pci device + * @dma_handle: handle returned for dma address + * @pdev: handle to pci device * * allocates memory for inquiry structure */ @@ -2045,8 +2044,8 @@ mega_free_inquiry(void *inquiry, dma_addr_t dma_handle, struct pci_dev *pdev) /** * proc_show_config() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display configuration information about the controller. */ @@ -2109,8 +2108,8 @@ proc_show_config(struct seq_file *m, void *v) /** * proc_show_stat() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display statistical information about the I/O activity. */ @@ -2143,8 +2142,8 @@ proc_show_stat(struct seq_file *m, void *v) /** * proc_show_mbox() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display mailbox information for the last command issued. This information * is good for debugging. @@ -2171,8 +2170,8 @@ proc_show_mbox(struct seq_file *m, void *v) /** * proc_show_rebuild_rate() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display current rebuild rate */ @@ -2214,8 +2213,8 @@ free_pdev: /** * proc_show_battery() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display information about the battery module on the controller. */ @@ -2317,9 +2316,9 @@ mega_print_inquiry(struct seq_file *m, char *scsi_inq) /** * proc_show_pdrv() - * @m - Synthetic file construction data - * @page - buffer to write the data in - * @adapter - pointer to our soft state + * @m: Synthetic file construction data + * @adapter: pointer to our soft state + * @channel: channel * * Display information about the physical drives. */ @@ -2433,8 +2432,8 @@ free_pdev: /** * proc_show_pdrv_ch0() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display information about the physical drives on physical channel 0. */ @@ -2447,8 +2446,8 @@ proc_show_pdrv_ch0(struct seq_file *m, void *v) /** * proc_show_pdrv_ch1() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display information about the physical drives on physical channel 1. */ @@ -2461,8 +2460,8 @@ proc_show_pdrv_ch1(struct seq_file *m, void *v) /** * proc_show_pdrv_ch2() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display information about the physical drives on physical channel 2. */ @@ -2475,8 +2474,8 @@ proc_show_pdrv_ch2(struct seq_file *m, void *v) /** * proc_show_pdrv_ch3() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display information about the physical drives on physical channel 3. */ @@ -2489,10 +2488,10 @@ proc_show_pdrv_ch3(struct seq_file *m, void *v) /** * proc_show_rdrv() - * @m - Synthetic file construction data - * @adapter - pointer to our soft state - * @start - starting logical drive to display - * @end - ending logical drive to display + * @m: Synthetic file construction data + * @adapter: pointer to our soft state + * @start: starting logical drive to display + * @end: ending logical drive to display * * We do not print the inquiry information since its already available through * /proc/scsi/scsi interface @@ -2674,8 +2673,8 @@ free_pdev: /** * proc_show_rdrv_10() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display real time information about the logical drives 0 through 9. */ @@ -2688,8 +2687,8 @@ proc_show_rdrv_10(struct seq_file *m, void *v) /** * proc_show_rdrv_20() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display real time information about the logical drives 0 through 9. */ @@ -2702,8 +2701,8 @@ proc_show_rdrv_20(struct seq_file *m, void *v) /** * proc_show_rdrv_30() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display real time information about the logical drives 0 through 9. */ @@ -2716,8 +2715,8 @@ proc_show_rdrv_30(struct seq_file *m, void *v) /** * proc_show_rdrv_40() - * @m - Synthetic file construction data - * @v - File iterator + * @m: Synthetic file construction data + * @v: File iterator * * Display real time information about the logical drives 0 through 9. */ @@ -2729,8 +2728,8 @@ proc_show_rdrv_40(struct seq_file *m, void *v) /** * mega_create_proc_entry() - * @index - index in soft state array - * @parent - parent node for this /proc entry + * @index: index in soft state array + * @parent: parent node for this /proc entry * * Creates /proc entries for our controllers. */ @@ -2785,7 +2784,7 @@ static inline void mega_create_proc_entry(int index, struct proc_dir_entry *pare #endif -/** +/* * megaraid_biosparam() * * Return the disk geometry for a particular disk @@ -2854,7 +2853,7 @@ megaraid_biosparam(struct scsi_device *sdev, struct block_device *bdev, /** * mega_init_scb() - * @adapter - pointer to our soft state + * @adapter: pointer to our soft state * * Allocate memory for the various pointers in the scb structures: * scatter-gather list pointer, passthru and extended passthru structure @@ -2934,8 +2933,8 @@ mega_init_scb(adapter_t *adapter) /** * megadev_open() - * @inode - unused - * @filep - unused + * @inode: unused + * @filep: unused * * Routines for the character/ioctl interface to the driver. Find out if this * is a valid open. @@ -2954,10 +2953,9 @@ megadev_open (struct inode *inode, struct file *filep) /** * megadev_ioctl() - * @inode - Our device inode - * @filep - unused - * @cmd - ioctl command - * @arg - user buffer + * @filep: Our device file + * @cmd: ioctl command + * @arg: user buffer * * ioctl entry point for our private ioctl interface. We move the data in from * the user space, prepare the command (if necessary, convert the old MIMD @@ -2977,14 +2975,13 @@ megadev_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) void *data = NULL; /* data to be transferred */ dma_addr_t data_dma_hndl; /* dma handle for data xfer area */ megacmd_t mc; - megastat_t __user *ustats; - int num_ldrv; +#if MEGA_HAVE_STATS + megastat_t __user *ustats = NULL; + int num_ldrv = 0; +#endif u32 uxferaddr = 0; struct pci_dev *pdev; - ustats = NULL; /* avoid compilation warnings */ - num_ldrv = 0; - /* * Make sure only USCSICMD are issued through this interface. * MIMD application would still fire different command. @@ -3370,8 +3367,8 @@ megadev_unlocked_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) /** * mega_m_to_n() - * @arg - user address - * @uioc - new ioctl structure + * @arg: user address + * @uioc: new ioctl structure * * A thin layer to convert older mimd interface ioctl structure to NIT ioctl * structure @@ -3498,8 +3495,8 @@ mega_m_to_n(void __user *arg, nitioctl_t *uioc) /* * mega_n_to_m() - * @arg - user address - * @mc - mailbox command + * @arg: user address + * @mc: mailbox command * * Updates the status information to the application, depending on application * conforms to older mimd ioctl interface or newer NIT ioctl interface @@ -3565,7 +3562,7 @@ mega_n_to_m(void __user *arg, megacmd_t *mc) /** * mega_is_bios_enabled() - * @adapter - pointer to our soft state + * @adapter: pointer to our soft state * * issue command to find out if the BIOS is enabled for this controller */ @@ -3574,7 +3571,6 @@ mega_is_bios_enabled(adapter_t *adapter) { unsigned char raw_mbox[sizeof(struct mbox_out)]; mbox_t *mbox; - int ret; mbox = (mbox_t *)raw_mbox; @@ -3587,8 +3583,7 @@ mega_is_bios_enabled(adapter_t *adapter) raw_mbox[0] = IS_BIOS_ENABLED; raw_mbox[2] = GET_BIOS; - - ret = issue_scb_block(adapter, raw_mbox); + issue_scb_block(adapter, raw_mbox); return *(char *)adapter->mega_buffer; } @@ -3596,7 +3591,7 @@ mega_is_bios_enabled(adapter_t *adapter) /** * mega_enum_raid_scsi() - * @adapter - pointer to our soft state + * @adapter: pointer to our soft state * * Find out what channels are RAID/SCSI. This information is used to * differentiate the virtual channels and physical channels and to support @@ -3651,7 +3646,7 @@ mega_enum_raid_scsi(adapter_t *adapter) /** * mega_get_boot_drv() - * @adapter - pointer to our soft state + * @adapter: pointer to our soft state * * Find out which device is the boot device. Note, any logical drive or any * phyical device (e.g., a CDROM) can be designated as a boot device. @@ -3718,7 +3713,7 @@ mega_get_boot_drv(adapter_t *adapter) /** * mega_support_random_del() - * @adapter - pointer to our soft state + * @adapter: pointer to our soft state * * Find out if this controller supports random deletion and addition of * logical drives @@ -3748,7 +3743,7 @@ mega_support_random_del(adapter_t *adapter) /** * mega_support_ext_cdb() - * @adapter - pointer to our soft state + * @adapter: pointer to our soft state * * Find out if this firmware support cdblen > 10 */ @@ -3776,8 +3771,8 @@ mega_support_ext_cdb(adapter_t *adapter) /** * mega_del_logdrv() - * @adapter - pointer to our soft state - * @logdrv - logical drive to be deleted + * @adapter: pointer to our soft state + * @logdrv: logical drive to be deleted * * Delete the specified logical drive. It is the responsibility of the user * app to let the OS know about this operation. @@ -3862,7 +3857,7 @@ mega_do_del_logdrv(adapter_t *adapter, int logdrv) /** * mega_get_max_sgl() - * @adapter - pointer to our soft state + * @adapter: pointer to our soft state * * Find out the maximum number of scatter-gather elements supported by this * version of the firmware @@ -3908,7 +3903,7 @@ mega_get_max_sgl(adapter_t *adapter) /** * mega_support_cluster() - * @adapter - pointer to our soft state + * @adapter: pointer to our soft state * * Find out if this firmware support cluster calls. */ @@ -3950,8 +3945,8 @@ mega_support_cluster(adapter_t *adapter) #ifdef CONFIG_PROC_FS /** * mega_adapinq() - * @adapter - pointer to our soft state - * @dma_handle - DMA address of the buffer + * @adapter: pointer to our soft state + * @dma_handle: DMA address of the buffer * * Issue internal commands while interrupts are available. * We only issue direct mailbox commands from within the driver. ioctl() @@ -3983,11 +3978,12 @@ mega_adapinq(adapter_t *adapter, dma_addr_t dma_handle) } -/** mega_internal_dev_inquiry() - * @adapter - pointer to our soft state - * @ch - channel for this device - * @tgt - ID of this device - * @buf_dma_handle - DMA address of the buffer +/** + * mega_internal_dev_inquiry() + * @adapter: pointer to our soft state + * @ch: channel for this device + * @tgt: ID of this device + * @buf_dma_handle: DMA address of the buffer * * Issue the scsi inquiry for the specified device. */ @@ -4056,9 +4052,9 @@ mega_internal_dev_inquiry(adapter_t *adapter, u8 ch, u8 tgt, /** * mega_internal_command() - * @adapter - pointer to our soft state - * @mc - the mailbox command - * @pthru - Passthru structure for DCDB commands + * @adapter: pointer to our soft state + * @mc: the mailbox command + * @pthru: Passthru structure for DCDB commands * * Issue the internal commands in interrupt mode. * The last argument is the address of the passthru structure if the command diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 8f918df631bfe41a372feb26e56f0a714801eb0c..19469a2c0ea36f617f5cb33636c4d7dea4b54f71 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -3304,7 +3304,6 @@ blocked_mailbox: * megaraid_mbox_display_scb - display SCB information, mostly debug purposes * @adapter : controller's soft state * @scb : SCB to be displayed - * @level : debug level for console print * * Diplay information about the given SCB iff the current debug level is * verbose. @@ -3972,7 +3971,8 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter) /** * megaraid_sysfs_show_app_hndl - display application handle for this adapter - * @cdev : class device object representation for the host + * @dev : class device object representation for the host + * @attr : device attribute (unused) * @buf : buffer to send data to * * Display the handle used by the applications while executing management diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index e83163c66884508278ba28a400a2e0d6f79e36a4..8df53446641ac0f8ee14034435c6e383a2eda5fb 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -95,7 +95,6 @@ mraid_mm_open(struct inode *inode, struct file *filep) /** * mraid_mm_ioctl - module entry-point for ioctls - * @inode : inode (ignored) * @filep : file operations pointer (ignored) * @cmd : ioctl command * @arg : user ioctl packet diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index af2c7a2a95657d14be454f11687a00c432775cb7..5e4137f10e0e9465d18b1cf28024b7ed5971fa7a 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -2709,4 +2709,24 @@ int megasas_adp_reset_wait_for_ready(struct megasas_instance *instance, int ocr_context); int megasas_irqpoll(struct irq_poll *irqpoll, int budget); void megasas_dump_fusion_io(struct scsi_cmnd *scmd); +u32 megasas_readl(struct megasas_instance *instance, + const volatile void __iomem *addr); +struct megasas_cmd *megasas_get_cmd(struct megasas_instance *instance); +void megasas_return_cmd(struct megasas_instance *instance, + struct megasas_cmd *cmd); +int megasas_issue_polled(struct megasas_instance *instance, + struct megasas_cmd *cmd); +void megaraid_sas_kill_hba(struct megasas_instance *instance); +void megasas_check_and_restore_queue_depth(struct megasas_instance *instance); +void megasas_start_timer(struct megasas_instance *instance); +int megasas_sriov_start_heartbeat(struct megasas_instance *instance, + int initial); +int megasas_alloc_cmds(struct megasas_instance *instance); +void megasas_free_cmds(struct megasas_instance *instance); + +void megasas_init_debugfs(void); +void megasas_exit_debugfs(void); +void megasas_setup_debugfs(struct megasas_instance *instance); +void megasas_destroy_debugfs(struct megasas_instance *instance); + #endif /*LSI_MEGARAID_SAS_H */ diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 00668335c2afc936b410a67ba42d8425b93e0052..861f7140f52e852b7ee375f1a3dce4af068f6b9c 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -202,10 +202,6 @@ static bool support_pci_lane_margining; static spinlock_t poll_aen_lock; extern struct dentry *megasas_debugfs_root; -extern void megasas_init_debugfs(void); -extern void megasas_exit_debugfs(void); -extern void megasas_setup_debugfs(struct megasas_instance *instance); -extern void megasas_destroy_debugfs(struct megasas_instance *instance); void megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, @@ -427,14 +423,14 @@ megasas_decode_evt(struct megasas_instance *instance) evt_detail->description); } -/** -* The following functions are defined for xscale -* (deviceid : 1064R, PERC5) controllers -*/ +/* + * The following functions are defined for xscale + * (deviceid : 1064R, PERC5) controllers + */ /** * megasas_enable_intr_xscale - Enables interrupts - * @regs: MFI register set + * @instance: Adapter soft state */ static inline void megasas_enable_intr_xscale(struct megasas_instance *instance) @@ -450,7 +446,7 @@ megasas_enable_intr_xscale(struct megasas_instance *instance) /** * megasas_disable_intr_xscale -Disables interrupt - * @regs: MFI register set + * @instance: Adapter soft state */ static inline void megasas_disable_intr_xscale(struct megasas_instance *instance) @@ -466,7 +462,7 @@ megasas_disable_intr_xscale(struct megasas_instance *instance) /** * megasas_read_fw_status_reg_xscale - returns the current FW status value - * @regs: MFI register set + * @instance: Adapter soft state */ static u32 megasas_read_fw_status_reg_xscale(struct megasas_instance *instance) @@ -475,7 +471,7 @@ megasas_read_fw_status_reg_xscale(struct megasas_instance *instance) } /** * megasas_clear_interrupt_xscale - Check & clear interrupt - * @regs: MFI register set + * @instance: Adapter soft state */ static int megasas_clear_intr_xscale(struct megasas_instance *instance) @@ -509,9 +505,10 @@ megasas_clear_intr_xscale(struct megasas_instance *instance) /** * megasas_fire_cmd_xscale - Sends command to the FW - * @frame_phys_addr : Physical address of cmd - * @frame_count : Number of frames for the command - * @regs : MFI register set + * @instance: Adapter soft state + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set */ static inline void megasas_fire_cmd_xscale(struct megasas_instance *instance, @@ -529,7 +526,8 @@ megasas_fire_cmd_xscale(struct megasas_instance *instance, /** * megasas_adp_reset_xscale - For controller reset - * @regs: MFI register set + * @instance: Adapter soft state + * @regs: MFI register set */ static int megasas_adp_reset_xscale(struct megasas_instance *instance, @@ -570,7 +568,8 @@ megasas_adp_reset_xscale(struct megasas_instance *instance, /** * megasas_check_reset_xscale - For controller reset check - * @regs: MFI register set + * @instance: Adapter soft state + * @regs: MFI register set */ static int megasas_check_reset_xscale(struct megasas_instance *instance, @@ -599,19 +598,19 @@ static struct megasas_instance_template megasas_instance_template_xscale = { .issue_dcmd = megasas_issue_dcmd, }; -/** -* This is the end of set of functions & definitions specific -* to xscale (deviceid : 1064R, PERC5) controllers -*/ +/* + * This is the end of set of functions & definitions specific + * to xscale (deviceid : 1064R, PERC5) controllers + */ -/** -* The following functions are defined for ppc (deviceid : 0x60) -* controllers -*/ +/* + * The following functions are defined for ppc (deviceid : 0x60) + * controllers + */ /** * megasas_enable_intr_ppc - Enables interrupts - * @regs: MFI register set + * @instance: Adapter soft state */ static inline void megasas_enable_intr_ppc(struct megasas_instance *instance) @@ -629,7 +628,7 @@ megasas_enable_intr_ppc(struct megasas_instance *instance) /** * megasas_disable_intr_ppc - Disable interrupt - * @regs: MFI register set + * @instance: Adapter soft state */ static inline void megasas_disable_intr_ppc(struct megasas_instance *instance) @@ -645,7 +644,7 @@ megasas_disable_intr_ppc(struct megasas_instance *instance) /** * megasas_read_fw_status_reg_ppc - returns the current FW status value - * @regs: MFI register set + * @instance: Adapter soft state */ static u32 megasas_read_fw_status_reg_ppc(struct megasas_instance *instance) @@ -655,7 +654,7 @@ megasas_read_fw_status_reg_ppc(struct megasas_instance *instance) /** * megasas_clear_interrupt_ppc - Check & clear interrupt - * @regs: MFI register set + * @instance: Adapter soft state */ static int megasas_clear_intr_ppc(struct megasas_instance *instance) @@ -688,9 +687,10 @@ megasas_clear_intr_ppc(struct megasas_instance *instance) /** * megasas_fire_cmd_ppc - Sends command to the FW - * @frame_phys_addr : Physical address of cmd - * @frame_count : Number of frames for the command - * @regs : MFI register set + * @instance: Adapter soft state + * @frame_phys_addr: Physical address of cmd + * @frame_count: Number of frames for the command + * @regs: MFI register set */ static inline void megasas_fire_cmd_ppc(struct megasas_instance *instance, @@ -708,7 +708,8 @@ megasas_fire_cmd_ppc(struct megasas_instance *instance, /** * megasas_check_reset_ppc - For controller reset check - * @regs: MFI register set + * @instance: Adapter soft state + * @regs: MFI register set */ static int megasas_check_reset_ppc(struct megasas_instance *instance, @@ -738,7 +739,7 @@ static struct megasas_instance_template megasas_instance_template_ppc = { /** * megasas_enable_intr_skinny - Enables interrupts - * @regs: MFI register set + * @instance: Adapter soft state */ static inline void megasas_enable_intr_skinny(struct megasas_instance *instance) @@ -756,7 +757,7 @@ megasas_enable_intr_skinny(struct megasas_instance *instance) /** * megasas_disable_intr_skinny - Disables interrupt - * @regs: MFI register set + * @instance: Adapter soft state */ static inline void megasas_disable_intr_skinny(struct megasas_instance *instance) @@ -772,7 +773,7 @@ megasas_disable_intr_skinny(struct megasas_instance *instance) /** * megasas_read_fw_status_reg_skinny - returns the current FW status value - * @regs: MFI register set + * @instance: Adapter soft state */ static u32 megasas_read_fw_status_reg_skinny(struct megasas_instance *instance) @@ -782,7 +783,7 @@ megasas_read_fw_status_reg_skinny(struct megasas_instance *instance) /** * megasas_clear_interrupt_skinny - Check & clear interrupt - * @regs: MFI register set + * @instance: Adapter soft state */ static int megasas_clear_intr_skinny(struct megasas_instance *instance) @@ -825,9 +826,10 @@ megasas_clear_intr_skinny(struct megasas_instance *instance) /** * megasas_fire_cmd_skinny - Sends command to the FW - * @frame_phys_addr : Physical address of cmd - * @frame_count : Number of frames for the command - * @regs : MFI register set + * @instance: Adapter soft state + * @frame_phys_addr: Physical address of cmd + * @frame_count: Number of frames for the command + * @regs: MFI register set */ static inline void megasas_fire_cmd_skinny(struct megasas_instance *instance, @@ -847,7 +849,8 @@ megasas_fire_cmd_skinny(struct megasas_instance *instance, /** * megasas_check_reset_skinny - For controller reset check - * @regs: MFI register set + * @instance: Adapter soft state + * @regs: MFI register set */ static int megasas_check_reset_skinny(struct megasas_instance *instance, @@ -876,14 +879,14 @@ static struct megasas_instance_template megasas_instance_template_skinny = { }; -/** -* The following functions are defined for gen2 (deviceid : 0x78 0x79) -* controllers -*/ +/* + * The following functions are defined for gen2 (deviceid : 0x78 0x79) + * controllers + */ /** * megasas_enable_intr_gen2 - Enables interrupts - * @regs: MFI register set + * @instance: Adapter soft state */ static inline void megasas_enable_intr_gen2(struct megasas_instance *instance) @@ -902,7 +905,7 @@ megasas_enable_intr_gen2(struct megasas_instance *instance) /** * megasas_disable_intr_gen2 - Disables interrupt - * @regs: MFI register set + * @instance: Adapter soft state */ static inline void megasas_disable_intr_gen2(struct megasas_instance *instance) @@ -918,7 +921,7 @@ megasas_disable_intr_gen2(struct megasas_instance *instance) /** * megasas_read_fw_status_reg_gen2 - returns the current FW status value - * @regs: MFI register set + * @instance: Adapter soft state */ static u32 megasas_read_fw_status_reg_gen2(struct megasas_instance *instance) @@ -928,7 +931,7 @@ megasas_read_fw_status_reg_gen2(struct megasas_instance *instance) /** * megasas_clear_interrupt_gen2 - Check & clear interrupt - * @regs: MFI register set + * @instance: Adapter soft state */ static int megasas_clear_intr_gen2(struct megasas_instance *instance) @@ -961,11 +964,13 @@ megasas_clear_intr_gen2(struct megasas_instance *instance) return mfiStatus; } + /** * megasas_fire_cmd_gen2 - Sends command to the FW - * @frame_phys_addr : Physical address of cmd - * @frame_count : Number of frames for the command - * @regs : MFI register set + * @instance: Adapter soft state + * @frame_phys_addr: Physical address of cmd + * @frame_count: Number of frames for the command + * @regs: MFI register set */ static inline void megasas_fire_cmd_gen2(struct megasas_instance *instance, @@ -983,7 +988,8 @@ megasas_fire_cmd_gen2(struct megasas_instance *instance, /** * megasas_adp_reset_gen2 - For controller reset - * @regs: MFI register set + * @instance: Adapter soft state + * @reg_set: MFI register set */ static int megasas_adp_reset_gen2(struct megasas_instance *instance, @@ -1043,7 +1049,8 @@ megasas_adp_reset_gen2(struct megasas_instance *instance, /** * megasas_check_reset_gen2 - For controller reset check - * @regs: MFI register set + * @instance: Adapter soft state + * @regs: MFI register set */ static int megasas_check_reset_gen2(struct megasas_instance *instance, @@ -1071,10 +1078,10 @@ static struct megasas_instance_template megasas_instance_template_gen2 = { .issue_dcmd = megasas_issue_dcmd, }; -/** -* This is the end of set of functions & definitions -* specific to gen2 (deviceid : 0x78, 0x79) controllers -*/ +/* + * This is the end of set of functions & definitions + * specific to gen2 (deviceid : 0x78, 0x79) controllers + */ /* * Template added for TB (Fusion) @@ -1609,7 +1616,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, /** * megasas_cmd_type - Checks if the cmd is for logical drive/sysPD * and whether it's RW or non RW - * @scmd: SCSI command + * @cmd: SCSI command * */ inline int megasas_cmd_type(struct scsi_cmnd *cmd) @@ -1749,8 +1756,8 @@ out_return_cmd: /** * megasas_queue_command - Queue entry point + * @shost: adapter SCSI host * @scmd: SCSI command to be queued - * @done: Callback entry point */ static int megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd) @@ -2916,11 +2923,7 @@ megasas_dump(void *buf, int sz, int format) /** * megasas_dump_reg_set - This function will print hexdump of register set - * @buf: Buffer to be dumped - * @sz: Size in bytes - * @format: Different formats of dumping e.g. format=n will - * cause only 'n' 32 bit words to be dumped in a - * single line. + * @reg_set: Register set to be dumped */ inline void megasas_dump_reg_set(void __iomem *reg_set) @@ -2997,6 +3000,7 @@ megasas_dump_sys_regs(void __iomem *reg_set, char *buf) /** * megasas_reset_bus_host - Bus & host reset handler entry point + * @scmd: Mid-layer SCSI command */ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) { @@ -3777,7 +3781,7 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance) megasas_register_aen(instance, seq_num, class_locale.word); } -/** +/* * Move the internal reset pending commands to a deferred queue. * * We move the commands pending at internal reset time to a @@ -3785,7 +3789,7 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance) * completion of the internal reset sequence. if the internal reset * did not complete in time, the kernel reset handler would flush * these commands. - **/ + */ static void megasas_internal_reset_defer_cmds(struct megasas_instance *instance) { @@ -3963,8 +3967,11 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, tasklet_schedule(&instance->isr_tasklet); return IRQ_HANDLED; } + /** * megasas_isr - isr entry point + * @irq: IRQ number + * @devp: IRQ context address */ static irqreturn_t megasas_isr(int irq, void *devp) { @@ -3986,6 +3993,7 @@ static irqreturn_t megasas_isr(int irq, void *devp) /** * megasas_transition_to_ready - Move the FW to READY state * @instance: Adapter soft state + * @ocr: Adapter reset state * * During the initialization, FW passes can potentially be in any one of * several possible states. If the FW in operational, waiting-for-handshake @@ -4743,7 +4751,7 @@ megasas_get_ld_list(struct megasas_instance *instance) /** * megasas_ld_list_query - Returns FW's ld_list structure * @instance: Adapter soft state - * @ld_list: ld_list structure + * @query_type: ld_list structure type * * Issues an internal command (DCMD) to get the FW's controller PD * list structure. This information is mainly used to find out SYSTEM @@ -5602,9 +5610,13 @@ megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe) &instance->irq_context[i])) { dev_err(&instance->pdev->dev, "Failed to register IRQ for vector %d.\n", i); - for (j = 0; j < i; j++) + for (j = 0; j < i; j++) { + if (j < instance->low_latency_index_start) + irq_set_affinity_hint( + pci_irq_vector(pdev, j), NULL); free_irq(pci_irq_vector(pdev, j), &instance->irq_context[j]); + } /* Retry irq register for IO_APIC*/ instance->msix_vectors = 0; instance->msix_load_balance = false; @@ -5642,6 +5654,9 @@ megasas_destroy_irqs(struct megasas_instance *instance) { if (instance->msix_vectors) for (i = 0; i < instance->msix_vectors; i++) { + if (i < instance->low_latency_index_start) + irq_set_affinity_hint( + pci_irq_vector(instance->pdev, i), NULL); free_irq(pci_irq_vector(instance->pdev, i), &instance->irq_context[i]); } @@ -5653,7 +5668,6 @@ megasas_destroy_irqs(struct megasas_instance *instance) { /** * megasas_setup_jbod_map - setup jbod map for FP seq_number. * @instance: Adapter soft state - * @is_probe: Driver probe check * * Return 0 on success. */ @@ -6494,7 +6508,7 @@ dcmd_failed: * megasas_register_aen - Registers for asynchronous event notification * @instance: Adapter soft state * @seq_num: The starting sequence number - * @class_locale: Class of the event + * @class_locale_word: Class of the event * * This function subscribes for AEN for events beyond the @seq_num. It requests * to be notified if and only if the event is of type @class_locale @@ -7014,8 +7028,9 @@ static inline void megasas_free_ctrl_mem(struct megasas_instance *instance) * megasas_alloc_ctrl_dma_buffers - Allocate consistent DMA buffers during * driver load time * - * @instance- Adapter soft instance - * @return- O for SUCCESS + * @instance: Adapter soft instance + * + * @return: O for SUCCESS */ static inline int megasas_alloc_ctrl_dma_buffers(struct megasas_instance *instance) @@ -7931,7 +7946,7 @@ skip_firing_dcmds: /** * megasas_shutdown - Shutdown entry point - * @device: Generic device structure + * @pdev: Generic device structure */ static void megasas_shutdown(struct pci_dev *pdev) { @@ -7956,8 +7971,10 @@ skip_firing_dcmds: pci_free_irq_vectors(instance->pdev); } -/** +/* * megasas_mgmt_open - char node "open" entry point + * @inode: char node inode + * @filep: char node file */ static int megasas_mgmt_open(struct inode *inode, struct file *filep) { @@ -7970,8 +7987,11 @@ static int megasas_mgmt_open(struct inode *inode, struct file *filep) return 0; } -/** +/* * megasas_mgmt_fasync - Async notifier registration from applications + * @fd: char node file descriptor number + * @filep: char node file + * @mode: notifier on/off * * This function adds the calling process to a driver global queue. When an * event occurs, SIGIO will be sent to all processes in this queue. @@ -7997,9 +8017,11 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode) return rc; } -/** +/* * megasas_mgmt_poll - char node "poll" entry point - * */ + * @filep: char node file + * @wait: Events to poll for + */ static __poll_t megasas_mgmt_poll(struct file *file, poll_table *wait) { __poll_t mask; @@ -8057,7 +8079,8 @@ static int megasas_set_crash_dump_params_ioctl(struct megasas_cmd *cmd) /** * megasas_mgmt_fw_ioctl - Issues management ioctls to FW * @instance: Adapter soft state - * @argp: User's ioctl packet + * @user_ioc: User's ioctl packet + * @ioc: ioctl packet */ static int megasas_mgmt_fw_ioctl(struct megasas_instance *instance, @@ -8397,6 +8420,9 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) /** * megasas_mgmt_ioctl - char node ioctl entry point + * @file: char device file pointer + * @cmd: ioctl command + * @arg: ioctl command arguments address */ static long megasas_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index 3b3d04d7671f63c61eead207f2d3f7ac7306019c..b6c08d6200335923195e20c1af49d7433f192f58 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -80,21 +80,20 @@ u32 mega_mod64(u64 dividend, u32 divisor) } /** - * @param dividend : Dividend - * @param divisor : Divisor + * mega_div64_32 - Do a 64-bit division + * @dividend: Dividend + * @divisor: Divisor * * @return quotient **/ static u64 mega_div64_32(uint64_t dividend, uint32_t divisor) { - u32 remainder; - u64 d; + u64 d = dividend; if (!divisor) printk(KERN_ERR "megasas : DIVISOR is zero in mod fn\n"); - d = dividend; - remainder = do_div(d, divisor); + do_div(d, divisor); return d; } diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index fcf03f733e4172eff8ea33b72164a8e2cbba51ff..0824410f78f8a241a549eaf14ee759b5e15ed151 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -48,9 +48,6 @@ #include "megaraid_sas.h" -extern void megasas_free_cmds(struct megasas_instance *instance); -extern struct megasas_cmd *megasas_get_cmd(struct megasas_instance - *instance); extern void megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, u8 alt_status); @@ -58,24 +55,14 @@ int wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, int seconds); -void -megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd); -int megasas_alloc_cmds(struct megasas_instance *instance); int megasas_clear_intr_fusion(struct megasas_instance *instance); -int -megasas_issue_polled(struct megasas_instance *instance, - struct megasas_cmd *cmd); -void -megasas_check_and_restore_queue_depth(struct megasas_instance *instance); int megasas_transition_to_ready(struct megasas_instance *instance, int ocr); -void megaraid_sas_kill_hba(struct megasas_instance *instance); extern u32 megasas_dbg_lvl; int megasas_sriov_start_heartbeat(struct megasas_instance *instance, int initial); -void megasas_start_timer(struct megasas_instance *instance); extern struct megasas_mgmt_info megasas_mgmt_info; extern unsigned int resetwaittime; extern unsigned int dual_qdepth_disable; @@ -84,15 +71,13 @@ static void megasas_free_reply_fusion(struct megasas_instance *instance); static inline void megasas_configure_queue_sizes(struct megasas_instance *instance); static void megasas_fusion_crash_dump(struct megasas_instance *instance); -extern u32 megasas_readl(struct megasas_instance *instance, - const volatile void __iomem *addr); /** * megasas_adp_reset_wait_for_ready - initiate chip reset and wait for * controller to come to ready state - * @instance - adapter's soft state - * @do_adp_reset - If true, do a chip reset - * @ocr_context - If called from OCR context this will + * @instance: adapter's soft state + * @do_adp_reset: If true, do a chip reset + * @ocr_context: If called from OCR context this will * be set to 1, else 0 * * This function initates a chip reset followed by a wait for controller to @@ -146,10 +131,10 @@ out: /** * megasas_check_same_4gb_region - check if allocation * crosses same 4GB boundary or not - * @instance - adapter's soft instance - * start_addr - start address of DMA allocation - * size - size of allocation in bytes - * return - true : allocation does not cross same + * @instance: adapter's soft instance + * @start_addr: start address of DMA allocation + * @size: size of allocation in bytes + * @return: true : allocation does not cross same * 4GB boundary * false: allocation crosses same * 4GB boundary @@ -174,7 +159,7 @@ static inline bool megasas_check_same_4gb_region /** * megasas_enable_intr_fusion - Enables interrupts - * @regs: MFI register set + * @instance: adapter's soft instance */ static void megasas_enable_intr_fusion(struct megasas_instance *instance) @@ -196,7 +181,7 @@ megasas_enable_intr_fusion(struct megasas_instance *instance) /** * megasas_disable_intr_fusion - Disables interrupt - * @regs: MFI register set + * @instance: adapter's soft instance */ static void megasas_disable_intr_fusion(struct megasas_instance *instance) @@ -238,6 +223,7 @@ megasas_clear_intr_fusion(struct megasas_instance *instance) /** * megasas_get_cmd_fusion - Get a command from the free pool * @instance: Adapter soft state + * @blk_tag: Command tag * * Returns a blk_tag indexed mpt frame */ @@ -309,8 +295,8 @@ megasas_fire_cmd_fusion(struct megasas_instance *instance, /** * megasas_fusion_update_can_queue - Do all Adapter Queue depth related calculations here - * @instance: Adapter soft state - * fw_boot_context: Whether this function called during probe or after OCR + * @instance: Adapter soft state + * @fw_boot_context: Whether this function called during probe or after OCR * * This function is only for fusion controllers. * Update host can queue, if firmware downgrade max supported firmware commands. @@ -1016,6 +1002,7 @@ fail_exit: * wait_and_poll - Issues a polling command * @instance: Adapter soft state * @cmd: Command packet to be issued + * @seconds: Maximum poll time * * For polling, MFI requires the cmd_status to be set to 0xFF before posting. */ @@ -1906,6 +1893,7 @@ fail_alloc_mfi_cmds: /** * megasas_fault_detect_work - Worker function of * FW fault handling workqueue. + * @work: FW fault work struct */ static void megasas_fault_detect_work(struct work_struct *work) @@ -1989,11 +1977,13 @@ megasas_fusion_stop_watchdog(struct megasas_instance *instance) /** * map_cmd_status - Maps FW cmd status to OS cmd status - * @cmd : Pointer to cmd - * @status : status of cmd returned by FW - * @ext_status : ext status of cmd returned by FW + * @fusion: fusion context + * @scmd: Pointer to cmd + * @status: status of cmd returned by FW + * @ext_status: ext status of cmd returned by FW + * @data_length: command data length + * @sense: command sense data */ - static void map_cmd_status(struct fusion_context *fusion, struct scsi_cmnd *scmd, u8 status, u8 ext_status, @@ -2234,7 +2224,7 @@ megasas_make_prp_nvme(struct megasas_instance *instance, struct scsi_cmnd *scmd, * @scp: SCSI command from the mid-layer * @sgl_ptr: SGL to be filled in * @cmd: cmd we are working on - * @sge_count sge count + * @sge_count: sge count * */ static void @@ -2343,9 +2333,12 @@ int megasas_make_sgl(struct megasas_instance *instance, struct scsi_cmnd *scp, /** * megasas_set_pd_lba - Sets PD LBA - * @cdb: CDB + * @io_request: IO request * @cdb_len: cdb length - * @start_blk: Start block of IO + * @io_info: IO information + * @scp: SCSI command + * @local_map_ptr: Raid map + * @ref_tag: Primary reference tag * * Used to set the PD LBA in CDB for FP IOs */ @@ -2603,10 +2596,12 @@ static void megasas_stream_detect(struct megasas_instance *instance, * affinity (cpu of the controller) and raid_flags in the raid context * based on IO type. * + * @fusion: Fusion context * @praid_context: IO RAID context * @raid: LD raid map * @fp_possible: Is fast path possible? * @is_read: Is read IO? + * @scsi_buff_len: SCSI command buffer length * */ static void @@ -2940,7 +2935,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, /** * megasas_build_ld_nonrw_fusion - prepares non rw ios for virtual disk * @instance: Adapter soft state - * @scp: SCSI command + * @scmd: SCSI command * @cmd: Command to be prepared * * Prepares the io_request frame for non-rw io cmds for vd. @@ -3028,7 +3023,7 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance, /** * megasas_build_syspd_fusion - prepares rw/non-rw ios for syspd * @instance: Adapter soft state - * @scp: SCSI command + * @scmd: SCSI command * @cmd: Command to be prepared * @fp_possible: parameter to detect fast path or firmware path io. * @@ -3405,7 +3400,7 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, * megasas_complete_r1_command - * completes R1 FP write commands which has valid peer smid * @instance: Adapter soft state - * @cmd_fusion: MPT command frame + * @cmd: MPT command frame * */ static inline void @@ -3459,6 +3454,9 @@ megasas_complete_r1_command(struct megasas_instance *instance, /** * complete_cmd_fusion - Completes command * @instance: Adapter soft state + * @MSIxIndex: MSI number + * @irq_context: IRQ context + * * Completes all commands that is in reply descriptor queue */ static int @@ -3634,6 +3632,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex, /** * megasas_enable_irq_poll() - enable irqpoll + * @instance: Adapter soft state */ static void megasas_enable_irq_poll(struct megasas_instance *instance) { @@ -3650,7 +3649,7 @@ static void megasas_enable_irq_poll(struct megasas_instance *instance) /** * megasas_sync_irqs - Synchronizes all IRQs owned by adapter - * @instance: Adapter soft state + * @instance_addr: Adapter soft state address */ static void megasas_sync_irqs(unsigned long instance_addr) { @@ -3706,7 +3705,7 @@ int megasas_irqpoll(struct irq_poll *irqpoll, int budget) /** * megasas_complete_cmd_dpc_fusion - Completes command - * @instance: Adapter soft state + * @instance_addr: Adapter soft state address * * Tasklet to complete cmds */ @@ -3729,6 +3728,8 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) /** * megasas_isr_fusion - isr entry point + * @irq: IRQ number + * @devp: IRQ context */ static irqreturn_t megasas_isr_fusion(int irq, void *devp) { @@ -3761,7 +3762,7 @@ static irqreturn_t megasas_isr_fusion(int irq, void *devp) /** * build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru * @instance: Adapter soft state - * mfi_cmd: megasas_cmd pointer + * @mfi_cmd: megasas_cmd pointer * */ static void @@ -3878,7 +3879,7 @@ megasas_release_fusion(struct megasas_instance *instance) /** * megasas_read_fw_status_reg_fusion - returns the current FW status value - * @regs: MFI register set + * @instance: Adapter soft state */ static u32 megasas_read_fw_status_reg_fusion(struct megasas_instance *instance) @@ -3889,7 +3890,7 @@ megasas_read_fw_status_reg_fusion(struct megasas_instance *instance) /** * megasas_alloc_host_crash_buffer - Host buffers for Crash dump collection from Firmware * @instance: Controller's soft instance - * return: Number of allocated host crash buffers + * @return: Number of allocated host crash buffers */ static void megasas_alloc_host_crash_buffer(struct megasas_instance *instance) @@ -3927,6 +3928,7 @@ megasas_free_host_crash_buffer(struct megasas_instance *instance) /** * megasas_adp_reset_fusion - For controller reset + * @instance: Controller's soft instance * @regs: MFI register set */ static int @@ -4004,6 +4006,7 @@ megasas_adp_reset_fusion(struct megasas_instance *instance, /** * megasas_check_reset_fusion - For controller reset check + * @instance: Controller's soft instance * @regs: MFI register set */ static int @@ -4333,8 +4336,8 @@ static int megasas_track_scsiio(struct megasas_instance *instance, /** * megasas_tm_response_code - translation of device response code - * @ioc: per adapter object - * @mpi_reply: MPI reply returned by firmware + * @instance: Controller's soft instance + * @mpi_reply: MPI reply returned by firmware * * Return nothing. */ @@ -4389,9 +4392,9 @@ megasas_tm_response_code(struct megasas_instance *instance, * @device_handle: device handle * @channel: the channel assigned by the OS * @id: the id assigned by the OS - * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in megaraid_sas_fusion.c) * @smid_task: smid assigned to the task - * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF + * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in megaraid_sas_fusion.c) + * @mr_device_priv_data: private data * Context: user * * MegaRaid use MPT interface for Task Magement request. diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index f9f8f4921654f03980db6a033eff25c57d7d417a..fd1d03064079729580c2c911a6cfa55d2137b975 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1045,6 +1045,8 @@ static void handle_error(struct mesh_state *ms) while ((in_8(&mr->bus_status1) & BS1_RST) != 0) udelay(1); printk("done\n"); + if (ms->dma_started) + halt_dma(ms); handle_reset(ms); /* request_q is empty, no point in mesh_start() */ return; @@ -1357,7 +1359,8 @@ static void halt_dma(struct mesh_state *ms) ms->conn_tgt, ms->data_ptr, scsi_bufflen(cmd), ms->tgts[ms->conn_tgt].data_goes_out); } - scsi_dma_unmap(cmd); + if (cmd) + scsi_dma_unmap(cmd); ms->dma_started = 0; } @@ -1712,6 +1715,9 @@ static int mesh_host_reset(struct scsi_cmnd *cmd) spin_lock_irqsave(ms->host->host_lock, flags); + if (ms->dma_started) + halt_dma(ms); + /* Reset the controller & dbdma channel */ out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* stop dma */ out_8(&mr->exception, 0xff); /* clear all exception bits */ diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 96b78fdc6b8a942cee5eab39bf1b3e7f1713df63..1d64524cd86315c4e31c5427f9e2649904b5e557 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -190,7 +190,7 @@ module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, /** * _base_readl_aero - retry readl for max three times. - * @addr - MPT Fusion system interface register address + * @addr: MPT Fusion system interface register address * * Retry the readl() for max three times if it gets zero value * while reading the system interface register. @@ -817,6 +817,7 @@ mpt3sas_base_coredump_info(struct MPT3SAS_ADAPTER *ioc, u16 fault_code) * mpt3sas_base_wait_for_coredump_completion - Wait until coredump * completes or times out * @ioc: per adapter object + * @caller: caller function name * * Returns 0 for success, non-zero for failure. */ @@ -1718,8 +1719,8 @@ _base_interrupt(int irq, void *bus_id) /** * _base_irqpoll - IRQ poll callback handler - * @irqpoll - irq_poll object - * @budget - irq poll weight + * @irqpoll: irq_poll object + * @budget: irq poll weight * * returns number of reply descriptors processed */ @@ -3048,8 +3049,8 @@ fall_back: /** * _base_check_and_enable_high_iops_queues - enable high iops mode - * @ ioc - per adapter object - * @ hba_msix_vector_count - msix vectors supported by HBA + * @ioc: per adapter object + * @hba_msix_vector_count: msix vectors supported by HBA * * Enable high iops queues only if * - HBA is a SEA/AERO controller and @@ -5621,6 +5622,7 @@ _base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout) * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by * a write to the doorbell) * @ioc: per adapter object + * @timeout: timeout in seconds * * Return: 0 for success, non-zero for failure. * @@ -5833,7 +5835,7 @@ _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout) /** * mpt3sas_wait_for_ioc - IOC's operational state is checked here. * @ioc: per adapter object - * @wait_count: timeout in seconds + * @timeout: timeout in seconds * * Return: Waits up to timeout seconds for the IOC to * become operational. Returns 0 if IOC is present diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 4fca3939c034cda4f1d02dc4f21cc9362a404cc5..4ff876c312728313cf763916f0cad9fd29f7898a 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1770,7 +1770,7 @@ void mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc, void mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc, struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data); void mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, - u32 tigger_bitmask); + u32 trigger_bitmask); void mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event, u16 log_entry_qualifier); void mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index 62ddf53ab3aea1b742d5a1373ce48202411d9ba3..11026e0ef3d05f206734d3d14ebdfb4f5fe48a35 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -303,7 +303,6 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t u8 retry_count, issue_host_reset = 0; struct config_request mem; u32 ioc_status = UINT_MAX; - u8 issue_reset = 0; mutex_lock(&ioc->config_cmds.mutex); if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) { @@ -386,9 +385,9 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t if (!(ioc->logging_level & MPT_DEBUG_CONFIG)) _config_display_some_debug(ioc, smid, "config_request", NULL); - mpt3sas_check_cmd_timeout(ioc, - ioc->config_cmds.status, mpi_request, - sizeof(Mpi2ConfigRequest_t)/4, issue_reset); + ioc_err(ioc, "%s: command timeout\n", __func__); + mpt3sas_base_check_cmd_timeout(ioc, ioc->config_cmds.status, + mpi_request, sizeof(Mpi2ConfigRequest_t) / 4); retry_count++; if (ioc->config_cmds.smid == smid) mpt3sas_base_free_smid(ioc, smid); diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 983e568ff2317ec52d4a02530afd5d0b308daf49..43260306668cfb8d7f9fbb45b672f4c24bc6f61e 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -3662,8 +3662,9 @@ static DEVICE_ATTR_RW(diag_trigger_mpi); /** * drv_support_bitmap_show - driver supported feature bitmap - * @cdev - pointer to embedded class device - * @buf - the buffer returned + * @cdev: pointer to embedded class device + * @attr: unused + * @buf: the buffer returned * * A sysfs 'read-only' shost attribute. */ @@ -3680,8 +3681,9 @@ static DEVICE_ATTR_RO(drv_support_bitmap); /** * enable_sdev_max_qd_show - display whether sdev max qd is enabled/disabled - * @cdev - pointer to embedded class device - * @buf - the buffer returned + * @cdev: pointer to embedded class device + * @attr: unused + * @buf: the buffer returned * * A sysfs read/write shost attribute. This attribute is used to set the * targets queue depth to HBA IO queue depth if this attribute is enabled. @@ -3698,8 +3700,10 @@ enable_sdev_max_qd_show(struct device *cdev, /** * enable_sdev_max_qd_store - Enable/disable sdev max qd - * @cdev - pointer to embedded class device - * @buf - the buffer returned + * @cdev: pointer to embedded class device + * @attr: unused + * @buf: the buffer returned + * @count: unused * * A sysfs read/write shost attribute. This attribute is used to set the * targets queue depth to HBA IO queue depth if this attribute is enabled. diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h index 6586a463bea9730f14820ccc5bf2919ce605bb94..405eada2669da909d3ccff5c76853f1b7e9eb961 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h +++ b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h @@ -69,7 +69,7 @@ #define MASTER_TRIGGER_TASK_MANAGMENT (0x00000004) #define MASTER_TRIGGER_DEVICE_REMOVAL (0x00000008) -/* fake firmware event for tigger */ +/* fake firmware event for trigger */ #define MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED (0x6E) /** diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index b0de3bdb01db06329a4195f25db3cf9fbc9b2a56..978f5283c88354ea434a8bbcff7d920c18a3bc14 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -177,15 +177,16 @@ out: static irqreturn_t mvs_interrupt(int irq, void *opaque) { - u32 core_nr; u32 stat; struct mvs_info *mvi; struct sas_ha_struct *sha = opaque; #ifndef CONFIG_SCSI_MVSAS_TASKLET u32 i; -#endif + u32 core_nr; core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; +#endif + mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; if (unlikely(!mvi)) @@ -299,7 +300,7 @@ err_out: int mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex) { - unsigned long res_start, res_len, res_flag, res_flag_ex = 0; + unsigned long res_start, res_len, res_flag_ex = 0; struct pci_dev *pdev = mvi->pdev; if (bar_ex != -1) { /* @@ -327,7 +328,6 @@ int mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex) goto err_out; } - res_flag = pci_resource_flags(pdev, bar); mvi->regs = ioremap(res_start, res_len); if (!mvi->regs) { diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c index 5c5666491c2ee87f895363298abd34f2b8d07fbe..103803e779f2df71fd0e0d7b691905ea8ece5428 100644 --- a/drivers/scsi/myrs.c +++ b/drivers/scsi/myrs.c @@ -87,7 +87,7 @@ static char *myrs_raid_level_name(enum myrs_raid_level level) return NULL; } -/** +/* * myrs_reset_cmd - clears critical fields in struct myrs_cmdblk */ static inline void myrs_reset_cmd(struct myrs_cmdblk *cmd_blk) @@ -98,7 +98,7 @@ static inline void myrs_reset_cmd(struct myrs_cmdblk *cmd_blk) cmd_blk->status = 0; } -/** +/* * myrs_qcmd - queues Command for DAC960 V2 Series Controllers. */ static void myrs_qcmd(struct myrs_hba *cs, struct myrs_cmdblk *cmd_blk) @@ -122,7 +122,7 @@ static void myrs_qcmd(struct myrs_hba *cs, struct myrs_cmdblk *cmd_blk) cs->next_cmd_mbox = next_mbox; } -/** +/* * myrs_exec_cmd - executes V2 Command and waits for completion. */ static void myrs_exec_cmd(struct myrs_hba *cs, @@ -140,7 +140,7 @@ static void myrs_exec_cmd(struct myrs_hba *cs, wait_for_completion(&complete); } -/** +/* * myrs_report_progress - prints progress message */ static void myrs_report_progress(struct myrs_hba *cs, unsigned short ldev_num, @@ -153,7 +153,7 @@ static void myrs_report_progress(struct myrs_hba *cs, unsigned short ldev_num, (100 * (int)(blocks >> 7)) / (int)(size >> 7)); } -/** +/* * myrs_get_ctlr_info - executes a Controller Information IOCTL Command */ static unsigned char myrs_get_ctlr_info(struct myrs_hba *cs) @@ -214,7 +214,7 @@ static unsigned char myrs_get_ctlr_info(struct myrs_hba *cs) return status; } -/** +/* * myrs_get_ldev_info - executes a Logical Device Information IOCTL Command */ static unsigned char myrs_get_ldev_info(struct myrs_hba *cs, @@ -301,7 +301,7 @@ static unsigned char myrs_get_ldev_info(struct myrs_hba *cs, return status; } -/** +/* * myrs_get_pdev_info - executes a "Read Physical Device Information" Command */ static unsigned char myrs_get_pdev_info(struct myrs_hba *cs, @@ -345,7 +345,7 @@ static unsigned char myrs_get_pdev_info(struct myrs_hba *cs, return status; } -/** +/* * myrs_dev_op - executes a "Device Operation" Command */ static unsigned char myrs_dev_op(struct myrs_hba *cs, @@ -369,7 +369,7 @@ static unsigned char myrs_dev_op(struct myrs_hba *cs, return status; } -/** +/* * myrs_translate_pdev - translates a Physical Device Channel and * TargetID into a Logical Device. */ @@ -414,7 +414,7 @@ static unsigned char myrs_translate_pdev(struct myrs_hba *cs, return status; } -/** +/* * myrs_get_event - executes a Get Event Command */ static unsigned char myrs_get_event(struct myrs_hba *cs, @@ -476,7 +476,7 @@ static unsigned char myrs_get_fwstatus(struct myrs_hba *cs) return status; } -/** +/* * myrs_enable_mmio_mbox - enables the Memory Mailbox Interface */ static bool myrs_enable_mmio_mbox(struct myrs_hba *cs, @@ -577,7 +577,7 @@ out_free: return (status == MYRS_STATUS_SUCCESS); } -/** +/* * myrs_get_config - reads the Configuration Information */ static int myrs_get_config(struct myrs_hba *cs) @@ -682,7 +682,7 @@ static int myrs_get_config(struct myrs_hba *cs) return 0; } -/** +/* * myrs_log_event - prints a Controller Event message */ static struct { @@ -2338,11 +2338,11 @@ Failure: return NULL; } -/** +/* * myrs_err_status reports Controller BIOS Messages passed through - the Error Status Register when the driver performs the BIOS handshaking. - It returns true for fatal errors and false otherwise. -*/ + * the Error Status Register when the driver performs the BIOS handshaking. + * It returns true for fatal errors and false otherwise. + */ static bool myrs_err_status(struct myrs_hba *cs, unsigned char status, unsigned char parm0, unsigned char parm1) diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index d79ce97a04bd77478d8a9dd1ad0d985044b11d3d..8655ff1249bbc981e50f41f6294ec2bc6dc7baa8 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -134,6 +134,7 @@ static inline void nsp_inc_resid(struct scsi_cmnd *SCpnt, int residInc) scsi_set_resid(SCpnt, scsi_get_resid(SCpnt) + residInc); } +__printf(4, 5) static void nsp_cs_message(const char *func, int line, char *type, char *fmt, ...) { va_list args; @@ -689,14 +690,14 @@ static int nsp_fifo_count(struct scsi_cmnd *SCpnt) { unsigned int base = SCpnt->device->host->io_port; unsigned int count; - unsigned int l, m, h, dummy; + unsigned int l, m, h; nsp_index_write(base, POINTERCLR, POINTER_CLEAR | ACK_COUNTER); l = nsp_index_read(base, TRANSFERCOUNT); m = nsp_index_read(base, TRANSFERCOUNT); h = nsp_index_read(base, TRANSFERCOUNT); - dummy = nsp_index_read(base, TRANSFERCOUNT); /* required this! */ + nsp_index_read(base, TRANSFERCOUNT); /* required this! */ count = (h << 16) | (m << 8) | (l << 0); diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index 3c9f42779dd02a38dd7582eb29ac86d711577b1b..77c805db27242e1b88c9826ad620b5da37f5104b 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -47,6 +47,7 @@ /** * pm8001_ctl_mpi_interface_rev_show - MPI interface revision number * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read-only' shost attribute. @@ -72,6 +73,7 @@ DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL); /** * controller_fatal_error_show - check controller is under fatal err * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read only' shost attribute. @@ -91,6 +93,7 @@ static DEVICE_ATTR_RO(controller_fatal_error); /** * pm8001_ctl_fw_version_show - firmware version * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read-only' shost attribute. @@ -121,6 +124,7 @@ static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL); /** * pm8001_ctl_ila_version_show - ila version * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read-only' shost attribute. @@ -146,6 +150,7 @@ static DEVICE_ATTR(ila_version, 0444, pm8001_ctl_ila_version_show, NULL); /** * pm8001_ctl_inactive_fw_version_show - Inacative firmware version number * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read-only' shost attribute. @@ -172,6 +177,7 @@ DEVICE_ATTR(inc_fw_ver, 0444, pm8001_ctl_inactive_fw_version_show, NULL); /** * pm8001_ctl_max_out_io_show - max outstanding io supported * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read-only' shost attribute. @@ -195,6 +201,7 @@ static DEVICE_ATTR(max_out_io, S_IRUGO, pm8001_ctl_max_out_io_show, NULL); /** * pm8001_ctl_max_devices_show - max devices support * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read-only' shost attribute. @@ -221,6 +228,7 @@ static DEVICE_ATTR(max_devices, S_IRUGO, pm8001_ctl_max_devices_show, NULL); * pm8001_ctl_max_sg_list_show - max sg list supported iff not 0.0 for no * hardware limitation * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read-only' shost attribute. @@ -265,6 +273,7 @@ show_sas_spec_support_status(unsigned int mode, char *buf) /** * pm8001_ctl_sas_spec_support_show - sas spec supported * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read-only' shost attribute. @@ -292,6 +301,7 @@ static DEVICE_ATTR(sas_spec_support, S_IRUGO, /** * pm8001_ctl_sas_address_show - sas address * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * This is the controller sas address @@ -313,6 +323,7 @@ static DEVICE_ATTR(host_sas_address, S_IRUGO, /** * pm8001_ctl_logging_level_show - logging level * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read/write' shost attribute. @@ -326,6 +337,7 @@ static ssize_t pm8001_ctl_logging_level_show(struct device *cdev, return snprintf(buf, PAGE_SIZE, "%08xh\n", pm8001_ha->logging_level); } + static ssize_t pm8001_ctl_logging_level_store(struct device *cdev, struct device_attribute *attr, const char *buf, size_t count) { @@ -346,6 +358,7 @@ static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, /** * pm8001_ctl_aap_log_show - aap1 event log * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read-only' shost attribute. @@ -382,6 +395,7 @@ static DEVICE_ATTR(aap_log, S_IRUGO, pm8001_ctl_aap_log_show, NULL); /** * pm8001_ctl_ib_queue_log_show - Out bound Queue log * @cdev:pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * A sysfs 'read-only' shost attribute. */ @@ -414,6 +428,7 @@ static DEVICE_ATTR(ib_log, S_IRUGO, pm8001_ctl_ib_queue_log_show, NULL); /** * pm8001_ctl_ob_queue_log_show - Out bound Queue log * @cdev:pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * A sysfs 'read-only' shost attribute. */ @@ -446,6 +461,7 @@ static DEVICE_ATTR(ob_log, S_IRUGO, pm8001_ctl_ob_queue_log_show, NULL); /** * pm8001_ctl_bios_version_show - Bios version Display * @cdev:pointer to embedded class device + * @attr: device attribute (unused) * @buf:the buffer returned * A sysfs 'read-only' shost attribute. */ @@ -483,6 +499,7 @@ static DEVICE_ATTR(bios_version, S_IRUGO, pm8001_ctl_bios_version_show, NULL); /** * event_log_size_show - event log size * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs read shost attribute. @@ -501,6 +518,7 @@ static DEVICE_ATTR_RO(event_log_size); /** * pm8001_ctl_aap_log_show - IOP event log * @cdev: pointer to embedded class device + * @attr: device attribute (unused) * @buf: the buffer returned * * A sysfs 'read-only' shost attribute. @@ -538,6 +556,7 @@ static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL); /** ** pm8001_ctl_fatal_log_show - fatal error logging ** @cdev:pointer to embedded class device + ** @attr: device attribute ** @buf: the buffer returned ** ** A sysfs 'read-only' shost attribute. @@ -557,6 +576,7 @@ static DEVICE_ATTR(fatal_log, S_IRUGO, pm8001_ctl_fatal_log_show, NULL); /** ** non_fatal_log_show - non fatal error logging ** @cdev:pointer to embedded class device + ** @attr: device attribute ** @buf: the buffer returned ** ** A sysfs 'read-only' shost attribute. @@ -601,8 +621,9 @@ static DEVICE_ATTR_RW(non_fatal_count); /** ** pm8001_ctl_gsm_log_show - gsm dump collection ** @cdev:pointer to embedded class device + ** @attr: device attribute (unused) ** @buf: the buffer returned - **A sysfs 'read-only' shost attribute. + ** A sysfs 'read-only' shost attribute. **/ static ssize_t pm8001_ctl_gsm_log_show(struct device *cdev, struct device_attribute *attr, char *buf) diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 0b4499210b955c122e7fb95403178a3052bddd65..e9a939230b1520d1ec0a062e684489e6389e4a67 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -333,6 +333,7 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) /** * update_inbnd_queue_table - update the inbound queue table to the HBA. * @pm8001_ha: our hba card information + * @number: entry in the queue */ static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number) @@ -354,6 +355,7 @@ static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha, /** * update_outbnd_queue_table - update the outbound queue table to the HBA. * @pm8001_ha: our hba card information + * @number: entry in the queue */ static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number) @@ -473,7 +475,7 @@ static void mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, /** * mpi_set_open_retry_interval_reg * @pm8001_ha: our hba card information - * @interval - interval time for each OPEN_REJECT (RETRY). The units are in 1us. + * @interval: interval time for each OPEN_REJECT (RETRY). The units are in 1us. */ static void mpi_set_open_retry_interval_reg(struct pm8001_hba_info *pm8001_ha, u32 interval) @@ -1231,6 +1233,7 @@ pm8001_chip_intx_interrupt_disable(struct pm8001_hba_info *pm8001_ha) /** * pm8001_chip_msix_interrupt_enable - enable PM8001 chip interrupt * @pm8001_ha: our hba card information + * @int_vec_idx: interrupt number to enable */ static void pm8001_chip_msix_interrupt_enable(struct pm8001_hba_info *pm8001_ha, @@ -1249,6 +1252,7 @@ pm8001_chip_msix_interrupt_enable(struct pm8001_hba_info *pm8001_ha, /** * pm8001_chip_msix_interrupt_disable - disable PM8001 chip interrupt * @pm8001_ha: our hba card information + * @int_vec_idx: interrupt number to disable */ static void pm8001_chip_msix_interrupt_disable(struct pm8001_hba_info *pm8001_ha, @@ -1264,6 +1268,7 @@ pm8001_chip_msix_interrupt_disable(struct pm8001_hba_info *pm8001_ha, /** * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt * @pm8001_ha: our hba card information + * @vec: unused */ static void pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec) @@ -1278,6 +1283,7 @@ pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec) /** * pm8001_chip_intx_interrupt_disable- disable PM8001 chip interrupt * @pm8001_ha: our hba card information + * @vec: unused */ static void pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec) @@ -4500,7 +4506,6 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, /** * pm8001_chip_phy_start_req - start phy via PHY_START COMMAND * @pm8001_ha: our hba card information. - * @num: the inbound queue number * @phy_id: the phy id which we wanted to start up. */ static int @@ -4536,7 +4541,6 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) /** * pm8001_chip_phy_stop_req - start phy via PHY_STOP COMMAND * @pm8001_ha: our hba card information. - * @num: the inbound queue number * @phy_id: the phy id which we wanted to start up. */ static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, @@ -4556,7 +4560,7 @@ static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, return ret; } -/** +/* * see comments on pm8001_mpi_reg_resp. */ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, @@ -4616,7 +4620,7 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, return rc; } -/** +/* * see comments on pm8001_mpi_reg_resp. */ int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, @@ -4641,9 +4645,8 @@ int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, /** * pm8001_chip_phy_ctl_req - support the local phy operation * @pm8001_ha: our hba card information. - * @num: the inbound queue number - * @phy_id: the phy id which we wanted to operate - * @phy_op: + * @phyId: the phy id which we wanted to operate + * @phy_op: the phy operation to request */ static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, u32 phyId, u32 phy_op) @@ -4679,8 +4682,7 @@ static u32 pm8001_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha) /** * pm8001_chip_isr - PM8001 isr handler. * @pm8001_ha: our hba card information. - * @irq: irq number. - * @stat: stat. + * @vec: IRQ number */ static irqreturn_t pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) @@ -4717,10 +4719,8 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc, return ret; } -/** +/* * pm8001_chip_abort_task - SAS abort task when error or exception happened. - * @task: the task we wanted to aborted. - * @flag: the abort flag. */ int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, struct pm8001_device *pm8001_dev, u8 flag, u32 task_tag, u32 cmd_tag) @@ -4959,6 +4959,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, * pm8001_chip_fw_flash_update_build - support the firmware update operation * @pm8001_ha: our hba card information. * @fw_flash_updata_info: firmware flash update param + * @tag: Tag to apply to the payload */ int pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha, diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 9e99262a2b9dd362a01b74bb7c5c0c978659dc48..20fa96cbc9d3d933c33e8d211640f7bc5ed837eb 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -57,7 +57,7 @@ MODULE_PARM_DESC(link_rate, "Enable link rate.\n" static struct scsi_transport_template *pm8001_stt; -/** +/* * chip info structure to identify chip key functionality as * encryption available/not, no of ports, hw specific function ref */ @@ -80,7 +80,7 @@ LIST_HEAD(hba_list); struct workqueue_struct *pm8001_wq; -/** +/* * The main structure which LLDD must register for scsi core. */ static struct scsi_host_template pm8001_sht = { @@ -109,7 +109,7 @@ static struct scsi_host_template pm8001_sht = { .track_queue_depth = 1, }; -/** +/* * Sas layer call this function to execute specific task. */ static struct sas_domain_function_template pm8001_transport_ops = { @@ -129,9 +129,9 @@ static struct sas_domain_function_template pm8001_transport_ops = { }; /** - *pm8001_phy_init - initiate our adapter phys - *@pm8001_ha: our hba structure. - *@phy_id: phy id. + * pm8001_phy_init - initiate our adapter phys + * @pm8001_ha: our hba structure. + * @phy_id: phy id. */ static void pm8001_phy_init(struct pm8001_hba_info *pm8001_ha, int phy_id) { @@ -155,9 +155,8 @@ static void pm8001_phy_init(struct pm8001_hba_info *pm8001_ha, int phy_id) } /** - *pm8001_free - free hba - *@pm8001_ha: our hba structure. - * + * pm8001_free - free hba + * @pm8001_ha: our hba structure. */ static void pm8001_free(struct pm8001_hba_info *pm8001_ha) { @@ -205,6 +204,7 @@ static void pm8001_tasklet(unsigned long opaque) * pm8001_interrupt_handler_msix - main MSIX interrupt handler. * It obtains the vector number and calls the equivalent bottom * half or services directly. + * @irq: interrupt number * @opaque: the passed outbound queue/vector. Host structure is * retrieved from the same. */ @@ -230,6 +230,7 @@ static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque) /** * pm8001_interrupt_handler_intx - main INTx interrupt handler. + * @irq: interrupt number * @dev_id: sas_ha structure. The HBA is retrieved from sas_has structure. */ @@ -257,8 +258,8 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha); /** * pm8001_alloc - initiate our hba structure and 6 DMAs area. - * @pm8001_ha:our hba structure. - * + * @pm8001_ha: our hba structure. + * @ent: PCI device ID structure to match on */ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, const struct pci_device_id *ent) @@ -615,7 +616,7 @@ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost, /** * pm8001_init_sas_add - initialize sas address - * @chip_info: our ha struct. + * @pm8001_ha: our ha struct. * * Currently we just set the fixed SAS address to our HBA,for manufacture, * it should read from the EEPROM @@ -893,8 +894,7 @@ static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha) #ifdef PM8001_USE_MSIX /** * pm8001_setup_msix - enable MSI-X interrupt - * @chip_info: our ha struct. - * @irq_handler: irq_handler + * @pm8001_ha: our ha struct. */ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) { @@ -975,7 +975,7 @@ static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha) /** * pm8001_request_irq - register interrupt - * @chip_info: our ha struct. + * @pm8001_ha: our ha struct. */ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) { diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index b7cbc312843e9a5b097332ab405db06265830664..337e79d6837ffa86d6dde1e6a0d077692800ce37 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -129,6 +129,7 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr, *pphys_addr_lo = lower_32_bits(phys_align); return 0; } + /** * pm8001_find_ha_by_dev - from domain device which come from sas layer to * find out our hba struct. @@ -366,17 +367,15 @@ static int sas_find_local_port_id(struct domain_device *dev) return 0; } +#define DEV_IS_GONE(pm8001_dev) \ + ((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED))) /** * pm8001_task_exec - queue the task(ssp, smp && ata) to the hardware. * @task: the task to be execute. - * @num: if can_queue great than 1, the task can be queued up. for SMP task, - * we always execute one one time. * @gfp_flags: gfp_flags. * @is_tmf: if it is task management task. * @tmf: the task management IU */ -#define DEV_IS_GONE(pm8001_dev) \ - ((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED))) static int pm8001_task_exec(struct sas_task *task, gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf) { @@ -577,6 +576,7 @@ static struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha) /** * pm8001_find_dev - find a matching pm8001_device * @pm8001_ha: our hba card information + * @device_id: device ID to match against */ struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, u32 device_id) @@ -995,6 +995,7 @@ void pm8001_open_reject_retry( /** * Standard mandates link reset for ATA (type 0) and hard reset for * SSP (type 1) , only for RECOVERY + * @dev: the device structure for the device to reset. */ int pm8001_I_T_nexus_reset(struct domain_device *dev) { diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 05c944a3bdca0c8ef8b00d7db9dec7baec8626f4..b42f41d1ed49a08ff57556ecd2a7e6249187e527 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -66,7 +66,7 @@ int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shift_value) return 0; } -void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset, +static void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset, const void *destination, u32 dw_count, u32 bus_base_number) { @@ -912,6 +912,7 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) /** * update_inbnd_queue_table - update the inbound queue table to the HBA. * @pm8001_ha: our hba card information + * @number: entry in the queue */ static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number) @@ -948,6 +949,7 @@ static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha, /** * update_outbnd_queue_table - update the outbound queue table to the HBA. * @pm8001_ha: our hba card information + * @number: entry in the queue */ static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number) @@ -1711,6 +1713,7 @@ pm80xx_chip_intx_interrupt_disable(struct pm8001_hba_info *pm8001_ha) /** * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt * @pm8001_ha: our hba card information + * @vec: interrupt number to enable */ static void pm80xx_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec) @@ -1729,6 +1732,7 @@ pm80xx_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec) /** * pm8001_chip_interrupt_disable- disable PM8001 chip interrupt * @pm8001_ha: our hba card information + * @vec: interrupt number to disable */ static void pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec) @@ -4822,7 +4826,6 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, /** * pm80xx_chip_phy_start_req - start phy via PHY_START COMMAND * @pm8001_ha: our hba card information. - * @num: the inbound queue number * @phy_id: the phy id which we wanted to start up. */ static int @@ -4864,7 +4867,6 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) /** * pm8001_chip_phy_stop_req - start phy via PHY_STOP COMMAND * @pm8001_ha: our hba card information. - * @num: the inbound queue number * @phy_id: the phy id which we wanted to start up. */ static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, @@ -4884,7 +4886,7 @@ static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, return ret; } -/** +/* * see comments on pm8001_mpi_reg_resp. */ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, @@ -4957,9 +4959,8 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, /** * pm80xx_chip_phy_ctl_req - support the local phy operation * @pm8001_ha: our hba card information. - * @num: the inbound queue number - * @phy_id: the phy id which we wanted to operate - * @phy_op: + * @phyId: the phy id which we wanted to operate + * @phy_op: phy operation to request */ static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, u32 phyId, u32 phy_op) @@ -4998,8 +4999,7 @@ static u32 pm80xx_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha) /** * pm8001_chip_isr - PM8001 isr handler. * @pm8001_ha: our hba card information. - * @irq: irq number. - * @stat: stat. + * @vec: irq number. */ static irqreturn_t pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) @@ -5013,8 +5013,9 @@ pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) return IRQ_HANDLED; } -void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, - u32 operation, u32 phyid, u32 length, u32 *buf) +static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, + u32 operation, u32 phyid, + u32 length, u32 *buf) { u32 tag , i, j = 0; int rc; diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index a406cc825426ca6f5b1de0b48028d5ae2c4ebc00..0ae800c5b7396aa5944eb36bf8bbb4ae5f1f632c 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -779,7 +779,6 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) (DID_OK << 16) + (h << 8) + (l & STATUS_MASK); } return 0; /* Finished */ - break; default: printk(KERN_ERR "ppa: Invalid scsi phase\n"); @@ -847,10 +846,8 @@ static int ppa_abort(struct scsi_cmnd *cmd) case 1: /* Have not connected to interface */ dev->cur_cmd = NULL; /* Forget the problem */ return SUCCESS; - break; default: /* SCSI command sent, can not abort */ return FAILED; - break; } } diff --git a/drivers/scsi/qedf/qedf_debugfs.c b/drivers/scsi/qedf/qedf_debugfs.c index b88bed9bb1338a83be19714cb6af4563191e3e80..a3ed681c8ce3f89ca3377643e27a381c3f8ef5aa 100644 --- a/drivers/scsi/qedf/qedf_debugfs.c +++ b/drivers/scsi/qedf/qedf_debugfs.c @@ -14,10 +14,9 @@ static struct dentry *qedf_dbg_root; -/** +/* * qedf_dbg_host_init - setup the debugfs file for the pf - * @pf: the pf that is starting up - **/ + */ void qedf_dbg_host_init(struct qedf_dbg_ctx *qedf, const struct qedf_debugfs_ops *dops, @@ -42,10 +41,9 @@ qedf_dbg_host_init(struct qedf_dbg_ctx *qedf, } } -/** +/* * qedf_dbg_host_exit - clear out the pf's debugfs entries - * @pf: the pf that is stopping - **/ + */ void qedf_dbg_host_exit(struct qedf_dbg_ctx *qedf_dbg) { @@ -56,9 +54,9 @@ qedf_dbg_host_exit(struct qedf_dbg_ctx *qedf_dbg) qedf_dbg->bdf_dentry = NULL; } -/** +/* * qedf_dbg_init - start up debugfs for the driver - **/ + */ void qedf_dbg_init(char *drv_name) { @@ -68,9 +66,9 @@ qedf_dbg_init(char *drv_name) qedf_dbg_root = debugfs_create_dir(drv_name, NULL); } -/** +/* * qedf_dbg_exit - clean out the driver's debugfs entries - **/ + */ void qedf_dbg_exit(void) { diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c index 0f6a15c1a04b32a7ae0bbd8bb47d444ec83f6dc5..acd9774a9387c3f468c4ee027dce8170a3fc063e 100644 --- a/drivers/scsi/qedf/qedf_io.c +++ b/drivers/scsi/qedf/qedf_io.c @@ -22,7 +22,6 @@ static void qedf_cmd_timeout(struct work_struct *work) container_of(work, struct qedf_ioreq, timeout_work.work); struct qedf_ctx *qedf; struct qedf_rport *fcport; - u8 op = 0; if (io_req == NULL) { QEDF_INFO(NULL, QEDF_LOG_IO, "io_req is NULL.\n"); @@ -89,7 +88,6 @@ static void qedf_cmd_timeout(struct work_struct *work) io_req->event = QEDF_IOREQ_EV_ELS_TMO; /* Call callback function to complete command */ if (io_req->cb_func && io_req->cb_arg) { - op = io_req->cb_arg->op; io_req->cb_func(io_req->cb_arg); io_req->cb_arg = NULL; } @@ -487,7 +485,7 @@ static int qedf_map_sg(struct qedf_ioreq *io_req) int sg_count = 0; int bd_count = 0; u32 sg_len; - u64 addr, end_addr; + u64 addr; int i = 0; sg_count = dma_map_sg(&qedf->pdev->dev, scsi_sglist(sc), @@ -502,10 +500,9 @@ static int qedf_map_sg(struct qedf_ioreq *io_req) scsi_for_each_sg(sc, sg, sg_count, i) { sg_len = (u32)sg_dma_len(sg); addr = (u64)sg_dma_address(sg); - end_addr = (u64)(addr + sg_len); /* - * Intermediate s/g element so check if start and end address + * Intermediate s/g element so check if start address * is page aligned. Only required for writes and only if the * number of scatter/gather elements is 8 or more. */ @@ -860,7 +857,6 @@ int qedf_post_io_req(struct qedf_rport *fcport, struct qedf_ioreq *io_req) struct qedf_ctx *qedf = lport_priv(lport); struct e4_fcoe_task_context *task_ctx; u16 xid; - enum fcoe_task_type req_type = 0; struct fcoe_wqe *sqe; u16 sqe_idx; @@ -873,11 +869,9 @@ int qedf_post_io_req(struct qedf_rport *fcport, struct qedf_ioreq *io_req) io_req->cpu = smp_processor_id(); if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) { - req_type = FCOE_TASK_TYPE_READ_INITIATOR; io_req->io_req_flags = QEDF_READ; qedf->input_requests++; } else if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) { - req_type = FCOE_TASK_TYPE_WRITE_INITIATOR; io_req->io_req_flags = QEDF_WRITE; qedf->output_requests++; } else { @@ -1130,8 +1124,6 @@ static void qedf_unmap_sg_list(struct qedf_ctx *qedf, struct qedf_ioreq *io_req) void qedf_scsi_completion(struct qedf_ctx *qedf, struct fcoe_cqe *cqe, struct qedf_ioreq *io_req) { - u16 xid; - struct e4_fcoe_task_context *task_ctx; struct scsi_cmnd *sc_cmd; struct fcoe_cqe_rsp_info *fcp_rsp; struct qedf_rport *fcport; @@ -1155,8 +1147,6 @@ void qedf_scsi_completion(struct qedf_ctx *qedf, struct fcoe_cqe *cqe, return; } - xid = io_req->xid; - task_ctx = qedf_get_task_mem(&qedf->tasks, xid); sc_cmd = io_req->sc_cmd; fcp_rsp = &cqe->cqe_info.rsp_info; @@ -1342,7 +1332,6 @@ out: void qedf_scsi_done(struct qedf_ctx *qedf, struct qedf_ioreq *io_req, int result) { - u16 xid; struct scsi_cmnd *sc_cmd; int refcount; @@ -1364,7 +1353,6 @@ void qedf_scsi_done(struct qedf_ctx *qedf, struct qedf_ioreq *io_req, */ clear_bit(QEDF_CMD_OUTSTANDING, &io_req->flags); - xid = io_req->xid; sc_cmd = io_req->sc_cmd; if (!sc_cmd) { @@ -1863,7 +1851,6 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts) struct fc_rport_priv *rdata; struct qedf_ctx *qedf; u16 xid; - u32 r_a_tov = 0; int rc = 0; unsigned long flags; struct fcoe_wqe *sqe; @@ -1886,7 +1873,6 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts) goto out; } - r_a_tov = rdata->r_a_tov; lport = qedf->lport; if (lport->state != LPORT_ST_READY || !(lport->link_up)) { @@ -1964,14 +1950,12 @@ void qedf_process_abts_compl(struct qedf_ctx *qedf, struct fcoe_cqe *cqe, struct qedf_ioreq *io_req) { uint32_t r_ctl; - uint16_t xid; int rc; struct qedf_rport *fcport = io_req->fcport; QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_SCSI_TM, "Entered with xid = " "0x%x cmd_type = %d\n", io_req->xid, io_req->cmd_type); - xid = io_req->xid; r_ctl = cqe->cqe_info.abts_info.r_ctl; /* This was added at a point when we were scheduling abts_compl & @@ -2159,8 +2143,6 @@ int qedf_initiate_cleanup(struct qedf_ioreq *io_req, { struct qedf_rport *fcport; struct qedf_ctx *qedf; - uint16_t xid; - struct e4_fcoe_task_context *task; int tmo = 0; int rc = SUCCESS; unsigned long flags; @@ -2220,12 +2202,9 @@ int qedf_initiate_cleanup(struct qedf_ioreq *io_req, refcount, fcport, fcport->rdata->ids.port_id); /* Cleanup cmds re-use the same TID as the original I/O */ - xid = io_req->xid; io_req->cmd_type = QEDF_CLEANUP; io_req->return_scsi_cmd_on_abts = return_scsi_cmd_on_abts; - task = qedf_get_task_mem(&qedf->tasks, xid); - init_completion(&io_req->cleanup_done); spin_lock_irqsave(&fcport->rport_lock, flags); @@ -2531,7 +2510,6 @@ void qedf_process_unsol_compl(struct qedf_ctx *qedf, uint16_t que_idx, struct fcoe_cqe *cqe) { unsigned long flags; - uint16_t tmp; uint16_t pktlen = cqe->cqe_info.unsolic_info.pkt_len; u32 payload_len, crc; struct fc_frame_header *fh; @@ -2629,9 +2607,9 @@ increment_prod: qedf->bdq_prod_idx = 0; writew(qedf->bdq_prod_idx, qedf->bdq_primary_prod); - tmp = readw(qedf->bdq_primary_prod); + readw(qedf->bdq_primary_prod); writew(qedf->bdq_prod_idx, qedf->bdq_secondary_prod); - tmp = readw(qedf->bdq_secondary_prod); + readw(qedf->bdq_secondary_prod); spin_unlock_irqrestore(&qedf->hba_lock, flags); } diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 6e77e4908605c5418a2dc09ca29d30282bf262b8..3f04f2c8136638117803e9db000ccbcfbe8006e6 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -1041,9 +1041,8 @@ static int qedf_xmit_l2_frame(struct qedf_rport *fcport, struct fc_frame *fp) return rc; } -/** +/* * qedf_xmit - qedf FCoE frame transmit function - * */ static int qedf_xmit(struct fc_lport *lport, struct fc_frame *fp) { @@ -1437,7 +1436,7 @@ static void qedf_cleanup_fcport(struct qedf_ctx *qedf, kref_put(&rdata->kref, fc_rport_destroy); } -/** +/* * This event_callback is called after successful completion of libfc * initiated target login. qedf can proceed with initiating the session * establishment. @@ -3222,7 +3221,6 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) void *task_start, *task_end; struct qed_slowpath_params slowpath_params; struct qed_probe_params qed_params; - u16 tmp; /* * When doing error recovery we didn't reap the lport so don't try @@ -3416,9 +3414,9 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) "Writing %d to primary and secondary BDQ doorbell registers.\n", qedf->bdq_prod_idx); writew(qedf->bdq_prod_idx, qedf->bdq_primary_prod); - tmp = readw(qedf->bdq_primary_prod); + readw(qedf->bdq_primary_prod); writew(qedf->bdq_prod_idx, qedf->bdq_secondary_prod); - tmp = readw(qedf->bdq_secondary_prod); + readw(qedf->bdq_secondary_prod); qed_ops->common->set_power_state(qedf->cdev, PCI_D0); diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c index 946cebc4c9322a1349147fd5f7e9cfa262013c1d..6ed74583b1b9b1cc7c89bbad3bc468f70fb08b93 100644 --- a/drivers/scsi/qedi/qedi_fw.c +++ b/drivers/scsi/qedi/qedi_fw.c @@ -352,7 +352,6 @@ static void qedi_put_rq_bdq_buf(struct qedi_ctx *qedi, struct iscsi_cqe_unsolicited *cqe, int count) { - u16 tmp; u16 idx = 0; struct scsi_bd *pbl; @@ -381,10 +380,10 @@ static void qedi_put_rq_bdq_buf(struct qedi_ctx *qedi, qedi->bdq_prod_idx += count; writew(qedi->bdq_prod_idx, qedi->bdq_primary_prod); - tmp = readw(qedi->bdq_primary_prod); + readw(qedi->bdq_primary_prod); writew(qedi->bdq_prod_idx, qedi->bdq_secondary_prod); - tmp = readw(qedi->bdq_secondary_prod); + readw(qedi->bdq_secondary_prod); } static void qedi_unsol_pdu_adjust_bdq(struct qedi_ctx *qedi, diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 425e665ec08b2aceaa87f0d6166574649624cdf6..c14ac7882afaccad43cb14904d0fbd2229aeb321 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -1546,7 +1546,7 @@ static const struct { }, }; -char *qedi_get_iscsi_error(enum iscsi_error_types err_code) +static char *qedi_get_iscsi_error(enum iscsi_error_types err_code) { int i; char *msg = NULL; diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 81a307695cc91caf23d871865c7c542ccaaac9be..6f038ae5efcafc00560cb19b97f1ddab788475d1 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -1155,7 +1155,6 @@ static int qedi_queue_cqe(struct qedi_ctx *qedi, union iscsi_cqe *cqe, { struct qedi_work *qedi_work; struct qedi_conn *q_conn; - struct iscsi_conn *conn; struct qedi_cmd *qedi_cmd; u32 iscsi_cid; int rc = 0; @@ -1168,7 +1167,6 @@ static int qedi_queue_cqe(struct qedi_ctx *qedi, union iscsi_cqe *cqe, iscsi_cid); return -1; } - conn = q_conn->cls_conn->dd_data; switch (cqe->cqe_common.cqe_type) { case ISCSI_CQE_TYPE_SOLICITED: @@ -1962,7 +1960,7 @@ void qedi_reset_host_mtu(struct qedi_ctx *qedi, u16 mtu) qedi_ops->ll2->start(qedi->cdev, ¶ms); } -/** +/* * qedi_get_nvram_block: - Scan through the iSCSI NVRAM block (while accounting * for gaps) for the matching absolute-pf-id of the QEDI device. */ @@ -2429,7 +2427,6 @@ static int __qedi_probe(struct pci_dev *pdev, int mode) struct qed_probe_params qed_params; void *task_start, *task_end; int rc; - u16 tmp; if (mode != QEDI_MODE_RECOVERY) { qedi = qedi_host_alloc(pdev); @@ -2528,9 +2525,9 @@ static int __qedi_probe(struct pci_dev *pdev, int mode) "Writing %d to primary and secondary BDQ doorbell registers.\n", qedi->bdq_prod_idx); writew(qedi->bdq_prod_idx, qedi->bdq_primary_prod); - tmp = readw(qedi->bdq_primary_prod); + readw(qedi->bdq_primary_prod); writew(qedi->bdq_prod_idx, qedi->bdq_secondary_prod); - tmp = readw(qedi->bdq_secondary_prod); + readw(qedi->bdq_secondary_prod); ether_addr_copy(qedi->mac, qedi->dev_info.common.hw_mac); QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_DISC, "MAC address is %pM.\n", diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 88c0338a2ec7d9dc55d676d35bd7088535b8625f..67efde1d4b8e011a22f64980c87238daa8777aa0 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -223,8 +223,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct bsg_job *bsg_job) /* validate fcp priority data */ - if (!qla24xx_fcp_prio_cfg_valid(vha, - (struct qla_fcp_prio_cfg *) ha->fcp_prio_cfg, 1)) { + if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 1)) { bsg_reply->result = (DID_ERROR << 16); ret = -EINVAL; /* If buffer was invalidatic int diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 19005710f7f66d96b1f36601b57dce192205264d..1be811a5d69d74900f4dfa43947300b1bd13706d 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -11,10 +11,8 @@ * ---------------------------------------------------------------------- * | Level | Last Value Used | Holes | * ---------------------------------------------------------------------- - * | Module Init and Probe | 0x0193 | 0x0146 | - * | | | 0x015b-0x0160 | - * | | | 0x016e | - * | Mailbox commands | 0x1206 | 0x11a2-0x11ff | + * | Module Init and Probe | 0x0199 | | + * | Mailbox commands | 0x1206 | 0x11a5-0x11ff | * | Device Discovery | 0x2134 | 0x210e-0x2116 | * | | | 0x211a | * | | | 0x211c-0x2128 | @@ -26,11 +24,7 @@ * | | | 0x3036,0x3038 | * | | | 0x303a | * | DPC Thread | 0x4023 | 0x4002,0x4013 | - * | Async Events | 0x5090 | 0x502b-0x502f | - * | | | 0x5047 | - * | | | 0x5084,0x5075 | - * | | | 0x503d,0x5044 | - * | | | 0x505f | + * | Async Events | 0x509c | | * | Timer Routines | 0x6012 | | * | User Space Interactions | 0x70e3 | 0x7018,0x702e | * | | | 0x7020,0x7024 | @@ -1063,7 +1057,7 @@ qla2100_fw_dump(scsi_qla_host_t *vha) } if (rval == QLA_SUCCESS) - qla2xxx_copy_queues(ha, &fw->risc_ram[cnt]); + qla2xxx_copy_queues(ha, &fw->queue_dump[0]); qla2xxx_dump_post_process(base_vha, rval); } @@ -2447,6 +2441,23 @@ qla83xx_fw_dump_failed_0: /* Driver Debug Functions. */ /****************************************************************************/ +/* Write the debug message prefix into @pbuf. */ +static void ql_dbg_prefix(char *pbuf, int pbuf_size, + const scsi_qla_host_t *vha, uint msg_id) +{ + if (vha) { + const struct pci_dev *pdev = vha->hw->pdev; + + /* []-:: */ + snprintf(pbuf, pbuf_size, "%s [%s]-%04x:%ld: ", QL_MSGHDR, + dev_name(&(pdev->dev)), msg_id, vha->host_no); + } else { + /* []-: : */ + snprintf(pbuf, pbuf_size, "%s [%s]-%04x: : ", QL_MSGHDR, + "0000:00:00.0", msg_id); + } +} + /* * This function is for formatting and logging debug information. * It is to be used when vha is available. It formats the message @@ -2465,41 +2476,19 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; + char pbuf[64]; va_start(va, fmt); vaf.fmt = fmt; vaf.va = &va; - if (!ql_mask_match(level)) { - char pbuf[64]; + ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), vha, id); - if (vha != NULL) { - const struct pci_dev *pdev = vha->hw->pdev; - /* : Message */ - snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x:%ld: ", - QL_MSGHDR, dev_name(&(pdev->dev)), id, - vha->host_no); - } else { - snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ", - QL_MSGHDR, "0000:00:00.0", id); - } - pbuf[sizeof(pbuf) - 1] = 0; + if (!ql_mask_match(level)) trace_ql_dbg_log(pbuf, &vaf); - va_end(va); - return; - } - - if (vha != NULL) { - const struct pci_dev *pdev = vha->hw->pdev; - /* : Message */ - pr_warn("%s [%s]-%04x:%ld: %pV", - QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset, - vha->host_no, &vaf); - } else { - pr_warn("%s [%s]-%04x: : %pV", - QL_MSGHDR, "0000:00:00.0", id + ql_dbg_offset, &vaf); - } + else + pr_warn("%s%pV", pbuf, &vaf); va_end(va); @@ -2524,6 +2513,7 @@ ql_dbg_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; + char pbuf[128]; if (pdev == NULL) return; @@ -2535,9 +2525,8 @@ ql_dbg_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...) vaf.fmt = fmt; vaf.va = &va; - /* : Message */ - pr_warn("%s [%s]-%04x: : %pV", - QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset, &vaf); + ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, id + ql_dbg_offset); + pr_warn("%s%pV", pbuf, &vaf); va_end(va); } @@ -2565,16 +2554,7 @@ ql_log(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) if (level > ql_errlev) return; - if (vha != NULL) { - const struct pci_dev *pdev = vha->hw->pdev; - /* : Message */ - snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x:%ld: ", - QL_MSGHDR, dev_name(&(pdev->dev)), id, vha->host_no); - } else { - snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ", - QL_MSGHDR, "0000:00:00.0", id); - } - pbuf[sizeof(pbuf) - 1] = 0; + ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), vha, id); va_start(va, fmt); @@ -2625,10 +2605,7 @@ ql_log_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...) if (level > ql_errlev) return; - /* : Message */ - snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ", - QL_MSGHDR, dev_name(&(pdev->dev)), id); - pbuf[sizeof(pbuf) - 1] = 0; + ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, id); va_start(va, fmt); @@ -2679,7 +2656,6 @@ ql_dump_regs(uint level, scsi_qla_host_t *vha, uint id) "mbox[%d] %#04x\n", i, rd_reg_word(mbx_reg)); } - void ql_dump_buffer(uint level, scsi_qla_host_t *vha, uint id, const void *buf, uint size) @@ -2724,16 +2700,7 @@ ql_log_qp(uint32_t level, struct qla_qpair *qpair, int32_t id, if (level > ql_errlev) return; - if (qpair != NULL) { - const struct pci_dev *pdev = qpair->pdev; - /* : Message */ - snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: ", - QL_MSGHDR, dev_name(&(pdev->dev)), id); - } else { - snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ", - QL_MSGHDR, "0000:00:00.0", id); - } - pbuf[sizeof(pbuf) - 1] = 0; + ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), qpair ? qpair->vha : NULL, id); va_start(va, fmt); @@ -2777,6 +2744,7 @@ ql_dbg_qp(uint32_t level, struct qla_qpair *qpair, int32_t id, { va_list va; struct va_format vaf; + char pbuf[128]; if (!ql_mask_match(level)) return; @@ -2786,16 +2754,9 @@ ql_dbg_qp(uint32_t level, struct qla_qpair *qpair, int32_t id, vaf.fmt = fmt; vaf.va = &va; - if (qpair != NULL) { - const struct pci_dev *pdev = qpair->pdev; - /* : Message */ - pr_warn("%s [%s]-%04x: %pV", - QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset, - &vaf); - } else { - pr_warn("%s [%s]-%04x: : %pV", - QL_MSGHDR, "0000:00:00.0", id + ql_dbg_offset, &vaf); - } + ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), qpair ? qpair->vha : NULL, + id + ql_dbg_offset); + pr_warn("%s%pV", pbuf, &vaf); va_end(va); diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 54ed020e6f7567e975e39d6a3b2119c1515b31aa..91eb6901815c967696ff5a80bf89f69d15c945dd 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -53,6 +53,7 @@ struct qla2100_fw_dump { __be16 fpm_b0_reg[64]; __be16 fpm_b1_reg[64]; __be16 risc_ram[0xf000]; + u8 queue_dump[]; }; struct qla24xx_fw_dump { diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 42dbf90d4651077105b36f0213d6a16f2ac6ebee..8c92af5e43909334b1e40341c8b27f2e533eb0d1 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -34,6 +34,8 @@ #include #include +#include + /* Big endian Fibre Channel S_ID (source ID) or D_ID (destination ID). */ typedef struct { uint8_t domain; @@ -1053,6 +1055,7 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define MBA_LIP_F8 0x8016 /* Received a LIP F8. */ #define MBA_LOOP_INIT_ERR 0x8017 /* Loop Initialization Error. */ #define MBA_FABRIC_AUTH_REQ 0x801b /* Fabric Authentication Required. */ +#define MBA_CONGN_NOTI_RECV 0x801e /* Congestion Notification Received */ #define MBA_SCSI_COMPLETION 0x8020 /* SCSI Command Complete. */ #define MBA_CTIO_COMPLETION 0x8021 /* CTIO Complete. */ #define MBA_IP_COMPLETION 0x8022 /* IP Transmit Command Complete. */ @@ -1304,7 +1307,6 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define RNID_TYPE_ASIC_TEMP 0xC #define ELS_CMD_MAP_SIZE 32 -#define ELS_COMMAND_RDP 0x18 /* * Firmware state codes from get firmware state mailbox command @@ -1509,6 +1511,25 @@ typedef struct { uint8_t reserved_3[26]; } init_cb_t; +/* Special Features Control Block */ +struct init_sf_cb { + uint8_t format; + uint8_t reserved0; + /* + * BIT 15-14 = Reserved + * BIT_13 = SAN Congestion Management (1 - Enabled, 0 - Disabled) + * BIT_12 = Remote Write Optimization (1 - Enabled, 0 - Disabled) + * BIT 11-0 = Reserved + */ + uint16_t flags; + uint8_t reserved1[32]; + uint16_t discard_OHRB_timeout_value; + uint16_t remote_write_opt_queue_num; + uint8_t reserved2[40]; + uint8_t scm_related_parameter[16]; + uint8_t reserved3[32]; +}; + /* * Get Link Status mailbox command return buffer. */ @@ -2182,6 +2203,8 @@ typedef struct { struct dsd64 rsp_dsd; } ms_iocb_entry_t; +#define SCM_EDC_ACC_RECEIVED BIT_6 +#define SCM_RDF_ACC_RECEIVED BIT_7 /* * ISP queue - Mailbox Command entry structure definition. @@ -3851,6 +3874,12 @@ struct qla_hw_data { uint32_t n2n_bigger:1; uint32_t secure_adapter:1; uint32_t secure_fw:1; + /* Supported by Adapter */ + uint32_t scm_supported_a:1; + /* Supported by Firmware */ + uint32_t scm_supported_f:1; + /* Enabled in Driver */ + uint32_t scm_enabled:1; } flags; uint16_t max_exchg; @@ -4168,6 +4197,13 @@ struct qla_hw_data { int init_cb_size; dma_addr_t ex_init_cb_dma; struct ex_init_cb_81xx *ex_init_cb; + dma_addr_t sf_init_cb_dma; + struct init_sf_cb *sf_init_cb; + + void *scm_fpin_els_buff; + uint64_t scm_fpin_els_buff_size; + bool scm_fpin_valid; + bool scm_fpin_payload_size; void *async_pd; dma_addr_t async_pd_dma; @@ -4230,6 +4266,12 @@ struct qla_hw_data { #define FW_ATTR_H_NVME BIT_10 #define FW_ATTR_H_NVME_UPDATED BIT_14 + /* About firmware SCM support */ +#define FW_ATTR_EXT0_SCM_SUPPORTED BIT_12 + /* Brocade fabric attached */ +#define FW_ATTR_EXT0_SCM_BROCADE 0x00001000 + /* Cisco fabric attached */ +#define FW_ATTR_EXT0_SCM_CISCO 0x00002000 uint16_t fw_attributes_ext[2]; uint32_t fw_memory_size; uint32_t fw_transfer_size; @@ -4522,15 +4564,31 @@ struct active_regions { #define QLA_SET_DATA_RATE_NOLR 1 #define QLA_SET_DATA_RATE_LR 2 /* Set speed and initiate LR */ +#define QLA_DEFAULT_PAYLOAD_SIZE 64 +/* + * This item might be allocated with a size > sizeof(struct purex_item). + * The "size" variable gives the size of the payload (which + * is variable) starting at "iocb". + */ struct purex_item { struct list_head list; struct scsi_qla_host *vha; - void (*process_item)(struct scsi_qla_host *vha, void *pkt); + void (*process_item)(struct scsi_qla_host *vha, + struct purex_item *pkt); + atomic_t in_use; + uint16_t size; struct { uint8_t iocb[64]; } iocb; }; +#define SCM_FLAG_RDF_REJECT 0x00 +#define SCM_FLAG_RDF_COMPLETED 0x01 + +#define QLA_CON_PRIMITIVE_RECEIVED 0x1 +#define QLA_CONGESTION_ARB_WARNING 0x1 +#define QLA_CONGESTION_ARB_ALARM 0X2 + /* * Qlogic scsi host structure */ @@ -4725,6 +4783,7 @@ typedef struct scsi_qla_host { struct list_head head; spinlock_t lock; } purex_list; + struct purex_item default_item; struct name_list_extended gnl; /* Count of active session/fcport */ @@ -4738,6 +4797,7 @@ typedef struct scsi_qla_host { __le16 dport_data[4]; struct list_head gpnid_list; struct fab_scan scan; + uint8_t scm_fabric_connection_flags; unsigned int irq_offset; } scsi_qla_host_t; diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index d1e12a29c3f7d3b96960284edf1e9bfd1ea47a10..bba1b77fba7e5907d685e178e8cf237cf460c7e2 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -610,7 +610,7 @@ struct sts_entry_24xx { __le32 residual_len; /* FW calc residual transfer length. */ union { - uint16_t reserved_1; + __le16 reserved_1; __le16 nvme_rsp_pyld_len; }; @@ -723,6 +723,8 @@ struct ct_entry_24xx { struct dsd64 dsd[2]; }; +#define PURX_ELS_HEADER_SIZE 0x18 + /* * ISP queue - PUREX IOCB entry structure definition */ @@ -2020,7 +2022,9 @@ struct nvram_81xx { * BIT 0 = Extended BB credits for LR * BIT 1 = Virtual Fabric Enable * BIT 2-5 = Distance Support if BIT 0 is on - * BIT 6-15 = Unused + * BIT 6 = Prefer FCP + * BIT 7 = SCM Disabled if BIT is set (1) + * BIT 8-15 = Unused */ uint16_t enhanced_features; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 061f91b521b3ff9a102d0e285beedab5fa69c4c8..0ced18f3104e541d9caa2969c5adc2fd07878adc 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -127,6 +127,7 @@ int qla_post_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport); void qla_do_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport); int qla2x00_reserve_mgmt_server_loop_id(scsi_qla_host_t *); void qla_rscn_replay(fc_port_t *fcport); +void qla24xx_free_purex_item(struct purex_item *item); extern bool qla24xx_risc_firmware_invalid(uint32_t *); /* @@ -229,7 +230,8 @@ void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *, int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_post_relogin_work(struct scsi_qla_host *vha); void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *); -void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt); +void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, + struct purex_item *pkt); /* * Global Functions in qla_mid.c source file. diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 2436a17f5cd91581a42d480ae6286687a81053b9..57a2d76aa691d6707c180f6e72a4ffe4b1ab63dd 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3749,7 +3749,7 @@ enable_82xx_npiv: } /* Enable PUREX PASSTHRU */ - if (ql2xrdpenable) + if (ql2xrdpenable || ha->flags.scm_supported_f) qla25xx_set_els_cmds_supported(vha); } else goto failed; @@ -3962,7 +3962,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ha->fw_options[2] &= ~BIT_8; } - if (ql2xrdpenable) + if (ql2xrdpenable || ha->flags.scm_supported_f) ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; /* Enable Async 8130/8131 events -- transceiver insertion/removal */ @@ -6996,36 +6996,41 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) static int qla2x00_restart_isp(scsi_qla_host_t *vha) { - int status = 0; + int status; struct qla_hw_data *ha = vha->hw; /* If firmware needs to be loaded */ if (qla2x00_isp_firmware(vha)) { vha->flags.online = 0; status = ha->isp_ops->chip_diag(vha); - if (!status) - status = qla2x00_setup_chip(vha); + if (status) + return status; + status = qla2x00_setup_chip(vha); + if (status) + return status; } - if (!status && !(status = qla2x00_init_rings(vha))) { - clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); - ha->flags.chip_reset_done = 1; + status = qla2x00_init_rings(vha); + if (status) + return status; - /* Initialize the queues in use */ - qla25xx_init_queues(ha); + clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); + ha->flags.chip_reset_done = 1; - status = qla2x00_fw_ready(vha); - if (!status) { - /* Issue a marker after FW becomes ready. */ - qla2x00_marker(vha, ha->base_qpair, 0, 0, MK_SYNC_ALL); - set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); - } + /* Initialize the queues in use */ + qla25xx_init_queues(ha); + status = qla2x00_fw_ready(vha); + if (status) { /* if no cable then assume it's good */ - if ((vha->device_flags & DFLG_NO_CABLE)) - status = 0; + return vha->device_flags & DFLG_NO_CABLE ? 0 : status; } - return (status); + + /* Issue a marker after FW becomes ready. */ + qla2x00_marker(vha, ha->base_qpair, 0, 0, MK_SYNC_ALL); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + + return 0; } static int @@ -8514,6 +8519,11 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) icb->node_name[0] &= 0xF0; } + if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) { + if ((nv->enhanced_features & BIT_7) == 0) + ha->flags.scm_supported_a = 1; + } + /* Set host adapter parameters. */ ha->flags.disable_risc_code_load = 0; ha->flags.enable_lip_reset = 0; diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 1fb6ccac07ccd152e3bfcf0d5e0dc6442ae58177..861dc522723ce1d8341abb844f814a5d1ca62204 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -11,7 +11,7 @@ * Continuation Type 1 IOCBs to allocate. * * @vha: HA context - * @dsds: number of data segment decriptors needed + * @dsds: number of data segment descriptors needed * * Returns the number of IOCB entries needed to store @dsds. */ diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 8865c35d34211a33b194d3bf010cd7c50a75f3d5..e3d2dea0b057c0a997d8dba6e4589174e32aa501 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -44,7 +44,7 @@ qla2x00_get_cmd_direction(srb_t *sp) * qla2x00_calc_iocbs_32() - Determine number of Command Type 2 and * Continuation Type 0 IOCBs to allocate. * - * @dsds: number of data segment decriptors needed + * @dsds: number of data segment descriptors needed * * Returns the number of IOCB entries needed to store @dsds. */ @@ -66,7 +66,7 @@ qla2x00_calc_iocbs_32(uint16_t dsds) * qla2x00_calc_iocbs_64() - Determine number of Command Type 3 and * Continuation Type 1 IOCBs to allocate. * - * @dsds: number of data segment decriptors needed + * @dsds: number of data segment descriptors needed * * Returns the number of IOCB entries needed to store @dsds. */ @@ -669,7 +669,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, * qla24xx_calc_dsd_lists() - Determine number of DSD list required * for Command Type 6. * - * @dsds: number of data segment decriptors needed + * @dsds: number of data segment descriptors needed * * Returns the number of dsd list needed to store @dsds. */ @@ -2305,8 +2305,8 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp) pkt = req->ring_ptr; memset(pkt, 0, REQUEST_ENTRY_SIZE); if (IS_QLAFX00(ha)) { - wrt_reg_byte((void __iomem *)&pkt->entry_count, req_cnt); - wrt_reg_word((void __iomem *)&pkt->handle, handle); + wrt_reg_byte((u8 __force __iomem *)&pkt->entry_count, req_cnt); + wrt_reg_dword((__le32 __force __iomem *)&pkt->handle, handle); } else { pkt->entry_count = req_cnt; pkt->handle = handle; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index cf0800546740126f09211c0b2b8f2b0f7482c884..27bcd346af7c2530c0cb147d897e0bdf13d25bb8 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -22,6 +22,31 @@ static void qla2x00_status_entry(scsi_qla_host_t *, struct rsp_que *, void *); static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *); static int qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *, sts_entry_t *); +static void qla27xx_process_purex_fpin(struct scsi_qla_host *vha, + struct purex_item *item); +static struct purex_item *qla24xx_alloc_purex_item(scsi_qla_host_t *vha, + uint16_t size); +static struct purex_item *qla24xx_copy_std_pkt(struct scsi_qla_host *vha, + void *pkt); +static struct purex_item *qla27xx_copy_fpin_pkt(struct scsi_qla_host *vha, + void **pkt, struct rsp_que **rsp); + +static void +qla27xx_process_purex_fpin(struct scsi_qla_host *vha, struct purex_item *item) +{ + void *pkt = &item->iocb; + uint16_t pkt_size = item->size; + + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x508d, + "%s: Enter\n", __func__); + + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x508e, + "-------- ELS REQ -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x508f, + pkt, pkt_size); + + fc_host_fpin_rcv(vha->host, pkt_size, (char *)pkt); +} const char *const port_state_str[] = { "Unknown", @@ -31,35 +56,11 @@ const char *const port_state_str[] = { "ONLINE" }; -static void qla24xx_purex_iocb(scsi_qla_host_t *vha, void *pkt, - void (*process_item)(struct scsi_qla_host *vha, void *pkt)) -{ - struct purex_list *list = &vha->purex_list; - struct purex_item *item; - ulong flags; - - item = kzalloc(sizeof(*item), GFP_KERNEL); - if (!item) { - ql_log(ql_log_warn, vha, 0x5092, - ">> Failed allocate purex list item.\n"); - return; - } - - item->vha = vha; - item->process_item = process_item; - memcpy(&item->iocb, pkt, sizeof(item->iocb)); - - spin_lock_irqsave(&list->lock, flags); - list_add_tail(&item->list, &list->head); - spin_unlock_irqrestore(&list->lock, flags); - - set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); -} - static void -qla24xx_process_abts(struct scsi_qla_host *vha, void *pkt) +qla24xx_process_abts(struct scsi_qla_host *vha, struct purex_item *pkt) { - struct abts_entry_24xx *abts = pkt; + struct abts_entry_24xx *abts = + (struct abts_entry_24xx *)&pkt->iocb; struct qla_hw_data *ha = vha->hw; struct els_entry_24xx *rsp_els; struct abts_entry_24xx *abts_rsp; @@ -789,6 +790,179 @@ qla27xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb) } } +static struct purex_item * +qla24xx_alloc_purex_item(scsi_qla_host_t *vha, uint16_t size) +{ + struct purex_item *item = NULL; + uint8_t item_hdr_size = sizeof(*item); + + if (size > QLA_DEFAULT_PAYLOAD_SIZE) { + item = kzalloc(item_hdr_size + + (size - QLA_DEFAULT_PAYLOAD_SIZE), GFP_ATOMIC); + } else { + if (atomic_inc_return(&vha->default_item.in_use) == 1) { + item = &vha->default_item; + goto initialize_purex_header; + } else { + item = kzalloc(item_hdr_size, GFP_ATOMIC); + } + } + if (!item) { + ql_log(ql_log_warn, vha, 0x5092, + ">> Failed allocate purex list item.\n"); + + return NULL; + } + +initialize_purex_header: + item->vha = vha; + item->size = size; + return item; +} + +static void +qla24xx_queue_purex_item(scsi_qla_host_t *vha, struct purex_item *pkt, + void (*process_item)(struct scsi_qla_host *vha, + struct purex_item *pkt)) +{ + struct purex_list *list = &vha->purex_list; + ulong flags; + + pkt->process_item = process_item; + + spin_lock_irqsave(&list->lock, flags); + list_add_tail(&pkt->list, &list->head); + spin_unlock_irqrestore(&list->lock, flags); + + set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); +} + +/** + * qla24xx_copy_std_pkt() - Copy over purex ELS which is + * contained in a single IOCB. + * purex packet. + * @vha: SCSI driver HA context + * @pkt: ELS packet + */ +static struct purex_item +*qla24xx_copy_std_pkt(struct scsi_qla_host *vha, void *pkt) +{ + struct purex_item *item; + + item = qla24xx_alloc_purex_item(vha, + QLA_DEFAULT_PAYLOAD_SIZE); + if (!item) + return item; + + memcpy(&item->iocb, pkt, sizeof(item->iocb)); + return item; +} + +/** + * qla27xx_copy_fpin_pkt() - Copy over fpin packets that can + * span over multiple IOCBs. + * @vha: SCSI driver HA context + * @pkt: ELS packet + * @rsp: Response queue + */ +static struct purex_item * +qla27xx_copy_fpin_pkt(struct scsi_qla_host *vha, void **pkt, + struct rsp_que **rsp) +{ + struct purex_entry_24xx *purex = *pkt; + struct rsp_que *rsp_q = *rsp; + sts_cont_entry_t *new_pkt; + uint16_t no_bytes = 0, total_bytes = 0, pending_bytes = 0; + uint16_t buffer_copy_offset = 0; + uint16_t entry_count, entry_count_remaining; + struct purex_item *item; + void *fpin_pkt = NULL; + + total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF) + - PURX_ELS_HEADER_SIZE; + pending_bytes = total_bytes; + entry_count = entry_count_remaining = purex->entry_count; + no_bytes = (pending_bytes > sizeof(purex->els_frame_payload)) ? + sizeof(purex->els_frame_payload) : pending_bytes; + ql_log(ql_log_info, vha, 0x509a, + "FPIN ELS, frame_size 0x%x, entry count %d\n", + total_bytes, entry_count); + + item = qla24xx_alloc_purex_item(vha, total_bytes); + if (!item) + return item; + + fpin_pkt = &item->iocb; + + memcpy(fpin_pkt, &purex->els_frame_payload[0], no_bytes); + buffer_copy_offset += no_bytes; + pending_bytes -= no_bytes; + --entry_count_remaining; + + ((response_t *)purex)->signature = RESPONSE_PROCESSED; + wmb(); + + do { + while ((total_bytes > 0) && (entry_count_remaining > 0)) { + if (rsp_q->ring_ptr->signature == RESPONSE_PROCESSED) { + ql_dbg(ql_dbg_async, vha, 0x5084, + "Ran out of IOCBs, partial data 0x%x\n", + buffer_copy_offset); + cpu_relax(); + continue; + } + + new_pkt = (sts_cont_entry_t *)rsp_q->ring_ptr; + *pkt = new_pkt; + + if (new_pkt->entry_type != STATUS_CONT_TYPE) { + ql_log(ql_log_warn, vha, 0x507a, + "Unexpected IOCB type, partial data 0x%x\n", + buffer_copy_offset); + break; + } + + rsp_q->ring_index++; + if (rsp_q->ring_index == rsp_q->length) { + rsp_q->ring_index = 0; + rsp_q->ring_ptr = rsp_q->ring; + } else { + rsp_q->ring_ptr++; + } + no_bytes = (pending_bytes > sizeof(new_pkt->data)) ? + sizeof(new_pkt->data) : pending_bytes; + if ((buffer_copy_offset + no_bytes) <= total_bytes) { + memcpy(((uint8_t *)fpin_pkt + + buffer_copy_offset), new_pkt->data, + no_bytes); + buffer_copy_offset += no_bytes; + pending_bytes -= no_bytes; + --entry_count_remaining; + } else { + ql_log(ql_log_warn, vha, 0x5044, + "Attempt to copy more that we got, optimizing..%x\n", + buffer_copy_offset); + memcpy(((uint8_t *)fpin_pkt + + buffer_copy_offset), new_pkt->data, + total_bytes - buffer_copy_offset); + } + + ((response_t *)new_pkt)->signature = RESPONSE_PROCESSED; + wmb(); + } + + if (pending_bytes != 0 || entry_count_remaining != 0) { + ql_log(ql_log_fatal, vha, 0x508b, + "Dropping partial FPIN, underrun bytes = 0x%x, entry cnts 0x%x\n", + total_bytes, entry_count_remaining); + qla24xx_free_purex_item(item); + return NULL; + } + } while (entry_count_remaining > 0); + host_to_fcp_swap((uint8_t *)&item->iocb, total_bytes); + return item; +} + /** * qla2x00_async_event() - Process aynchronous events. * @vha: SCSI driver HA context @@ -1302,6 +1476,19 @@ global_port_update: qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry); } break; + case MBA_CONGN_NOTI_RECV: + if (!ha->flags.scm_enabled || + mb[1] != QLA_CON_PRIMITIVE_RECEIVED) + break; + + if (mb[2] == QLA_CONGESTION_ARB_WARNING) { + ql_dbg(ql_dbg_async, vha, 0x509b, + "Congestion Warning %04x %04x.\n", mb[1], mb[2]); + } else if (mb[2] == QLA_CONGESTION_ARB_ALARM) { + ql_log(ql_log_warn, vha, 0x509b, + "Congestion Alarm %04x %04x.\n", mb[1], mb[2]); + } + break; /* case MBA_RIO_RESPONSE: */ case MBA_ZIO_RESPONSE: ql_dbg(ql_dbg_async, vha, 0x5015, @@ -3229,6 +3416,8 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, { struct sts_entry_24xx *pkt; struct qla_hw_data *ha = vha->hw; + struct purex_entry_24xx *purex_entry; + struct purex_item *pure_item; if (!ha->flags.fw_started) return; @@ -3280,8 +3469,11 @@ process_err: break; case ABTS_RECV_24XX: if (qla_ini_mode_enabled(vha)) { - qla24xx_purex_iocb(vha, pkt, - qla24xx_process_abts); + pure_item = qla24xx_copy_std_pkt(vha, pkt); + if (!pure_item) + break; + qla24xx_queue_purex_item(vha, pure_item, + qla24xx_process_abts); break; } if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || @@ -3329,24 +3521,40 @@ process_err: (struct vp_ctrl_entry_24xx *)pkt); break; case PUREX_IOCB_TYPE: - { - struct purex_entry_24xx *purex = (void *)pkt; - - if (purex->els_frame_payload[3] != ELS_COMMAND_RDP) { - ql_dbg(ql_dbg_init, vha, 0x5091, - "Discarding ELS Request opcode %#x...\n", - purex->els_frame_payload[3]); + purex_entry = (void *)pkt; + switch (purex_entry->els_frame_payload[3]) { + case ELS_RDP: + pure_item = qla24xx_copy_std_pkt(vha, pkt); + if (!pure_item) + break; + qla24xx_queue_purex_item(vha, pure_item, + qla24xx_process_purex_rdp); + break; + case ELS_FPIN: + if (!vha->hw->flags.scm_enabled) { + ql_log(ql_log_warn, vha, 0x5094, + "SCM not active for this port\n"); + break; + } + pure_item = qla27xx_copy_fpin_pkt(vha, + (void **)&pkt, &rsp); + if (!pure_item) + break; + qla24xx_queue_purex_item(vha, pure_item, + qla27xx_process_purex_fpin); break; + + default: + ql_log(ql_log_warn, vha, 0x509c, + "Discarding ELS Request opcode 0x%x\n", + purex_entry->els_frame_payload[3]); } - qla24xx_purex_iocb(vha, pkt, qla24xx_process_purex_rdp); break; - } default: /* Type Not Supported. */ ql_dbg(ql_dbg_async, vha, 0x5042, - "Received unknown response pkt type %x " - "entry status=%x.\n", - pkt->entry_type, pkt->entry_status); + "Received unknown response pkt type 0x%x entry status=%x.\n", + pkt->entry_type, pkt->entry_status); break; } ((response_t *)pkt)->signature = RESPONSE_PROCESSED; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index df31ee0d59b2060393da0d5f8f721d7d3180b048..73883435ab587b008446ce919702f48ed19e6da0 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -59,6 +59,7 @@ static struct rom_cmd { { MBC_IOCB_COMMAND_A64 }, { MBC_GET_ADAPTER_LOOP_ID }, { MBC_READ_SFP }, + { MBC_SET_RNID_PARAMS }, { MBC_GET_RNID_PARAMS }, { MBC_GET_SET_ZIO_THRESHOLD }, }; @@ -1124,6 +1125,16 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) (ha->flags.secure_fw) ? "Supported" : "Not Supported"); } + + if (ha->flags.scm_supported_a && + (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_SCM_SUPPORTED)) { + ha->flags.scm_supported_f = 1; + memset(ha->sf_init_cb, 0, sizeof(struct init_sf_cb)); + ha->sf_init_cb->flags |= BIT_13; + } + ql_log(ql_log_info, vha, 0x11a3, "SCM in FW: %s\n", + (ha->flags.scm_supported_f) ? "Supported" : + "Not Supported"); } failed: @@ -1633,8 +1644,11 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10; if (IS_FWI2_CAPABLE(vha->hw)) mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16; - if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) + if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) { mcp->in_mb |= MBX_15; + mcp->out_mb |= MBX_7|MBX_21|MBX_22|MBX_23; + } + mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); @@ -1687,8 +1701,22 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, } } - if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) + if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) { vha->bbcr = mcp->mb[15]; + if (mcp->mb[7] & SCM_EDC_ACC_RECEIVED) { + ql_log(ql_log_info, vha, 0x11a4, + "SCM: EDC ELS completed, flags 0x%x\n", + mcp->mb[21]); + } + if (mcp->mb[7] & SCM_RDF_ACC_RECEIVED) { + vha->hw->flags.scm_enabled = 1; + vha->scm_fabric_connection_flags |= + SCM_FLAG_RDF_COMPLETED; + ql_log(ql_log_info, vha, 0x11a5, + "SCM: RDF ELS completed, flags 0x%x\n", + mcp->mb[23]); + } + } } return rval; @@ -1801,6 +1829,17 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) mcp->mb[14] = sizeof(*ha->ex_init_cb); mcp->out_mb |= MBX_14|MBX_13|MBX_12|MBX_11|MBX_10; } + + if (ha->flags.scm_supported_f) { + mcp->mb[1] |= BIT_1; + mcp->mb[16] = MSW(ha->sf_init_cb_dma); + mcp->mb[17] = LSW(ha->sf_init_cb_dma); + mcp->mb[18] = MSW(MSD(ha->sf_init_cb_dma)); + mcp->mb[19] = LSW(MSD(ha->sf_init_cb_dma)); + mcp->mb[15] = sizeof(*ha->sf_init_cb); + mcp->out_mb |= MBX_19|MBX_18|MBX_17|MBX_16|MBX_15; + } + /* 1 and 2 should normally be captured. */ mcp->in_mb = MBX_2|MBX_1|MBX_0; if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) @@ -4866,6 +4905,7 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma, return rval; } +#define PUREX_CMD_COUNT 2 int qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha) { @@ -4874,12 +4914,12 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha) mbx_cmd_t *mcp = &mc; uint8_t *els_cmd_map; dma_addr_t els_cmd_map_dma; - uint cmd_opcode = ELS_COMMAND_RDP; - uint index = cmd_opcode / 8; - uint bit = cmd_opcode % 8; + uint8_t cmd_opcode[PUREX_CMD_COUNT]; + uint8_t i, index, purex_bit; struct qla_hw_data *ha = vha->hw; - if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha)) + if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) && + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return QLA_SUCCESS; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1197, @@ -4893,7 +4933,17 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha) return QLA_MEMORY_ALLOC_FAILED; } - els_cmd_map[index] |= 1 << bit; + memset(els_cmd_map, 0, ELS_CMD_MAP_SIZE); + + /* List of Purex ELS */ + cmd_opcode[0] = ELS_FPIN; + cmd_opcode[1] = ELS_RDP; + + for (i = 0; i < PUREX_CMD_COUNT; i++) { + index = cmd_opcode[i] / 8; + purex_bit = cmd_opcode[i] % 8; + els_cmd_map[index] |= 1 << purex_bit; + } mcp->mb[0] = MBC_SET_RNID_PARAMS; mcp->mb[1] = RNID_TYPE_ELS_CMD << 8; diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 0baf55b7e88f891016f8bd458b7e26975977ac4f..71273eb634d3299a2f6fca1c0564f79c55362d8f 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -966,26 +966,21 @@ qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val) static int qla82xx_flash_wait_write_finish(struct qla_hw_data *ha) { - long timeout = 0; - uint32_t done = 1 ; uint32_t val; - int ret = 0; + int i, ret; scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0); - while ((done != 0) && (ret == 0)) { + for (i = 0; i < 50000; i++) { ret = qla82xx_read_status_reg(ha, &val); - done = val & 1; - timeout++; + if (ret < 0 || (val & 1) == 0) + return ret; udelay(10); cond_resched(); - if (timeout >= 50000) { - ql_log(ql_log_warn, vha, 0xb00d, - "Timeout reached waiting for write finish.\n"); - return -1; - } } - return ret; + ql_log(ql_log_warn, vha, 0xb00d, + "Timeout reached waiting for write finish.\n"); + return -1; } static int @@ -1172,6 +1167,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha) * Offset 4: Offset and number of addr/value pairs * that present in CRB initialize sequence */ + n = 0; if (qla82xx_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafeUL || qla82xx_rom_fast_read(ha, 4, &n) != 0) { ql_log(ql_log_fatal, vha, 0x006e, diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index e92fad99338cd92314f60205f03a97bf0e39d356..9b59f032a569bf31ac95ca0e6297d3049f03244a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4218,6 +4218,16 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, "ex_init_cb=%p.\n", ha->ex_init_cb); } + /* Get consistent memory allocated for Special Features-CB. */ + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + ha->sf_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, + &ha->sf_init_cb_dma); + if (!ha->sf_init_cb) + goto fail_sf_init_cb; + ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0199, + "sf_init_cb=%p.\n", ha->sf_init_cb); + } + INIT_LIST_HEAD(&ha->gbl_dsd_list); /* Get consistent memory allocated for Async Port-Database. */ @@ -4271,6 +4281,8 @@ fail_sfp_data: fail_loop_id_map: dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma); fail_async_pd: + dma_pool_free(ha->s_dma_pool, ha->sf_init_cb, ha->sf_init_cb_dma); +fail_sf_init_cb: dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma); fail_ex_init_cb: kfree(ha->npiv_info); @@ -4693,6 +4705,10 @@ qla2x00_mem_free(struct qla_hw_data *ha) ha->ms_iocb = NULL; ha->ms_iocb_dma = 0; + if (ha->sf_init_cb) + dma_pool_free(ha->s_dma_pool, + ha->sf_init_cb, ha->sf_init_cb_dma); + if (ha->ex_init_cb) dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma); @@ -4780,6 +4796,8 @@ qla2x00_mem_free(struct qla_hw_data *ha) kfree(ha->swl); ha->swl = NULL; kfree(ha->loop_id_map); + ha->sf_init_cb = NULL; + ha->sf_init_cb_dma = 0; ha->loop_id_map = NULL; } @@ -5893,10 +5911,12 @@ qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha) * vha: SCSI qla host * purex: RDP request received by HBA */ -void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) +void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, + struct purex_item *item) { struct qla_hw_data *ha = vha->hw; - struct purex_entry_24xx *purex = pkt; + struct purex_entry_24xx *purex = + (struct purex_entry_24xx *)&item->iocb; dma_addr_t rsp_els_dma; dma_addr_t rsp_payload_dma; dma_addr_t stat_dma; @@ -6306,6 +6326,15 @@ dealloc: rsp_els, rsp_els_dma); } +void +qla24xx_free_purex_item(struct purex_item *item) +{ + if (item == &item->vha->default_item) + memset(&item->vha->default_item, 0, sizeof(struct purex_item)); + else + kfree(item); +} + void qla24xx_process_purex_list(struct purex_list *list) { struct list_head head = LIST_HEAD_INIT(head); @@ -6318,8 +6347,8 @@ void qla24xx_process_purex_list(struct purex_list *list) list_for_each_entry_safe(item, next, &head, list) { list_del(&item->list); - item->process_item(item->vha, &item->iocb); - kfree(item); + item->process_item(item->vha, item); + qla24xx_free_purex_item(item); } } diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 010f12523b2af6f9c831dd19255466d7ac2bd5e8..1cff7c69d4483d3fdc6d1f57e167900b6f159649 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -258,7 +258,7 @@ struct fcp_hdr { __be16 ox_id; uint16_t rx_id; __le32 parameter; -} __packed; +}; struct fcp_hdr_le { le_id_t d_id; @@ -273,7 +273,7 @@ struct fcp_hdr_le { __le16 rx_id; __le16 ox_id; __le32 parameter; -} __packed; +}; #define F_CTL_EXCH_CONTEXT_RESP BIT_23 #define F_CTL_SEQ_CONTEXT_RESIP BIT_22 diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 68183a96a417bdeb4fcdc8020bda5de39f9a9d70..44bfe162654a5102636489ba76678ec7e7eaaca4 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -1971,6 +1971,7 @@ static int __init tcm_qla2xxx_init(void) BUILD_BUG_ON(sizeof(struct ctio_crc2_to_fw) != 64); BUILD_BUG_ON(sizeof(struct ctio_crc_from_fw) != 64); BUILD_BUG_ON(sizeof(struct ctio_to_2xxx) != 64); + BUILD_BUG_ON(sizeof(struct fcp_hdr) != 24); BUILD_BUG_ON(sizeof(struct fcp_hdr_le) != 24); BUILD_BUG_ON(sizeof(struct nack_to_isp) != 64); diff --git a/drivers/scsi/qla4xxx/ql4_83xx.c b/drivers/scsi/qla4xxx/ql4_83xx.c index 638f72c5ab052f810770a14546d16ffcc8ec741e..de10e67de8c01dd096a07e81d164a47c2fb2cc06 100644 --- a/drivers/scsi/qla4xxx/ql4_83xx.c +++ b/drivers/scsi/qla4xxx/ql4_83xx.c @@ -1406,16 +1406,16 @@ exit_isp_reset: static void qla4_83xx_dump_pause_control_regs(struct scsi_qla_host *ha) { u32 val = 0, val1 = 0; - int i, status = QLA_SUCCESS; + int i; - status = qla4_83xx_rd_reg_indirect(ha, QLA83XX_SRE_SHIM_CONTROL, &val); + qla4_83xx_rd_reg_indirect(ha, QLA83XX_SRE_SHIM_CONTROL, &val); DEBUG2(ql4_printk(KERN_INFO, ha, "SRE-Shim Ctrl:0x%x\n", val)); /* Port 0 Rx Buffer Pause Threshold Registers. */ DEBUG2(ql4_printk(KERN_INFO, ha, "Port 0 Rx Buffer Pause Threshold Registers[TC7..TC0]:")); for (i = 0; i < 8; i++) { - status = qla4_83xx_rd_reg_indirect(ha, + qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT0_RXB_PAUSE_THRS + (i * 0x4), &val); DEBUG2(pr_info("0x%x ", val)); } @@ -1426,7 +1426,7 @@ static void qla4_83xx_dump_pause_control_regs(struct scsi_qla_host *ha) DEBUG2(ql4_printk(KERN_INFO, ha, "Port 1 Rx Buffer Pause Threshold Registers[TC7..TC0]:")); for (i = 0; i < 8; i++) { - status = qla4_83xx_rd_reg_indirect(ha, + qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT1_RXB_PAUSE_THRS + (i * 0x4), &val); DEBUG2(pr_info("0x%x ", val)); } @@ -1437,7 +1437,7 @@ static void qla4_83xx_dump_pause_control_regs(struct scsi_qla_host *ha) DEBUG2(ql4_printk(KERN_INFO, ha, "Port 0 RxB Traffic Class Max Cell Registers[3..0]:")); for (i = 0; i < 4; i++) { - status = qla4_83xx_rd_reg_indirect(ha, + qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT0_RXB_TC_MAX_CELL + (i * 0x4), &val); DEBUG2(pr_info("0x%x ", val)); } @@ -1448,7 +1448,7 @@ static void qla4_83xx_dump_pause_control_regs(struct scsi_qla_host *ha) DEBUG2(ql4_printk(KERN_INFO, ha, "Port 1 RxB Traffic Class Max Cell Registers[3..0]:")); for (i = 0; i < 4; i++) { - status = qla4_83xx_rd_reg_indirect(ha, + qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT1_RXB_TC_MAX_CELL + (i * 0x4), &val); DEBUG2(pr_info("0x%x ", val)); } @@ -1459,15 +1459,11 @@ static void qla4_83xx_dump_pause_control_regs(struct scsi_qla_host *ha) DEBUG2(ql4_printk(KERN_INFO, ha, "Port 0 RxB Rx Traffic Class Stats [TC7..TC0]")); for (i = 7; i >= 0; i--) { - status = qla4_83xx_rd_reg_indirect(ha, - QLA83XX_PORT0_RXB_TC_STATS, - &val); + qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT0_RXB_TC_STATS, &val); val &= ~(0x7 << 29); /* Reset bits 29 to 31 */ qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT0_RXB_TC_STATS, (val | (i << 29))); - status = qla4_83xx_rd_reg_indirect(ha, - QLA83XX_PORT0_RXB_TC_STATS, - &val); + qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT0_RXB_TC_STATS, &val); DEBUG2(pr_info("0x%x ", val)); } @@ -1477,24 +1473,18 @@ static void qla4_83xx_dump_pause_control_regs(struct scsi_qla_host *ha) DEBUG2(ql4_printk(KERN_INFO, ha, "Port 1 RxB Rx Traffic Class Stats [TC7..TC0]")); for (i = 7; i >= 0; i--) { - status = qla4_83xx_rd_reg_indirect(ha, - QLA83XX_PORT1_RXB_TC_STATS, - &val); + qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT1_RXB_TC_STATS, &val); val &= ~(0x7 << 29); /* Reset bits 29 to 31 */ qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT1_RXB_TC_STATS, (val | (i << 29))); - status = qla4_83xx_rd_reg_indirect(ha, - QLA83XX_PORT1_RXB_TC_STATS, - &val); + qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT1_RXB_TC_STATS, &val); DEBUG2(pr_info("0x%x ", val)); } DEBUG2(pr_info("\n")); - status = qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT2_IFB_PAUSE_THRS, - &val); - status = qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT3_IFB_PAUSE_THRS, - &val1); + qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT2_IFB_PAUSE_THRS, &val); + qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT3_IFB_PAUSE_THRS, &val1); DEBUG2(ql4_printk(KERN_INFO, ha, "IFB-Pause Thresholds: Port 2:0x%x, Port 3:0x%x\n", diff --git a/drivers/scsi/qla4xxx/ql4_83xx.h b/drivers/scsi/qla4xxx/ql4_83xx.h index 775fdf9fcc876f5a53a16feaf1981e86c46e0caf..f34583e5f8deeaa99a514173707928f10e138539 100644 --- a/drivers/scsi/qla4xxx/ql4_83xx.h +++ b/drivers/scsi/qla4xxx/ql4_83xx.h @@ -87,23 +87,6 @@ #define QLA83XX_FW_API 0x356C #define QLA83XX_DRV_OP_MODE 0x3570 -static const uint32_t qla4_83xx_reg_tbl[] = { - QLA83XX_PEG_HALT_STATUS1, - QLA83XX_PEG_HALT_STATUS2, - QLA83XX_PEG_ALIVE_COUNTER, - QLA83XX_CRB_DRV_ACTIVE, - QLA83XX_CRB_DEV_STATE, - QLA83XX_CRB_DRV_STATE, - QLA83XX_CRB_DRV_SCRATCH, - QLA83XX_CRB_DEV_PART_INFO1, - QLA83XX_CRB_IDC_VER_MAJOR, - QLA83XX_FW_VER_MAJOR, - QLA83XX_FW_VER_MINOR, - QLA83XX_FW_VER_SUB, - QLA83XX_CMDPEG_STATE, - QLA83XX_ASIC_TEMP, -}; - #define QLA83XX_CRB_WIN_BASE 0x3800 #define QLA83XX_CRB_WIN_FUNC(f) (QLA83XX_CRB_WIN_BASE+((f)*4)) #define QLA83XX_SEM_LOCK_BASE 0x3840 diff --git a/drivers/scsi/qla4xxx/ql4_bsg.c b/drivers/scsi/qla4xxx/ql4_bsg.c index 415ee5eb3fc7e79518c667263629141ac5c43031..9231917066d3e6c3e30b79d806e3a710ee1ddfcf 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.c +++ b/drivers/scsi/qla4xxx/ql4_bsg.c @@ -805,7 +805,7 @@ static int qla4xxx_execute_diag_test(struct bsg_job *bsg_job) /** * qla4xxx_process_vendor_specific - handle vendor specific bsg request - * @job: iscsi_bsg_job to handle + * @bsg_job: iscsi_bsg_job to handle **/ int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job) { @@ -852,7 +852,7 @@ int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job) /** * qla4xxx_bsg_request - handle bsg request from ISCSI transport - * @job: iscsi_bsg_job to handle + * @bsg_job: iscsi_bsg_job to handle */ int qla4xxx_bsg_request(struct bsg_job *bsg_job) { diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 2bf5e3e639e1aed822c4949c5305b9a6bf74dd05..4a7ef971a387c7bb4bb9bb7f916c4da43d55cd75 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -14,7 +14,6 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha) { uint32_t value; - uint8_t func_number; unsigned long flags; /* Get the function number */ @@ -22,7 +21,6 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha) value = readw(&ha->reg->ctrl_status); spin_unlock_irqrestore(&ha->hardware_lock, flags); - func_number = (uint8_t) ((value >> 4) & 0x30); switch (value & ISP_CONTROL_FN_MASK) { case ISP_CONTROL_FN0_SCSI: ha->mac_index = 1; @@ -667,6 +665,9 @@ void qla4xxx_pci_config(struct scsi_qla_host *ha) pci_set_master(ha->pdev); status = pci_set_mwi(ha->pdev); + if (status) + ql4_printk(KERN_WARNING, ha, "Failed to set MWI\n"); + /* * We want to respect framework's setting of PCI configuration space * command register and also want to make sure that all bits of @@ -945,6 +946,7 @@ void qla4xxx_free_ddb_index(struct scsi_qla_host *ha) /** * qla4xxx_initialize_adapter - initiailizes hba * @ha: Pointer to host adapter structure. + * @is_reset: Is this init path or reset path * * This routine parforms all of the steps necessary to initialize the adapter. * @@ -1156,9 +1158,10 @@ int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, /** * qla4xxx_process_ddb_changed - process ddb state change - * @ha - Pointer to host adapter structure. - * @fw_ddb_index - Firmware's device database index - * @state - Device state + * @ha: Pointer to host adapter structure. + * @fw_ddb_index: Firmware's device database index + * @state: Device state + * @conn_err: Unused * * This routine processes a Decive Database Changed AEN Event. **/ diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index 17222eb497622991ccdbd2473b3653c893661cac..a8df2d7eb069913127d5c12571d51fec5eef0eba 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -78,7 +78,7 @@ static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, * @ha: Pointer to host adapter structure. * @ddb_entry: Pointer to device database entry * @lun: SCSI LUN - * @marker_type: marker identifier + * @mrkr_mod: marker identifier * * This routine issues a marker IOCB. **/ diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index d2cd33d8d67fc9c7de67553217ccb3c1fd77ab54..ade5eafdf81e8b4126a05c11eca55c4fb339e6b6 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -582,7 +582,7 @@ exit_prq_error: /** * qla4_83xx_loopback_in_progress: Is loopback in progress? * @ha: Pointer to host adapter structure. - * @ret: 1 = loopback in progress, 0 = loopback not in progress + * returns: 1 = loopback in progress, 0 = loopback not in progress **/ static int qla4_83xx_loopback_in_progress(struct scsi_qla_host *ha) { @@ -651,7 +651,7 @@ static void qla4xxx_default_router_changed(struct scsi_qla_host *ha, /** * qla4xxx_isr_decode_mailbox - decodes mailbox status * @ha: Pointer to host adapter structure. - * @mailbox_status: Mailbox status. + * @mbox_status: Mailbox status. * * This routine decodes the mailbox status during the ISR. * Hardware_lock locked upon entry. runs in interrupt context. @@ -1044,6 +1044,7 @@ void qla4_83xx_interrupt_service_routine(struct scsi_qla_host *ha, /** * qla4_82xx_interrupt_service_routine - isr * @ha: pointer to host adapter structure. + * @intr_status: Local interrupt status/type. * * This is the main interrupt service routine. * hardware_lock locked upon entry. runs in interrupt context. @@ -1069,6 +1070,7 @@ void qla4_82xx_interrupt_service_routine(struct scsi_qla_host *ha, /** * qla4xxx_interrupt_service_routine - isr * @ha: pointer to host adapter structure. + * @intr_status: Local interrupt status/type. * * This is the main interrupt service routine. * hardware_lock locked upon entry. runs in interrupt context. diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 02636b4785c5875dbb40945b1c9b15948918ee56..bc8de7d402d58501762721f5a164c6b63018844f 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -47,7 +47,7 @@ void qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int out_count) /** * qla4xxx_is_intr_poll_mode – Are we allowed to poll for interrupts? * @ha: Pointer to host adapter structure. - * @ret: 1=polling mode, 0=non-polling mode + * returns: 1=polling mode, 0=non-polling mode **/ static int qla4xxx_is_intr_poll_mode(struct scsi_qla_host *ha) { @@ -810,7 +810,7 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha) return QLA_SUCCESS; } -/** +/* * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry * @ha: Pointer to host adapter structure. * @fw_ddb_index: Firmware's device database index @@ -1259,8 +1259,7 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, /** * qla4xxx_reset_target - issues target Reset * @ha: Pointer to host adapter structure. - * @db_entry: Pointer to device database entry - * @un_entry: Pointer to lun entry structure + * @ddb_entry: Pointer to device database entry * * This routine performs a TARGET RESET on the specified target. * The caller must ensure that the ddb_entry pointers diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 5a31877c9d04f7d387ab9ed02b5603b91b0a63ca..038e19b1e3c2d1765a00a0627fbe68b9cbf09507 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -974,10 +974,10 @@ qla4_82xx_rom_fast_read(struct scsi_qla_host *ha, int addr, int *valp) return ret; } -/** +/* * This routine does CRB initialize sequence * to put the ISP into operational state - **/ + */ static int qla4_82xx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) { @@ -2645,7 +2645,7 @@ static uint32_t qla4_84xx_minidump_process_rddfe(struct scsi_qla_host *ha, uint32_t addr1, addr2, value, data, temp, wrval; uint8_t stride, stride2; uint16_t count; - uint32_t poll, mask, data_size, modify_mask; + uint32_t poll, mask, modify_mask; uint32_t wait_count = 0; uint32_t *data_ptr = *d_ptr; struct qla8044_minidump_entry_rddfe *rddfe; @@ -2661,7 +2661,6 @@ static uint32_t qla4_84xx_minidump_process_rddfe(struct scsi_qla_host *ha, poll = le32_to_cpu(rddfe->poll); mask = le32_to_cpu(rddfe->mask); modify_mask = le32_to_cpu(rddfe->modify_mask); - data_size = le32_to_cpu(rddfe->data_size); addr2 = addr1 + stride; @@ -2742,7 +2741,7 @@ static uint32_t qla4_84xx_minidump_process_rdmdio(struct scsi_qla_host *ha, uint8_t stride1, stride2; uint32_t addr3, addr4, addr5, addr6, addr7; uint16_t count, loop_cnt; - uint32_t poll, mask; + uint32_t mask; uint32_t *data_ptr = *d_ptr; struct qla8044_minidump_entry_rdmdio *rdmdio; @@ -2754,7 +2753,6 @@ static uint32_t qla4_84xx_minidump_process_rdmdio(struct scsi_qla_host *ha, stride2 = le32_to_cpu(rdmdio->stride_2); count = le32_to_cpu(rdmdio->count); - poll = le32_to_cpu(rdmdio->poll); mask = le32_to_cpu(rdmdio->mask); value2 = le32_to_cpu(rdmdio->value_2); @@ -2813,7 +2811,7 @@ static uint32_t qla4_84xx_minidump_process_pollwr(struct scsi_qla_host *ha, struct qla8xxx_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr) { - uint32_t addr1, addr2, value1, value2, poll, mask, r_value; + uint32_t addr1, addr2, value1, value2, poll, r_value; struct qla8044_minidump_entry_pollwr *pollwr_hdr; uint32_t wait_count = 0; uint32_t rval = QLA_SUCCESS; @@ -2825,7 +2823,6 @@ static uint32_t qla4_84xx_minidump_process_pollwr(struct scsi_qla_host *ha, value2 = le32_to_cpu(pollwr_hdr->value_2); poll = le32_to_cpu(pollwr_hdr->poll); - mask = le32_to_cpu(pollwr_hdr->mask); while (wait_count < poll) { ha->isp_ops->rd_reg_indirect(ha, addr1, &r_value); @@ -3220,6 +3217,7 @@ md_failed: /** * qla4_8xxx_uevent_emit - Send uevent when the firmware dump is ready. * @ha: pointer to adapter structure + * @code: uevent code to act upon **/ static void qla4_8xxx_uevent_emit(struct scsi_qla_host *ha, u32 code) { @@ -3688,9 +3686,9 @@ done_read: return dwptr; } -/** +/* * Address and length are byte address - **/ + */ static uint8_t * qla4_82xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, uint32_t offset, uint32_t length) diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h index 98fe78613eb7b6934974e76ef7591d3753ca9ec6..b7a6e7f169ca9b77ab0bf5e7097aae43763fdbf3 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.h +++ b/drivers/scsi/qla4xxx/ql4_nx.h @@ -599,23 +599,6 @@ enum qla_regs { QLA8XXX_CRB_TEMP_STATE, }; -static const uint32_t qla4_82xx_reg_tbl[] = { - QLA82XX_PEG_HALT_STATUS1, - QLA82XX_PEG_HALT_STATUS2, - QLA82XX_PEG_ALIVE_COUNTER, - QLA82XX_CRB_DRV_ACTIVE, - QLA82XX_CRB_DEV_STATE, - QLA82XX_CRB_DRV_STATE, - QLA82XX_CRB_DRV_SCRATCH, - QLA82XX_CRB_DEV_PART_INFO, - QLA82XX_CRB_DRV_IDC_VERSION, - QLA82XX_FW_VERSION_MAJOR, - QLA82XX_FW_VERSION_MINOR, - QLA82XX_FW_VERSION_SUB, - CRB_CMDPEG_STATE, - CRB_TEMP_STATE, -}; - /* Every driver should use these Device State */ #define QLA8XXX_DEV_COLD 1 #define QLA8XXX_DEV_INITIALIZING 2 diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 5dc697ce8b5dd85f82acfd9b32571798d01007f9..bab87e47b238dbdb0c4a07e534238661140d84cd 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -188,6 +188,40 @@ static int qla4xxx_sysfs_ddb_logout_sid(struct iscsi_cls_session *cls_sess); static struct qla4_8xxx_legacy_intr_set legacy_intr[] = QLA82XX_LEGACY_INTR_CONFIG; +static const uint32_t qla4_82xx_reg_tbl[] = { + QLA82XX_PEG_HALT_STATUS1, + QLA82XX_PEG_HALT_STATUS2, + QLA82XX_PEG_ALIVE_COUNTER, + QLA82XX_CRB_DRV_ACTIVE, + QLA82XX_CRB_DEV_STATE, + QLA82XX_CRB_DRV_STATE, + QLA82XX_CRB_DRV_SCRATCH, + QLA82XX_CRB_DEV_PART_INFO, + QLA82XX_CRB_DRV_IDC_VERSION, + QLA82XX_FW_VERSION_MAJOR, + QLA82XX_FW_VERSION_MINOR, + QLA82XX_FW_VERSION_SUB, + CRB_CMDPEG_STATE, + CRB_TEMP_STATE, +}; + +static const uint32_t qla4_83xx_reg_tbl[] = { + QLA83XX_PEG_HALT_STATUS1, + QLA83XX_PEG_HALT_STATUS2, + QLA83XX_PEG_ALIVE_COUNTER, + QLA83XX_CRB_DRV_ACTIVE, + QLA83XX_CRB_DEV_STATE, + QLA83XX_CRB_DRV_STATE, + QLA83XX_CRB_DRV_SCRATCH, + QLA83XX_CRB_DEV_PART_INFO1, + QLA83XX_CRB_IDC_VER_MAJOR, + QLA83XX_FW_VER_MAJOR, + QLA83XX_FW_VER_MINOR, + QLA83XX_FW_VER_SUB, + QLA83XX_CMDPEG_STATE, + QLA83XX_ASIC_TEMP, +}; + static struct scsi_host_template qla4xxx_driver_template = { .module = THIS_MODULE, .name = DRIVER_NAME, @@ -1845,12 +1879,10 @@ exit_get_stats: static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc) { struct iscsi_cls_session *session; - struct iscsi_session *sess; unsigned long flags; enum blk_eh_timer_return ret = BLK_EH_DONE; session = starget_to_session(scsi_target(sc->device)); - sess = session->dd_data; spin_lock_irqsave(&session->lock, flags); if (session->state == ISCSI_SESSION_FAILED) @@ -3059,7 +3091,6 @@ qla4xxx_session_create(struct iscsi_endpoint *ep, struct ddb_entry *ddb_entry; uint16_t ddb_index; struct iscsi_session *sess; - struct sockaddr *dst_addr; int ret; if (!ep) { @@ -3068,7 +3099,6 @@ qla4xxx_session_create(struct iscsi_endpoint *ep, } qla_ep = ep->dd_data; - dst_addr = (struct sockaddr *)&qla_ep->dst_addr; ha = to_qla_host(qla_ep->host); DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__, ha->host_no)); @@ -4515,7 +4545,7 @@ static void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess) /** * qla4xxx_timer - checks every second for work to do. - * @ha: Pointer to host adapter structure. + * @t: Context to obtain pointer to host adapter structure. **/ static void qla4xxx_timer(struct timer_list *t) { @@ -5269,7 +5299,7 @@ static void qla4xxx_do_work(struct scsi_qla_host *ha) /** * qla4xxx_do_dpc - dpc routine - * @data: in our case pointer to adapter structure + * @work: Context to obtain pointer to host adapter structure. * * This routine is a task that is schedule by the interrupt handler * to perform the background processing for interrupts. We put it @@ -5492,7 +5522,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) int qla4_8xxx_iospace_config(struct scsi_qla_host *ha) { int status = 0; - unsigned long mem_base, mem_len, db_base, db_len; + unsigned long mem_base, mem_len; struct pci_dev *pdev = ha->pdev; status = pci_request_regions(pdev, DRIVER_NAME); @@ -5536,9 +5566,6 @@ int qla4_8xxx_iospace_config(struct scsi_qla_host *ha) ((uint8_t *)ha->nx_pcibase); } - db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */ - db_len = pci_resource_len(pdev, 4); - return 0; iospace_error_exit: return -ENOMEM; @@ -6249,14 +6276,12 @@ kset_free: static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry, struct ql4_tuple_ddb *tddb) { - struct scsi_qla_host *ha; struct iscsi_cls_session *cls_sess; struct iscsi_cls_conn *cls_conn; struct iscsi_session *sess; struct iscsi_conn *conn; DEBUG2(printk(KERN_INFO "Func: %s\n", __func__)); - ha = ddb_entry->ha; cls_sess = ddb_entry->sess; sess = cls_sess->dd_data; cls_conn = ddb_entry->conn; @@ -8591,7 +8616,7 @@ exit_login_resp: /** * qla4xxx_probe_adapter - callback function to probe HBA * @pdev: pointer to pci_dev structure - * @pci_device_id: pointer to pci_device entry + * @ent: pointer to pci_device entry * * This routine will probe for Qlogic 4xxx iSCSI host adapters. * It returns zero if successful. It also initializes all data necessary for @@ -8977,7 +9002,7 @@ static void qla4xxx_destroy_fw_ddb_session(struct scsi_qla_host *ha) } /** * qla4xxx_remove_adapter - callback function to remove adapter. - * @pci_dev: PCI device pointer + * @pdev: PCI device pointer **/ static void qla4xxx_remove_adapter(struct pci_dev *pdev) { @@ -9144,8 +9169,8 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha) /** * qla4xxx_eh_wait_for_commands - wait for active cmds to finish. * @ha: pointer to HBA - * @t: target id - * @l: lun id + * @stgt: pointer to SCSI target + * @sdev: pointer to SCSI device * * This function waits for all outstanding commands to a lun to complete. It * returns 0 if all pending commands are returned and 1 otherwise. @@ -9615,6 +9640,7 @@ qla4xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) * qla4xxx_pci_mmio_enabled() gets called if * qla4xxx_pci_error_detected() returns PCI_ERS_RESULT_CAN_RECOVER * and read/write to the device still works. + * @pdev: PCI device pointer **/ static pci_ers_result_t qla4xxx_pci_mmio_enabled(struct pci_dev *pdev) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 56c24a73e0c7cfb366528509c86389fc1aff6c32..24619c3bebd521fc4b21f2eddd73ba2d95bcb1a2 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -754,9 +754,6 @@ static int __init init_scsi(void) { int error; - error = scsi_init_queue(); - if (error) - return error; error = scsi_init_procfs(); if (error) goto cleanup_queue; diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 843cccb38cb768fba25219757cf00553d51b69e5..064ed680c05309c64aeb0d7ae1881f8f0bcb7329 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -9,7 +9,7 @@ * * Copyright (C) 2001 - 2020 Douglas Gilbert * - * For documentation see http://sg.danny.cz/sg/sdebug26.html + * For documentation see http://sg.danny.cz/sg/scsi_debug.html */ @@ -60,8 +60,8 @@ #include "scsi_logging.h" /* make sure inq_product_rev string corresponds to this version */ -#define SDEBUG_VERSION "0189" /* format to fit INQUIRY revision field */ -static const char *sdebug_version_date = "20200421"; +#define SDEBUG_VERSION "0190" /* format to fit INQUIRY revision field */ +static const char *sdebug_version_date = "20200710"; #define MY_NAME "scsi_debug" @@ -151,6 +151,7 @@ static const char *sdebug_version_date = "20200421"; #define DEF_STRICT 0 #define DEF_STATISTICS false #define DEF_SUBMIT_QUEUES 1 +#define DEF_TUR_MS_TO_READY 0 #define DEF_UUID_CTL 0 #define JDELAY_OVERRIDDEN -9999 @@ -187,21 +188,8 @@ static const char *sdebug_version_date = "20200421"; SDEBUG_OPT_SHORT_TRANSFER | \ SDEBUG_OPT_HOST_BUSY | \ SDEBUG_OPT_CMD_ABORT) -/* When "every_nth" > 0 then modulo "every_nth" commands: - * - a missing response is simulated if SDEBUG_OPT_TIMEOUT is set - * - a RECOVERED_ERROR is simulated on successful read and write - * commands if SDEBUG_OPT_RECOVERED_ERR is set. - * - a TRANSPORT_ERROR is simulated on successful read and write - * commands if SDEBUG_OPT_TRANSPORT_ERR is set. - * - similarly for DIF_ERR, DIX_ERR, SHORT_TRANSFER, HOST_BUSY and - * CMD_ABORT - * - * When "every_nth" < 0 then after "- every_nth" commands the selected - * error will be injected. The error will be injected on every subsequent - * command until some other action occurs; for example, the user writing - * a new value (other than -1 or 1) to every_nth: - * echo 0 > /sys/bus/pseudo/drivers/scsi_debug/every_nth - */ +#define SDEBUG_OPT_RECOV_DIF_DIX (SDEBUG_OPT_RECOVERED_ERR | \ + SDEBUG_OPT_DIF_ERR | SDEBUG_OPT_DIX_ERR) /* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs) are returned in * priority order. In the subset implemented here lower numbers have higher @@ -301,7 +289,7 @@ struct sdebug_dev_info { struct sdebug_host_info *sdbg_host; unsigned long uas_bm[1]; atomic_t num_in_q; - atomic_t stopped; + atomic_t stopped; /* 1: by SSU, 2: device start */ bool used; /* For ZBC devices */ @@ -314,6 +302,7 @@ struct sdebug_dev_info { unsigned int nr_exp_open; unsigned int nr_closed; unsigned int max_open; + ktime_t create_ts; /* time since bootup that this device was created */ struct sdeb_zone_state *zstate; }; @@ -344,6 +333,7 @@ struct sdebug_defer { struct execute_work ew; int sqa_idx; /* index of sdebug_queue array */ int qc_idx; /* index of sdebug_queued_cmd array within sqa_idx */ + int hc_idx; /* hostwide tag index */ int issuing_cpu; bool init_hrt; bool init_wq; @@ -357,13 +347,6 @@ struct sdebug_queued_cmd { */ struct sdebug_defer *sd_dp; struct scsi_cmnd *a_cmnd; - unsigned int inj_recovered:1; - unsigned int inj_transport:1; - unsigned int inj_dif:1; - unsigned int inj_dix:1; - unsigned int inj_short:1; - unsigned int inj_host_busy:1; - unsigned int inj_cmd_abort:1; }; struct sdebug_queue { @@ -377,6 +360,7 @@ static atomic_t sdebug_cmnd_count; /* number of incoming commands */ static atomic_t sdebug_completions; /* count of deferred completions */ static atomic_t sdebug_miss_cpus; /* submission + completion cpus differ */ static atomic_t sdebug_a_tsf; /* 'almost task set full' counter */ +static atomic_t sdeb_inject_pending; struct opcode_info_t { u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff */ @@ -759,6 +743,7 @@ static int sdebug_dsense = DEF_D_SENSE; static int sdebug_every_nth = DEF_EVERY_NTH; static int sdebug_fake_rw = DEF_FAKE_RW; static unsigned int sdebug_guard = DEF_GUARD; +static int sdebug_host_max_queue; /* per host */ static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED; static int sdebug_max_luns = DEF_MAX_LUNS; static int sdebug_max_queue = SDEBUG_CANQUEUE; /* per submit queue */ @@ -777,6 +762,7 @@ static int sdebug_opt_xferlen_exp = DEF_OPT_XFERLEN_EXP; static int sdebug_ptype = DEF_PTYPE; /* SCSI peripheral device type */ static int sdebug_scsi_level = DEF_SCSI_LEVEL; static int sdebug_sector_size = DEF_SECTOR_SIZE; +static int sdeb_tur_ms_to_ready = DEF_TUR_MS_TO_READY; static int sdebug_virtual_gb = DEF_VIRTUAL_GB; static int sdebug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; static unsigned int sdebug_lbpu = DEF_LBPU; @@ -1729,75 +1715,68 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) return ret; } +/* See resp_iec_m_pg() for how this data is manipulated */ static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x0}; static int resp_requests(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) { - unsigned char *sbuff; unsigned char *cmd = scp->cmnd; - unsigned char arr[SCSI_SENSE_BUFFERSIZE]; - bool dsense; + unsigned char arr[SCSI_SENSE_BUFFERSIZE]; /* assume >= 18 bytes */ + bool dsense = !!(cmd[1] & 1); + int alloc_len = cmd[4]; int len = 18; + int stopped_state = atomic_read(&devip->stopped); memset(arr, 0, sizeof(arr)); - dsense = !!(cmd[1] & 1); - sbuff = scp->sense_buffer; - if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) { + if (stopped_state > 0) { /* some "pollable" data [spc6r02: 5.12.2] */ + if (dsense) { + arr[0] = 0x72; + arr[1] = NOT_READY; + arr[2] = LOGICAL_UNIT_NOT_READY; + arr[3] = (stopped_state == 2) ? 0x1 : 0x2; + len = 8; + } else { + arr[0] = 0x70; + arr[2] = NOT_READY; /* NO_SENSE in sense_key */ + arr[7] = 0xa; /* 18 byte sense buffer */ + arr[12] = LOGICAL_UNIT_NOT_READY; + arr[13] = (stopped_state == 2) ? 0x1 : 0x2; + } + } else if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) { + /* Information exceptions control mode page: TEST=1, MRIE=6 */ if (dsense) { arr[0] = 0x72; arr[1] = 0x0; /* NO_SENSE in sense_key */ arr[2] = THRESHOLD_EXCEEDED; - arr[3] = 0xff; /* TEST set and MRIE==6 */ + arr[3] = 0xff; /* Failure prediction(false) */ len = 8; } else { arr[0] = 0x70; arr[2] = 0x0; /* NO_SENSE in sense_key */ arr[7] = 0xa; /* 18 byte sense buffer */ arr[12] = THRESHOLD_EXCEEDED; - arr[13] = 0xff; /* TEST set and MRIE==6 */ + arr[13] = 0xff; /* Failure prediction(false) */ } - } else { - memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE); - if (arr[0] >= 0x70 && dsense == sdebug_dsense) - ; /* have sense and formats match */ - else if (arr[0] <= 0x70) { - if (dsense) { - memset(arr, 0, 8); - arr[0] = 0x72; - len = 8; - } else { - memset(arr, 0, 18); - arr[0] = 0x70; - arr[7] = 0xa; - } - } else if (dsense) { - memset(arr, 0, 8); - arr[0] = 0x72; - arr[1] = sbuff[2]; /* sense key */ - arr[2] = sbuff[12]; /* asc */ - arr[3] = sbuff[13]; /* ascq */ + } else { /* nothing to report */ + if (dsense) { len = 8; + memset(arr, 0, len); + arr[0] = 0x72; } else { - memset(arr, 0, 18); + memset(arr, 0, len); arr[0] = 0x70; - arr[2] = sbuff[1]; arr[7] = 0xa; - arr[12] = sbuff[1]; - arr[13] = sbuff[3]; } - } - mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0); - return fill_from_dev_buffer(scp, arr, len); + return fill_from_dev_buffer(scp, arr, min_t(int, len, alloc_len)); } -static int resp_start_stop(struct scsi_cmnd *scp, - struct sdebug_dev_info *devip) +static int resp_start_stop(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) { unsigned char *cmd = scp->cmnd; - int power_cond, stop; + int power_cond, want_stop, stopped_state; bool changing; power_cond = (cmd[4] & 0xf0) >> 4; @@ -1805,10 +1784,33 @@ static int resp_start_stop(struct scsi_cmnd *scp, mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7); return check_condition_result; } - stop = !(cmd[4] & 1); - changing = atomic_read(&devip->stopped) == !stop; - atomic_xchg(&devip->stopped, stop); - if (!changing || cmd[1] & 0x1) /* state unchanged or IMMED set */ + want_stop = !(cmd[4] & 1); + stopped_state = atomic_read(&devip->stopped); + if (stopped_state == 2) { + ktime_t now_ts = ktime_get_boottime(); + + if (ktime_to_ns(now_ts) > ktime_to_ns(devip->create_ts)) { + u64 diff_ns = ktime_to_ns(ktime_sub(now_ts, devip->create_ts)); + + if (diff_ns >= ((u64)sdeb_tur_ms_to_ready * 1000000)) { + /* tur_ms_to_ready timer extinguished */ + atomic_set(&devip->stopped, 0); + stopped_state = 0; + } + } + if (stopped_state == 2) { + if (want_stop) { + stopped_state = 1; /* dummy up success */ + } else { /* Disallow tur_ms_to_ready delay to be overridden */ + mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 0 /* START bit */); + return check_condition_result; + } + } + } + changing = (stopped_state != want_stop); + if (changing) + atomic_xchg(&devip->stopped, want_stop); + if (!changing || (cmd[1] & 0x1)) /* state unchanged or IMMED bit set in cdb */ return SDEG_RES_IMMED_MASK; else return 0; @@ -3109,7 +3111,6 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) struct sdeb_store_info *sip = devip2sip(devip, true); rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck; u8 *cmd = scp->cmnd; - struct sdebug_queued_cmd *sqcp; switch (cmd[0]) { case READ_16: @@ -3162,15 +3163,11 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) sdev_printk(KERN_ERR, scp->device, "Unprotected RD " "to DIF device\n"); } - if (unlikely(sdebug_any_injecting_opt)) { - sqcp = (struct sdebug_queued_cmd *)scp->host_scribble; - - if (sqcp) { - if (sqcp->inj_short) - num /= 2; - } - } else - sqcp = NULL; + if (unlikely((sdebug_opts & SDEBUG_OPT_SHORT_TRANSFER) && + atomic_read(&sdeb_inject_pending))) { + num /= 2; + atomic_set(&sdeb_inject_pending, 0); + } ret = check_device_access_params(scp, lba, num, false); if (ret) @@ -3211,21 +3208,20 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) scsi_set_resid(scp, scsi_bufflen(scp) - ret); - if (unlikely(sqcp)) { - if (sqcp->inj_recovered) { - mk_sense_buffer(scp, RECOVERED_ERROR, - THRESHOLD_EXCEEDED, 0); + if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) && + atomic_read(&sdeb_inject_pending))) { + if (sdebug_opts & SDEBUG_OPT_RECOVERED_ERR) { + mk_sense_buffer(scp, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); + atomic_set(&sdeb_inject_pending, 0); return check_condition_result; - } else if (sqcp->inj_transport) { - mk_sense_buffer(scp, ABORTED_COMMAND, - TRANSPORT_PROBLEM, ACK_NAK_TO); - return check_condition_result; - } else if (sqcp->inj_dif) { + } else if (sdebug_opts & SDEBUG_OPT_DIF_ERR) { /* Logical block guard check failed */ mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); + atomic_set(&sdeb_inject_pending, 0); return illegal_condition_result; - } else if (sqcp->inj_dix) { + } else if (SDEBUG_OPT_DIX_ERR & sdebug_opts) { mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); + atomic_set(&sdeb_inject_pending, 0); return illegal_condition_result; } } @@ -3504,23 +3500,21 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) "%s: write: cdb indicated=%u, IO sent=%d bytes\n", my_name, num * sdebug_sector_size, ret); - if (unlikely(sdebug_any_injecting_opt)) { - struct sdebug_queued_cmd *sqcp = - (struct sdebug_queued_cmd *)scp->host_scribble; - - if (sqcp) { - if (sqcp->inj_recovered) { - mk_sense_buffer(scp, RECOVERED_ERROR, - THRESHOLD_EXCEEDED, 0); - return check_condition_result; - } else if (sqcp->inj_dif) { - /* Logical block guard check failed */ - mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); - return illegal_condition_result; - } else if (sqcp->inj_dix) { - mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); - return illegal_condition_result; - } + if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) && + atomic_read(&sdeb_inject_pending))) { + if (sdebug_opts & SDEBUG_OPT_RECOVERED_ERR) { + mk_sense_buffer(scp, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); + atomic_set(&sdeb_inject_pending, 0); + return check_condition_result; + } else if (sdebug_opts & SDEBUG_OPT_DIF_ERR) { + /* Logical block guard check failed */ + mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); + atomic_set(&sdeb_inject_pending, 0); + return illegal_condition_result; + } else if (sdebug_opts & SDEBUG_OPT_DIX_ERR) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); + atomic_set(&sdeb_inject_pending, 0); + return illegal_condition_result; } } return 0; @@ -3662,28 +3656,24 @@ static int resp_write_scat(struct scsi_cmnd *scp, "%s: write: cdb indicated=%u, IO sent=%d bytes\n", my_name, num_by, ret); - if (unlikely(sdebug_any_injecting_opt)) { - struct sdebug_queued_cmd *sqcp = - (struct sdebug_queued_cmd *)scp->host_scribble; - - if (sqcp) { - if (sqcp->inj_recovered) { - mk_sense_buffer(scp, RECOVERED_ERROR, - THRESHOLD_EXCEEDED, 0); - ret = illegal_condition_result; - goto err_out_unlock; - } else if (sqcp->inj_dif) { - /* Logical block guard check failed */ - mk_sense_buffer(scp, ABORTED_COMMAND, - 0x10, 1); - ret = illegal_condition_result; - goto err_out_unlock; - } else if (sqcp->inj_dix) { - mk_sense_buffer(scp, ILLEGAL_REQUEST, - 0x10, 1); - ret = illegal_condition_result; - goto err_out_unlock; - } + if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) && + atomic_read(&sdeb_inject_pending))) { + if (sdebug_opts & SDEBUG_OPT_RECOVERED_ERR) { + mk_sense_buffer(scp, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); + atomic_set(&sdeb_inject_pending, 0); + ret = check_condition_result; + goto err_out_unlock; + } else if (sdebug_opts & SDEBUG_OPT_DIF_ERR) { + /* Logical block guard check failed */ + mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); + atomic_set(&sdeb_inject_pending, 0); + ret = illegal_condition_result; + goto err_out_unlock; + } else if (sdebug_opts & SDEBUG_OPT_DIX_ERR) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); + atomic_set(&sdeb_inject_pending, 0); + ret = illegal_condition_result; + goto err_out_unlock; } } sg_off += num_by; @@ -4049,7 +4039,7 @@ static int resp_sync_cache(struct scsi_cmnd *scp, mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); return check_condition_result; } - if (!write_since_sync || cmd[1] & 0x2) + if (!write_since_sync || (cmd[1] & 0x2)) res = SDEG_RES_IMMED_MASK; else /* delay if write_since_sync and IMMED clear */ write_since_sync = false; @@ -4707,15 +4697,28 @@ fini: static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd) { - u32 tag = blk_mq_unique_tag(cmnd->request); - u16 hwq = blk_mq_unique_tag_to_hwq(tag); + u16 hwq; - pr_debug("tag=%#x, hwq=%d\n", tag, hwq); - if (WARN_ON_ONCE(hwq >= submit_queues)) - hwq = 0; + if (sdebug_host_max_queue) { + /* Provide a simple method to choose the hwq */ + hwq = smp_processor_id() % submit_queues; + } else { + u32 tag = blk_mq_unique_tag(cmnd->request); + + hwq = blk_mq_unique_tag_to_hwq(tag); + + pr_debug("tag=%#x, hwq=%d\n", tag, hwq); + if (WARN_ON_ONCE(hwq >= submit_queues)) + hwq = 0; + } return sdebug_q_arr + hwq; } +static u32 get_tag(struct scsi_cmnd *cmnd) +{ + return blk_mq_unique_tag(cmnd->request); +} + /* Queued (deferred) command completions converge here. */ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) { @@ -4747,8 +4750,8 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) scp = sqcp->a_cmnd; if (unlikely(scp == NULL)) { spin_unlock_irqrestore(&sqp->qc_lock, iflags); - pr_err("scp is NULL, sqa_idx=%d, qc_idx=%d\n", - sd_dp->sqa_idx, qc_idx); + pr_err("scp is NULL, sqa_idx=%d, qc_idx=%d, hc_idx=%d\n", + sd_dp->sqa_idx, qc_idx, sd_dp->hc_idx); return; } devip = (struct sdebug_dev_info *)scp->device->hostdata; @@ -4925,6 +4928,8 @@ static struct sdebug_dev_info *sdebug_device_create( devip->zmodel = BLK_ZONED_NONE; } devip->sdbg_host = sdbg_host; + devip->create_ts = ktime_get_boottime(); + atomic_set(&devip->stopped, (sdeb_tur_ms_to_ready > 0 ? 2 : 0)); list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list); } return devip; @@ -5333,24 +5338,11 @@ static void clear_queue_stats(void) atomic_set(&sdebug_a_tsf, 0); } -static void setup_inject(struct sdebug_queue *sqp, - struct sdebug_queued_cmd *sqcp) +static bool inject_on_this_cmd(void) { - if ((atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) > 0) { - if (sdebug_every_nth > 0) - sqcp->inj_recovered = sqcp->inj_transport - = sqcp->inj_dif - = sqcp->inj_dix = sqcp->inj_short - = sqcp->inj_host_busy = sqcp->inj_cmd_abort = 0; - return; - } - sqcp->inj_recovered = !!(SDEBUG_OPT_RECOVERED_ERR & sdebug_opts); - sqcp->inj_transport = !!(SDEBUG_OPT_TRANSPORT_ERR & sdebug_opts); - sqcp->inj_dif = !!(SDEBUG_OPT_DIF_ERR & sdebug_opts); - sqcp->inj_dix = !!(SDEBUG_OPT_DIX_ERR & sdebug_opts); - sqcp->inj_short = !!(SDEBUG_OPT_SHORT_TRANSFER & sdebug_opts); - sqcp->inj_host_busy = !!(SDEBUG_OPT_HOST_BUSY & sdebug_opts); - sqcp->inj_cmd_abort = !!(SDEBUG_OPT_CMD_ABORT & sdebug_opts); + if (sdebug_every_nth == 0) + return false; + return (atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) == 0; } #define INCLUSIVE_TIMING_MAX_NS 1000000 /* 1 millisecond */ @@ -5367,7 +5359,8 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, int delta_jiff, int ndelay) { bool new_sd_dp; - int k, num_in_q, qdepth, inject; + bool inject = false; + int k, num_in_q, qdepth; unsigned long iflags; u64 ns_from_boot = 0; struct sdebug_queue *sqp; @@ -5393,7 +5386,6 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, } num_in_q = atomic_read(&devip->num_in_q); qdepth = cmnd->device->queue_depth; - inject = 0; if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) { if (scsi_result) { spin_unlock_irqrestore(&sqp->qc_lock, iflags); @@ -5407,7 +5399,7 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, (atomic_inc_return(&sdebug_a_tsf) >= abs(sdebug_every_nth))) { atomic_set(&sdebug_a_tsf, 0); - inject = 1; + inject = true; scsi_result = device_qfull_result; } } @@ -5430,35 +5422,47 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, else return SCSI_MLQUEUE_HOST_BUSY; } - __set_bit(k, sqp->in_use_bm); + set_bit(k, sqp->in_use_bm); atomic_inc(&devip->num_in_q); sqcp = &sqp->qc_arr[k]; sqcp->a_cmnd = cmnd; cmnd->host_scribble = (unsigned char *)sqcp; sd_dp = sqcp->sd_dp; spin_unlock_irqrestore(&sqp->qc_lock, iflags); - if (unlikely(sdebug_every_nth && sdebug_any_injecting_opt)) - setup_inject(sqp, sqcp); - if (sd_dp == NULL) { + if (!sd_dp) { sd_dp = kzalloc(sizeof(*sd_dp), GFP_ATOMIC); - if (sd_dp == NULL) + if (!sd_dp) { + atomic_dec(&devip->num_in_q); + clear_bit(k, sqp->in_use_bm); return SCSI_MLQUEUE_HOST_BUSY; + } new_sd_dp = true; } else { new_sd_dp = false; } + /* Set the hostwide tag */ + if (sdebug_host_max_queue) + sd_dp->hc_idx = get_tag(cmnd); + if (ndelay > 0 && ndelay < INCLUSIVE_TIMING_MAX_NS) ns_from_boot = ktime_get_boottime_ns(); /* one of the resp_*() response functions is called here */ - cmnd->result = pfp != NULL ? pfp(cmnd, devip) : 0; + cmnd->result = pfp ? pfp(cmnd, devip) : 0; if (cmnd->result & SDEG_RES_IMMED_MASK) { cmnd->result &= ~SDEG_RES_IMMED_MASK; delta_jiff = ndelay = 0; } if (cmnd->result == 0 && scsi_result != 0) cmnd->result = scsi_result; + if (cmnd->result == 0 && unlikely(sdebug_opts & SDEBUG_OPT_TRANSPORT_ERR)) { + if (atomic_read(&sdeb_inject_pending)) { + mk_sense_buffer(cmnd, ABORTED_COMMAND, TRANSPORT_PROBLEM, ACK_NAK_TO); + atomic_set(&sdeb_inject_pending, 0); + cmnd->result = check_condition_result; + } + } if (unlikely(sdebug_verbose && cmnd->result)) sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", @@ -5524,21 +5528,20 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, if (sdebug_statistics) sd_dp->issuing_cpu = raw_smp_processor_id(); sd_dp->defer_t = SDEB_DEFER_WQ; - if (unlikely(sqcp->inj_cmd_abort)) + if (unlikely((sdebug_opts & SDEBUG_OPT_CMD_ABORT) && + atomic_read(&sdeb_inject_pending))) sd_dp->aborted = true; schedule_work(&sd_dp->ew.work); - if (unlikely(sqcp->inj_cmd_abort)) { - sdev_printk(KERN_INFO, sdp, "abort request tag %d\n", - cmnd->request->tag); + if (unlikely((sdebug_opts & SDEBUG_OPT_CMD_ABORT) && + atomic_read(&sdeb_inject_pending))) { + sdev_printk(KERN_INFO, sdp, "abort request tag %d\n", cmnd->request->tag); blk_abort_request(cmnd->request); + atomic_set(&sdeb_inject_pending, 0); } } - if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) && - (scsi_result == device_qfull_result))) - sdev_printk(KERN_INFO, sdp, - "%s: num_in_q=%d +1, %s%s\n", __func__, - num_in_q, (inject ? " " : ""), - "status: TASK SET FULL"); + if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) && scsi_result == device_qfull_result)) + sdev_printk(KERN_INFO, sdp, "%s: num_in_q=%d +1, %s%s\n", __func__, + num_in_q, (inject ? " " : ""), "status: TASK SET FULL"); return 0; respond_in_thread: /* call back to mid-layer using invocation thread */ @@ -5569,6 +5572,7 @@ module_param_named(every_nth, sdebug_every_nth, int, S_IRUGO | S_IWUSR); module_param_named(fake_rw, sdebug_fake_rw, int, S_IRUGO | S_IWUSR); module_param_named(guard, sdebug_guard, uint, S_IRUGO); module_param_named(host_lock, sdebug_host_lock, bool, S_IRUGO | S_IWUSR); +module_param_named(host_max_queue, sdebug_host_max_queue, int, S_IRUGO); module_param_string(inq_product, sdebug_inq_product_id, sizeof(sdebug_inq_product_id), S_IRUGO | S_IWUSR); module_param_string(inq_rev, sdebug_inq_product_rev, @@ -5605,6 +5609,7 @@ module_param_named(sector_size, sdebug_sector_size, int, S_IRUGO); module_param_named(statistics, sdebug_statistics, bool, S_IRUGO | S_IWUSR); module_param_named(strict, sdebug_strict, bool, S_IRUGO | S_IWUSR); module_param_named(submit_queues, submit_queues, int, S_IRUGO); +module_param_named(tur_ms_to_ready, sdeb_tur_ms_to_ready, int, S_IRUGO); module_param_named(unmap_alignment, sdebug_unmap_alignment, int, S_IRUGO); module_param_named(unmap_granularity, sdebug_unmap_granularity, int, S_IRUGO); module_param_named(unmap_max_blocks, sdebug_unmap_max_blocks, int, S_IRUGO); @@ -5639,6 +5644,8 @@ MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)"); MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)"); MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); MODULE_PARM_DESC(host_lock, "host_lock is ignored (def=0)"); +MODULE_PARM_DESC(host_max_queue, + "host max # of queued cmds (0 to max(def) [max_queue fixed equal for !0])"); MODULE_PARM_DESC(inq_product, "SCSI INQUIRY product string (def=\"scsi_debug\")"); MODULE_PARM_DESC(inq_rev, "SCSI INQUIRY revision string (def=\"" SDEBUG_VERSION "\")"); @@ -5671,6 +5678,7 @@ MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)"); MODULE_PARM_DESC(statistics, "collect statistics on commands, queues (def=0)"); MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)"); MODULE_PARM_DESC(submit_queues, "support for block multi-queue (def=1)"); +MODULE_PARM_DESC(tur_ms_to_ready, "TEST UNIT READY millisecs before initial good status (def=0)"); MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)"); MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)"); MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)"); @@ -6072,17 +6080,27 @@ static ssize_t every_nth_store(struct device_driver *ddp, const char *buf, size_t count) { int nth; + char work[20]; - if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) { - sdebug_every_nth = nth; - if (nth && !sdebug_statistics) { - pr_info("every_nth needs statistics=1, set it\n"); - sdebug_statistics = true; + if (sscanf(buf, "%10s", work) == 1) { + if (strncasecmp(work, "0x", 2) == 0) { + if (kstrtoint(work + 2, 16, &nth) == 0) + goto every_nth_done; + } else { + if (kstrtoint(work, 10, &nth) == 0) + goto every_nth_done; } - tweak_cmnd_count(); - return count; } return -EINVAL; + +every_nth_done: + sdebug_every_nth = nth; + if (nth && !sdebug_statistics) { + pr_info("every_nth needs statistics=1, set it\n"); + sdebug_statistics = true; + } + tweak_cmnd_count(); + return count; } static DRIVER_ATTR_RW(every_nth); @@ -6138,7 +6156,8 @@ static ssize_t max_queue_store(struct device_driver *ddp, const char *buf, struct sdebug_queue *sqp; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) && - (n <= SDEBUG_CANQUEUE)) { + (n <= SDEBUG_CANQUEUE) && + (sdebug_host_max_queue == 0)) { block_unblock_all_queues(true); k = 0; for (j = 0, sqp = sdebug_q_arr; j < submit_queues; @@ -6161,6 +6180,17 @@ static ssize_t max_queue_store(struct device_driver *ddp, const char *buf, } static DRIVER_ATTR_RW(max_queue); +static ssize_t host_max_queue_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_host_max_queue); +} + +/* + * Since this is used for .can_queue, and we get the hc_idx tag from the bitmap + * in range [0, sdebug_host_max_queue), we can't change it. + */ +static DRIVER_ATTR_RO(host_max_queue); + static ssize_t no_uld_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_no_uld); @@ -6487,6 +6517,12 @@ static ssize_t zbc_show(struct device_driver *ddp, char *buf) } static DRIVER_ATTR_RO(zbc); +static ssize_t tur_ms_to_ready_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", sdeb_tur_ms_to_ready); +} +static DRIVER_ATTR_RO(tur_ms_to_ready); + /* Note: The following array creates attribute files in the /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these files (over those found in the /sys/module/scsi_debug/parameters @@ -6500,6 +6536,7 @@ static struct attribute *sdebug_drv_attrs[] = { &driver_attr_ptype.attr, &driver_attr_dsense.attr, &driver_attr_fake_rw.attr, + &driver_attr_host_max_queue.attr, &driver_attr_no_lun_0.attr, &driver_attr_num_tgts.attr, &driver_attr_dev_size_mb.attr, @@ -6528,6 +6565,7 @@ static struct attribute *sdebug_drv_attrs[] = { &driver_attr_strict.attr, &driver_attr_uuid_ctl.attr, &driver_attr_cdb_len.attr, + &driver_attr_tur_ms_to_ready.attr, &driver_attr_zbc.attr, NULL, }; @@ -6610,6 +6648,26 @@ static int __init scsi_debug_init(void) pr_err("submit_queues must be 1 or more\n"); return -EINVAL; } + + if ((sdebug_max_queue > SDEBUG_CANQUEUE) || (sdebug_max_queue < 1)) { + pr_err("max_queue must be in range [1, %d]\n", SDEBUG_CANQUEUE); + return -EINVAL; + } + + if ((sdebug_host_max_queue > SDEBUG_CANQUEUE) || + (sdebug_host_max_queue < 0)) { + pr_err("host_max_queue must be in range [0 %d]\n", + SDEBUG_CANQUEUE); + return -EINVAL; + } + + if (sdebug_host_max_queue && + (sdebug_max_queue != sdebug_host_max_queue)) { + sdebug_max_queue = sdebug_host_max_queue; + pr_warn("fixing max submit queue depth to host max queue depth, %d\n", + sdebug_max_queue); + } + sdebug_q_arr = kcalloc(submit_queues, sizeof(struct sdebug_queue), GFP_KERNEL); if (sdebug_q_arr == NULL) @@ -7044,10 +7102,47 @@ static bool fake_timeout(struct scsi_cmnd *scp) return false; } -static bool fake_host_busy(struct scsi_cmnd *scp) +/* Response to TUR or media access command when device stopped */ +static int resp_not_ready(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) { - return (sdebug_opts & SDEBUG_OPT_HOST_BUSY) && - (atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) == 0; + int stopped_state; + u64 diff_ns = 0; + ktime_t now_ts = ktime_get_boottime(); + struct scsi_device *sdp = scp->device; + + stopped_state = atomic_read(&devip->stopped); + if (stopped_state == 2) { + if (ktime_to_ns(now_ts) > ktime_to_ns(devip->create_ts)) { + diff_ns = ktime_to_ns(ktime_sub(now_ts, devip->create_ts)); + if (diff_ns >= ((u64)sdeb_tur_ms_to_ready * 1000000)) { + /* tur_ms_to_ready timer extinguished */ + atomic_set(&devip->stopped, 0); + return 0; + } + } + mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x1); + if (sdebug_verbose) + sdev_printk(KERN_INFO, sdp, + "%s: Not ready: in process of becoming ready\n", my_name); + if (scp->cmnd[0] == TEST_UNIT_READY) { + u64 tur_nanosecs_to_ready = (u64)sdeb_tur_ms_to_ready * 1000000; + + if (diff_ns <= tur_nanosecs_to_ready) + diff_ns = tur_nanosecs_to_ready - diff_ns; + else + diff_ns = tur_nanosecs_to_ready; + /* As per 20-061r2 approved for spc6 by T10 on 20200716 */ + do_div(diff_ns, 1000000); /* diff_ns becomes milliseconds */ + scsi_set_sense_information(scp->sense_buffer, SCSI_SENSE_BUFFERSIZE, + diff_ns); + return check_condition_result; + } + } + mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); + if (sdebug_verbose) + sdev_printk(KERN_INFO, sdp, "%s: Not ready: initializing command required\n", + my_name); + return check_condition_result; } static int scsi_debug_queuecommand(struct Scsi_Host *shost, @@ -7058,7 +7153,6 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, const struct opcode_info_t *oip; const struct opcode_info_t *r_oip; struct sdebug_dev_info *devip; - u8 *cmd = scp->cmnd; int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *); int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *) = NULL; @@ -7068,10 +7162,15 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, u16 sa; u8 opcode = cmd[0]; bool has_wlun_rl; + bool inject_now; scsi_set_resid(scp, 0); - if (sdebug_statistics) + if (sdebug_statistics) { atomic_inc(&sdebug_cmnd_count); + inject_now = inject_on_this_cmd(); + } else { + inject_now = false; + } if (unlikely(sdebug_verbose && !(SDEBUG_OPT_NO_CDB_NOISE & sdebug_opts))) { char b[120]; @@ -7089,7 +7188,7 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, sdev_printk(KERN_INFO, sdp, "%s: tag=%#x, cmd %s\n", my_name, blk_mq_unique_tag(scp->request), b); } - if (fake_host_busy(scp)) + if (unlikely(inject_now && (sdebug_opts & SDEBUG_OPT_HOST_BUSY))) return SCSI_MLQUEUE_HOST_BUSY; has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS); if (unlikely((sdp->lun >= sdebug_max_luns) && !has_wlun_rl)) @@ -7103,6 +7202,9 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, if (NULL == devip) goto err_out; } + if (unlikely(inject_now && !atomic_read(&sdeb_inject_pending))) + atomic_set(&sdeb_inject_pending, 1); + na = oip->num_attached; r_pfp = oip->pfp; if (na) { /* multiple commands with this opcode */ @@ -7167,14 +7269,11 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, if (errsts) goto check_cond; } - if (unlikely((F_M_ACCESS & flags) && atomic_read(&devip->stopped))) { - mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); - if (sdebug_verbose) - sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: " - "%s\n", my_name, "initializing command " - "required"); - errsts = check_condition_result; - goto fini; + if (unlikely(((F_M_ACCESS & flags) || scp->cmnd[0] == TEST_UNIT_READY) && + atomic_read(&devip->stopped))) { + errsts = resp_not_ready(scp, devip); + if (errsts) + goto fini; } if (sdebug_fake_rw && (F_FAKE_RW & flags)) goto fini; @@ -7248,7 +7347,10 @@ static int sdebug_driver_probe(struct device *dev) sdbg_host = to_sdebug_host(dev); - sdebug_driver_template.can_queue = sdebug_max_queue; + if (sdebug_host_max_queue) + sdebug_driver_template.can_queue = sdebug_host_max_queue; + else + sdebug_driver_template.can_queue = sdebug_max_queue; if (!sdebug_clustering) sdebug_driver_template.dma_boundary = PAGE_SIZE - 1; @@ -7263,9 +7365,13 @@ static int sdebug_driver_probe(struct device *dev) my_name, submit_queues, nr_cpu_ids); submit_queues = nr_cpu_ids; } - /* Decide whether to tell scsi subsystem that we want mq */ - /* Following should give the same answer for each host */ - hpnt->nr_hw_queues = submit_queues; + /* + * Decide whether to tell scsi subsystem that we want mq. The + * following should give the same answer for each host. If the host + * has a limit of hostwide max commands, then do not set. + */ + if (!sdebug_host_max_queue) + hpnt->nr_hw_queues = submit_queues; sdbg_host->shost = hpnt; *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index c866a4f338716890cc17f82f09c6097573447558..7c6dd6f751907bf961334d7fae0f4d41d5e7bdad 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -52,7 +52,6 @@ #define SCSI_INLINE_SG_CNT 2 #endif -static struct kmem_cache *scsi_sdb_cache; static struct kmem_cache *scsi_sense_cache; static struct kmem_cache *scsi_sense_isadma_cache; static DEFINE_MUTEX(scsi_sense_cache_mutex); @@ -390,7 +389,7 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev) spin_unlock_irqrestore(shost->host_lock, flags); scsi_kick_queue(sdev->request_queue); spin_lock_irqsave(shost->host_lock, flags); - + scsi_device_put(sdev); } out: @@ -1461,18 +1460,18 @@ static void scsi_softirq_done(struct request *rq) scsi_log_completion(cmd, disposition); switch (disposition) { - case SUCCESS: - scsi_finish_command(cmd); - break; - case NEEDS_RETRY: - scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY); - break; - case ADD_TO_MLQUEUE: - scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); - break; - default: - scsi_eh_scmd_add(cmd); - break; + case SUCCESS: + scsi_finish_command(cmd); + break; + case NEEDS_RETRY: + scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY); + break; + case ADD_TO_MLQUEUE: + scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); + break; + default: + scsi_eh_scmd_add(cmd); + break; } } @@ -1953,24 +1952,10 @@ void scsi_unblock_requests(struct Scsi_Host *shost) } EXPORT_SYMBOL(scsi_unblock_requests); -int __init scsi_init_queue(void) -{ - scsi_sdb_cache = kmem_cache_create("scsi_data_buffer", - sizeof(struct scsi_data_buffer), - 0, 0, NULL); - if (!scsi_sdb_cache) { - printk(KERN_ERR "SCSI: can't init scsi sdb cache\n"); - return -ENOMEM; - } - - return 0; -} - void scsi_exit_queue(void) { kmem_cache_destroy(scsi_sense_cache); kmem_cache_destroy(scsi_sense_isadma_cache); - kmem_cache_destroy(scsi_sdb_cache); } /** @@ -2037,7 +2022,6 @@ scsi_mode_select(struct scsi_device *sdev, int pf, int sp, int modepage, real_buffer[1] = data->medium_type; real_buffer[2] = data->device_specific; real_buffer[3] = data->block_descriptor_length; - cmd[0] = MODE_SELECT; cmd[4] = len; @@ -2123,7 +2107,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, if (scsi_sense_valid(sshdr)) { if ((sshdr->sense_key == ILLEGAL_REQUEST) && (sshdr->asc == 0x20) && (sshdr->ascq == 0)) { - /* + /* * Invalid command operation code */ sdev->use_10_for_ms = 0; @@ -2132,7 +2116,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, } } - if(scsi_status_is_good(result)) { + if (scsi_status_is_good(result)) { if (unlikely(buffer[0] == 0x86 && buffer[1] == 0x0b && (modepage == 6 || modepage == 8))) { /* Initio breakage? */ @@ -2142,7 +2126,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, data->device_specific = 0; data->longlba = 0; data->block_descriptor_length = 0; - } else if(use_10_for_ms) { + } else if (use_10_for_ms) { data->length = buffer[0]*256 + buffer[1] + 2; data->medium_type = buffer[2]; data->device_specific = buffer[3]; @@ -2225,7 +2209,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) goto illegal; } break; - + case SDEV_RUNNING: switch (oldstate) { case SDEV_CREATED: @@ -2510,7 +2494,7 @@ EXPORT_SYMBOL_GPL(sdev_evt_send_simple); * (which must be a legal transition). When the device is in this * state, only special requests will be accepted, all others will * be deferred. Since special requests may also be requeued requests, - * a successful return doesn't guarantee the device will be + * a successful return doesn't guarantee the device will be * totally quiescent. * * Must be called with user context, may sleep. @@ -2636,10 +2620,10 @@ int scsi_internal_device_block_nowait(struct scsi_device *sdev) return err; } - /* + /* * The device has transitioned to SDEV_BLOCK. Stop the * block layer from calling the midlayer with this device's - * request queue. + * request queue. */ blk_mq_quiesce_queue_nowait(q); return 0; @@ -2674,7 +2658,7 @@ static int scsi_internal_device_block(struct scsi_device *sdev) return err; } - + void scsi_start_queue(struct scsi_device *sdev) { struct request_queue *q = sdev->request_queue; @@ -2833,8 +2817,10 @@ scsi_host_block(struct Scsi_Host *shost) mutex_lock(&sdev->state_mutex); ret = scsi_internal_device_block_nowait(sdev); mutex_unlock(&sdev->state_mutex); - if (ret) + if (ret) { + scsi_device_put(sdev); break; + } } /* diff --git a/drivers/scsi/scsi_logging.c b/drivers/scsi/scsi_logging.c index c91fa3feb9300ecfe93864f2dc6718266c91a185..8ea44c6595efa7ce7f9bc7560b7351832668a573 100644 --- a/drivers/scsi/scsi_logging.c +++ b/drivers/scsi/scsi_logging.c @@ -205,13 +205,9 @@ void scsi_print_command(struct scsi_cmnd *cmd) /* Print opcode in one line and use separate lines for CDB */ off += scnprintf(logbuf + off, logbuf_len - off, "\n"); dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s", logbuf); - scsi_log_release_buffer(logbuf); for (k = 0; k < cmd->cmd_len; k += 16) { size_t linelen = min(cmd->cmd_len - k, 16); - logbuf = scsi_log_reserve_buffer(&logbuf_len); - if (!logbuf) - break; off = sdev_format_header(logbuf, logbuf_len, scmd_name(cmd), cmd->request->tag); @@ -224,9 +220,8 @@ void scsi_print_command(struct scsi_cmnd *cmd) } dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s", logbuf); - scsi_log_release_buffer(logbuf); } - return; + goto out; } if (!WARN_ON(off > logbuf_len - 49)) { off += scnprintf(logbuf + off, logbuf_len - off, " "); @@ -236,6 +231,7 @@ void scsi_print_command(struct scsi_cmnd *cmd) } out_printk: dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s", logbuf); +out: scsi_log_release_buffer(logbuf); } EXPORT_SYMBOL(scsi_print_command); diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index 5f0ad8b32e3af5900b571ae3ffa828f5e85eb6fb..3717eea37ecb386fd772e6dd90182b3674d41ceb 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c @@ -80,10 +80,6 @@ static int scsi_dev_type_resume(struct device *dev, dev_dbg(dev, "scsi resume: %d\n", err); if (err == 0) { - bool was_runtime_suspended; - - was_runtime_suspended = pm_runtime_suspended(dev); - pm_runtime_disable(dev); err = pm_runtime_set_active(dev); pm_runtime_enable(dev); @@ -97,10 +93,8 @@ static int scsi_dev_type_resume(struct device *dev, */ if (!err && scsi_is_sdev_device(dev)) { struct scsi_device *sdev = to_scsi_device(dev); - if (was_runtime_suspended) - blk_post_runtime_resume(sdev->request_queue, 0); - else - blk_set_runtime_active(sdev->request_queue); + + blk_set_runtime_active(sdev->request_queue); } } diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 22b6585e28b431e46b4b00c2ac2bb5b541e1a494..d12ada03596136a08a7ef07f1bfe646bf80c39fc 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -93,7 +93,6 @@ extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev); extern void scsi_start_queue(struct scsi_device *sdev); extern int scsi_mq_setup_tags(struct Scsi_Host *shost); extern void scsi_mq_destroy_tags(struct Scsi_Host *shost); -extern int scsi_init_queue(void); extern void scsi_exit_queue(void); extern void scsi_evt_thread(struct work_struct *work); struct request_queue; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 7ae5024e78243b412dd37b3aee8d86fb1621c001..2eb3e4f9375a57fd35008564f12ad55423a9b05f 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1623,7 +1623,6 @@ static DEFINE_MUTEX(rx_queue_mutex); static DEFINE_MUTEX(conn_mutex); static LIST_HEAD(sesslist); -static LIST_HEAD(sessdestroylist); static DEFINE_SPINLOCK(sesslock); static LIST_HEAD(connlist); static LIST_HEAD(connlist_err); @@ -1978,10 +1977,11 @@ void iscsi_unblock_session(struct iscsi_cls_session *session) { queue_work(iscsi_eh_timer_workq, &session->unblock_work); /* - * make sure all the events have completed before tell the driver - * it is safe + * Blocking the session can be done from any context so we only + * queue the block work. Make sure the unblock work has completed + * because it flushes/cancels the other works and updates the state. */ - flush_workqueue(iscsi_eh_timer_workq); + flush_work(&session->unblock_work); } EXPORT_SYMBOL_GPL(iscsi_unblock_session); @@ -2036,11 +2036,11 @@ static void __iscsi_unbind_session(struct work_struct *work) spin_unlock_irqrestore(&session->lock, flags); mutex_unlock(&ihost->mutex); + scsi_remove_target(&session->dev); + if (session->ida_used) ida_simple_remove(&iscsi_sess_ida, target_id); - scsi_remove_target(&session->dev); - unbind_session_exit: iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION); ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n"); @@ -2202,14 +2202,13 @@ void iscsi_remove_session(struct iscsi_cls_session *session) ISCSI_DBG_TRANS_SESSION(session, "Removing session\n"); spin_lock_irqsave(&sesslock, flags); - list_del(&session->sess_list); + if (!list_empty(&session->sess_list)) + list_del(&session->sess_list); spin_unlock_irqrestore(&sesslock, flags); - /* make sure there are no blocks/unblocks queued */ - flush_workqueue(iscsi_eh_timer_workq); - /* make sure the timedout callout is not running */ - if (!cancel_delayed_work(&session->recovery_work)) - flush_workqueue(iscsi_eh_timer_workq); + flush_work(&session->block_work); + flush_work(&session->unblock_work); + cancel_delayed_work_sync(&session->recovery_work); /* * If we are blocked let commands flow again. The lld or iscsi * layer should set up the queuecommand to fail commands. @@ -3291,7 +3290,7 @@ static int iscsi_set_flashnode_param(struct iscsi_transport *transport, pr_err("%s could not find host no %u\n", __func__, ev->u.set_flashnode.host_no); err = -ENODEV; - goto put_host; + goto exit_set_fnode; } idx = ev->u.set_flashnode.flashnode_idx; @@ -3679,7 +3678,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) /* Prevent this session from being found again */ spin_lock_irqsave(&sesslock, flags); - list_move(&session->sess_list, &sessdestroylist); + list_del_init(&session->sess_list); spin_unlock_irqrestore(&sesslock, flags); queue_work(iscsi_destroy_workq, &session->destroy_work); @@ -4766,7 +4765,9 @@ static __init int iscsi_transport_init(void) goto release_nls; } - iscsi_destroy_workq = create_singlethread_workqueue("iscsi_destroy"); + iscsi_destroy_workq = alloc_workqueue("%s", + WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND, + 1, "iscsi_destroy"); if (!iscsi_destroy_workq) { err = -ENOMEM; goto destroy_wq; diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 182fd25c7c43fa286d757b8128b33a60abce3cfe..e443dee43bcf1ab649c092e0406c4506484435a4 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -563,7 +563,7 @@ show_sas_phy_enable(struct device *dev, struct device_attribute *attr, { struct sas_phy *phy = transport_class_to_phy(dev); - return snprintf(buf, 20, "%d", phy->enabled); + return snprintf(buf, 20, "%d\n", phy->enabled); } static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable, diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index d4d1104fac991c3a90ea7ec96a21c0fd2c1d501d..cba1cf6a1c12dc720277b20e6ecafbc30a3e5677 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -395,6 +395,10 @@ static void srp_reconnect_work(struct work_struct *work) } } +/* + * scsi_target_block() must have been called before this function is + * called to guarantee that no .queuecommand() calls are in progress. + */ static void __rport_fail_io_fast(struct srp_rport *rport) { struct Scsi_Host *shost = rport_to_shost(rport); @@ -404,11 +408,7 @@ static void __rport_fail_io_fast(struct srp_rport *rport) if (srp_rport_set_state(rport, SRP_RPORT_FAIL_FAST)) return; - /* - * Call scsi_target_block() to wait for ongoing shost->queuecommand() - * calls before invoking i->f->terminate_rport_io(). - */ - scsi_target_block(rport->dev.parent); + scsi_target_unblock(rport->dev.parent, SDEV_TRANSPORT_OFFLINE); /* Involve the LLD if possible to terminate all I/O on the rport. */ @@ -570,8 +570,6 @@ int srp_reconnect_rport(struct srp_rport *rport) * failure timers if these had not yet been started. */ __rport_fail_io_fast(rport); - scsi_target_unblock(&shost->shost_gendev, - SDEV_TRANSPORT_OFFLINE); __srp_start_tl_fail_timers(rport); } else if (rport->state != SRP_RPORT_BLOCKED) { scsi_target_unblock(&shost->shost_gendev, diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index d90fefffe31b743dcb2101797a7093f0df45900a..acde0ca357695f5ed417d13599018f084b88a925 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1479,7 +1479,7 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) * @bdev: target block device * @mode: FMODE_* mask * @cmd: ioctl command number - * @arg: this is third argument given to ioctl(2) system call. + * @p: this is third argument given to ioctl(2) system call. * Often contains a pointer. * * Returns 0 if successful (some ioctls return positive numbers on diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 3a74f4b45134f59303c27185632025ebadd97486..27c0f4e9b1d4a5f8cc28a6cf673e6a4d5773ee12 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -229,17 +229,11 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba, #else /* CONFIG_BLK_DEV_ZONED */ -static inline int sd_zbc_init(void) -{ - return 0; -} - static inline int sd_zbc_init_disk(struct scsi_disk *sdkp) { return 0; } -static inline void sd_zbc_exit(void) {} static inline void sd_zbc_release_disk(struct scsi_disk *sdkp) {} static inline int sd_zbc_read_zones(struct scsi_disk *sdkp, diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index d8b2c49d645b293c3cb112b4a46d820c82077b20..4717e79bff5571f976532f21f6cd242fac6cc7cd 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -585,7 +585,7 @@ static int sd_zbc_check_zoned_characteristics(struct scsi_disk *sdkp, * sd_zbc_check_capacity - Check the device capacity * @sdkp: Target disk * @buf: command buffer - * @zblock: zone size in number of blocks + * @zblocks: zone size in number of blocks * * Get the device zone size and check that the device capacity as reported * by READ CAPACITY matches the max_lba value (plus one) of the report zones @@ -742,7 +742,6 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf) max_append = min_t(u32, logical_to_sectors(sdkp->device, zone_blocks), q->limits.max_segments << (PAGE_SHIFT - 9)); - max_append = min_t(u32, max_append, queue_max_hw_sectors(q)); blk_queue_max_zone_append_sectors(q, max_append); diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 624467e2590ab0f2dd9507c2c6c5aa03d32e93d4..8f5f5dc863a4a082c2ab98cd59aed9c20ab98798 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1038,7 +1038,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, do_work = true; process_err_fn = storvsc_device_scan; /* - * Retry the I/O that trigerred this. + * Retry the I/O that triggered this. */ set_host_byte(scmnd, DID_REQUEUE); } @@ -1105,6 +1105,10 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, data_transfer_length = 0; } + /* Validate data_transfer_length (from Hyper-V) */ + if (data_transfer_length > cmd_request->payload->range.len) + data_transfer_length = cmd_request->payload->range.len; + scsi_set_resid(scmnd, cmd_request->payload->range.len - data_transfer_length); @@ -1145,6 +1149,11 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device, /* Copy over the status...etc */ stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status; stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status; + + /* Validate sense_info_length (from Hyper-V) */ + if (vstor_packet->vm_srb.sense_info_length > sense_buffer_size) + vstor_packet->vm_srb.sense_info_length = sense_buffer_size; + stor_pkt->vm_srb.sense_info_length = vstor_packet->vm_srb.sense_info_length; @@ -1570,6 +1579,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) request = &stor_device->reset_request; vstor_packet = &request->vstor_packet; + memset(vstor_packet, 0, sizeof(struct vstor_packet)); init_completion(&request->wait_event); @@ -1673,6 +1683,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) /* Setup the cmd request */ cmd_request->cmd = scmnd; + memset(&cmd_request->vstor_packet, 0, sizeof(struct vstor_packet)); vm_srb = &cmd_request->vstor_packet.vm_srb; vm_srb->win8_extension.time_out_value = 60; diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 2ca018ce796f74446488e0e5965d07faf5e6c3d7..af20ad963b05d401a652c7a715674cf3008a14f3 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1774,6 +1774,7 @@ static pci_ers_result_t sym2_io_slot_dump(struct pci_dev *pdev) /** * sym2_reset_workarounds - hardware-specific work-arounds + * @pdev: pointer to PCI device * * This routine is similar to sym_set_workarounds(), except * that, at this point, we already know that the device was diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index a428cae4535b7086979916a9bb293f7359a04669..8410117d5aa4413285c8d47fe9584a66127144eb 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -5352,8 +5352,10 @@ void sym_complete_error(struct sym_hcb *np, struct sym_ccb *cp) { struct scsi_device *sdev; struct scsi_cmnd *cmd; +#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING struct sym_tcb *tp; struct sym_lcb *lp; +#endif int resid; int i; @@ -5370,11 +5372,13 @@ void sym_complete_error(struct sym_hcb *np, struct sym_ccb *cp) cp->host_status, cp->ssss_status, cp->host_flags); } +#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING /* * Get target and lun pointers. */ tp = &np->target[cp->target]; lp = sym_lp(tp, sdev->lun); +#endif /* * Check for extended errors. @@ -5481,8 +5485,10 @@ finish: */ void sym_complete_ok (struct sym_hcb *np, struct sym_ccb *cp) { +#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING struct sym_tcb *tp; struct sym_lcb *lp; +#endif struct scsi_cmnd *cmd; int resid; @@ -5498,11 +5504,13 @@ void sym_complete_ok (struct sym_hcb *np, struct sym_ccb *cp) */ cmd = cp->cmd; +#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING /* * Get target and lun pointers. */ tp = &np->target[cp->target]; lp = sym_lp(tp, cp->lun); +#endif /* * If all data have been transferred, given than no diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index 4c0a9661049a71d15481d9a3fee845f3e7e16436..f6394999b98c0e467528842a23571caae0b391d0 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -99,6 +99,7 @@ config SCSI_UFS_DWC_TC_PLATFORM config SCSI_UFS_QCOM tristate "QCOM specific hooks to UFS controller platform driver" depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM + select QCOM_SCM select RESET_CONTROLLER help This selects the QCOM specific additions to UFSHCD platform driver. @@ -161,6 +162,18 @@ config SCSI_UFS_BSG Select this if you need a bsg device node for your UFS controller. If unsure, say N. +config SCSI_UFS_EXYNOS + tristate "EXYNOS specific hooks to UFS controller platform driver" + depends on SCSI_UFSHCD_PLATFORM && (ARCH_EXYNOS || COMPILE_TEST) + select PHY_SAMSUNG_UFS + help + This selects the EXYNOS specific additions to UFSHCD platform driver. + UFS host on EXYNOS includes HCI and UNIPRO layer, and associates with + UFS-PHY driver. + + Select this if you have UFS host controller on EXYNOS chipset. + If unsure, say N. + config SCSI_UFS_CRYPTO bool "UFS Crypto Engine Support" depends on SCSI_UFSHCD && BLK_INLINE_ENCRYPTION diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 197e178f44bce3441d28b10d9181affb34f6e121..4679af1b564ebb49b6d5e074e52b71c43f3b9f42 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -3,7 +3,10 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_CDNS_PLATFORM) += cdns-pltfrm.o -obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o +obj-$(CONFIG_SCSI_UFS_QCOM) += ufs_qcom.o +ufs_qcom-y += ufs-qcom.o +ufs_qcom-$(CONFIG_SCSI_UFS_CRYPTO) += ufs-qcom-ice.o +obj-$(CONFIG_SCSI_UFS_EXYNOS) += ufs-exynos.o obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o ufshcd-core-y += ufshcd.o ufs-sysfs.o ufshcd-core-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c new file mode 100644 index 0000000000000000000000000000000000000000..8f1b6f61a77637f8813ae0add5100b2f7cdfd7b3 --- /dev/null +++ b/drivers/scsi/ufs/ufs-exynos.c @@ -0,0 +1,1297 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * UFS Host Controller driver for Exynos specific extensions + * + * Copyright (C) 2014-2015 Samsung Electronics Co., Ltd. + * Author: Seungwon Jeon + * Author: Alim Akhtar + * + */ + +#include +#include +#include +#include +#include +#include + +#include "ufshcd.h" +#include "ufshcd-pltfrm.h" +#include "ufshci.h" +#include "unipro.h" + +#include "ufs-exynos.h" + +/* + * Exynos's Vendor specific registers for UFSHCI + */ +#define HCI_TXPRDT_ENTRY_SIZE 0x00 +#define PRDT_PREFECT_EN BIT(31) +#define PRDT_SET_SIZE(x) ((x) & 0x1F) +#define HCI_RXPRDT_ENTRY_SIZE 0x04 +#define HCI_1US_TO_CNT_VAL 0x0C +#define CNT_VAL_1US_MASK 0x3FF +#define HCI_UTRL_NEXUS_TYPE 0x40 +#define HCI_UTMRL_NEXUS_TYPE 0x44 +#define HCI_SW_RST 0x50 +#define UFS_LINK_SW_RST BIT(0) +#define UFS_UNIPRO_SW_RST BIT(1) +#define UFS_SW_RST_MASK (UFS_UNIPRO_SW_RST | UFS_LINK_SW_RST) +#define HCI_DATA_REORDER 0x60 +#define HCI_UNIPRO_APB_CLK_CTRL 0x68 +#define UNIPRO_APB_CLK(v, x) (((v) & ~0xF) | ((x) & 0xF)) +#define HCI_AXIDMA_RWDATA_BURST_LEN 0x6C +#define HCI_GPIO_OUT 0x70 +#define HCI_ERR_EN_PA_LAYER 0x78 +#define HCI_ERR_EN_DL_LAYER 0x7C +#define HCI_ERR_EN_N_LAYER 0x80 +#define HCI_ERR_EN_T_LAYER 0x84 +#define HCI_ERR_EN_DME_LAYER 0x88 +#define HCI_CLKSTOP_CTRL 0xB0 +#define REFCLK_STOP BIT(2) +#define UNIPRO_MCLK_STOP BIT(1) +#define UNIPRO_PCLK_STOP BIT(0) +#define CLK_STOP_MASK (REFCLK_STOP |\ + UNIPRO_MCLK_STOP |\ + UNIPRO_PCLK_STOP) +#define HCI_MISC 0xB4 +#define REFCLK_CTRL_EN BIT(7) +#define UNIPRO_PCLK_CTRL_EN BIT(6) +#define UNIPRO_MCLK_CTRL_EN BIT(5) +#define HCI_CORECLK_CTRL_EN BIT(4) +#define CLK_CTRL_EN_MASK (REFCLK_CTRL_EN |\ + UNIPRO_PCLK_CTRL_EN |\ + UNIPRO_MCLK_CTRL_EN) +/* Device fatal error */ +#define DFES_ERR_EN BIT(31) +#define DFES_DEF_L2_ERRS (UIC_DATA_LINK_LAYER_ERROR_RX_BUF_OF |\ + UIC_DATA_LINK_LAYER_ERROR_PA_INIT) +#define DFES_DEF_L3_ERRS (UIC_NETWORK_UNSUPPORTED_HEADER_TYPE |\ + UIC_NETWORK_BAD_DEVICEID_ENC |\ + UIC_NETWORK_LHDR_TRAP_PACKET_DROPPING) +#define DFES_DEF_L4_ERRS (UIC_TRANSPORT_UNSUPPORTED_HEADER_TYPE |\ + UIC_TRANSPORT_UNKNOWN_CPORTID |\ + UIC_TRANSPORT_NO_CONNECTION_RX |\ + UIC_TRANSPORT_BAD_TC) + +enum { + UNIPRO_L1_5 = 0,/* PHY Adapter */ + UNIPRO_L2, /* Data Link */ + UNIPRO_L3, /* Network */ + UNIPRO_L4, /* Transport */ + UNIPRO_DME, /* DME */ +}; + +/* + * UNIPRO registers + */ +#define UNIPRO_COMP_VERSION 0x000 +#define UNIPRO_DME_PWR_REQ 0x090 +#define UNIPRO_DME_PWR_REQ_POWERMODE 0x094 +#define UNIPRO_DME_PWR_REQ_LOCALL2TIMER0 0x098 +#define UNIPRO_DME_PWR_REQ_LOCALL2TIMER1 0x09C +#define UNIPRO_DME_PWR_REQ_LOCALL2TIMER2 0x0A0 +#define UNIPRO_DME_PWR_REQ_REMOTEL2TIMER0 0x0A4 +#define UNIPRO_DME_PWR_REQ_REMOTEL2TIMER1 0x0A8 +#define UNIPRO_DME_PWR_REQ_REMOTEL2TIMER2 0x0AC + +/* + * UFS Protector registers + */ +#define UFSPRSECURITY 0x010 +#define NSSMU BIT(14) +#define UFSPSBEGIN0 0x200 +#define UFSPSEND0 0x204 +#define UFSPSLUN0 0x208 +#define UFSPSCTRL0 0x20C + +#define CNTR_DIV_VAL 40 + +static void exynos_ufs_auto_ctrl_hcc(struct exynos_ufs *ufs, bool en); +static void exynos_ufs_ctrl_clkstop(struct exynos_ufs *ufs, bool en); + +static inline void exynos_ufs_enable_auto_ctrl_hcc(struct exynos_ufs *ufs) +{ + exynos_ufs_auto_ctrl_hcc(ufs, true); +} + +static inline void exynos_ufs_disable_auto_ctrl_hcc(struct exynos_ufs *ufs) +{ + exynos_ufs_auto_ctrl_hcc(ufs, false); +} + +static inline void exynos_ufs_disable_auto_ctrl_hcc_save( + struct exynos_ufs *ufs, u32 *val) +{ + *val = hci_readl(ufs, HCI_MISC); + exynos_ufs_auto_ctrl_hcc(ufs, false); +} + +static inline void exynos_ufs_auto_ctrl_hcc_restore( + struct exynos_ufs *ufs, u32 *val) +{ + hci_writel(ufs, *val, HCI_MISC); +} + +static inline void exynos_ufs_gate_clks(struct exynos_ufs *ufs) +{ + exynos_ufs_ctrl_clkstop(ufs, true); +} + +static inline void exynos_ufs_ungate_clks(struct exynos_ufs *ufs) +{ + exynos_ufs_ctrl_clkstop(ufs, false); +} + +static int exynos7_ufs_drv_init(struct device *dev, struct exynos_ufs *ufs) +{ + return 0; +} + +static int exynos7_ufs_pre_link(struct exynos_ufs *ufs) +{ + struct ufs_hba *hba = ufs->hba; + u32 val = ufs->drv_data->uic_attr->pa_dbg_option_suite; + int i; + + exynos_ufs_enable_ov_tm(hba); + for_each_ufs_tx_lane(ufs, i) + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x297, i), 0x17); + for_each_ufs_rx_lane(ufs, i) { + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x362, i), 0xff); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x363, i), 0x00); + } + exynos_ufs_disable_ov_tm(hba); + + for_each_ufs_tx_lane(ufs, i) + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(TX_HIBERN8_CONTROL, i), 0x0); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_TXPHY_CFGUPDT), 0x1); + udelay(1); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OPTION_SUITE), val | (1 << 12)); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_SKIP_RESET_PHY), 0x1); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_SKIP_LINE_RESET), 0x1); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_LINE_RESET_REQ), 0x1); + udelay(1600); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OPTION_SUITE), val); + + return 0; +} + +static int exynos7_ufs_post_link(struct exynos_ufs *ufs) +{ + struct ufs_hba *hba = ufs->hba; + int i; + + exynos_ufs_enable_ov_tm(hba); + for_each_ufs_tx_lane(ufs, i) { + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x28b, i), 0x83); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x29a, i), 0x07); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x277, i), + TX_LINERESET_N(exynos_ufs_calc_time_cntr(ufs, 200000))); + } + exynos_ufs_disable_ov_tm(hba); + + exynos_ufs_enable_dbg_mode(hba); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_SAVECONFIGTIME), 0xbb8); + exynos_ufs_disable_dbg_mode(hba); + + return 0; +} + +static int exynos7_ufs_pre_pwr_change(struct exynos_ufs *ufs, + struct ufs_pa_layer_attr *pwr) +{ + unipro_writel(ufs, 0x22, UNIPRO_DBG_FORCE_DME_CTRL_STATE); + + return 0; +} + +static int exynos7_ufs_post_pwr_change(struct exynos_ufs *ufs, + struct ufs_pa_layer_attr *pwr) +{ + struct ufs_hba *hba = ufs->hba; + int lanes = max_t(u32, pwr->lane_rx, pwr->lane_tx); + + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_RXPHY_CFGUPDT), 0x1); + + if (lanes == 1) { + exynos_ufs_enable_dbg_mode(hba); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), 0x1); + exynos_ufs_disable_dbg_mode(hba); + } + + return 0; +} + +/* + * exynos_ufs_auto_ctrl_hcc - HCI core clock control by h/w + * Control should be disabled in the below cases + * - Before host controller S/W reset + * - Access to UFS protector's register + */ +static void exynos_ufs_auto_ctrl_hcc(struct exynos_ufs *ufs, bool en) +{ + u32 misc = hci_readl(ufs, HCI_MISC); + + if (en) + hci_writel(ufs, misc | HCI_CORECLK_CTRL_EN, HCI_MISC); + else + hci_writel(ufs, misc & ~HCI_CORECLK_CTRL_EN, HCI_MISC); +} + +static void exynos_ufs_ctrl_clkstop(struct exynos_ufs *ufs, bool en) +{ + u32 ctrl = hci_readl(ufs, HCI_CLKSTOP_CTRL); + u32 misc = hci_readl(ufs, HCI_MISC); + + if (en) { + hci_writel(ufs, misc | CLK_CTRL_EN_MASK, HCI_MISC); + hci_writel(ufs, ctrl | CLK_STOP_MASK, HCI_CLKSTOP_CTRL); + } else { + hci_writel(ufs, ctrl & ~CLK_STOP_MASK, HCI_CLKSTOP_CTRL); + hci_writel(ufs, misc & ~CLK_CTRL_EN_MASK, HCI_MISC); + } +} + +static int exynos_ufs_get_clk_info(struct exynos_ufs *ufs) +{ + struct ufs_hba *hba = ufs->hba; + struct list_head *head = &hba->clk_list_head; + struct ufs_clk_info *clki; + u32 pclk_rate; + u32 f_min, f_max; + u8 div = 0; + int ret = 0; + + if (list_empty(head)) + goto out; + + list_for_each_entry(clki, head, list) { + if (!IS_ERR(clki->clk)) { + if (!strcmp(clki->name, "core_clk")) + ufs->clk_hci_core = clki->clk; + else if (!strcmp(clki->name, "sclk_unipro_main")) + ufs->clk_unipro_main = clki->clk; + } + } + + if (!ufs->clk_hci_core || !ufs->clk_unipro_main) { + dev_err(hba->dev, "failed to get clk info\n"); + ret = -EINVAL; + goto out; + } + + ufs->mclk_rate = clk_get_rate(ufs->clk_unipro_main); + pclk_rate = clk_get_rate(ufs->clk_hci_core); + f_min = ufs->pclk_avail_min; + f_max = ufs->pclk_avail_max; + + if (ufs->opts & EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL) { + do { + pclk_rate /= (div + 1); + + if (pclk_rate <= f_max) + break; + div++; + } while (pclk_rate >= f_min); + } + + if (unlikely(pclk_rate < f_min || pclk_rate > f_max)) { + dev_err(hba->dev, "not available pclk range %d\n", pclk_rate); + ret = -EINVAL; + goto out; + } + + ufs->pclk_rate = pclk_rate; + ufs->pclk_div = div; + +out: + return ret; +} + +static void exynos_ufs_set_unipro_pclk_div(struct exynos_ufs *ufs) +{ + if (ufs->opts & EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL) { + u32 val; + + val = hci_readl(ufs, HCI_UNIPRO_APB_CLK_CTRL); + hci_writel(ufs, UNIPRO_APB_CLK(val, ufs->pclk_div), + HCI_UNIPRO_APB_CLK_CTRL); + } +} + +static void exynos_ufs_set_pwm_clk_div(struct exynos_ufs *ufs) +{ + struct ufs_hba *hba = ufs->hba; + struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; + + ufshcd_dme_set(hba, + UIC_ARG_MIB(CMN_PWM_CLK_CTRL), attr->cmn_pwm_clk_ctrl); +} + +static void exynos_ufs_calc_pwm_clk_div(struct exynos_ufs *ufs) +{ + struct ufs_hba *hba = ufs->hba; + struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; + const unsigned int div = 30, mult = 20; + const unsigned long pwm_min = 3 * 1000 * 1000; + const unsigned long pwm_max = 9 * 1000 * 1000; + const int divs[] = {32, 16, 8, 4}; + unsigned long clk = 0, _clk, clk_period; + int i = 0, clk_idx = -1; + + clk_period = UNIPRO_PCLK_PERIOD(ufs); + for (i = 0; i < ARRAY_SIZE(divs); i++) { + _clk = NSEC_PER_SEC * mult / (clk_period * divs[i] * div); + if (_clk >= pwm_min && _clk <= pwm_max) { + if (_clk > clk) { + clk_idx = i; + clk = _clk; + } + } + } + + if (clk_idx == -1) { + ufshcd_dme_get(hba, UIC_ARG_MIB(CMN_PWM_CLK_CTRL), &clk_idx); + dev_err(hba->dev, + "failed to decide pwm clock divider, will not change\n"); + } + + attr->cmn_pwm_clk_ctrl = clk_idx & PWM_CLK_CTRL_MASK; +} + +long exynos_ufs_calc_time_cntr(struct exynos_ufs *ufs, long period) +{ + const int precise = 10; + long pclk_rate = ufs->pclk_rate; + long clk_period, fraction; + + clk_period = UNIPRO_PCLK_PERIOD(ufs); + fraction = ((NSEC_PER_SEC % pclk_rate) * precise) / pclk_rate; + + return (period * precise) / ((clk_period * precise) + fraction); +} + +static void exynos_ufs_specify_phy_time_attr(struct exynos_ufs *ufs) +{ + struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; + struct ufs_phy_time_cfg *t_cfg = &ufs->t_cfg; + + t_cfg->tx_linereset_p = + exynos_ufs_calc_time_cntr(ufs, attr->tx_dif_p_nsec); + t_cfg->tx_linereset_n = + exynos_ufs_calc_time_cntr(ufs, attr->tx_dif_n_nsec); + t_cfg->tx_high_z_cnt = + exynos_ufs_calc_time_cntr(ufs, attr->tx_high_z_cnt_nsec); + t_cfg->tx_base_n_val = + exynos_ufs_calc_time_cntr(ufs, attr->tx_base_unit_nsec); + t_cfg->tx_gran_n_val = + exynos_ufs_calc_time_cntr(ufs, attr->tx_gran_unit_nsec); + t_cfg->tx_sleep_cnt = + exynos_ufs_calc_time_cntr(ufs, attr->tx_sleep_cnt); + + t_cfg->rx_linereset = + exynos_ufs_calc_time_cntr(ufs, attr->rx_dif_p_nsec); + t_cfg->rx_hibern8_wait = + exynos_ufs_calc_time_cntr(ufs, attr->rx_hibern8_wait_nsec); + t_cfg->rx_base_n_val = + exynos_ufs_calc_time_cntr(ufs, attr->rx_base_unit_nsec); + t_cfg->rx_gran_n_val = + exynos_ufs_calc_time_cntr(ufs, attr->rx_gran_unit_nsec); + t_cfg->rx_sleep_cnt = + exynos_ufs_calc_time_cntr(ufs, attr->rx_sleep_cnt); + t_cfg->rx_stall_cnt = + exynos_ufs_calc_time_cntr(ufs, attr->rx_stall_cnt); +} + +static void exynos_ufs_config_phy_time_attr(struct exynos_ufs *ufs) +{ + struct ufs_hba *hba = ufs->hba; + struct ufs_phy_time_cfg *t_cfg = &ufs->t_cfg; + int i; + + exynos_ufs_set_pwm_clk_div(ufs); + + exynos_ufs_enable_ov_tm(hba); + + for_each_ufs_rx_lane(ufs, i) { + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_FILLER_ENABLE, i), + ufs->drv_data->uic_attr->rx_filler_enable); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_LINERESET_VAL, i), + RX_LINERESET(t_cfg->rx_linereset)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_BASE_NVAL_07_00, i), + RX_BASE_NVAL_L(t_cfg->rx_base_n_val)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_BASE_NVAL_15_08, i), + RX_BASE_NVAL_H(t_cfg->rx_base_n_val)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_GRAN_NVAL_07_00, i), + RX_GRAN_NVAL_L(t_cfg->rx_gran_n_val)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_GRAN_NVAL_10_08, i), + RX_GRAN_NVAL_H(t_cfg->rx_gran_n_val)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_OV_SLEEP_CNT_TIMER, i), + RX_OV_SLEEP_CNT(t_cfg->rx_sleep_cnt)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_OV_STALL_CNT_TIMER, i), + RX_OV_STALL_CNT(t_cfg->rx_stall_cnt)); + } + + for_each_ufs_tx_lane(ufs, i) { + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_LINERESET_P_VAL, i), + TX_LINERESET_P(t_cfg->tx_linereset_p)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_HIGH_Z_CNT_07_00, i), + TX_HIGH_Z_CNT_L(t_cfg->tx_high_z_cnt)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_HIGH_Z_CNT_11_08, i), + TX_HIGH_Z_CNT_H(t_cfg->tx_high_z_cnt)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_BASE_NVAL_07_00, i), + TX_BASE_NVAL_L(t_cfg->tx_base_n_val)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_BASE_NVAL_15_08, i), + TX_BASE_NVAL_H(t_cfg->tx_base_n_val)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_GRAN_NVAL_07_00, i), + TX_GRAN_NVAL_L(t_cfg->tx_gran_n_val)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_GRAN_NVAL_10_08, i), + TX_GRAN_NVAL_H(t_cfg->tx_gran_n_val)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_OV_SLEEP_CNT_TIMER, i), + TX_OV_H8_ENTER_EN | + TX_OV_SLEEP_CNT(t_cfg->tx_sleep_cnt)); + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_MIN_ACTIVATETIME, i), + ufs->drv_data->uic_attr->tx_min_activatetime); + } + + exynos_ufs_disable_ov_tm(hba); +} + +static void exynos_ufs_config_phy_cap_attr(struct exynos_ufs *ufs) +{ + struct ufs_hba *hba = ufs->hba; + struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; + int i; + + exynos_ufs_enable_ov_tm(hba); + + for_each_ufs_rx_lane(ufs, i) { + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_HS_G1_SYNC_LENGTH_CAP, i), + attr->rx_hs_g1_sync_len_cap); + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_HS_G2_SYNC_LENGTH_CAP, i), + attr->rx_hs_g2_sync_len_cap); + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_HS_G3_SYNC_LENGTH_CAP, i), + attr->rx_hs_g3_sync_len_cap); + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_HS_G1_PREP_LENGTH_CAP, i), + attr->rx_hs_g1_prep_sync_len_cap); + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_HS_G2_PREP_LENGTH_CAP, i), + attr->rx_hs_g2_prep_sync_len_cap); + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_HS_G3_PREP_LENGTH_CAP, i), + attr->rx_hs_g3_prep_sync_len_cap); + } + + if (attr->rx_adv_fine_gran_sup_en == 0) { + for_each_ufs_rx_lane(ufs, i) { + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_ADV_GRANULARITY_CAP, i), 0); + + if (attr->rx_min_actv_time_cap) + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_MIN_ACTIVATETIME_CAP, + i), attr->rx_min_actv_time_cap); + + if (attr->rx_hibern8_time_cap) + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_HIBERN8TIME_CAP, i), + attr->rx_hibern8_time_cap); + } + } else if (attr->rx_adv_fine_gran_sup_en == 1) { + for_each_ufs_rx_lane(ufs, i) { + if (attr->rx_adv_fine_gran_step) + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_ADV_GRANULARITY_CAP, + i), RX_ADV_FINE_GRAN_STEP( + attr->rx_adv_fine_gran_step)); + + if (attr->rx_adv_min_actv_time_cap) + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL( + RX_ADV_MIN_ACTIVATETIME_CAP, i), + attr->rx_adv_min_actv_time_cap); + + if (attr->rx_adv_hibern8_time_cap) + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_ADV_HIBERN8TIME_CAP, + i), + attr->rx_adv_hibern8_time_cap); + } + } + + exynos_ufs_disable_ov_tm(hba); +} + +static void exynos_ufs_establish_connt(struct exynos_ufs *ufs) +{ + struct ufs_hba *hba = ufs->hba; + enum { + DEV_ID = 0x00, + PEER_DEV_ID = 0x01, + PEER_CPORT_ID = 0x00, + TRAFFIC_CLASS = 0x00, + }; + + /* allow cport attributes to be set */ + ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), CPORT_IDLE); + + /* local unipro attributes */ + ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID), DEV_ID); + ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID_VALID), TRUE); + ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERDEVICEID), PEER_DEV_ID); + ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERCPORTID), PEER_CPORT_ID); + ufshcd_dme_set(hba, UIC_ARG_MIB(T_CPORTFLAGS), CPORT_DEF_FLAGS); + ufshcd_dme_set(hba, UIC_ARG_MIB(T_TRAFFICCLASS), TRAFFIC_CLASS); + ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), CPORT_CONNECTED); +} + +static void exynos_ufs_config_smu(struct exynos_ufs *ufs) +{ + u32 reg, val; + + exynos_ufs_disable_auto_ctrl_hcc_save(ufs, &val); + + /* make encryption disabled by default */ + reg = ufsp_readl(ufs, UFSPRSECURITY); + ufsp_writel(ufs, reg | NSSMU, UFSPRSECURITY); + ufsp_writel(ufs, 0x0, UFSPSBEGIN0); + ufsp_writel(ufs, 0xffffffff, UFSPSEND0); + ufsp_writel(ufs, 0xff, UFSPSLUN0); + ufsp_writel(ufs, 0xf1, UFSPSCTRL0); + + exynos_ufs_auto_ctrl_hcc_restore(ufs, &val); +} + +static void exynos_ufs_config_sync_pattern_mask(struct exynos_ufs *ufs, + struct ufs_pa_layer_attr *pwr) +{ + struct ufs_hba *hba = ufs->hba; + u8 g = max_t(u32, pwr->gear_rx, pwr->gear_tx); + u32 mask, sync_len; + enum { + SYNC_LEN_G1 = 80 * 1000, /* 80us */ + SYNC_LEN_G2 = 40 * 1000, /* 44us */ + SYNC_LEN_G3 = 20 * 1000, /* 20us */ + }; + int i; + + if (g == 1) + sync_len = SYNC_LEN_G1; + else if (g == 2) + sync_len = SYNC_LEN_G2; + else if (g == 3) + sync_len = SYNC_LEN_G3; + else + return; + + mask = exynos_ufs_calc_time_cntr(ufs, sync_len); + mask = (mask >> 8) & 0xff; + + exynos_ufs_enable_ov_tm(hba); + + for_each_ufs_rx_lane(ufs, i) + ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(RX_SYNC_MASK_LENGTH, i), mask); + + exynos_ufs_disable_ov_tm(hba); +} + +static int exynos_ufs_pre_pwr_mode(struct ufs_hba *hba, + struct ufs_pa_layer_attr *dev_max_params, + struct ufs_pa_layer_attr *dev_req_params) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + struct phy *generic_phy = ufs->phy; + struct ufs_dev_params ufs_exynos_cap; + int ret; + + if (!dev_req_params) { + pr_err("%s: incoming dev_req_params is NULL\n", __func__); + ret = -EINVAL; + goto out; + } + + + ufs_exynos_cap.tx_lanes = UFS_EXYNOS_LIMIT_NUM_LANES_TX; + ufs_exynos_cap.rx_lanes = UFS_EXYNOS_LIMIT_NUM_LANES_RX; + ufs_exynos_cap.hs_rx_gear = UFS_EXYNOS_LIMIT_HSGEAR_RX; + ufs_exynos_cap.hs_tx_gear = UFS_EXYNOS_LIMIT_HSGEAR_TX; + ufs_exynos_cap.pwm_rx_gear = UFS_EXYNOS_LIMIT_PWMGEAR_RX; + ufs_exynos_cap.pwm_tx_gear = UFS_EXYNOS_LIMIT_PWMGEAR_TX; + ufs_exynos_cap.rx_pwr_pwm = UFS_EXYNOS_LIMIT_RX_PWR_PWM; + ufs_exynos_cap.tx_pwr_pwm = UFS_EXYNOS_LIMIT_TX_PWR_PWM; + ufs_exynos_cap.rx_pwr_hs = UFS_EXYNOS_LIMIT_RX_PWR_HS; + ufs_exynos_cap.tx_pwr_hs = UFS_EXYNOS_LIMIT_TX_PWR_HS; + ufs_exynos_cap.hs_rate = UFS_EXYNOS_LIMIT_HS_RATE; + ufs_exynos_cap.desired_working_mode = + UFS_EXYNOS_LIMIT_DESIRED_MODE; + + ret = ufshcd_get_pwr_dev_param(&ufs_exynos_cap, + dev_max_params, dev_req_params); + if (ret) { + pr_err("%s: failed to determine capabilities\n", __func__); + goto out; + } + + if (ufs->drv_data->pre_pwr_change) + ufs->drv_data->pre_pwr_change(ufs, dev_req_params); + + if (ufshcd_is_hs_mode(dev_req_params)) { + exynos_ufs_config_sync_pattern_mask(ufs, dev_req_params); + + switch (dev_req_params->hs_rate) { + case PA_HS_MODE_A: + case PA_HS_MODE_B: + phy_calibrate(generic_phy); + break; + } + } + + return 0; +out: + return ret; +} + +#define PWR_MODE_STR_LEN 64 +static int exynos_ufs_post_pwr_mode(struct ufs_hba *hba, + struct ufs_pa_layer_attr *pwr_max, + struct ufs_pa_layer_attr *pwr_req) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + struct phy *generic_phy = ufs->phy; + int gear = max_t(u32, pwr_req->gear_rx, pwr_req->gear_tx); + int lanes = max_t(u32, pwr_req->lane_rx, pwr_req->lane_tx); + char pwr_str[PWR_MODE_STR_LEN] = ""; + + /* let default be PWM Gear 1, Lane 1 */ + if (!gear) + gear = 1; + + if (!lanes) + lanes = 1; + + if (ufs->drv_data->post_pwr_change) + ufs->drv_data->post_pwr_change(ufs, pwr_req); + + if ((ufshcd_is_hs_mode(pwr_req))) { + switch (pwr_req->hs_rate) { + case PA_HS_MODE_A: + case PA_HS_MODE_B: + phy_calibrate(generic_phy); + break; + } + + snprintf(pwr_str, PWR_MODE_STR_LEN, "%s series_%s G_%d L_%d", + "FAST", pwr_req->hs_rate == PA_HS_MODE_A ? "A" : "B", + gear, lanes); + } else { + snprintf(pwr_str, PWR_MODE_STR_LEN, "%s G_%d L_%d", + "SLOW", gear, lanes); + } + + dev_info(hba->dev, "Power mode changed to : %s\n", pwr_str); + + return 0; +} + +static void exynos_ufs_specify_nexus_t_xfer_req(struct ufs_hba *hba, + int tag, bool op) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + u32 type; + + type = hci_readl(ufs, HCI_UTRL_NEXUS_TYPE); + + if (op) + hci_writel(ufs, type | (1 << tag), HCI_UTRL_NEXUS_TYPE); + else + hci_writel(ufs, type & ~(1 << tag), HCI_UTRL_NEXUS_TYPE); +} + +static void exynos_ufs_specify_nexus_t_tm_req(struct ufs_hba *hba, + int tag, u8 func) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + u32 type; + + type = hci_readl(ufs, HCI_UTMRL_NEXUS_TYPE); + + switch (func) { + case UFS_ABORT_TASK: + case UFS_QUERY_TASK: + hci_writel(ufs, type | (1 << tag), HCI_UTMRL_NEXUS_TYPE); + break; + case UFS_ABORT_TASK_SET: + case UFS_CLEAR_TASK_SET: + case UFS_LOGICAL_RESET: + case UFS_QUERY_TASK_SET: + hci_writel(ufs, type & ~(1 << tag), HCI_UTMRL_NEXUS_TYPE); + break; + } +} + +static int exynos_ufs_phy_init(struct exynos_ufs *ufs) +{ + struct ufs_hba *hba = ufs->hba; + struct phy *generic_phy = ufs->phy; + int ret = 0; + + if (ufs->avail_ln_rx == 0 || ufs->avail_ln_tx == 0) { + ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILRXDATALANES), + &ufs->avail_ln_rx); + ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILTXDATALANES), + &ufs->avail_ln_tx); + WARN(ufs->avail_ln_rx != ufs->avail_ln_tx, + "available data lane is not equal(rx:%d, tx:%d)\n", + ufs->avail_ln_rx, ufs->avail_ln_tx); + } + + phy_set_bus_width(generic_phy, ufs->avail_ln_rx); + ret = phy_init(generic_phy); + if (ret) { + dev_err(hba->dev, "%s: phy init failed, ret = %d\n", + __func__, ret); + goto out_exit_phy; + } + + return 0; + +out_exit_phy: + phy_exit(generic_phy); + + return ret; +} + +static void exynos_ufs_config_unipro(struct exynos_ufs *ufs) +{ + struct ufs_hba *hba = ufs->hba; + + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_CLK_PERIOD), + DIV_ROUND_UP(NSEC_PER_SEC, ufs->mclk_rate)); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTRAILINGCLOCKS), + ufs->drv_data->uic_attr->tx_trailingclks); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OPTION_SUITE), + ufs->drv_data->uic_attr->pa_dbg_option_suite); +} + +static void exynos_ufs_config_intr(struct exynos_ufs *ufs, u32 errs, u8 index) +{ + switch (index) { + case UNIPRO_L1_5: + hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_PA_LAYER); + break; + case UNIPRO_L2: + hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_DL_LAYER); + break; + case UNIPRO_L3: + hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_N_LAYER); + break; + case UNIPRO_L4: + hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_T_LAYER); + break; + case UNIPRO_DME: + hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_DME_LAYER); + break; + } +} + +static int exynos_ufs_pre_link(struct ufs_hba *hba) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + + /* hci */ + exynos_ufs_config_intr(ufs, DFES_DEF_L2_ERRS, UNIPRO_L2); + exynos_ufs_config_intr(ufs, DFES_DEF_L3_ERRS, UNIPRO_L3); + exynos_ufs_config_intr(ufs, DFES_DEF_L4_ERRS, UNIPRO_L4); + exynos_ufs_set_unipro_pclk_div(ufs); + + /* unipro */ + exynos_ufs_config_unipro(ufs); + + /* m-phy */ + exynos_ufs_phy_init(ufs); + exynos_ufs_config_phy_time_attr(ufs); + exynos_ufs_config_phy_cap_attr(ufs); + + if (ufs->drv_data->pre_link) + ufs->drv_data->pre_link(ufs); + + return 0; +} + +static void exynos_ufs_fit_aggr_timeout(struct exynos_ufs *ufs) +{ + u32 val; + + val = exynos_ufs_calc_time_cntr(ufs, IATOVAL_NSEC / CNTR_DIV_VAL); + hci_writel(ufs, val & CNT_VAL_1US_MASK, HCI_1US_TO_CNT_VAL); +} + +static int exynos_ufs_post_link(struct ufs_hba *hba) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + struct phy *generic_phy = ufs->phy; + struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; + + exynos_ufs_establish_connt(ufs); + exynos_ufs_fit_aggr_timeout(ufs); + + hci_writel(ufs, 0xa, HCI_DATA_REORDER); + hci_writel(ufs, PRDT_SET_SIZE(12), HCI_TXPRDT_ENTRY_SIZE); + hci_writel(ufs, PRDT_SET_SIZE(12), HCI_RXPRDT_ENTRY_SIZE); + hci_writel(ufs, (1 << hba->nutrs) - 1, HCI_UTRL_NEXUS_TYPE); + hci_writel(ufs, (1 << hba->nutmrs) - 1, HCI_UTMRL_NEXUS_TYPE); + hci_writel(ufs, 0xf, HCI_AXIDMA_RWDATA_BURST_LEN); + + if (ufs->opts & EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB) + ufshcd_dme_set(hba, + UIC_ARG_MIB(T_DBG_SKIP_INIT_HIBERN8_EXIT), TRUE); + + if (attr->pa_granularity) { + exynos_ufs_enable_dbg_mode(hba); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_GRANULARITY), + attr->pa_granularity); + exynos_ufs_disable_dbg_mode(hba); + + if (attr->pa_tactivate) + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), + attr->pa_tactivate); + if (attr->pa_hibern8time && + !(ufs->opts & EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER)) + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME), + attr->pa_hibern8time); + } + + if (ufs->opts & EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER) { + if (!attr->pa_granularity) + ufshcd_dme_get(hba, UIC_ARG_MIB(PA_GRANULARITY), + &attr->pa_granularity); + if (!attr->pa_hibern8time) + ufshcd_dme_get(hba, UIC_ARG_MIB(PA_HIBERN8TIME), + &attr->pa_hibern8time); + /* + * not wait for HIBERN8 time to exit hibernation + */ + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME), 0); + + if (attr->pa_granularity < 1 || attr->pa_granularity > 6) { + /* Valid range for granularity: 1 ~ 6 */ + dev_warn(hba->dev, + "%s: pa_granularity %d is invalid, assuming backwards compatibility\n", + __func__, + attr->pa_granularity); + attr->pa_granularity = 6; + } + } + + phy_calibrate(generic_phy); + + if (ufs->drv_data->post_link) + ufs->drv_data->post_link(ufs); + + return 0; +} + +static int exynos_ufs_parse_dt(struct device *dev, struct exynos_ufs *ufs) +{ + struct device_node *np = dev->of_node; + struct exynos_ufs_drv_data *drv_data = &exynos_ufs_drvs; + struct exynos_ufs_uic_attr *attr; + int ret = 0; + + while (drv_data->compatible) { + if (of_device_is_compatible(np, drv_data->compatible)) { + ufs->drv_data = drv_data; + break; + } + drv_data++; + } + + if (ufs->drv_data && ufs->drv_data->uic_attr) { + attr = ufs->drv_data->uic_attr; + } else { + dev_err(dev, "failed to get uic attributes\n"); + ret = -EINVAL; + goto out; + } + + ufs->pclk_avail_min = PCLK_AVAIL_MIN; + ufs->pclk_avail_max = PCLK_AVAIL_MAX; + + attr->rx_adv_fine_gran_sup_en = RX_ADV_FINE_GRAN_SUP_EN; + attr->rx_adv_fine_gran_step = RX_ADV_FINE_GRAN_STEP_VAL; + attr->rx_adv_min_actv_time_cap = RX_ADV_MIN_ACTV_TIME_CAP; + attr->pa_granularity = PA_GRANULARITY_VAL; + attr->pa_tactivate = PA_TACTIVATE_VAL; + attr->pa_hibern8time = PA_HIBERN8TIME_VAL; + +out: + return ret; +} + +static int exynos_ufs_init(struct ufs_hba *hba) +{ + struct device *dev = hba->dev; + struct platform_device *pdev = to_platform_device(dev); + struct exynos_ufs *ufs; + struct resource *res; + int ret; + + ufs = devm_kzalloc(dev, sizeof(*ufs), GFP_KERNEL); + if (!ufs) + return -ENOMEM; + + /* exynos-specific hci */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vs_hci"); + ufs->reg_hci = devm_ioremap_resource(dev, res); + if (IS_ERR(ufs->reg_hci)) { + dev_err(dev, "cannot ioremap for hci vendor register\n"); + return PTR_ERR(ufs->reg_hci); + } + + /* unipro */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "unipro"); + ufs->reg_unipro = devm_ioremap_resource(dev, res); + if (IS_ERR(ufs->reg_unipro)) { + dev_err(dev, "cannot ioremap for unipro register\n"); + return PTR_ERR(ufs->reg_unipro); + } + + /* ufs protector */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ufsp"); + ufs->reg_ufsp = devm_ioremap_resource(dev, res); + if (IS_ERR(ufs->reg_ufsp)) { + dev_err(dev, "cannot ioremap for ufs protector register\n"); + return PTR_ERR(ufs->reg_ufsp); + } + + ret = exynos_ufs_parse_dt(dev, ufs); + if (ret) { + dev_err(dev, "failed to get dt info.\n"); + goto out; + } + + ufs->phy = devm_phy_get(dev, "ufs-phy"); + if (IS_ERR(ufs->phy)) { + ret = PTR_ERR(ufs->phy); + dev_err(dev, "failed to get ufs-phy\n"); + goto out; + } + + ret = phy_power_on(ufs->phy); + if (ret) + goto phy_off; + + ufs->hba = hba; + ufs->opts = ufs->drv_data->opts; + ufs->rx_sel_idx = PA_MAXDATALANES; + if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX) + ufs->rx_sel_idx = 0; + hba->priv = (void *)ufs; + hba->quirks = ufs->drv_data->quirks; + if (ufs->drv_data->drv_init) { + ret = ufs->drv_data->drv_init(dev, ufs); + if (ret) { + dev_err(dev, "failed to init drv-data\n"); + goto out; + } + } + + ret = exynos_ufs_get_clk_info(ufs); + if (ret) + goto out; + exynos_ufs_specify_phy_time_attr(ufs); + exynos_ufs_config_smu(ufs); + return 0; + +phy_off: + phy_power_off(ufs->phy); +out: + hba->priv = NULL; + return ret; +} + +static int exynos_ufs_host_reset(struct ufs_hba *hba) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + unsigned long timeout = jiffies + msecs_to_jiffies(1); + u32 val; + int ret = 0; + + exynos_ufs_disable_auto_ctrl_hcc_save(ufs, &val); + + hci_writel(ufs, UFS_SW_RST_MASK, HCI_SW_RST); + + do { + if (!(hci_readl(ufs, HCI_SW_RST) & UFS_SW_RST_MASK)) + goto out; + } while (time_before(jiffies, timeout)); + + dev_err(hba->dev, "timeout host sw-reset\n"); + ret = -ETIMEDOUT; + +out: + exynos_ufs_auto_ctrl_hcc_restore(ufs, &val); + return ret; +} + +static void exynos_ufs_dev_hw_reset(struct ufs_hba *hba) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + + hci_writel(ufs, 0 << 0, HCI_GPIO_OUT); + udelay(5); + hci_writel(ufs, 1 << 0, HCI_GPIO_OUT); +} + +static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, u8 enter) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; + + if (!enter) { + if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL) + exynos_ufs_disable_auto_ctrl_hcc(ufs); + exynos_ufs_ungate_clks(ufs); + + if (ufs->opts & EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER) { + const unsigned int granularity_tbl[] = { + 1, 4, 8, 16, 32, 100 + }; + int h8_time = attr->pa_hibern8time * + granularity_tbl[attr->pa_granularity - 1]; + unsigned long us; + s64 delta; + + do { + delta = h8_time - ktime_us_delta(ktime_get(), + ufs->entry_hibern8_t); + if (delta <= 0) + break; + + us = min_t(s64, delta, USEC_PER_MSEC); + if (us >= 10) + usleep_range(us, us + 10); + } while (1); + } + } +} + +static void exynos_ufs_post_hibern8(struct ufs_hba *hba, u8 enter) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + + if (!enter) { + u32 cur_mode = 0; + u32 pwrmode; + + if (ufshcd_is_hs_mode(&ufs->dev_req_params)) + pwrmode = FAST_MODE; + else + pwrmode = SLOW_MODE; + + ufshcd_dme_get(hba, UIC_ARG_MIB(PA_PWRMODE), &cur_mode); + if (cur_mode != (pwrmode << 4 | pwrmode)) { + dev_warn(hba->dev, "%s: power mode change\n", __func__); + hba->pwr_info.pwr_rx = (cur_mode >> 4) & 0xf; + hba->pwr_info.pwr_tx = cur_mode & 0xf; + ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info); + } + + if (!(ufs->opts & EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB)) + exynos_ufs_establish_connt(ufs); + } else { + ufs->entry_hibern8_t = ktime_get(); + exynos_ufs_gate_clks(ufs); + if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL) + exynos_ufs_enable_auto_ctrl_hcc(ufs); + } +} + +static int exynos_ufs_hce_enable_notify(struct ufs_hba *hba, + enum ufs_notify_change_status status) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + int ret = 0; + + switch (status) { + case PRE_CHANGE: + ret = exynos_ufs_host_reset(hba); + if (ret) + return ret; + exynos_ufs_dev_hw_reset(hba); + break; + case POST_CHANGE: + exynos_ufs_calc_pwm_clk_div(ufs); + if (!(ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL)) + exynos_ufs_enable_auto_ctrl_hcc(ufs); + break; + } + + return ret; +} + +static int exynos_ufs_link_startup_notify(struct ufs_hba *hba, + enum ufs_notify_change_status status) +{ + int ret = 0; + + switch (status) { + case PRE_CHANGE: + ret = exynos_ufs_pre_link(hba); + break; + case POST_CHANGE: + ret = exynos_ufs_post_link(hba); + break; + } + + return ret; +} + +static int exynos_ufs_pwr_change_notify(struct ufs_hba *hba, + enum ufs_notify_change_status status, + struct ufs_pa_layer_attr *dev_max_params, + struct ufs_pa_layer_attr *dev_req_params) +{ + int ret = 0; + + switch (status) { + case PRE_CHANGE: + ret = exynos_ufs_pre_pwr_mode(hba, dev_max_params, + dev_req_params); + break; + case POST_CHANGE: + ret = exynos_ufs_post_pwr_mode(hba, NULL, dev_req_params); + break; + } + + return ret; +} + +static void exynos_ufs_hibern8_notify(struct ufs_hba *hba, + enum uic_cmd_dme enter, + enum ufs_notify_change_status notify) +{ + switch ((u8)notify) { + case PRE_CHANGE: + exynos_ufs_pre_hibern8(hba, enter); + break; + case POST_CHANGE: + exynos_ufs_post_hibern8(hba, enter); + break; + } +} + +static int exynos_ufs_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + + if (!ufshcd_is_link_active(hba)) + phy_power_off(ufs->phy); + + return 0; +} + +static int exynos_ufs_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + + if (!ufshcd_is_link_active(hba)) + phy_power_on(ufs->phy); + + exynos_ufs_config_smu(ufs); + + return 0; +} + +static struct ufs_hba_variant_ops ufs_hba_exynos_ops = { + .name = "exynos_ufs", + .init = exynos_ufs_init, + .hce_enable_notify = exynos_ufs_hce_enable_notify, + .link_startup_notify = exynos_ufs_link_startup_notify, + .pwr_change_notify = exynos_ufs_pwr_change_notify, + .setup_xfer_req = exynos_ufs_specify_nexus_t_xfer_req, + .setup_task_mgmt = exynos_ufs_specify_nexus_t_tm_req, + .hibern8_notify = exynos_ufs_hibern8_notify, + .suspend = exynos_ufs_suspend, + .resume = exynos_ufs_resume, +}; + +static int exynos_ufs_probe(struct platform_device *pdev) +{ + int err; + struct device *dev = &pdev->dev; + + err = ufshcd_pltfrm_init(pdev, &ufs_hba_exynos_ops); + if (err) + dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); + + return err; +} + +static int exynos_ufs_remove(struct platform_device *pdev) +{ + struct ufs_hba *hba = platform_get_drvdata(pdev); + + pm_runtime_get_sync(&(pdev)->dev); + ufshcd_remove(hba); + return 0; +} + +struct exynos_ufs_drv_data exynos_ufs_drvs = { + + .compatible = "samsung,exynos7-ufs", + .uic_attr = &exynos7_uic_attr, + .quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN | + UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR | + UFSHCI_QUIRK_BROKEN_HCE | + UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR | + UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR, + .opts = EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL | + EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL | + EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX | + EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB | + EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER, + .drv_init = exynos7_ufs_drv_init, + .pre_link = exynos7_ufs_pre_link, + .post_link = exynos7_ufs_post_link, + .pre_pwr_change = exynos7_ufs_pre_pwr_change, + .post_pwr_change = exynos7_ufs_post_pwr_change, +}; + +static const struct of_device_id exynos_ufs_of_match[] = { + { .compatible = "samsung,exynos7-ufs", + .data = &exynos_ufs_drvs }, + {}, +}; + +static const struct dev_pm_ops exynos_ufs_pm_ops = { + .suspend = ufshcd_pltfrm_suspend, + .resume = ufshcd_pltfrm_resume, + .runtime_suspend = ufshcd_pltfrm_runtime_suspend, + .runtime_resume = ufshcd_pltfrm_runtime_resume, + .runtime_idle = ufshcd_pltfrm_runtime_idle, +}; + +static struct platform_driver exynos_ufs_pltform = { + .probe = exynos_ufs_probe, + .remove = exynos_ufs_remove, + .shutdown = ufshcd_pltfrm_shutdown, + .driver = { + .name = "exynos-ufshc", + .pm = &exynos_ufs_pm_ops, + .of_match_table = of_match_ptr(exynos_ufs_of_match), + }, +}; +module_platform_driver(exynos_ufs_pltform); + +MODULE_AUTHOR("Alim Akhtar "); +MODULE_AUTHOR("Seungwon Jeon "); +MODULE_DESCRIPTION("Exynos UFS HCI Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/scsi/ufs/ufs-exynos.h b/drivers/scsi/ufs/ufs-exynos.h new file mode 100644 index 0000000000000000000000000000000000000000..76d6e39efb2f082ed23ee97b47c26d6085c11990 --- /dev/null +++ b/drivers/scsi/ufs/ufs-exynos.h @@ -0,0 +1,287 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * UFS Host Controller driver for Exynos specific extensions + * + * Copyright (C) 2014-2015 Samsung Electronics Co., Ltd. + * + */ + +#ifndef _UFS_EXYNOS_H_ +#define _UFS_EXYNOS_H_ + +/* + * UNIPRO registers + */ +#define UNIPRO_DBG_FORCE_DME_CTRL_STATE 0x150 + +/* + * MIBs for PA debug registers + */ +#define PA_DBG_CLK_PERIOD 0x9514 +#define PA_DBG_TXPHY_CFGUPDT 0x9518 +#define PA_DBG_RXPHY_CFGUPDT 0x9519 +#define PA_DBG_MODE 0x9529 +#define PA_DBG_SKIP_RESET_PHY 0x9539 +#define PA_DBG_OV_TM 0x9540 +#define PA_DBG_SKIP_LINE_RESET 0x9541 +#define PA_DBG_LINE_RESET_REQ 0x9543 +#define PA_DBG_OPTION_SUITE 0x9564 +#define PA_DBG_OPTION_SUITE_DYN 0x9565 + +/* + * MIBs for Transport Layer debug registers + */ +#define T_DBG_SKIP_INIT_HIBERN8_EXIT 0xc001 + +/* + * Exynos MPHY attributes + */ +#define TX_LINERESET_N_VAL 0x0277 +#define TX_LINERESET_N(v) (((v) >> 10) & 0xFF) +#define TX_LINERESET_P_VAL 0x027D +#define TX_LINERESET_P(v) (((v) >> 12) & 0xFF) +#define TX_OV_SLEEP_CNT_TIMER 0x028E +#define TX_OV_H8_ENTER_EN (1 << 7) +#define TX_OV_SLEEP_CNT(v) (((v) >> 5) & 0x7F) +#define TX_HIGH_Z_CNT_11_08 0x028C +#define TX_HIGH_Z_CNT_H(v) (((v) >> 8) & 0xF) +#define TX_HIGH_Z_CNT_07_00 0x028D +#define TX_HIGH_Z_CNT_L(v) ((v) & 0xFF) +#define TX_BASE_NVAL_07_00 0x0293 +#define TX_BASE_NVAL_L(v) ((v) & 0xFF) +#define TX_BASE_NVAL_15_08 0x0294 +#define TX_BASE_NVAL_H(v) (((v) >> 8) & 0xFF) +#define TX_GRAN_NVAL_07_00 0x0295 +#define TX_GRAN_NVAL_L(v) ((v) & 0xFF) +#define TX_GRAN_NVAL_10_08 0x0296 +#define TX_GRAN_NVAL_H(v) (((v) >> 8) & 0x3) + +#define RX_FILLER_ENABLE 0x0316 +#define RX_FILLER_EN (1 << 1) +#define RX_LINERESET_VAL 0x0317 +#define RX_LINERESET(v) (((v) >> 12) & 0xFF) +#define RX_LCC_IGNORE 0x0318 +#define RX_SYNC_MASK_LENGTH 0x0321 +#define RX_HIBERN8_WAIT_VAL_BIT_20_16 0x0331 +#define RX_HIBERN8_WAIT_VAL_BIT_15_08 0x0332 +#define RX_HIBERN8_WAIT_VAL_BIT_07_00 0x0333 +#define RX_OV_SLEEP_CNT_TIMER 0x0340 +#define RX_OV_SLEEP_CNT(v) (((v) >> 6) & 0x1F) +#define RX_OV_STALL_CNT_TIMER 0x0341 +#define RX_OV_STALL_CNT(v) (((v) >> 4) & 0xFF) +#define RX_BASE_NVAL_07_00 0x0355 +#define RX_BASE_NVAL_L(v) ((v) & 0xFF) +#define RX_BASE_NVAL_15_08 0x0354 +#define RX_BASE_NVAL_H(v) (((v) >> 8) & 0xFF) +#define RX_GRAN_NVAL_07_00 0x0353 +#define RX_GRAN_NVAL_L(v) ((v) & 0xFF) +#define RX_GRAN_NVAL_10_08 0x0352 +#define RX_GRAN_NVAL_H(v) (((v) >> 8) & 0x3) + +#define CMN_PWM_CLK_CTRL 0x0402 +#define PWM_CLK_CTRL_MASK 0x3 + +#define IATOVAL_NSEC 20000 /* unit: ns */ +#define UNIPRO_PCLK_PERIOD(ufs) (NSEC_PER_SEC / ufs->pclk_rate) + +struct exynos_ufs; + +/* vendor specific pre-defined parameters */ +#define SLOW 1 +#define FAST 2 + +#define UFS_EXYNOS_LIMIT_NUM_LANES_RX 2 +#define UFS_EXYNOS_LIMIT_NUM_LANES_TX 2 +#define UFS_EXYNOS_LIMIT_HSGEAR_RX UFS_HS_G3 +#define UFS_EXYNOS_LIMIT_HSGEAR_TX UFS_HS_G3 +#define UFS_EXYNOS_LIMIT_PWMGEAR_RX UFS_PWM_G4 +#define UFS_EXYNOS_LIMIT_PWMGEAR_TX UFS_PWM_G4 +#define UFS_EXYNOS_LIMIT_RX_PWR_PWM SLOW_MODE +#define UFS_EXYNOS_LIMIT_TX_PWR_PWM SLOW_MODE +#define UFS_EXYNOS_LIMIT_RX_PWR_HS FAST_MODE +#define UFS_EXYNOS_LIMIT_TX_PWR_HS FAST_MODE +#define UFS_EXYNOS_LIMIT_HS_RATE PA_HS_MODE_B +#define UFS_EXYNOS_LIMIT_DESIRED_MODE FAST + +#define RX_ADV_FINE_GRAN_SUP_EN 0x1 +#define RX_ADV_FINE_GRAN_STEP_VAL 0x3 +#define RX_ADV_MIN_ACTV_TIME_CAP 0x9 + +#define PA_GRANULARITY_VAL 0x6 +#define PA_TACTIVATE_VAL 0x3 +#define PA_HIBERN8TIME_VAL 0x20 + +#define PCLK_AVAIL_MIN 70000000 +#define PCLK_AVAIL_MAX 133000000 + +struct exynos_ufs_uic_attr { + /* TX Attributes */ + unsigned int tx_trailingclks; + unsigned int tx_dif_p_nsec; + unsigned int tx_dif_n_nsec; + unsigned int tx_high_z_cnt_nsec; + unsigned int tx_base_unit_nsec; + unsigned int tx_gran_unit_nsec; + unsigned int tx_sleep_cnt; + unsigned int tx_min_activatetime; + /* RX Attributes */ + unsigned int rx_filler_enable; + unsigned int rx_dif_p_nsec; + unsigned int rx_hibern8_wait_nsec; + unsigned int rx_base_unit_nsec; + unsigned int rx_gran_unit_nsec; + unsigned int rx_sleep_cnt; + unsigned int rx_stall_cnt; + unsigned int rx_hs_g1_sync_len_cap; + unsigned int rx_hs_g2_sync_len_cap; + unsigned int rx_hs_g3_sync_len_cap; + unsigned int rx_hs_g1_prep_sync_len_cap; + unsigned int rx_hs_g2_prep_sync_len_cap; + unsigned int rx_hs_g3_prep_sync_len_cap; + /* Common Attributes */ + unsigned int cmn_pwm_clk_ctrl; + /* Internal Attributes */ + unsigned int pa_dbg_option_suite; + /* Changeable Attributes */ + unsigned int rx_adv_fine_gran_sup_en; + unsigned int rx_adv_fine_gran_step; + unsigned int rx_min_actv_time_cap; + unsigned int rx_hibern8_time_cap; + unsigned int rx_adv_min_actv_time_cap; + unsigned int rx_adv_hibern8_time_cap; + unsigned int pa_granularity; + unsigned int pa_tactivate; + unsigned int pa_hibern8time; +}; + +struct exynos_ufs_drv_data { + char *compatible; + struct exynos_ufs_uic_attr *uic_attr; + unsigned int quirks; + unsigned int opts; + /* SoC's specific operations */ + int (*drv_init)(struct device *dev, struct exynos_ufs *ufs); + int (*pre_link)(struct exynos_ufs *ufs); + int (*post_link)(struct exynos_ufs *ufs); + int (*pre_pwr_change)(struct exynos_ufs *ufs, + struct ufs_pa_layer_attr *pwr); + int (*post_pwr_change)(struct exynos_ufs *ufs, + struct ufs_pa_layer_attr *pwr); +}; + +struct ufs_phy_time_cfg { + u32 tx_linereset_p; + u32 tx_linereset_n; + u32 tx_high_z_cnt; + u32 tx_base_n_val; + u32 tx_gran_n_val; + u32 tx_sleep_cnt; + u32 rx_linereset; + u32 rx_hibern8_wait; + u32 rx_base_n_val; + u32 rx_gran_n_val; + u32 rx_sleep_cnt; + u32 rx_stall_cnt; +}; + +struct exynos_ufs { + struct ufs_hba *hba; + struct phy *phy; + void __iomem *reg_hci; + void __iomem *reg_unipro; + void __iomem *reg_ufsp; + struct clk *clk_hci_core; + struct clk *clk_unipro_main; + struct clk *clk_apb; + u32 pclk_rate; + u32 pclk_div; + u32 pclk_avail_min; + u32 pclk_avail_max; + u32 mclk_rate; + int avail_ln_rx; + int avail_ln_tx; + int rx_sel_idx; + struct ufs_pa_layer_attr dev_req_params; + struct ufs_phy_time_cfg t_cfg; + ktime_t entry_hibern8_t; + struct exynos_ufs_drv_data *drv_data; + + u32 opts; +#define EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL BIT(0) +#define EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB BIT(1) +#define EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL BIT(2) +#define EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX BIT(3) +#define EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER BIT(4) +}; + +#define for_each_ufs_rx_lane(ufs, i) \ + for (i = (ufs)->rx_sel_idx; \ + i < (ufs)->rx_sel_idx + (ufs)->avail_ln_rx; i++) +#define for_each_ufs_tx_lane(ufs, i) \ + for (i = 0; i < (ufs)->avail_ln_tx; i++) + +#define EXYNOS_UFS_MMIO_FUNC(name) \ +static inline void name##_writel(struct exynos_ufs *ufs, u32 val, u32 reg)\ +{ \ + writel(val, ufs->reg_##name + reg); \ +} \ + \ +static inline u32 name##_readl(struct exynos_ufs *ufs, u32 reg) \ +{ \ + return readl(ufs->reg_##name + reg); \ +} + +EXYNOS_UFS_MMIO_FUNC(hci); +EXYNOS_UFS_MMIO_FUNC(unipro); +EXYNOS_UFS_MMIO_FUNC(ufsp); +#undef EXYNOS_UFS_MMIO_FUNC + +long exynos_ufs_calc_time_cntr(struct exynos_ufs *, long); + +static inline void exynos_ufs_enable_ov_tm(struct ufs_hba *hba) +{ + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OV_TM), TRUE); +} + +static inline void exynos_ufs_disable_ov_tm(struct ufs_hba *hba) +{ + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OV_TM), FALSE); +} + +static inline void exynos_ufs_enable_dbg_mode(struct ufs_hba *hba) +{ + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_MODE), TRUE); +} + +static inline void exynos_ufs_disable_dbg_mode(struct ufs_hba *hba) +{ + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_MODE), FALSE); +} + +struct exynos_ufs_drv_data exynos_ufs_drvs; + +struct exynos_ufs_uic_attr exynos7_uic_attr = { + .tx_trailingclks = 0x10, + .tx_dif_p_nsec = 3000000, /* unit: ns */ + .tx_dif_n_nsec = 1000000, /* unit: ns */ + .tx_high_z_cnt_nsec = 20000, /* unit: ns */ + .tx_base_unit_nsec = 100000, /* unit: ns */ + .tx_gran_unit_nsec = 4000, /* unit: ns */ + .tx_sleep_cnt = 1000, /* unit: ns */ + .tx_min_activatetime = 0xa, + .rx_filler_enable = 0x2, + .rx_dif_p_nsec = 1000000, /* unit: ns */ + .rx_hibern8_wait_nsec = 4000000, /* unit: ns */ + .rx_base_unit_nsec = 100000, /* unit: ns */ + .rx_gran_unit_nsec = 4000, /* unit: ns */ + .rx_sleep_cnt = 1280, /* unit: ns */ + .rx_stall_cnt = 320, /* unit: ns */ + .rx_hs_g1_sync_len_cap = SYNC_LEN_COARSE(0xf), + .rx_hs_g2_sync_len_cap = SYNC_LEN_COARSE(0xf), + .rx_hs_g3_sync_len_cap = SYNC_LEN_COARSE(0xf), + .rx_hs_g1_prep_sync_len_cap = PREP_LEN(0xf), + .rx_hs_g2_prep_sync_len_cap = PREP_LEN(0xf), + .rx_hs_g3_prep_sync_len_cap = PREP_LEN(0xf), + .pa_dbg_option_suite = 0x30103, +}; +#endif /* _UFS_EXYNOS_H_ */ diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index d56ce8d97d4e8642ed666fd79c0515c138b5434b..29cd017c1aa066e77b0e3f884c72e4f6c5967ab4 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -12,9 +12,11 @@ #include #include #include +#include #include #include "ufshcd.h" +#include "ufshcd-crypto.h" #include "ufshcd-pltfrm.h" #include "ufs_quirks.h" #include "unipro.h" @@ -24,6 +26,9 @@ arm_smccc_smc(MTK_SIP_UFS_CONTROL, \ cmd, val, 0, 0, 0, 0, 0, &(res)) +#define ufs_mtk_crypto_ctrl(res, enable) \ + ufs_mtk_smc(UFS_MTK_SIP_CRYPTO_CTRL, enable, res) + #define ufs_mtk_ref_clk_notify(on, res) \ ufs_mtk_smc(UFS_MTK_SIP_REF_CLK_NOTIFICATION, on, res) @@ -31,6 +36,8 @@ ufs_mtk_smc(UFS_MTK_SIP_DEVICE_RESET, high, res) static struct ufs_dev_fix ufs_mtk_dev_fixups[] = { + UFS_FIX(UFS_VENDOR_MICRON, UFS_ANY_MODEL, + UFS_DEVICE_QUIRK_DELAY_AFTER_LPM), UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AFAMZDAR", UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES), END_FIX @@ -72,6 +79,18 @@ static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable) } } +static void ufs_mtk_crypto_enable(struct ufs_hba *hba) +{ + struct arm_smccc_res res; + + ufs_mtk_crypto_ctrl(res, 1); + if (res.a0) { + dev_info(hba->dev, "%s: crypto enable failed, err: %lu\n", + __func__, res.a0); + hba->caps &= ~UFSHCD_CAP_CRYPTO; + } +} + static int ufs_mtk_hce_enable_notify(struct ufs_hba *hba, enum ufs_notify_change_status status) { @@ -82,6 +101,9 @@ static int ufs_mtk_hce_enable_notify(struct ufs_hba *hba, hba->vps->hba_enable_delay_us = 0; else hba->vps->hba_enable_delay_us = 600; + + if (hba->caps & UFSHCD_CAP_CRYPTO) + ufs_mtk_crypto_enable(hba); } return 0; @@ -112,6 +134,12 @@ static int ufs_mtk_bind_mphy(struct ufs_hba *hba) if (err) host->mphy = NULL; + /* + * Allow unbound mphy because not every platform needs specific + * mphy control. + */ + if (err == -ENODEV) + err = 0; return err; } @@ -120,7 +148,7 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); struct arm_smccc_res res; - unsigned long timeout; + ktime_t timeout, time_checked; u32 value; if (host->ref_clk_enabled == on) @@ -135,8 +163,9 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) } /* Wait for ack */ - timeout = jiffies + msecs_to_jiffies(REFCLK_REQ_TIMEOUT_MS); + timeout = ktime_add_us(ktime_get(), REFCLK_REQ_TIMEOUT_US); do { + time_checked = ktime_get(); value = ufshcd_readl(hba, REG_UFS_REFCLK_CTRL); /* Wait until ack bit equals to req bit */ @@ -144,7 +173,7 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) goto out; usleep_range(100, 200); - } while (time_before(jiffies, timeout)); + } while (ktime_before(time_checked, timeout)); dev_err(hba->dev, "missing ack of refclk req, reg: 0x%x\n", value); @@ -177,15 +206,47 @@ static void ufs_mtk_setup_ref_clk_wait_us(struct ufs_hba *hba, host->ref_clk_ungating_wait_us = ungating_us; } -static u32 ufs_mtk_link_get_state(struct ufs_hba *hba) +static int ufs_mtk_wait_link_state(struct ufs_hba *hba, u32 state, + unsigned long max_wait_ms) { + ktime_t timeout, time_checked; u32 val; - ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL); - val = ufshcd_readl(hba, REG_UFS_PROBE); - val = val >> 28; + timeout = ktime_add_us(ktime_get(), ms_to_ktime(max_wait_ms)); + do { + time_checked = ktime_get(); + ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL); + val = ufshcd_readl(hba, REG_UFS_PROBE); + val = val >> 28; + + if (val == state) + return 0; + + /* Sleep for max. 200us */ + usleep_range(100, 200); + } while (ktime_before(time_checked, timeout)); - return val; + if (val == state) + return 0; + + return -ETIMEDOUT; +} + +static void ufs_mtk_mphy_power_on(struct ufs_hba *hba, bool on) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + struct phy *mphy = host->mphy; + + if (!mphy) + return; + + if (on && !host->mphy_powered_on) + phy_power_on(mphy); + else if (!on && host->mphy_powered_on) + phy_power_off(mphy); + else + return; + host->mphy_powered_on = on; } /** @@ -201,6 +262,7 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, { struct ufs_mtk_host *host = ufshcd_get_variant(hba); int ret = 0; + bool clk_pwr_off = false; /* * In case ufs_mtk_init() is not yet done, simply ignore. @@ -211,22 +273,29 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, return 0; if (!on && status == PRE_CHANGE) { - if (!ufshcd_is_link_active(hba)) { - ufs_mtk_setup_ref_clk(hba, on); - ret = phy_power_off(host->mphy); - } else { + if (ufshcd_is_link_off(hba)) { + clk_pwr_off = true; + } else if (ufshcd_is_link_hibern8(hba) || + (!ufshcd_can_hibern8_during_gating(hba) && + ufshcd_is_auto_hibern8_enabled(hba))) { /* - * Gate ref-clk if link state is in Hibern8 - * triggered by Auto-Hibern8. + * Gate ref-clk and poweroff mphy if link state is in + * OFF or Hibern8 by either Auto-Hibern8 or + * ufshcd_link_state_transition(). */ - if (!ufshcd_can_hibern8_during_gating(hba) && - ufshcd_is_auto_hibern8_enabled(hba) && - ufs_mtk_link_get_state(hba) == - VS_LINK_HIBERN8) - ufs_mtk_setup_ref_clk(hba, on); + ret = ufs_mtk_wait_link_state(hba, + VS_LINK_HIBERN8, + 15); + if (!ret) + clk_pwr_off = true; + } + + if (clk_pwr_off) { + ufs_mtk_setup_ref_clk(hba, on); + ufs_mtk_mphy_power_on(hba, on); } } else if (on && status == POST_CHANGE) { - ret = phy_power_on(host->mphy); + ufs_mtk_mphy_power_on(hba, on); ufs_mtk_setup_ref_clk(hba, on); } @@ -269,6 +338,9 @@ static int ufs_mtk_init(struct ufs_hba *hba) /* Enable clock-gating */ hba->caps |= UFSHCD_CAP_CLK_GATING; + /* Enable inline encryption */ + hba->caps |= UFSHCD_CAP_CRYPTO; + /* Enable WriteBooster */ hba->caps |= UFSHCD_CAP_WB_EN; hba->vps->wb_flush_threshold = UFS_WB_BUF_REMAIN_PERCENT(80); @@ -502,10 +574,22 @@ static int ufs_mtk_link_set_lpm(struct ufs_hba *hba) return 0; } +static void ufs_mtk_vreg_set_lpm(struct ufs_hba *hba, bool lpm) +{ + if (!hba->vreg_info.vccq2 || !hba->vreg_info.vcc) + return; + + if (lpm & !hba->vreg_info.vcc->enabled) + regulator_set_mode(hba->vreg_info.vccq2->reg, + REGULATOR_MODE_IDLE); + else if (!lpm) + regulator_set_mode(hba->vreg_info.vccq2->reg, + REGULATOR_MODE_NORMAL); +} + static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) { int err; - struct ufs_mtk_host *host = ufshcd_get_variant(hba); if (ufshcd_is_link_hibern8(hba)) { err = ufs_mtk_link_set_lpm(hba); @@ -518,23 +602,23 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) ufshcd_set_link_off(hba); return -EAGAIN; } + /* + * Make sure no error will be returned to prevent + * ufshcd_suspend() re-enabling regulators while vreg is still + * in low-power mode. + */ + ufs_mtk_vreg_set_lpm(hba, true); } - if (!ufshcd_is_link_active(hba)) - phy_power_off(host->mphy); - return 0; } static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) { - struct ufs_mtk_host *host = ufshcd_get_variant(hba); int err; - if (!ufshcd_is_link_active(hba)) - phy_power_on(host->mphy); - if (ufshcd_is_link_hibern8(hba)) { + ufs_mtk_vreg_set_lpm(hba, false); err = ufs_mtk_link_set_hpm(hba); if (err) { err = ufshcd_link_recovery(hba); diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h index 5bbd3e9cbae2abbb48b92fa57e0d06b0721bd240..8ed24d5fcff93c66adc2e68fe9ecc19464784e9e 100644 --- a/drivers/scsi/ufs/ufs-mediatek.h +++ b/drivers/scsi/ufs/ufs-mediatek.h @@ -28,7 +28,7 @@ #define REFCLK_REQUEST BIT(0) #define REFCLK_ACK BIT(1) -#define REFCLK_REQ_TIMEOUT_MS 3 +#define REFCLK_REQ_TIMEOUT_US 3000 /* * Vendor specific pre-defined parameters @@ -70,6 +70,7 @@ enum { */ #define MTK_SIP_UFS_CONTROL MTK_SIP_SMC_CMD(0x276) #define UFS_MTK_SIP_DEVICE_RESET BIT(1) +#define UFS_MTK_SIP_CRYPTO_CTRL BIT(2) #define UFS_MTK_SIP_REF_CLK_NOTIFICATION BIT(3) /* @@ -91,6 +92,7 @@ enum { struct ufs_mtk_host { struct ufs_hba *hba; struct phy *mphy; + bool mphy_powered_on; bool unipro_lpm; bool ref_clk_enabled; u16 ref_clk_ungating_wait_us; diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c new file mode 100644 index 0000000000000000000000000000000000000000..bbb0ad7590ec12ba42f7af436d307a282b0614c7 --- /dev/null +++ b/drivers/scsi/ufs/ufs-qcom-ice.c @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Qualcomm ICE (Inline Crypto Engine) support. + * + * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright 2019 Google LLC + */ + +#include +#include + +#include "ufshcd-crypto.h" +#include "ufs-qcom.h" + +#define AES_256_XTS_KEY_SIZE 64 + +/* QCOM ICE registers */ + +#define QCOM_ICE_REG_CONTROL 0x0000 +#define QCOM_ICE_REG_RESET 0x0004 +#define QCOM_ICE_REG_VERSION 0x0008 +#define QCOM_ICE_REG_FUSE_SETTING 0x0010 +#define QCOM_ICE_REG_PARAMETERS_1 0x0014 +#define QCOM_ICE_REG_PARAMETERS_2 0x0018 +#define QCOM_ICE_REG_PARAMETERS_3 0x001C +#define QCOM_ICE_REG_PARAMETERS_4 0x0020 +#define QCOM_ICE_REG_PARAMETERS_5 0x0024 + +/* QCOM ICE v3.X only */ +#define QCOM_ICE_GENERAL_ERR_STTS 0x0040 +#define QCOM_ICE_INVALID_CCFG_ERR_STTS 0x0030 +#define QCOM_ICE_GENERAL_ERR_MASK 0x0044 + +/* QCOM ICE v2.X only */ +#define QCOM_ICE_REG_NON_SEC_IRQ_STTS 0x0040 +#define QCOM_ICE_REG_NON_SEC_IRQ_MASK 0x0044 + +#define QCOM_ICE_REG_NON_SEC_IRQ_CLR 0x0048 +#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME1 0x0050 +#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME2 0x0054 +#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME1 0x0058 +#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME2 0x005C +#define QCOM_ICE_REG_STREAM1_BIST_ERROR_VEC 0x0060 +#define QCOM_ICE_REG_STREAM2_BIST_ERROR_VEC 0x0064 +#define QCOM_ICE_REG_STREAM1_BIST_FINISH_VEC 0x0068 +#define QCOM_ICE_REG_STREAM2_BIST_FINISH_VEC 0x006C +#define QCOM_ICE_REG_BIST_STATUS 0x0070 +#define QCOM_ICE_REG_BYPASS_STATUS 0x0074 +#define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000 +#define QCOM_ICE_REG_ENDIAN_SWAP 0x1004 +#define QCOM_ICE_REG_TEST_BUS_CONTROL 0x1010 +#define QCOM_ICE_REG_TEST_BUS_REG 0x1014 + +/* BIST ("built-in self-test"?) status flags */ +#define QCOM_ICE_BIST_STATUS_MASK 0xF0000000 + +#define QCOM_ICE_FUSE_SETTING_MASK 0x1 +#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2 +#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4 + +#define qcom_ice_writel(host, val, reg) \ + writel((val), (host)->ice_mmio + (reg)) +#define qcom_ice_readl(host, reg) \ + readl((host)->ice_mmio + (reg)) + +static bool qcom_ice_supported(struct ufs_qcom_host *host) +{ + struct device *dev = host->hba->dev; + u32 regval = qcom_ice_readl(host, QCOM_ICE_REG_VERSION); + int major = regval >> 24; + int minor = (regval >> 16) & 0xFF; + int step = regval & 0xFFFF; + + /* For now this driver only supports ICE version 3. */ + if (major != 3) { + dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n", + major, minor, step); + return false; + } + + dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n", + major, minor, step); + + /* If fuses are blown, ICE might not work in the standard way. */ + regval = qcom_ice_readl(host, QCOM_ICE_REG_FUSE_SETTING); + if (regval & (QCOM_ICE_FUSE_SETTING_MASK | + QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK | + QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) { + dev_warn(dev, "Fuses are blown; ICE is unusable!\n"); + return false; + } + return true; +} + +int ufs_qcom_ice_init(struct ufs_qcom_host *host) +{ + struct ufs_hba *hba = host->hba; + struct device *dev = hba->dev; + struct platform_device *pdev = to_platform_device(dev); + struct resource *res; + int err; + + if (!(ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES) & + MASK_CRYPTO_SUPPORT)) + return 0; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice"); + if (!res) { + dev_warn(dev, "ICE registers not found\n"); + goto disable; + } + + if (!qcom_scm_ice_available()) { + dev_warn(dev, "ICE SCM interface not found\n"); + goto disable; + } + + host->ice_mmio = devm_ioremap_resource(dev, res); + if (IS_ERR(host->ice_mmio)) { + err = PTR_ERR(host->ice_mmio); + dev_err(dev, "Failed to map ICE registers; err=%d\n", err); + return err; + } + + if (!qcom_ice_supported(host)) + goto disable; + + return 0; + +disable: + dev_warn(dev, "Disabling inline encryption support\n"); + hba->caps &= ~UFSHCD_CAP_CRYPTO; + return 0; +} + +static void qcom_ice_low_power_mode_enable(struct ufs_qcom_host *host) +{ + u32 regval; + + regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL); + /* + * Enable low power mode sequence + * [0]-0, [1]-0, [2]-0, [3]-E, [4]-0, [5]-0, [6]-0, [7]-0 + */ + regval |= 0x7000; + qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); +} + +static void qcom_ice_optimization_enable(struct ufs_qcom_host *host) +{ + u32 regval; + + /* ICE Optimizations Enable Sequence */ + regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL); + regval |= 0xD807100; + /* ICE HPG requires delay before writing */ + udelay(5); + qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); + udelay(5); +} + +int ufs_qcom_ice_enable(struct ufs_qcom_host *host) +{ + if (!(host->hba->caps & UFSHCD_CAP_CRYPTO)) + return 0; + qcom_ice_low_power_mode_enable(host); + qcom_ice_optimization_enable(host); + return ufs_qcom_ice_resume(host); +} + +/* Poll until all BIST bits are reset */ +static int qcom_ice_wait_bist_status(struct ufs_qcom_host *host) +{ + int count; + u32 reg; + + for (count = 0; count < 100; count++) { + reg = qcom_ice_readl(host, QCOM_ICE_REG_BIST_STATUS); + if (!(reg & QCOM_ICE_BIST_STATUS_MASK)) + break; + udelay(50); + } + if (reg) + return -ETIMEDOUT; + return 0; +} + +int ufs_qcom_ice_resume(struct ufs_qcom_host *host) +{ + int err; + + if (!(host->hba->caps & UFSHCD_CAP_CRYPTO)) + return 0; + + err = qcom_ice_wait_bist_status(host); + if (err) { + dev_err(host->hba->dev, "BIST status error (%d)\n", err); + return err; + } + return 0; +} + +/* + * Program a key into a QC ICE keyslot, or evict a keyslot. QC ICE requires + * vendor-specific SCM calls for this; it doesn't support the standard way. + */ +int ufs_qcom_ice_program_key(struct ufs_hba *hba, + const union ufs_crypto_cfg_entry *cfg, int slot) +{ + union ufs_crypto_cap_entry cap; + union { + u8 bytes[AES_256_XTS_KEY_SIZE]; + u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)]; + } key; + int i; + int err; + + if (!(cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE)) + return qcom_scm_ice_invalidate_key(slot); + + /* Only AES-256-XTS has been tested so far. */ + cap = hba->crypto_cap_array[cfg->crypto_cap_idx]; + if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS || + cap.key_size != UFS_CRYPTO_KEY_SIZE_256) { + dev_err_ratelimited(hba->dev, + "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n", + cap.algorithm_id, cap.key_size); + return -EINVAL; + } + + memcpy(key.bytes, cfg->crypto_key, AES_256_XTS_KEY_SIZE); + + /* + * The SCM call byte-swaps the 32-bit words of the key. So we have to + * do the same, in order for the final key be correct. + */ + for (i = 0; i < ARRAY_SIZE(key.words); i++) + __cpu_to_be32s(&key.words[i]); + + err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE, + QCOM_SCM_ICE_CIPHER_AES_256_XTS, + cfg->data_unit_size); + memzero_explicit(&key, sizeof(key)); + return err; +} diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 6ae6e18b18bad26c9e3f568b407e8b4c0d759476..583eef0ef16c7dbe5d87807b6a4ce298cc7409df 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -246,7 +246,7 @@ static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host) mb(); } -/** +/* * ufs_qcom_host_reset - reset host controller and PHY */ static int ufs_qcom_host_reset(struct ufs_hba *hba) @@ -365,7 +365,7 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, /* check if UFS PHY moved from DISABLED to HIBERN8 */ err = ufs_qcom_check_hibern8(hba); ufs_qcom_enable_hw_clk_gating(hba); - + ufs_qcom_ice_enable(host); break; default: dev_err(hba->dev, "%s: invalid status %d\n", __func__, status); @@ -375,7 +375,7 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, return err; } -/** +/* * Returns zero for success and non-zero in case of a failure */ static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, @@ -613,6 +613,10 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) return err; } + err = ufs_qcom_ice_resume(host); + if (err) + return err; + hba->is_sys_suspended = false; return 0; } @@ -1071,6 +1075,7 @@ static void ufs_qcom_set_caps(struct ufs_hba *hba) hba->caps |= UFSHCD_CAP_CLK_SCALING; hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; hba->caps |= UFSHCD_CAP_WB_EN; + hba->caps |= UFSHCD_CAP_CRYPTO; if (host->hw_ver.major >= 0x2) { host->caps = UFS_QCOM_CAP_QUNIPRO | @@ -1275,7 +1280,8 @@ static int ufs_qcom_init(struct ufs_hba *hba) host->dev_ref_clk_en_mask = BIT(26); } else { /* "dev_ref_clk_ctrl_mem" is optional resource */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "dev_ref_clk_ctrl_mem"); if (res) { host->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res); @@ -1297,6 +1303,10 @@ static int ufs_qcom_init(struct ufs_hba *hba) ufs_qcom_set_caps(hba); ufs_qcom_advertise_quirks(hba); + err = ufs_qcom_ice_init(host); + if (err) + goto out_variant_clear; + ufs_qcom_set_bus_vote(hba, true); ufs_qcom_setup_clocks(hba, true, POST_CHANGE); @@ -1723,7 +1733,7 @@ static void ufs_qcom_config_scaling_param(struct ufs_hba *hba, } #endif -/** +/* * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations * * The variant operations configure the necessary controller and PHY @@ -1745,6 +1755,7 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { .dbg_register_dump = ufs_qcom_dump_dbg_regs, .device_reset = ufs_qcom_device_reset, .config_scaling_param = ufs_qcom_config_scaling_param, + .program_key = ufs_qcom_ice_program_key, }; /** diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index 2d95e7cc71874eacf38042f695532d07322f62f4..97247d17e258ad621f0e18ff47282d5aed7d6762 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -227,6 +227,9 @@ struct ufs_qcom_host { void __iomem *dev_ref_clk_ctrl_mmio; bool is_dev_ref_clk_enabled; struct ufs_hw_version hw_ver; +#ifdef CONFIG_SCSI_UFS_CRYPTO + void __iomem *ice_mmio; +#endif u32 dev_ref_clk_en_mask; @@ -264,4 +267,28 @@ static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host) return false; } +/* ufs-qcom-ice.c */ + +#ifdef CONFIG_SCSI_UFS_CRYPTO +int ufs_qcom_ice_init(struct ufs_qcom_host *host); +int ufs_qcom_ice_enable(struct ufs_qcom_host *host); +int ufs_qcom_ice_resume(struct ufs_qcom_host *host); +int ufs_qcom_ice_program_key(struct ufs_hba *hba, + const union ufs_crypto_cfg_entry *cfg, int slot); +#else +static inline int ufs_qcom_ice_init(struct ufs_qcom_host *host) +{ + return 0; +} +static inline int ufs_qcom_ice_enable(struct ufs_qcom_host *host) +{ + return 0; +} +static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host) +{ + return 0; +} +#define ufs_qcom_ice_program_key NULL +#endif /* !CONFIG_SCSI_UFS_CRYPTO */ + #endif /* UFS_QCOM_H_ */ diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index c70845d41449e6087745a28afcc01dc350375ff2..f8ab16f30fdca4b4a5435f7adb9e560a52551e24 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -1,36 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Universal Flash Storage Host controller driver - * - * This code is based on drivers/scsi/ufs/ufs.h * Copyright (C) 2011-2013 Samsung India Software Operations * * Authors: * Santosh Yaraganavi * Vinayak Holikatti - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * See the COPYING file in the top-level directory or visit - * - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This program is provided "AS IS" and "WITH ALL FAULTS" and - * without warranty of any kind. You are solely responsible for - * determining the appropriateness of using and distributing - * the program and assume all risks associated with your exercise - * of rights with respect to the program, including but not limited - * to infringement of third party rights, the risks and costs of - * program errors, damage to or loss of data, programs or equipment, - * and unavailability or interruption of operations. Under no - * circumstances will the contributor of this Program be liable for - * any damages of any kind arising from your use or distribution of - * this program. */ #ifndef _UFS_H @@ -63,6 +38,7 @@ #define UFS_UPIU_MAX_UNIT_NUM_ID 0x7F #define UFS_MAX_LUNS (SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID) #define UFS_UPIU_WLUN_ID (1 << 7) +#define UFS_RPMB_UNIT 0xC4 /* WriteBooster buffer is available only for the logical unit from 0 to 7 */ #define UFS_UPIU_MAX_WB_LUN_ID 8 @@ -200,16 +176,6 @@ enum desc_header_offset { QUERY_DESC_DESC_TYPE_OFFSET = 0x01, }; -enum ufs_desc_def_size { - QUERY_DESC_DEVICE_DEF_SIZE = 0x59, - QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90, - QUERY_DESC_UNIT_DEF_SIZE = 0x2D, - QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06, - QUERY_DESC_GEOMETRY_DEF_SIZE = 0x48, - QUERY_DESC_POWER_DEF_SIZE = 0x62, - QUERY_DESC_HEALTH_DEF_SIZE = 0x25, -}; - /* Unit descriptor parameters offsets in bytes*/ enum unit_desc_param { UNIT_DESC_PARAM_LEN = 0x0, diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c index 516a7f573942f17c79bb7b46190e429232a033b1..bcfbbd0d5c4560af3abb0007cf5b5eb969cdd0de 100644 --- a/drivers/scsi/ufs/ufs_bsg.c +++ b/drivers/scsi/ufs/ufs_bsg.c @@ -11,13 +11,12 @@ static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len, { int desc_size = be16_to_cpu(qr->length); int desc_id = qr->idn; - int ret; if (desc_size <= 0) return -EINVAL; - ret = ufshcd_map_desc_id_to_length(hba, desc_id, desc_len); - if (ret || !*desc_len) + ufshcd_map_desc_id_to_length(hba, desc_id, desc_len); + if (!*desc_len) return -EINVAL; *desc_len = min_t(int, *desc_len, desc_size); diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h index e3175a63c676bda949658d304c48fcadda02c59e..07f559ac5883a9011c01cc426b0307a199f0be9a 100644 --- a/drivers/scsi/ufs/ufs_quirks.h +++ b/drivers/scsi/ufs/ufs_quirks.h @@ -12,9 +12,10 @@ #define UFS_ANY_VENDOR 0xFFFF #define UFS_ANY_MODEL "ANY_MODEL" -#define UFS_VENDOR_TOSHIBA 0x198 +#define UFS_VENDOR_MICRON 0x12C #define UFS_VENDOR_SAMSUNG 0x1CE #define UFS_VENDOR_SKHYNIX 0x1AD +#define UFS_VENDOR_TOSHIBA 0x198 #define UFS_VENDOR_WDC 0x145 /** @@ -108,4 +109,11 @@ struct ufs_dev_fix { */ #define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 10) +/* + * Some UFS devices require delay after VCC power rail is turned-off. + * Enable this quirk to introduce 5ms delays after VCC power-off during + * suspend flow. + */ +#define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM (1 << 11) + #endif /* UFS_QUIRKS_H_ */ diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index 8f78a815149911706ecd21e8eed5cbba85cf2043..f407b13883acbcb097045009523e9ca1bcec858d 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Universal Flash Storage Host controller PCI glue driver * @@ -7,30 +8,6 @@ * Authors: * Santosh Yaraganavi * Vinayak Holikatti - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * See the COPYING file in the top-level directory or visit - * - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This program is provided "AS IS" and "WITH ALL FAULTS" and - * without warranty of any kind. You are solely responsible for - * determining the appropriateness of using and distributing - * the program and assume all risks associated with your exercise - * of rights with respect to the program, including but not limited - * to infringement of third party rights, the risks and costs of - * program errors, damage to or loss of data, programs or equipment, - * and unavailability or interruption of operations. Under no - * circumstances will the contributor of this Program be liable for - * any damages of any kind arising from your use or distribution of - * this program. */ #include "ufshcd.h" diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index 76f9be71c31bf744ea3e41f32c8a18b21ee80592..3db0af66c71c0f59e177f013767979ed8f62e2e9 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -1,36 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Universal Flash Storage Host controller Platform bus based glue driver - * - * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c * Copyright (C) 2011-2013 Samsung India Software Operations * * Authors: * Santosh Yaraganavi * Vinayak Holikatti - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * See the COPYING file in the top-level directory or visit - * - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This program is provided "AS IS" and "WITH ALL FAULTS" and - * without warranty of any kind. You are solely responsible for - * determining the appropriateness of using and distributing - * the program and assume all risks associated with your exercise - * of rights with respect to the program, including but not limited - * to infringement of third party rights, the risks and costs of - * program errors, damage to or loss of data, programs or equipment, - * and unavailability or interruption of operations. Under no - * circumstances will the contributor of this Program be liable for - * any damages of any kind arising from your use or distribution of - * this program. */ #include diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 4b27ba0ae123f8561c528006892bc86242937760..f477f140bd94235a1ce678c605c9cb69ba33de26 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1,40 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Universal Flash Storage Host controller driver Core - * - * This code is based on drivers/scsi/ufs/ufshcd.c * Copyright (C) 2011-2013 Samsung India Software Operations * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * Authors: * Santosh Yaraganavi * Vinayak Holikatti - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * See the COPYING file in the top-level directory or visit - * - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This program is provided "AS IS" and "WITH ALL FAULTS" and - * without warranty of any kind. You are solely responsible for - * determining the appropriateness of using and distributing - * the program and assume all risks associated with your exercise - * of rights with respect to the program, including but not limited - * to infringement of third party rights, the risks and costs of - * program errors, damage to or loss of data, programs or equipment, - * and unavailability or interruption of operations. Under no - * circumstances will the contributor of this Program be liable for - * any damages of any kind arising from your use or distribution of - * this program. - * - * The Linux Foundation chooses to take subject only to the GPLv2 - * license terms, and distributes only under these terms. */ #include @@ -217,23 +189,22 @@ ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state, static struct ufs_dev_fix ufs_fixups[] = { /* UFS cards deviations table */ - UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, + UFS_FIX(UFS_VENDOR_MICRON, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM), UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, + UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM | + UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE | UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS), - UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, - UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE), + UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, + UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME), + UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1" /*H28U62301AMR*/, + UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME), UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM), UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG", UFS_DEVICE_QUIRK_PA_TACTIVATE), UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG", UFS_DEVICE_QUIRK_PA_TACTIVATE), - UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, - UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME), - UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1" /*H28U62301AMR*/, - UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME), - END_FIX }; @@ -340,6 +311,26 @@ static void ufshcd_add_tm_upiu_trace(struct ufs_hba *hba, unsigned int tag, &descp->input_param1); } +static void ufshcd_add_uic_command_trace(struct ufs_hba *hba, + struct uic_command *ucmd, + const char *str) +{ + u32 cmd; + + if (!trace_ufshcd_uic_command_enabled()) + return; + + if (!strcmp(str, "send")) + cmd = ucmd->command; + else + cmd = ufshcd_readl(hba, REG_UIC_COMMAND); + + trace_ufshcd_uic_command(dev_name(hba->dev), str, cmd, + ufshcd_readl(hba, REG_UIC_COMMAND_ARG_1), + ufshcd_readl(hba, REG_UIC_COMMAND_ARG_2), + ufshcd_readl(hba, REG_UIC_COMMAND_ARG_3)); +} + static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag, const char *str) { @@ -673,7 +664,11 @@ static inline int ufshcd_get_tr_ocs(struct ufshcd_lrb *lrbp) */ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos) { - ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR); + if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR) + ufshcd_writel(hba, (1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR); + else + ufshcd_writel(hba, ~(1 << pos), + REG_UTP_TRANSFER_REQ_LIST_CLEAR); } /** @@ -683,7 +678,10 @@ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos) */ static inline void ufshcd_utmrl_clear(struct ufs_hba *hba, u32 pos) { - ufshcd_writel(hba, ~(1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR); + if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR) + ufshcd_writel(hba, (1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR); + else + ufshcd_writel(hba, ~(1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR); } /** @@ -1320,6 +1318,7 @@ static int ufshcd_devfreq_get_dev_status(struct device *dev, unsigned long flags; struct list_head *clk_list = &hba->clk_list_head; struct ufs_clk_info *clki; + ktime_t curr_t; if (!ufshcd_is_clkscaling_supported(hba)) return -EINVAL; @@ -1327,6 +1326,7 @@ static int ufshcd_devfreq_get_dev_status(struct device *dev, memset(stat, 0, sizeof(*stat)); spin_lock_irqsave(hba->host->host_lock, flags); + curr_t = ktime_get(); if (!scaling->window_start_t) goto start_window; @@ -1338,18 +1338,17 @@ static int ufshcd_devfreq_get_dev_status(struct device *dev, */ stat->current_frequency = clki->curr_freq; if (scaling->is_busy_started) - scaling->tot_busy_t += ktime_to_us(ktime_sub(ktime_get(), - scaling->busy_start_t)); + scaling->tot_busy_t += ktime_us_delta(curr_t, + scaling->busy_start_t); - stat->total_time = jiffies_to_usecs((long)jiffies - - (long)scaling->window_start_t); + stat->total_time = ktime_us_delta(curr_t, scaling->window_start_t); stat->busy_time = scaling->tot_busy_t; start_window: - scaling->window_start_t = jiffies; + scaling->window_start_t = curr_t; scaling->tot_busy_t = 0; if (hba->outstanding_reqs) { - scaling->busy_start_t = ktime_get(); + scaling->busy_start_t = curr_t; scaling->is_busy_started = true; } else { scaling->busy_start_t = 0; @@ -1883,6 +1882,7 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) static void ufshcd_clk_scaling_start_busy(struct ufs_hba *hba) { bool queue_resume_work = false; + ktime_t curr_t = ktime_get(); if (!ufshcd_is_clkscaling_supported(hba)) return; @@ -1898,13 +1898,13 @@ static void ufshcd_clk_scaling_start_busy(struct ufs_hba *hba) &hba->clk_scaling.resume_work); if (!hba->clk_scaling.window_start_t) { - hba->clk_scaling.window_start_t = jiffies; + hba->clk_scaling.window_start_t = curr_t; hba->clk_scaling.tot_busy_t = 0; hba->clk_scaling.is_busy_started = false; } if (!hba->clk_scaling.is_busy_started) { - hba->clk_scaling.busy_start_t = ktime_get(); + hba->clk_scaling.busy_start_t = curr_t; hba->clk_scaling.is_busy_started = true; } } @@ -1931,8 +1931,11 @@ static void ufshcd_clk_scaling_update_busy(struct ufs_hba *hba) static inline void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag) { - hba->lrb[task_tag].issue_time_stamp = ktime_get(); - hba->lrb[task_tag].compl_time_stamp = ktime_set(0, 0); + struct ufshcd_lrb *lrbp = &hba->lrb[task_tag]; + + lrbp->issue_time_stamp = ktime_get(); + lrbp->compl_time_stamp = ktime_set(0, 0); + ufshcd_vops_setup_xfer_req(hba, task_tag, (lrbp->cmd ? true : false)); ufshcd_add_command_trace(hba, task_tag, "send"); ufshcd_clk_scaling_start_busy(hba); __set_bit(task_tag, &hba->outstanding_reqs); @@ -2069,6 +2072,8 @@ ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) ufshcd_writel(hba, uic_cmd->argument2, REG_UIC_COMMAND_ARG_2); ufshcd_writel(hba, uic_cmd->argument3, REG_UIC_COMMAND_ARG_3); + ufshcd_add_uic_command_trace(hba, uic_cmd, "send"); + /* Write UIC Cmd */ ufshcd_writel(hba, uic_cmd->command & COMMAND_OPCODE_MASK, REG_UIC_COMMAND); @@ -2178,8 +2183,14 @@ static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) return sg_segments; if (sg_segments) { - lrbp->utr_descriptor_ptr->prd_table_length = - cpu_to_le16((u16)sg_segments); + + if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) + lrbp->utr_descriptor_ptr->prd_table_length = + cpu_to_le16((sg_segments * + sizeof(struct ufshcd_sg_entry))); + else + lrbp->utr_descriptor_ptr->prd_table_length = + cpu_to_le16((u16) (sg_segments)); prd = (struct ufshcd_sg_entry *)lrbp->ucd_prdt_ptr; @@ -2250,7 +2261,7 @@ static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs) * @cmd_dir: requests data direction */ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, - u32 *upiu_flags, enum dma_data_direction cmd_dir) + u8 *upiu_flags, enum dma_data_direction cmd_dir) { struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr; u32 data_direction; @@ -2299,7 +2310,7 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, * @upiu_flags: flags */ static -void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32 upiu_flags) +void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u8 upiu_flags) { struct scsi_cmnd *cmd = lrbp->cmd; struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr; @@ -2332,7 +2343,7 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32 upiu_flags) * @upiu_flags: flags */ static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba, - struct ufshcd_lrb *lrbp, u32 upiu_flags) + struct ufshcd_lrb *lrbp, u8 upiu_flags) { struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr; struct ufs_query *query = &hba->dev_cmd.query; @@ -2388,7 +2399,7 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp) */ static int ufshcd_comp_devman_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { - u32 upiu_flags; + u8 upiu_flags; int ret = 0; if ((hba->ufs_version == UFSHCI_VERSION_10) || @@ -2416,7 +2427,7 @@ static int ufshcd_comp_devman_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) */ static int ufshcd_comp_scsi_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { - u32 upiu_flags; + u8 upiu_flags; int ret = 0; if ((hba->ufs_version == UFSHCI_VERSION_10) || @@ -2561,7 +2572,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) /* issue command to the controller */ spin_lock_irqsave(hba->host->host_lock, flags); - ufshcd_vops_setup_xfer_req(hba, tag, true); ufshcd_send_command(hba, tag); out_unlock: spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -2749,7 +2759,6 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, /* Make sure descriptors are ready before ringing the doorbell */ wmb(); spin_lock_irqsave(hba->host->host_lock, flags); - ufshcd_vops_setup_xfer_req(hba, tag, false); ufshcd_send_command(hba, tag); spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -3081,95 +3090,37 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba, } EXPORT_SYMBOL_GPL(ufshcd_query_descriptor_retry); -/** - * ufshcd_read_desc_length - read the specified descriptor length from header - * @hba: Pointer to adapter instance - * @desc_id: descriptor idn value - * @desc_index: descriptor index - * @desc_length: pointer to variable to read the length of descriptor - * - * Return 0 in case of success, non-zero otherwise - */ -static int ufshcd_read_desc_length(struct ufs_hba *hba, - enum desc_idn desc_id, - int desc_index, - int *desc_length) -{ - int ret; - u8 header[QUERY_DESC_HDR_SIZE]; - int header_len = QUERY_DESC_HDR_SIZE; - - if (desc_id >= QUERY_DESC_IDN_MAX) - return -EINVAL; - - ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, - desc_id, desc_index, 0, header, - &header_len); - - if (ret) { - dev_err(hba->dev, "%s: Failed to get descriptor header id %d", - __func__, desc_id); - return ret; - } else if (desc_id != header[QUERY_DESC_DESC_TYPE_OFFSET]) { - dev_warn(hba->dev, "%s: descriptor header id %d and desc_id %d mismatch", - __func__, header[QUERY_DESC_DESC_TYPE_OFFSET], - desc_id); - ret = -EINVAL; - } - - *desc_length = header[QUERY_DESC_LENGTH_OFFSET]; - return ret; - -} - /** * ufshcd_map_desc_id_to_length - map descriptor IDN to its length * @hba: Pointer to adapter instance * @desc_id: descriptor idn value * @desc_len: mapped desc length (out) - * - * Return 0 in case of success, non-zero otherwise */ -int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, - enum desc_idn desc_id, int *desc_len) +void ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, + int *desc_len) { - switch (desc_id) { - case QUERY_DESC_IDN_DEVICE: - *desc_len = hba->desc_size.dev_desc; - break; - case QUERY_DESC_IDN_POWER: - *desc_len = hba->desc_size.pwr_desc; - break; - case QUERY_DESC_IDN_GEOMETRY: - *desc_len = hba->desc_size.geom_desc; - break; - case QUERY_DESC_IDN_CONFIGURATION: - *desc_len = hba->desc_size.conf_desc; - break; - case QUERY_DESC_IDN_UNIT: - *desc_len = hba->desc_size.unit_desc; - break; - case QUERY_DESC_IDN_INTERCONNECT: - *desc_len = hba->desc_size.interc_desc; - break; - case QUERY_DESC_IDN_STRING: - *desc_len = QUERY_DESC_MAX_SIZE; - break; - case QUERY_DESC_IDN_HEALTH: - *desc_len = hba->desc_size.hlth_desc; - break; - case QUERY_DESC_IDN_RFU_0: - case QUERY_DESC_IDN_RFU_1: - *desc_len = 0; - break; - default: + if (desc_id >= QUERY_DESC_IDN_MAX || desc_id == QUERY_DESC_IDN_RFU_0 || + desc_id == QUERY_DESC_IDN_RFU_1) *desc_len = 0; - return -EINVAL; - } - return 0; + else + *desc_len = hba->desc_size[desc_id]; } EXPORT_SYMBOL(ufshcd_map_desc_id_to_length); +static void ufshcd_update_desc_length(struct ufs_hba *hba, + enum desc_idn desc_id, int desc_index, + unsigned char desc_len) +{ + if (hba->desc_size[desc_id] == QUERY_DESC_MAX_SIZE && + desc_id != QUERY_DESC_IDN_STRING && desc_index != UFS_RPMB_UNIT) + /* For UFS 3.1, the normal unit descriptor is 10 bytes larger + * than the RPMB unit, however, both descriptors share the same + * desc_idn, to cover both unit descriptors with one length, we + * choose the normal unit descriptor length by desc_index. + */ + hba->desc_size[desc_id] = desc_len; +} + /** * ufshcd_read_desc_param - read the specified descriptor parameter * @hba: Pointer to adapter instance @@ -3197,16 +3148,11 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, if (desc_id >= QUERY_DESC_IDN_MAX || !param_size) return -EINVAL; - /* Get the max length of descriptor from structure filled up at probe - * time. - */ - ret = ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len); - - /* Sanity checks */ - if (ret || !buff_len) { - dev_err(hba->dev, "%s: Failed to get full descriptor length", - __func__); - return ret; + /* Get the length of descriptor */ + ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len); + if (!buff_len) { + dev_err(hba->dev, "%s: Failed to get desc length", __func__); + return -EINVAL; } /* Check whether we need temp memory */ @@ -3238,9 +3184,13 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, goto out; } + /* Update descriptor length */ + buff_len = desc_buf[QUERY_DESC_LENGTH_OFFSET]; + ufshcd_update_desc_length(hba, desc_id, desc_index, buff_len); + /* Check wherher we will not copy more data, than available */ - if (is_kmalloc && param_size > buff_len) - param_size = buff_len; + if (is_kmalloc && (param_offset + param_size) > buff_len) + param_size = buff_len - param_offset; if (is_kmalloc) memcpy(param_read_buf, &desc_buf[param_offset], param_size); @@ -3250,16 +3200,6 @@ out: return ret; } -static inline int ufshcd_read_desc(struct ufs_hba *hba, - enum desc_idn desc_id, - int desc_index, - void *buf, - u32 size) -{ - return ufshcd_read_desc_param(hba, desc_id, desc_index, 0, buf, size); -} - - /** * struct uc_string_id - unicode string * @@ -3307,9 +3247,8 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, if (!uc_str) return -ENOMEM; - ret = ufshcd_read_desc(hba, QUERY_DESC_IDN_STRING, - desc_index, uc_str, - QUERY_DESC_MAX_SIZE); + ret = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_STRING, desc_index, 0, + (u8 *)uc_str, QUERY_DESC_MAX_SIZE); if (ret < 0) { dev_err(hba->dev, "Reading String Desc failed after %d retries. err = %d\n", QUERY_REQ_RETRIES, ret); @@ -3540,11 +3479,21 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) cpu_to_le32(upper_32_bits(cmd_desc_element_addr)); /* Response upiu and prdt offset should be in double words */ - utrdlp[i].response_upiu_offset = - cpu_to_le16(response_offset >> 2); - utrdlp[i].prd_table_offset = cpu_to_le16(prdt_offset >> 2); - utrdlp[i].response_upiu_length = - cpu_to_le16(ALIGNED_UPIU_SIZE >> 2); + if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) { + utrdlp[i].response_upiu_offset = + cpu_to_le16(response_offset); + utrdlp[i].prd_table_offset = + cpu_to_le16(prdt_offset); + utrdlp[i].response_upiu_length = + cpu_to_le16(ALIGNED_UPIU_SIZE); + } else { + utrdlp[i].response_upiu_offset = + cpu_to_le16(response_offset >> 2); + utrdlp[i].prd_table_offset = + cpu_to_le16(prdt_offset >> 2); + utrdlp[i].response_upiu_length = + cpu_to_le16(ALIGNED_UPIU_SIZE >> 2); + } ufshcd_init_lrb(hba, &hba->lrb[i], i); } @@ -3574,6 +3523,52 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) "dme-link-startup: error code %d\n", ret); return ret; } +/** + * ufshcd_dme_reset - UIC command for DME_RESET + * @hba: per adapter instance + * + * DME_RESET command is issued in order to reset UniPro stack. + * This function now deals with cold reset. + * + * Returns 0 on success, non-zero value on failure + */ +static int ufshcd_dme_reset(struct ufs_hba *hba) +{ + struct uic_command uic_cmd = {0}; + int ret; + + uic_cmd.command = UIC_CMD_DME_RESET; + + ret = ufshcd_send_uic_cmd(hba, &uic_cmd); + if (ret) + dev_err(hba->dev, + "dme-reset: error code %d\n", ret); + + return ret; +} + +/** + * ufshcd_dme_enable - UIC command for DME_ENABLE + * @hba: per adapter instance + * + * DME_ENABLE command is issued in order to enable UniPro stack. + * + * Returns 0 on success, non-zero value on failure + */ +static int ufshcd_dme_enable(struct ufs_hba *hba) +{ + struct uic_command uic_cmd = {0}; + int ret; + + uic_cmd.command = UIC_CMD_DME_ENABLE; + + ret = ufshcd_send_uic_cmd(hba, &uic_cmd); + if (ret) + dev_err(hba->dev, + "dme-reset: error code %d\n", ret); + + return ret; +} static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba) { @@ -4299,7 +4294,7 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba) } /** - * ufshcd_hba_enable - initialize the controller + * ufshcd_hba_execute_hce - initialize the controller * @hba: per adapter instance * * The controller resets itself and controller firmware initialization @@ -4308,7 +4303,7 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba) * * Returns 0 on success, non-zero value on failure */ -int ufshcd_hba_enable(struct ufs_hba *hba) +static int ufshcd_hba_execute_hce(struct ufs_hba *hba) { int retry; @@ -4356,6 +4351,32 @@ int ufshcd_hba_enable(struct ufs_hba *hba) return 0; } + +int ufshcd_hba_enable(struct ufs_hba *hba) +{ + int ret; + + if (hba->quirks & UFSHCI_QUIRK_BROKEN_HCE) { + ufshcd_set_link_off(hba); + ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE); + + /* enable UIC related interrupts */ + ufshcd_enable_intr(hba, UFSHCD_UIC_MASK); + ret = ufshcd_dme_reset(hba); + if (!ret) { + ret = ufshcd_dme_enable(hba); + if (!ret) + ufshcd_vops_hce_enable_notify(hba, POST_CHANGE); + if (ret) + dev_err(hba->dev, + "Host controller enable failed with non-hce\n"); + } + } else { + ret = ufshcd_hba_execute_hce(hba); + } + + return ret; +} EXPORT_SYMBOL_GPL(ufshcd_hba_enable); static int ufshcd_disable_tx_lcc(struct ufs_hba *hba, bool peer) @@ -4874,6 +4895,10 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) complete(hba->uic_async_done); retval = IRQ_HANDLED; } + + if (retval == IRQ_HANDLED) + ufshcd_add_uic_command_trace(hba, hba->active_uic_cmd, + "complete"); return retval; } @@ -4892,6 +4917,7 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, for_each_set_bit(index, &completed_reqs, hba->nutrs) { lrbp = &hba->lrb[index]; + lrbp->compl_time_stamp = ktime_get(); cmd = lrbp->cmd; if (cmd) { ufshcd_add_command_trace(hba, index, "complete"); @@ -4900,13 +4926,11 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, cmd->result = result; /* Mark completed command as NULL in LRB */ lrbp->cmd = NULL; - lrbp->compl_time_stamp = ktime_get(); /* Do not touch lrbp after scsi done */ cmd->scsi_done(cmd); __ufshcd_release(hba); } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE || lrbp->command_type == UTP_CMD_TYPE_UFS_STORAGE) { - lrbp->compl_time_stamp = ktime_get(); if (hba->dev_cmd.complete) { ufshcd_add_command_trace(hba, index, "dev_complete"); @@ -4943,7 +4967,8 @@ static irqreturn_t ufshcd_transfer_req_compl(struct ufs_hba *hba) * false interrupt if device completes another request after resetting * aggregation and before reading the DB. */ - if (ufshcd_is_intr_aggr_allowed(hba)) + if (ufshcd_is_intr_aggr_allowed(hba) && + !(hba->quirks & UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR)) ufshcd_reset_intr_aggr(hba); tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); @@ -6131,7 +6156,7 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, int tag; struct completion wait; unsigned long flags; - u32 upiu_flags; + u8 upiu_flags; down_read(&hba->clk_scaling_lock); @@ -6745,7 +6770,7 @@ out: static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba) { int ret; - int buff_len = hba->desc_size.pwr_desc; + int buff_len = hba->desc_size[QUERY_DESC_IDN_POWER]; u8 *desc_buf; u32 icc_level; @@ -6753,8 +6778,8 @@ static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba) if (!desc_buf) return; - ret = ufshcd_read_desc(hba, QUERY_DESC_IDN_POWER, 0, - desc_buf, buff_len); + ret = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_POWER, 0, 0, + desc_buf, buff_len); if (ret) { dev_err(hba->dev, "%s: Failed reading power descriptor.len = %d ret = %d", @@ -6857,20 +6882,31 @@ out: static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf) { + struct ufs_dev_info *dev_info = &hba->dev_info; u8 lun; u32 d_lu_wb_buf_alloc; if (!ufshcd_is_wb_allowed(hba)) return; + /* + * Probe WB only for UFS-2.2 and UFS-3.1 (and later) devices or + * UFS devices with quirk UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES + * enabled + */ + if (!(dev_info->wspecversion >= 0x310 || + dev_info->wspecversion == 0x220 || + (hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES))) + goto wb_disabled; - if (hba->desc_size.dev_desc < DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP + 4) + if (hba->desc_size[QUERY_DESC_IDN_DEVICE] < + DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP + 4) goto wb_disabled; - hba->dev_info.d_ext_ufs_feature_sup = + dev_info->d_ext_ufs_feature_sup = get_unaligned_be32(desc_buf + DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP); - if (!(hba->dev_info.d_ext_ufs_feature_sup & UFS_DEV_WRITE_BOOSTER_SUP)) + if (!(dev_info->d_ext_ufs_feature_sup & UFS_DEV_WRITE_BOOSTER_SUP)) goto wb_disabled; /* @@ -6879,17 +6915,17 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf) * a max of 1 lun would have wb buffer configured. * Now only shared buffer mode is supported. */ - hba->dev_info.b_wb_buffer_type = + dev_info->b_wb_buffer_type = desc_buf[DEVICE_DESC_PARAM_WB_TYPE]; - hba->dev_info.b_presrv_uspc_en = + dev_info->b_presrv_uspc_en = desc_buf[DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN]; - if (hba->dev_info.b_wb_buffer_type == WB_BUF_MODE_SHARED) { - hba->dev_info.d_wb_alloc_units = + if (dev_info->b_wb_buffer_type == WB_BUF_MODE_SHARED) { + dev_info->d_wb_alloc_units = get_unaligned_be32(desc_buf + DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS); - if (!hba->dev_info.d_wb_alloc_units) + if (!dev_info->d_wb_alloc_units) goto wb_disabled; } else { for (lun = 0; lun < UFS_UPIU_MAX_WB_LUN_ID; lun++) { @@ -6900,7 +6936,7 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf) (u8 *)&d_lu_wb_buf_alloc, sizeof(d_lu_wb_buf_alloc)); if (d_lu_wb_buf_alloc) { - hba->dev_info.wb_dedicated_lu = lun; + dev_info->wb_dedicated_lu = lun; break; } } @@ -6945,21 +6981,18 @@ static void ufs_fixup_device_setup(struct ufs_hba *hba) static int ufs_get_device_desc(struct ufs_hba *hba) { int err; - size_t buff_len; u8 model_index; u8 *desc_buf; struct ufs_dev_info *dev_info = &hba->dev_info; - buff_len = max_t(size_t, hba->desc_size.dev_desc, - QUERY_DESC_MAX_SIZE + 1); - desc_buf = kmalloc(buff_len, GFP_KERNEL); + desc_buf = kmalloc(QUERY_DESC_MAX_SIZE, GFP_KERNEL); if (!desc_buf) { err = -ENOMEM; goto out; } - err = ufshcd_read_desc(hba, QUERY_DESC_IDN_DEVICE, 0, desc_buf, - hba->desc_size.dev_desc); + err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_DEVICE, 0, 0, desc_buf, + hba->desc_size[QUERY_DESC_IDN_DEVICE]); if (err) { dev_err(hba->dev, "%s: Failed reading Device Desc. err = %d\n", __func__, err); @@ -6989,14 +7022,7 @@ static int ufs_get_device_desc(struct ufs_hba *hba) ufs_fixup_device_setup(hba); - /* - * Probe WB only for UFS-3.1 devices or UFS devices with quirk - * UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES enabled - */ - if (dev_info->wspecversion >= 0x310 || - dev_info->wspecversion == 0x220 || - (hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES)) - ufshcd_wb_probe(hba, desc_buf); + ufshcd_wb_probe(hba, desc_buf); /* * ufshcd_read_string_desc returns size of the string @@ -7188,61 +7214,21 @@ static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) hba->req_abort_count = 0; } -static void ufshcd_init_desc_sizes(struct ufs_hba *hba) -{ - int err; - - err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_DEVICE, 0, - &hba->desc_size.dev_desc); - if (err) - hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE; - - err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_POWER, 0, - &hba->desc_size.pwr_desc); - if (err) - hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE; - - err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_INTERCONNECT, 0, - &hba->desc_size.interc_desc); - if (err) - hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE; - - err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_CONFIGURATION, 0, - &hba->desc_size.conf_desc); - if (err) - hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE; - - err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_UNIT, 0, - &hba->desc_size.unit_desc); - if (err) - hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE; - - err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_GEOMETRY, 0, - &hba->desc_size.geom_desc); - if (err) - hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; - - err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_HEALTH, 0, - &hba->desc_size.hlth_desc); - if (err) - hba->desc_size.hlth_desc = QUERY_DESC_HEALTH_DEF_SIZE; -} - static int ufshcd_device_geo_params_init(struct ufs_hba *hba) { int err; size_t buff_len; u8 *desc_buf; - buff_len = hba->desc_size.geom_desc; + buff_len = hba->desc_size[QUERY_DESC_IDN_GEOMETRY]; desc_buf = kmalloc(buff_len, GFP_KERNEL); if (!desc_buf) { err = -ENOMEM; goto out; } - err = ufshcd_read_desc(hba, QUERY_DESC_IDN_GEOMETRY, 0, - desc_buf, buff_len); + err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_GEOMETRY, 0, 0, + desc_buf, buff_len); if (err) { dev_err(hba->dev, "%s: Failed reading Geometry Desc. err = %d\n", __func__, err); @@ -7330,10 +7316,11 @@ out: static int ufshcd_device_params_init(struct ufs_hba *hba) { bool flag; - int ret; + int ret, i; - /* Init check for device descriptor sizes */ - ufshcd_init_desc_sizes(hba); + /* Init device descriptor sizes */ + for (i = 0; i < QUERY_DESC_IDN_MAX; i++) + hba->desc_size[i] = QUERY_DESC_MAX_SIZE; /* Init UFS geometry descriptor related parameters */ ret = ufshcd_device_geo_params_init(hba); @@ -8126,6 +8113,8 @@ out: static void ufshcd_vreg_set_lpm(struct ufs_hba *hba) { + bool vcc_off = false; + /* * It seems some UFS devices may keep drawing more than sleep current * (atleast for 500us) from UFS rails (especially from VCCQ rail). @@ -8154,13 +8143,22 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba) if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) && !hba->dev_info.is_lu_power_on_wp) { ufshcd_setup_vreg(hba, false); + vcc_off = true; } else if (!ufshcd_is_ufs_dev_active(hba)) { ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); + vcc_off = true; if (!ufshcd_is_link_active(hba)) { ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq); ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2); } } + + /* + * Some UFS devices require delay after VCC power rail is turned-off. + */ + if (vcc_off && hba->vreg_info.vcc && + hba->dev_quirks & UFS_DEVICE_QUIRK_DELAY_AFTER_LPM) + usleep_range(5000, 5100); } static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index b811cc0fc57ee2b065185321d0bb76ce2a120f95..174c0d6365e847e894242ce8799528ba81178c47 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -1,37 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Universal Flash Storage Host controller driver - * - * This code is based on drivers/scsi/ufs/ufshcd.h * Copyright (C) 2011-2013 Samsung India Software Operations * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * Authors: * Santosh Yaraganavi * Vinayak Holikatti - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * See the COPYING file in the top-level directory or visit - * - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This program is provided "AS IS" and "WITH ALL FAULTS" and - * without warranty of any kind. You are solely responsible for - * determining the appropriateness of using and distributing - * the program and assume all risks associated with your exercise - * of rights with respect to the program, including but not limited - * to infringement of third party rights, the risks and costs of - * program errors, damage to or loss of data, programs or equipment, - * and unavailability or interruption of operations. Under no - * circumstances will the contributor of this Program be liable for - * any damages of any kind arising from your use or distribution of - * this program. */ #ifndef _UFSHCD_H @@ -89,8 +64,6 @@ enum dev_cmd_type { * @argument1: UIC command argument 1 * @argument2: UIC command argument 2 * @argument3: UIC command argument 3 - * @cmd_active: Indicate if UIC command is outstanding - * @result: UIC command result * @done: UIC command completion */ struct uic_command { @@ -98,8 +71,6 @@ struct uic_command { u32 argument1; u32 argument2; u32 argument3; - int cmd_active; - int result; struct completion done; }; @@ -243,16 +214,6 @@ struct ufs_dev_cmd { struct ufs_query query; }; -struct ufs_desc_size { - int dev_desc; - int pwr_desc; - int geom_desc; - int interc_desc; - int unit_desc; - int conf_desc; - int hlth_desc; -}; - /** * struct ufs_clk_info - UFS clock related info * @list: list headed by hba->clk_list_head @@ -421,7 +382,7 @@ struct ufs_saved_pwr_info { struct ufs_clk_scaling { int active_reqs; unsigned long tot_busy_t; - unsigned long window_start_t; + ktime_t window_start_t; ktime_t busy_start_t; struct device_attribute enable_attr; struct ufs_saved_pwr_info saved_pwr_info; @@ -531,11 +492,34 @@ enum ufshcd_quirks { */ UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION = 1 << 5, + /* + * Clear handling for transfer/task request list is just opposite. + */ + UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR = 1 << 6, + + /* + * This quirk needs to be enabled if host controller doesn't allow + * that the interrupt aggregation timer and counter are reset by s/w. + */ + UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR = 1 << 7, + + /* + * This quirks needs to be enabled if host controller cannot be + * enabled via HCE register. + */ + UFSHCI_QUIRK_BROKEN_HCE = 1 << 8, + + /* + * This quirk needs to be enabled if the host controller regards + * resolution of the values of PRDTO and PRDTL in UTRD as byte. + */ + UFSHCD_QUIRK_PRDT_BYTE_GRAN = 1 << 9, + /* * This quirk needs to be enabled if the host controller reports * OCS FATAL ERROR with device error through sense data */ - UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR = 1 << 6, + UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR = 1 << 10, }; enum ufshcd_caps { @@ -766,7 +750,7 @@ struct ufs_hba { bool is_urgent_bkops_lvl_checked; struct rw_semaphore clk_scaling_lock; - struct ufs_desc_size desc_size; + unsigned char desc_size[QUERY_DESC_IDN_MAX]; atomic_t scsi_block_reqs_cnt; struct device bsg_dev; @@ -1011,8 +995,8 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, int ufshcd_hold(struct ufs_hba *hba, bool async); void ufshcd_release(struct ufs_hba *hba); -int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, - int *desc_length); +void ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, + int *desc_length); u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba); diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index 7459f633e7af212a7bd2cdb3edcf46f57218b7a0..b29611524da9cbcc6d8c7a1b00338963d854d1a0 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h @@ -1,36 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Universal Flash Storage Host controller driver - * - * This code is based on drivers/scsi/ufs/ufshci.h * Copyright (C) 2011-2013 Samsung India Software Operations * * Authors: * Santosh Yaraganavi * Vinayak Holikatti - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * See the COPYING file in the top-level directory or visit - * - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This program is provided "AS IS" and "WITH ALL FAULTS" and - * without warranty of any kind. You are solely responsible for - * determining the appropriateness of using and distributing - * the program and assume all risks associated with your exercise - * of rights with respect to the program, including but not limited - * to infringement of third party rights, the risks and costs of - * program errors, damage to or loss of data, programs or equipment, - * and unavailability or interruption of operations. Under no - * circumstances will the contributor of this Program be liable for - * any damages of any kind arising from your use or distribution of - * this program. */ #ifndef _UFSHCI_H diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h index 766d551df3fc8232631c4187fbdad890d2c5b64f..4ee64782fd4885c0d8c77beb9938469cca90d88a 100644 --- a/drivers/scsi/ufs/unipro.h +++ b/drivers/scsi/ufs/unipro.h @@ -64,8 +64,25 @@ #define CFGRXOVR4 0x00E9 #define RXSQCTRL 0x00B5 #define CFGRXOVR6 0x00BF +#define RX_HS_G1_SYNC_LENGTH_CAP 0x008B +#define RX_HS_G1_PREP_LENGTH_CAP 0x008C +#define RX_HS_G2_SYNC_LENGTH_CAP 0x0094 +#define RX_HS_G3_SYNC_LENGTH_CAP 0x0095 +#define RX_HS_G2_PREP_LENGTH_CAP 0x0096 +#define RX_HS_G3_PREP_LENGTH_CAP 0x0097 +#define RX_ADV_GRANULARITY_CAP 0x0098 +#define RX_MIN_ACTIVATETIME_CAP 0x008F +#define RX_HIBERN8TIME_CAP 0x0092 +#define RX_ADV_HIBERN8TIME_CAP 0x0099 +#define RX_ADV_MIN_ACTIVATETIME_CAP 0x009A + #define is_mphy_tx_attr(attr) (attr < RX_MODE) +#define RX_ADV_FINE_GRAN_STEP(x) ((((x) & 0x3) << 1) | 0x1) +#define SYNC_LEN_FINE(x) ((x) & 0x3F) +#define SYNC_LEN_COARSE(x) ((1 << 6) | ((x) & 0x3F)) +#define PREP_LEN(x) ((x) & 0xF) + #define RX_MIN_ACTIVATETIME_UNIT_US 100 #define HIBERN8TIME_UNIT_US 100 @@ -124,6 +141,7 @@ #define PA_PACPREQEOBTIMEOUT 0x1591 #define PA_HIBERN8TIME 0x15A7 #define PA_LOCALVERINFO 0x15A9 +#define PA_GRANULARITY 0x15AA #define PA_TACTIVATE 0x15A8 #define PA_PACPFRAMECOUNT 0x15C0 #define PA_PACPERRORCOUNT 0x15C1 @@ -291,4 +309,19 @@ enum { TRUE, }; +/* CPort setting */ +#define E2EFC_ON (1 << 0) +#define E2EFC_OFF (0 << 0) +#define CSD_N_ON (0 << 1) +#define CSD_N_OFF (1 << 1) +#define CSV_N_ON (0 << 2) +#define CSV_N_OFF (1 << 2) +#define CPORT_DEF_FLAGS (CSV_N_OFF | CSD_N_OFF | E2EFC_OFF) + +/* CPort connection state */ +enum { + CPORT_IDLE = 0, + CPORT_CONNECTED, +}; + #endif /* _UNIPRO_H_ */ diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 0e0910c5b94242488ea306a8fb1df8e1fdda7048..8cc003aa4d0093bb0147c9810f10d7e0755c5d99 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -100,7 +100,7 @@ static void virtscsi_compute_resid(struct scsi_cmnd *sc, u32 resid) scsi_set_resid(sc, resid); } -/** +/* * virtscsi_complete_cmd - finish a scsi_cmd and invoke scsi_done * * Called with vq_lock held. @@ -350,6 +350,14 @@ static void virtscsi_rescan_hotunplug(struct virtio_scsi *vscsi) if (result == 0 && inq_result[0] >> 5) { /* PQ indicates the LUN is not attached */ scsi_remove_device(sdev); + } else if (host_byte(result) == DID_BAD_TARGET) { + /* + * If all LUNs of a virtio-scsi device are unplugged + * it will respond with BAD TARGET on any INQUIRY + * command. + * Remove the device in this case as well. + */ + scsi_remove_device(sdev); } } @@ -1002,14 +1010,10 @@ static int __init init(void) return 0; error: - if (virtscsi_cmd_pool) { - mempool_destroy(virtscsi_cmd_pool); - virtscsi_cmd_pool = NULL; - } - if (virtscsi_cmd_cache) { - kmem_cache_destroy(virtscsi_cmd_cache); - virtscsi_cmd_cache = NULL; - } + mempool_destroy(virtscsi_cmd_pool); + virtscsi_cmd_pool = NULL; + kmem_cache_destroy(virtscsi_cmd_cache); + virtscsi_cmd_cache = NULL; return ret; } diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index dccef1dcea329f82b4535116ab7cd3e171926728..3cbecb2d8fc098c27f47cdf7bc72abfd6a408d4f 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -986,7 +986,7 @@ static int lantiq_ssc_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 8) | SPI_BPW_MASK(16) | SPI_BPW_MASK(32); - spi->wq = alloc_ordered_workqueue(dev_name(dev), 0); + spi->wq = alloc_ordered_workqueue(dev_name(dev), WQ_MEM_RECLAIM); if (!spi->wq) { err = -ENOMEM; goto err_clk_put; diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index b3fb4d41e23141dc310adbc897a2315aa6c2d9ee..e6c831c6ccccf9f087087c18ea9cfbd44781ed36 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -56,8 +56,6 @@ source "drivers/staging/sm750fb/Kconfig" source "drivers/staging/emxx_udc/Kconfig" -source "drivers/staging/speakup/Kconfig" - source "drivers/staging/nvec/Kconfig" source "drivers/staging/media/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 3d8c7ea21a1036b9fb3c7974a0b3e9e2ccf2a931..a3b1fd0622f9b0218ed9b115972cd38f49651a29 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -20,7 +20,6 @@ obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_FB_SM750) += sm750fb/ obj-$(CONFIG_USB_EMXX) += emxx_udc/ -obj-$(CONFIG_SPEAKUP) += speakup/ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_STAGING_BOARD) += board/ diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index c05a214191dad3649bfb55d5f170775c6736a289..10b4be1f3e78e47e8809c4504fd51d8776700364 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -95,6 +95,15 @@ static DEFINE_MUTEX(ashmem_mutex); static struct kmem_cache *ashmem_area_cachep __read_mostly; static struct kmem_cache *ashmem_range_cachep __read_mostly; +/* + * A separate lockdep class for the backing shmem inodes to resolve the lockdep + * warning about the race between kswapd taking fs_reclaim before inode_lock + * and write syscall taking inode_lock and then fs_reclaim. + * Note that such race is impossible because ashmem does not support write + * syscalls operating on the backing shmem. + */ +static struct lock_class_key backing_shmem_inode_class; + static inline unsigned long range_size(struct ashmem_range *range) { return range->pgend - range->pgstart + 1; @@ -396,6 +405,7 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) if (!asma->file) { char *name = ASHMEM_NAME_DEF; struct file *vmfile; + struct inode *inode; if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') name = asma->name; @@ -407,6 +417,8 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) goto out; } vmfile->f_mode |= FMODE_LSEEK; + inode = file_inode(vmfile); + lockdep_set_class(&inode->i_rwsem, &backing_shmem_inode_class); asma->file = vmfile; /* * override mmap operation of the vmfile so that it can't be diff --git a/drivers/staging/android/ion/heaps/ion_system_heap.c b/drivers/staging/android/ion/heaps/ion_system_heap.c index d76595ecedb5d6a9e7c9d7293d2de820ed7ebc67..fc630492996f997a13d98cac2d0f844bab5b475d 100644 --- a/drivers/staging/android/ion/heaps/ion_system_heap.c +++ b/drivers/staging/android/ion/heaps/ion_system_heap.c @@ -167,7 +167,7 @@ static void ion_system_heap_free(struct ion_buffer *buffer) if (!(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) ion_buffer_zero(buffer); - for_each_sg(table->sgl, sg, table->nents, i) + for_each_sgtable_sg(table, sg, i) free_buffer_page(sys_heap, buffer, sg_page(sg)); sg_free_table(table); kfree(table); diff --git a/drivers/staging/clocking-wizard/Kconfig b/drivers/staging/clocking-wizard/Kconfig index 04be22dca9b6e38474f3b140b5c7154c92143c8b..69cf51445f082f25820a6a66786ef83fadedfbe7 100644 --- a/drivers/staging/clocking-wizard/Kconfig +++ b/drivers/staging/clocking-wizard/Kconfig @@ -5,6 +5,6 @@ config COMMON_CLK_XLNX_CLKWZRD tristate "Xilinx Clocking Wizard" - depends on COMMON_CLK && OF + depends on COMMON_CLK && OF && IOMEM help Support for the Xilinx Clocking Wizard IP core clock generator. diff --git a/drivers/staging/clocking-wizard/dt-binding.txt b/drivers/staging/clocking-wizard/dt-binding.txt index 723271e9331688a714f173614a4a3382e54f966e..efb67ff9f76c4ec710ae39de69da67ef700237c7 100644 --- a/drivers/staging/clocking-wizard/dt-binding.txt +++ b/drivers/staging/clocking-wizard/dt-binding.txt @@ -5,7 +5,7 @@ found in the product guide[2]. [1] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Clocking Wizard Product Guide -http://www.xilinx.com/support/documentation/ip_documentation/clk_wiz/v5_1/pg065-clk-wiz.pdf +https://www.xilinx.com/support/documentation/ip_documentation/clk_wiz/v5_1/pg065-clk-wiz.pdf Required properties: - compatible: Must be 'xlnx,clocking-wizard' diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index e85a99b68f31c101843920ba310f2751d29ab338..d99231c737fbfb52b03265b6e8937d11743907b3 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -2169,6 +2169,7 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, break; case COMEDI_CHANINFO: { struct comedi_chaninfo it; + if (copy_from_user(&it, (void __user *)arg, sizeof(it))) rc = -EFAULT; else @@ -2177,6 +2178,7 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, } case COMEDI_RANGEINFO: { struct comedi_rangeinfo it; + if (copy_from_user(&it, (void __user *)arg, sizeof(it))) rc = -EFAULT; else @@ -2249,6 +2251,7 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, } case COMEDI_INSN: { struct comedi_insn insn; + if (copy_from_user(&insn, (void __user *)arg, sizeof(insn))) rc = -EFAULT; else @@ -2953,7 +2956,7 @@ static int get_compat_cmd(struct comedi_cmd *cmd, cmd->scan_end_arg = v32.scan_end_arg; cmd->stop_src = v32.stop_src; cmd->stop_arg = v32.stop_arg; - cmd->chanlist = compat_ptr(v32.chanlist); + cmd->chanlist = (unsigned int __force *)compat_ptr(v32.chanlist); cmd->chanlist_len = v32.chanlist_len; cmd->data = compat_ptr(v32.data); cmd->data_len = v32.data_len; @@ -2980,7 +2983,7 @@ static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, v32.stop_src = cmd->stop_src; v32.stop_arg = cmd->stop_arg; /* Assume chanlist pointer is unchanged. */ - v32.chanlist = ptr_to_compat(cmd->chanlist); + v32.chanlist = ptr_to_compat((unsigned int __user *)cmd->chanlist); v32.chanlist_len = cmd->chanlist_len; v32.data = ptr_to_compat(cmd->data); v32.data_len = cmd->data_len; @@ -3426,6 +3429,6 @@ static void __exit comedi_cleanup(void) } module_exit(comedi_cleanup); -MODULE_AUTHOR("http://www.comedi.org"); +MODULE_AUTHOR("https://www.comedi.org"); MODULE_DESCRIPTION("Comedi core module"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/comedi_pci.c b/drivers/staging/comedi/comedi_pci.c index 126048b03f43e1cd6a1c6285fcfff96d1c4df587..54739af7eb71d716681ac2516ed84f347916377e 100644 --- a/drivers/staging/comedi/comedi_pci.c +++ b/drivers/staging/comedi/comedi_pci.c @@ -223,6 +223,6 @@ static void __exit comedi_pci_exit(void) } module_exit(comedi_pci_exit); -MODULE_AUTHOR("http://www.comedi.org"); +MODULE_AUTHOR("https://www.comedi.org"); MODULE_DESCRIPTION("Comedi PCI interface module"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/comedi_pcmcia.c b/drivers/staging/comedi/comedi_pcmcia.c index e16f35eae343b42d6f96565a7ff3c378e43c236c..bb273bb202e61735c29ac2b9ace65205883c8227 100644 --- a/drivers/staging/comedi/comedi_pcmcia.c +++ b/drivers/staging/comedi/comedi_pcmcia.c @@ -204,6 +204,6 @@ static void __exit comedi_pcmcia_exit(void) } module_exit(comedi_pcmcia_exit); -MODULE_AUTHOR("http://www.comedi.org"); +MODULE_AUTHOR("https://www.comedi.org"); MODULE_DESCRIPTION("Comedi PCMCIA interface module"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/comedi_usb.c b/drivers/staging/comedi/comedi_usb.c index c632c2bae72248f11d08a4c6a5748554a08509d8..eea8ebf32ed0c61a07b9b7368e2a2e1be1290be6 100644 --- a/drivers/staging/comedi/comedi_usb.c +++ b/drivers/staging/comedi/comedi_usb.c @@ -146,6 +146,6 @@ static void __exit comedi_usb_exit(void) } module_exit(comedi_usb_exit); -MODULE_AUTHOR("http://www.comedi.org"); +MODULE_AUTHOR("https://www.comedi.org"); MODULE_DESCRIPTION("Comedi USB interface module"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 3d6105b5a11b13abc7123aefc8d536f9ed706c74..e23335c75867941135812d4f7243a34bb87c2bb1 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -120,6 +120,6 @@ static struct comedi_driver dev_8255_driver = { }; module_comedi_driver(dev_8255_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for standalone 8255 devices"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 9ed05f962fdba6f3399e296006bd5704f0ee4bc3..5a810f0e532a63f7d3da51b4378e3ec82d9662f1 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -291,5 +291,5 @@ static struct pci_driver pci_8255_pci_driver = { module_comedi_pci_driver(pci_8255_driver, pci_8255_pci_driver); MODULE_DESCRIPTION("COMEDI - Generic PCI based 8255 Digital I/O boards"); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index e035c9f757a1ca317c7e71f61081c0bcd763fef7..35b75f0c9200b9d946d8964fe2af6f8950f31cef 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -389,6 +389,6 @@ static struct pci_driver apci1032_pci_driver = { }; module_comedi_pci_driver(apci1032_driver, apci1032_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("ADDI-DATA APCI-1032, 32 channel DI boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 816dd25b9d0e451d5312b762fd636be74e6ce067..11efb21555e395b2e2b86a38132a69f75fc1d9f6 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -882,6 +882,6 @@ static struct pci_driver apci1500_pci_driver = { }; module_comedi_pci_driver(apci1500_driver, apci1500_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("ADDI-DATA APCI-1500, 16 channel DI / 16 channel DO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c index 6c8213ee1a748e0ac9a418492c94d90a29b300f3..274ec9fb030ce0562fb70fabf2bf101524ba15b9 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -212,5 +212,5 @@ static struct pci_driver apci1516_pci_driver = { module_comedi_pci_driver(apci1516_driver, apci1516_pci_driver); MODULE_DESCRIPTION("ADDI-DATA APCI-1016/1516/2016, 16 channel DIO boards"); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index 1268ba34be5f0981d849236ee2d7659abb383731..fadefcb5c23704c951b358e3772ede3be6fecc7e 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -815,6 +815,6 @@ static struct pci_driver apci1564_pci_driver = { }; module_comedi_pci_driver(apci1564_driver, apci1564_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("ADDI-DATA APCI-1564, 32 channel DI / 32 channel DO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c index 050d0b4b32099d0c1a3b03d5587b153131aa7b3c..9bbef3b15f3fce465adb55acfc9ab8324990d2cd 100644 --- a/drivers/staging/comedi/drivers/addi_apci_16xx.c +++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c @@ -174,5 +174,5 @@ static struct pci_driver apci16xx_pci_driver = { module_comedi_pci_driver(apci16xx_driver, apci16xx_pci_driver); MODULE_DESCRIPTION("ADDI-DATA APCI-1648/1696, TTL I/O boards"); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index a122f3f3f5ec557636b28c57dae3b38974093622..e9a2b37a4ae0f4a1615fef902bd5390c024f5812 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -325,6 +325,6 @@ static struct pci_driver apci2032_pci_driver = { }; module_comedi_pci_driver(apci2032_driver, apci2032_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("ADDI-DATA APCI-2032, 32 channel DO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c index 140d1514a10660b38518da85363eeb85c71834cc..4c5aee784bd9f2475655537c481129e6cf4584fb 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2200.c +++ b/drivers/staging/comedi/drivers/addi_apci_2200.c @@ -139,5 +139,5 @@ static struct pci_driver apci2200_pci_driver = { module_comedi_pci_driver(apci2200_driver, apci2200_pci_driver); MODULE_DESCRIPTION("ADDI-DATA APCI-2200 Relay board, optically isolated"); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index d2810fdd5e63050bd84df5a5b29a129bd15a2764..1ed3b33d1a3027a8366a4f1ff31385b2c38cb6da 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -1112,6 +1112,6 @@ static struct pci_driver apci3120_pci_driver = { }; module_comedi_pci_driver(apci3120_driver, apci3120_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("ADDI-DATA APCI-3120, Analog input board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index b4aa588975df66b496b4dcf736928e641df79068..f0c9642f3f1aea48b4b8cafcc0cc29d0979a5854 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -413,5 +413,5 @@ static struct pci_driver apci3501_pci_driver = { module_comedi_pci_driver(apci3501_driver, apci3501_pci_driver); MODULE_DESCRIPTION("ADDI-DATA APCI-3501 Analog output board"); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index 55784f24e2a748936c1a1be4992867ee22ea84d3..a90d59377e187e8cb8c31e61e2e40ac0548e520a 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -956,6 +956,6 @@ static struct pci_driver apci3xxx_pci_driver = { }; module_comedi_pci_driver(apci3xxx_driver, apci3xxx_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index e21840e9002d8213c3a82eecd4b25742654824dd..9ae4cc523dd45f78b430db86d74857da6372ca60 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -196,6 +196,6 @@ static struct pci_driver adl_pci6208_pci_driver = { }; module_comedi_pci_driver(adl_pci6208_driver, adl_pci6208_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for ADLink 6208 series cards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index 3022793b1bc54f60000c0c08feede73797c1d67f..d5e1bda81557894debe7550e0c0d7d07bbc0a9a5 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -149,6 +149,6 @@ static struct pci_driver adl_pci8164_pci_driver = { }; module_comedi_pci_driver(adl_pci8164_driver, adl_pci8164_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index f4dba6271d0d736edb23a121d72bbc0dd5c28ad8..a062c5ab20e9f4a30363d88ba5493f8920a670da 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -742,6 +742,6 @@ static struct pci_driver adl_pci9111_pci_driver = { }; module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 2528ca0ede6df5651b471a5a43f431200a27aadb..cda3a4267dca3c7137b865635ddbb0c8e5eb8600 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -1731,6 +1731,6 @@ static struct pci_driver adl_pci9118_pci_driver = { }; module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index 5d431573bcca92599f204f083a6b85e8b5a8c6db..d719f76709ef5d0bd23c363ae8cac4d80e2da795 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -238,6 +238,6 @@ static struct comedi_driver adq12b_driver = { }; module_comedi_driver(adq12b_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index ddc0dc93d08b64182cc9d2b56325bde0e3af0931..692893c7e5c3d06ab2f7161f5d0a0d7df871be42 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -958,6 +958,6 @@ static struct pci_driver adv_pci1710_pci_driver = { }; module_comedi_pci_driver(adv_pci1710_driver, adv_pci1710_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi: Advantech PCI-1710 Series Multifunction DAS Cards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 771d61f87427dfd99c83f708f6050d541e254b67..23660a9fdb9c7f24c8a0d72bc42bf494c02f4042 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -222,6 +222,6 @@ static struct pci_driver adv_pci1723_pci_driver = { }; module_comedi_pci_driver(adv_pci1723_driver, adv_pci1723_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Advantech PCI-1723 Comedi driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adv_pci1760.c b/drivers/staging/comedi/drivers/adv_pci1760.c index f460f21efb90c52ec9abc065c7efd90934679878..6de8ab97d346cd8d2e23c877f596d9ebf479416d 100644 --- a/drivers/staging/comedi/drivers/adv_pci1760.c +++ b/drivers/staging/comedi/drivers/adv_pci1760.c @@ -419,6 +419,6 @@ static struct pci_driver pci1760_pci_driver = { }; module_comedi_pci_driver(pci1760_driver, pci1760_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Advantech PCI-1760"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 5fef2aef7e0350ddeae65dcb38b1b5eba7717a71..0df28ec00f371c15342444b9e69d1b76d934eb62 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -532,6 +532,6 @@ static struct pci_driver adv_pci_dio_pci_driver = { }; module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Advantech Digital I/O Cards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index f4beda1ed64090a03defb987f3158cf0d8a18093..4829115921a394ca52a2e3ada1e2eefcf6941779 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -272,6 +272,6 @@ static struct comedi_driver aio_aio12_8_driver = { }; module_comedi_driver(aio_aio12_8_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Access I/O AIO12-8 Analog I/O Board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 41c9c56816ef50aa555e2d07bbbd4eca90e3b7c7..fe38762350752f12eecd713dab270562805a3df7 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -230,6 +230,6 @@ static struct comedi_driver aio_iiro_16_driver = { }; module_comedi_driver(aio_iiro_16_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Access I/O Products 104-IIRO-16 board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 26e63d64ffc6d2116a6bac2b84c1c3545631ea49..fa19c9e7c56b7d5af6199d797a011bb64fad21fa 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -4,7 +4,7 @@ * * Driver for Amplicon PC212E, PC214E, PC215E, PC218E, PC272E. * - * Copyright (C) 2005-2013 MEV Ltd. + * Copyright (C) 2005-2013 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef @@ -260,6 +260,6 @@ static struct comedi_driver amplc_dio200_driver = { }; module_comedi_driver(amplc_dio200_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Amplicon 200 Series ISA DIO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_dio200.h b/drivers/staging/comedi/drivers/amplc_dio200.h index 1d81393be6dfe1070f41920cf74e3ece39b6d9c7..745baaf940ee6d3f37e3969e9af2f4d0e01d2d8e 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.h +++ b/drivers/staging/comedi/drivers/amplc_dio200.h @@ -5,7 +5,7 @@ * Header for amplc_dio200.c, amplc_dio200_common.c and * amplc_dio200_pci.c. * - * Copyright (C) 2005-2013 MEV Ltd. + * Copyright (C) 2005-2013 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index 0b2f04b02ebc2e78f75d0023c284b2dbc6a04532..a3454130d5f80ca401f0fb0b9b603863bf2c372a 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -4,7 +4,7 @@ * * Common support code for "amplc_dio200" and "amplc_dio200_pci". * - * Copyright (C) 2005-2013 MEV Ltd. + * Copyright (C) 2005-2013 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef @@ -853,6 +853,6 @@ static void __exit amplc_dio200_common_exit(void) } module_exit(amplc_dio200_common_exit); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi helper for amplc_dio200 and amplc_dio200_pci"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c index 30d239731e0bf69cfd682c14e038a98e41eed2d1..1bd7a42c8464dbef7f6ad180408971269bade256 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_pci.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c @@ -3,7 +3,7 @@ * * Driver for Amplicon PCI215, PCI272, PCIe215, PCIe236, PCIe296. * - * Copyright (C) 2005-2013 MEV Ltd. + * Copyright (C) 2005-2013 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef @@ -410,6 +410,6 @@ static struct pci_driver dio200_pci_pci_driver = { }; module_comedi_pci_driver(dio200_pci_comedi_driver, dio200_pci_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Amplicon 200 Series PCI(e) DIO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index b7dd15f5ec63c04b6843a857395ff9b6edd8ff98..c377af1d5246e5e8f87ee06d8a19c3188347efd6 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -3,7 +3,7 @@ * comedi/drivers/amplc_pc236.c * Driver for Amplicon PC36AT DIO boards. * - * Copyright (C) 2002 MEV Ltd. + * Copyright (C) 2002 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef @@ -71,6 +71,6 @@ static struct comedi_driver amplc_pc236_driver = { module_comedi_driver(amplc_pc236_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Amplicon PC36AT DIO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pc236.h b/drivers/staging/comedi/drivers/amplc_pc236.h index 45e933ee873597523052caf91f8724127678db39..7e72729f749257fd42c8a27a6b53e601b1a3ba82 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.h +++ b/drivers/staging/comedi/drivers/amplc_pc236.h @@ -3,7 +3,7 @@ * comedi/drivers/amplc_pc236.h * Header for "amplc_pc236", "amplc_pci236" and "amplc_pc236_common". * - * Copyright (C) 2002-2014 MEV Ltd. + * Copyright (C) 2002-2014 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef diff --git a/drivers/staging/comedi/drivers/amplc_pc236_common.c b/drivers/staging/comedi/drivers/amplc_pc236_common.c index 01b90e4eca8a01f14aba117677c24c6bc0baca52..043752663188fd37f3ae697677e549c6ce2a57f4 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236_common.c +++ b/drivers/staging/comedi/drivers/amplc_pc236_common.c @@ -3,7 +3,7 @@ * comedi/drivers/amplc_pc236_common.c * Common support code for "amplc_pc236" and "amplc_pci236". * - * Copyright (C) 2002-2014 MEV Ltd. + * Copyright (C) 2002-2014 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef @@ -186,6 +186,6 @@ static void __exit amplc_pc236_common_exit(void) } module_exit(amplc_pc236_common_exit); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi helper for amplc_pc236 and amplc_pci236"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 84c989f12faf5fc725f0376016e971c02b67e870..68da6098ee8402c0d0e30f84cf797d9a29b0a67b 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -2,7 +2,7 @@ /* * Driver for Amplicon PC263 relay board. * - * Copyright (C) 2002 MEV Ltd. + * Copyright (C) 2002 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef @@ -97,6 +97,6 @@ static struct comedi_driver amplc_pc263_driver = { module_comedi_driver(amplc_pc263_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Amplicon PC263 relay board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 657b736ef46d3b2f6ff811c3daceb23f8456a513..bcf6d61af8633d5c66f68d9eda186af0a0c9bf87 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -3,7 +3,7 @@ * comedi/drivers/amplc_pci224.c * Driver for Amplicon PCI224 and PCI234 AO boards. * - * Copyright (C) 2005 MEV Ltd. + * Copyright (C) 2005 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef @@ -1138,6 +1138,6 @@ static struct pci_driver amplc_pci224_pci_driver = { }; module_comedi_pci_driver(amplc_pci224_driver, amplc_pci224_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Amplicon PCI224 and PCI234 AO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index f7e673121864bdeb5867629b9b49014fe784f458..8911dc2bd2c64e0ebbac76997022fe2992cc1853 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2570,6 +2570,6 @@ static struct pci_driver amplc_pci230_pci_driver = { }; module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Amplicon PCI230(+) and PCI260(+)"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pci236.c b/drivers/staging/comedi/drivers/amplc_pci236.c index 86ea876a11be9babe0463a305400dfa5f50d43bb..e7f6fa4d101ae4cf55625b95ca6b822f16c419fc 100644 --- a/drivers/staging/comedi/drivers/amplc_pci236.c +++ b/drivers/staging/comedi/drivers/amplc_pci236.c @@ -3,7 +3,7 @@ * comedi/drivers/amplc_pci236.c * Driver for Amplicon PCI236 DIO boards. * - * Copyright (C) 2002-2014 MEV Ltd. + * Copyright (C) 2002-2014 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef @@ -139,6 +139,6 @@ static struct pci_driver amplc_pci236_pci_driver = { module_comedi_pci_driver(amplc_pci236_driver, amplc_pci236_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Amplicon PCI236 DIO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c index c3efe14020a84f5e8295f59800dc4d3d64662857..9217973f1141aa9f7f0d0455077c6012a6775cf4 100644 --- a/drivers/staging/comedi/drivers/amplc_pci263.c +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -2,7 +2,7 @@ /* * Driver for Amplicon PCI263 relay board. * - * Copyright (C) 2002 MEV Ltd. + * Copyright (C) 2002 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef @@ -106,6 +106,6 @@ static struct pci_driver amplc_pci263_pci_driver = { }; module_comedi_pci_driver(amplc_pci263_driver, amplc_pci263_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Amplicon PCI263 relay board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index 41cc784320a940072764c9cbd5030477943858d3..786fd15698dfbc929486b689faf6169ac8c562df 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -293,6 +293,6 @@ static struct comedi_driver c6xdigio_driver = { }; module_comedi_driver(c6xdigio_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for the C6x_DIGIO DSP daughter card"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 02ae00c953130b6a0ed3818bb342621aadddf836..48ec2ee953dc5dd91b94e0202ce128157126ff15 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1493,6 +1493,6 @@ static struct pci_driver cb_pcidas_pci_driver = { }; module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for MeasurementComputing PCI-DAS series"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index e1774e09a320369e321f754d344f089f31345744..fa987bb0e7cd4b628dcbcffc1c647ab3ffde3c47 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -4119,6 +4119,6 @@ static struct pci_driver cb_pcidas64_pci_driver = { }; module_comedi_pci_driver(cb_pcidas64_driver, cb_pcidas64_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 1d09dd265ab7e6c9007470ab5a1034fc84041efa..78cf1603638c1af71abc6857a60da0aef9105cd4 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -416,6 +416,6 @@ static struct pci_driver cb_pcidda_pci_driver = { }; module_comedi_pci_driver(cb_pcidda_driver, cb_pcidda_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index a9d052bfda3805a5702763bd6cc024d4372f8de7..2292f69da4f42388b66d8cf539c076822f7e6571 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -28,8 +28,8 @@ * No interrupts, multi channel or FIFO AI, * although the card looks like it could support this. * - * http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf - * http://www.mccdaq.com/PDFs/Manuals/pcie-das1602-16.pdf + * https://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf + * https://www.mccdaq.com/PDFs/Manuals/pcie-das1602-16.pdf */ #include @@ -470,6 +470,6 @@ static struct pci_driver cb_pcimdas_pci_driver = { }; module_comedi_pci_driver(cb_pcimdas_driver, cb_pcimdas_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for PCIM-DAS1602/16 and PCIe-DAS1602/16"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/comedi_8255.c b/drivers/staging/comedi/drivers/comedi_8255.c index 62baa0d79302359e25218dd95ec6456718cfaa11..3298725b9ba59c7e78bf82317520647fd2e8e7bb 100644 --- a/drivers/staging/comedi/drivers/comedi_8255.c +++ b/drivers/staging/comedi/drivers/comedi_8255.c @@ -271,6 +271,6 @@ static void __exit comedi_8255_module_exit(void) } module_exit(comedi_8255_module_exit); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi: Generic 8255 digital I/O support"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index efaa57372aeb0c3cc24911879142a2ef4c07a784..9361b2dcf949d4f0ca19b07a7a59b1020f7ca0fb 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -300,6 +300,6 @@ static struct comedi_driver parport_driver = { }; module_comedi_driver(parport_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi: Standard parallel port driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index ef4c7c8a2b71669cd43ef29ee17dadc2c029b5fa..cbc225eb19918c517580a28309c66431b9e0b220 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -844,6 +844,6 @@ static void __exit comedi_test_exit(void) } module_exit(comedi_test_exit); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index 49be795b4971458884e5fdc0f9bef5eed259f986..b8fdd9c1f16617a08dceb32a76ef4a5b203f3def 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -112,6 +112,6 @@ static struct pci_driver contec_pci_dio_pci_driver = { }; module_comedi_pci_driver(contec_pci_dio_driver, contec_pci_dio_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 28603dfadce2619b10fda6446823ff65eafee4e0..f64e747078bdbddf2cfc1f30614a22156433c700 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -18,7 +18,7 @@ * the source code for the Windows driver. * * The FPGA on the board requires firmware, which is available from - * http://www.comedi.org in the comedi_nonfree_firmware tarball. + * https://www.comedi.org in the comedi_nonfree_firmware tarball. * * Configuration options: not applicable, uses PCI auto config */ @@ -781,7 +781,7 @@ static struct pci_driver db2k_pci_driver = { }; module_comedi_pci_driver(db2k_driver, db2k_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(DB2K_FIRMWARE); diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 65e5f2e6c122cdf036b98dc5b58280e8e07565d0..b50743c5b822a61d3b2e588559f3f0cfc991914a 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -465,6 +465,6 @@ static void __exit das08_exit(void) } module_exit(das08_exit); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi common DAS08 support module"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c index b22a45bd21d1042d72c6c6a2dd2f4a949b8431c9..8c4cfa8214238740000b7f3c5545958871fbf44d 100644 --- a/drivers/staging/comedi/drivers/das08_isa.c +++ b/drivers/staging/comedi/drivers/das08_isa.c @@ -185,6 +185,6 @@ static struct comedi_driver das08_isa_driver = { }; module_comedi_driver(das08_isa_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c index 7856fc13466a181ad84a21623d638c4d4b199679..1cd903336a4c4fdebbaa6c0ae43703b1be6e65c3 100644 --- a/drivers/staging/comedi/drivers/das08_pci.c +++ b/drivers/staging/comedi/drivers/das08_pci.c @@ -91,6 +91,6 @@ static struct pci_driver das08_pci_driver = { }; module_comedi_pci_driver(das08_pci_comedi_driver, das08_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 81eb51b1be2534641ee87824b8bd22b2d0c3001b..4ac2622b0facdbb838ae18fcc5b848b6e3511d48 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1195,6 +1195,6 @@ static struct comedi_driver das16_driver = { }; module_comedi_driver(das16_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for DAS16 compatible boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index 4e36377b592aad5d066bc7699ddd7b306a6c55d7..75f3dbbe97ac8bbf4470f05a1b24ca62130e1b1f 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -617,6 +617,6 @@ static struct comedi_driver das16m1_driver = { }; module_comedi_driver(das16m1_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for CIO-DAS16/M1 ISA cards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index f16aa7e9f4f3ad00ccd9d410e6165ca662ec584b..f50891a6ee7d44af1a2d8595675756bbc2c889d3 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1359,6 +1359,6 @@ static struct comedi_driver das1800_driver = { }; module_comedi_driver(das1800_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for DAS1800 compatible ISA boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 8cf09ef3012fa5923c9978fbce0fcae6a094b7a0..4ea100ff6930f3c91fd5d5aac0192a343863cefb 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -739,6 +739,6 @@ static struct comedi_driver driver_das800 = { }; module_comedi_driver(driver_das800); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 75693cdde31384ea9aeab58bc289cd73865dd9d6..17e6018918bbf9bc51359f5214756c1adf36cd0d 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -611,6 +611,6 @@ static struct comedi_driver dmm32at_driver = { }; module_comedi_driver(dmm32at_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi: Diamond Systems Diamond-MM-32-AT"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index a29880981d81d1ef47d408c4f8888308aec25067..0d571d817b4ea095d52dfd6214b69f6c81e6ada5 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -640,6 +640,6 @@ static struct comedi_driver dt2801_driver = { }; module_comedi_driver(dt2801_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 8a1f9efe7d4e9f5cf880224123c31f783e96ee44..0eb5e6ba69160879f26c208d6b64813e05a99a9d 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -640,6 +640,6 @@ static struct comedi_driver dt2811_driver = { }; module_comedi_driver(dt2811_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Data Translation DT2811 series boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index d2c71573736144ea1cec4745041de66833d68277..bcf4d5444fafa74a0b832f47160d5ecd7f118062 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -285,6 +285,6 @@ static struct comedi_driver dt2814_driver = { }; module_comedi_driver(dt2814_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index 78a7c1b3448ab1088cf959bff6d4df4d85af0417..5906f32aa01f3f0ae55e9ed80e2ce430cbce9048 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -212,6 +212,6 @@ static struct comedi_driver dt2815_driver = { }; module_comedi_driver(dt2815_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 9babb2a5196a393cbfeec09091ea0d589cf98e26..7c1463e835d31b322790eac4889e8f54b20389c4 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -135,6 +135,6 @@ static struct comedi_driver dt2817_driver = { }; module_comedi_driver(dt2817_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 89dc84d3c8031ab36844a644815fbe8260f4387b..2656b4b0e3d09e4029219967c7dfd9f14dda21de 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1167,6 +1167,6 @@ static struct comedi_driver dt282x_driver = { }; module_comedi_driver(dt282x_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Data Translation DT2821 series"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 011e19161b78ae98e7ea51dadde17ef5a75921b9..ec27aa4730d4f578681c4daba49423f44be400cf 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -735,6 +735,6 @@ static struct pci_driver dt3000_pci_driver = { }; module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Data Translation DT3000 series boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index 41c50c7a8f59b355f1e40585047f35ec808a4dc7..b715f30659fa5ae6a433a2573a12545b6f2fef7d 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -138,6 +138,6 @@ static struct comedi_driver fl512_driver = { }; module_comedi_driver(fl512_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index dc62db1ee1dde83b3dfd550bf1cb9eaae5a3ea25..e35e4a74371416289137003d8596659e44250416 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -718,6 +718,6 @@ static struct pci_driver gsc_hpdi_pci_driver = { }; module_comedi_pci_driver(gsc_hpdi_driver, gsc_hpdi_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for General Standards PCI-HPDI32/PMC-HPDI32"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index b14aaed6b5254b48fe6e3594832bece4bf53c141..16d2b78de83c199e0e43d307e44084c07fc3e042 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -331,6 +331,6 @@ static struct pci_driver icp_multi_pci_driver = { }; module_comedi_pci_driver(icp_multi_driver, icp_multi_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Inova ICP_MULTI board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 3eaf7c59de75f8a74d44df34f40c18b534536a88..399255dbe3888976377f82096ed75976c2bf7507 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -519,6 +519,6 @@ static struct comedi_driver ii20k_driver = { }; module_comedi_driver(ii20k_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Intelligent Instruments PCI-20001C"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index c3c88e6d298f9a561cf19f71a0a65977f7969c5a..7a02c4fa3cda88541cb1220be7c8b1a623eb1450 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -24,7 +24,7 @@ * The DSP on the board requires initialization code, which can be * loaded by placing it in /lib/firmware/comedi. The initialization * code should be somewhere on the media you got with your card. One - * version is available from http://www.comedi.org in the + * version is available from https://www.comedi.org in the * comedi_nonfree_firmware tarball. The file is called "jr3pci.idm". */ @@ -810,7 +810,7 @@ static struct pci_driver jr3_pci_pci_driver = { }; module_comedi_pci_driver(jr3_pci_driver, jr3_pci_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for JR3/PCI force sensor board"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE("comedi/jr3pci.idm"); diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index e612cf605700776c066dbf9d74eab0f72b7e1788..bef1b20c1c8d82715fdb204ee28d8af3c268d4cb 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -227,6 +227,6 @@ static struct pci_driver ke_counter_pci_driver = { }; module_comedi_pci_driver(ke_counter_driver, ke_counter_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Kolter Electronic Counter Card"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index ee53571a89698857579daadef13dcce1465fc0c1..726e40dc17b6212a74b94caf654e4d2a9e6514ff 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -26,7 +26,7 @@ * * The firmware required by these boards is available in the * comedi_nonfree_firmware tarball available from - * http://www.comedi.org. + * https://www.comedi.org. */ #include @@ -1272,7 +1272,7 @@ static struct pci_driver me4000_pci_driver = { }; module_comedi_pci_driver(me4000_driver, me4000_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Meilhaus ME-4000 series boards"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(ME4000_FIRMWARE); diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index 169742be17b86f345afb3e4a5af8dce34937dfe1..ef18e387471b358cb55c7645c2ac0871a8c6dcbd 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -550,7 +550,7 @@ static struct pci_driver me_daq_pci_driver = { }; module_comedi_pci_driver(me_daq_driver, me_daq_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(ME2600_FIRMWARE); diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index cc9fc263573e11b394a5880eb0b2afafc6a62ea4..70960e3ba878085e3536b005511d484b62351298 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -933,6 +933,6 @@ static void __exit mite_module_exit(void) } module_exit(mite_module_exit); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi helper for NI Mite PCI interface chip"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index bf3a3a08c7ab89fc581afeac5c5064b58768cefc..646f4c086204fe6831464d4e16a9def1501fdabb 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -306,6 +306,6 @@ static struct comedi_driver mpc624_driver = { }; module_comedi_driver(mpc624_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Micro/sys MPC-624 PC/104 board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index c85c9ab3655fd55ad752b40a0438ee4eacba3d45..c1897aee9a9a7361bca33d3f07e2c6b63efc4652 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -327,6 +327,6 @@ static struct comedi_driver multiq3_driver = { }; module_comedi_driver(multiq3_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Quanser Consulting MultiQ-3 board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index 4518c2680b7c5e986b660ed575acc02fef5f17e7..99e744172f4d4f41eee619b0fdf83d7e0041442b 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -486,6 +486,6 @@ static struct pci_driver ni6527_pci_driver = { }; module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for National Instruments PCI-6527"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 996074e471d3648106723a0b69682523f87f3217..eb3f9f7109da9378ead1833cac4511dd15e655ac 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -817,6 +817,6 @@ static struct pci_driver ni_65xx_pci_driver = { }; module_comedi_pci_driver(ni_65xx_driver, ni_65xx_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for NI PCI-65xx static dio boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 75d5c9c2459602986079e4730cd97cb86de7f368..e60d0125bcb27552fbaee6337cde912aa6b3b426 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1250,6 +1250,6 @@ static struct pci_driver ni_660x_pci_driver = { }; module_comedi_pci_driver(ni_660x_driver, ni_660x_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for NI 660x counter/timer boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 4e4ae31c8d0b8b43e9c56ea0022971148a92f7f3..c197e47486bec687ab1d671f7ab8d35d128e63fe 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -277,6 +277,6 @@ static struct pci_driver ni_670x_pci_driver = { }; module_comedi_pci_driver(ni_670x_driver, ni_670x_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 76e8d047f71eacdbd7225fde107927b1440fa974..10ad7b88713e94e886e3d4403049104feec3c1e4 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -777,6 +777,6 @@ static struct comedi_driver ni_at_a2150_driver = { }; module_comedi_driver(ni_at_a2150_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 814895d01ffa10a80c8da1bf3ed0502b5091c7c2..2a0fb4d460db1110e19505cd92d3bf7b10a3c952 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -369,6 +369,6 @@ static struct comedi_driver ni_at_ao_driver = { }; module_comedi_driver(ni_at_ao_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for NI AT-AO-6/10 boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 2b7bfe0dd7f3fd5ba320205ee0b25694f277a63b..56c78da475e70d0c1b24948f77a1b7337a1ad12d 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -354,7 +354,7 @@ static struct comedi_driver ni_atmio_driver = { }; module_comedi_driver(ni_atmio_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 0bca7d7520157733676713953456ea2b14662a8a..dffce1aa3e698a19247a49160736bcda5a9b6e9e 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -724,6 +724,6 @@ static struct comedi_driver atmio16d_driver = { }; module_comedi_driver(atmio16d_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 81fd4c26a16f2fcd76a2aff4f29af82545ee50a8..d40fc89f9cef254b59c477dad3ddcbb155813f6b 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -34,8 +34,8 @@ * * IRQ is assigned but not used. * - * Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf - * User Manual: http://www.ni.com/pdf/manuals/320676d.pdf + * Manuals: Register level: https://www.ni.com/pdf/manuals/340698.pdf + * User Manual: https://www.ni.com/pdf/manuals/320676d.pdf */ #include diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index c6cf37ccbc920a171222de00dfe418f57b0643a4..1f4a07bd1d2693ecc20e53ac9a1a2cbf75750e2b 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -27,7 +27,7 @@ * Kernel-level ISA plug-and-play support for the lab-pc-1200 boards * has not yet been added to the driver, mainly due to the fact that * I don't know the device id numbers. If you have one of these boards, - * please file a bug report at http://comedi.org/ so I can get the + * please file a bug report at https://comedi.org/ so I can get the * necessary information from you. * * The 1200 series boards have onboard calibration dacs for correcting @@ -111,6 +111,6 @@ static struct comedi_driver labpc_driver = { }; module_comedi_driver(labpc_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for NI Lab-PC ISA boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index ce0f85026277d42b4b2efda2757dda76a347689c..dd97946eacaf5d6cf3a6bedd2e9584f5ebd0acbb 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -1358,6 +1358,6 @@ static void __exit labpc_common_exit(void) } module_exit(labpc_common_exit); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi helper for ni_labpc, ni_labpc_pci, ni_labpc_cs"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 5657736a94082b9c585b66e20720f57b7d821a0a..a551aca6e6155364ac57455833e10d41ba877a85 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -176,6 +176,6 @@ static void __exit ni_labpc_isadma_cleanup_module(void) } module_exit(ni_labpc_isadma_cleanup_module); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi NI Lab-PC ISA DMA support"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index d7d5a797355826929a5630c2cc31eee0e0d85660..ec180b0fedf75088388037cb91870ba6f2a1e5a1 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -128,5 +128,5 @@ static struct pci_driver labpc_pci_driver = { module_comedi_pci_driver(labpc_pci_comedi_driver, labpc_pci_driver); MODULE_DESCRIPTION("Comedi: National Instruments Lab-PC PCI-1200 driver"); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index d99f4065b96d6e5ff0e6c3179372881fbd9cdd57..9266e13f6271698be1428be12af52d0593583b68 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -2390,7 +2390,7 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) #endif break; case AIMODE_SAMPLE: - /*generate FIFO interrupts on non-empty */ + /* generate FIFO interrupts on non-empty */ ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, NISTC_AI_MODE3_REG); break; diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 8f3864799c1999215daba274697b17c3edb4adad..623f8d08d13a593a34a8424a1031b753bdd6acda 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -33,7 +33,7 @@ * The PCI-6534 requires a firmware upload after power-up to work, the * firmware data and instructions for loading it with comedi_config * it are contained in the comedi_nonfree_firmware tarball available from - * http://www.comedi.org + * https://www.comedi.org */ #define USE_DMA @@ -1005,6 +1005,6 @@ static struct pci_driver ni_pcidio_pci_driver = { }; module_comedi_pci_driver(ni_pcidio_driver, ni_pcidio_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index c1d70eec24ab1a592a7569c8536be494bc8de9f9..6c813a490ba5e6e1e8953ae3d8b63e706a82f9a9 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1472,6 +1472,6 @@ static struct pci_driver ni_pcimio_pci_driver = { }; module_comedi_pci_driver(ni_pcimio_driver, ni_pcimio_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_routes.c b/drivers/staging/comedi/drivers/ni_routes.c index 07cb970340dba56fd6703601ecbb810971a1adc8..c426a9286f154e9c0340a5191bc8bd888d050f8c 100644 --- a/drivers/staging/comedi/drivers/ni_routes.c +++ b/drivers/staging/comedi/drivers/ni_routes.c @@ -556,7 +556,7 @@ static void __exit ni_routes_module_exit(void) module_init(ni_routes_module_init); module_exit(ni_routes_module_exit); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi helper for routing signals-->terminals for NI"); MODULE_LICENSE("GPL"); /* **** END simple module entry/exit functions **** */ diff --git a/drivers/staging/comedi/drivers/ni_usb6501.c b/drivers/staging/comedi/drivers/ni_usb6501.c index 360e86a19fe323383fad2029bfad5f0d38fbb5bc..5b6d9d783b2f74339159a7bb814a78d9d8e77b26 100644 --- a/drivers/staging/comedi/drivers/ni_usb6501.c +++ b/drivers/staging/comedi/drivers/ni_usb6501.c @@ -79,7 +79,7 @@ * RES: 00 01 00 0C 00 08 01 00 00 00 00 02 * * - * Please visit http://www.brickedbrain.com if you need + * Please visit https://www.brickedbrain.com if you need * additional information or have any questions. * */ diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index a5937206bf1cd914116af7aad9f9a8cdbd4dafae..2dbf69e3096507d8f18433152cabf3199b95fdf4 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -508,6 +508,6 @@ static struct comedi_driver pcl711_driver = { }; module_comedi_driver(pcl711_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for PCL-711 compatible boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 9c174f1f2fcf56487d982122cc40a311732cce52..1a5799278a7a7e355566c3c6143c268b352a7e4e 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -148,6 +148,6 @@ static struct comedi_driver pcl724_driver = { }; module_comedi_driver(pcl724_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for 8255 based ISA and PC/104 DIO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index 0963d85873a9e3f61fc109b4316464c6eb3019ce..58b3d07ae90758bcb82af858eee6140191dd12b7 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -418,6 +418,6 @@ static struct comedi_driver pcl726_driver = { }; module_comedi_driver(pcl726_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Advantech PCL-726 & compatibles"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index 3d1e9150e5b53188a85a9b4f49b49a1123d37c8b..32a29129e6e87578b123feb9335eca171649258b 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -345,6 +345,6 @@ static struct comedi_driver pcl730_driver = { }; module_comedi_driver(pcl730_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index aefc1b849cf79db883753f2e0efc9e9cb171d0f2..b87ab3840eeef265c6c31c3201b9b48eec2609b0 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1331,6 +1331,6 @@ static struct comedi_driver pcl812_driver = { }; module_comedi_driver(pcl812_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index d87cf6d4a161a202bccc0dc7419a17485d2fd2b7..c368a337a0ae08c73095b3a82fc65f6032927359 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -691,6 +691,6 @@ static struct comedi_driver pcl816_driver = { }; module_comedi_driver(pcl816_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 0af5315d435755a8b55d07859398516a889ec93c..63e3011158f2308cbe92bb254ae7aec2162d130d 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1132,6 +1132,6 @@ static struct comedi_driver pcl818_driver = { }; module_comedi_driver(pcl818_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 5779e005c0cb063a49c4ba43956828e07562f6cd..0cb1ad06040290d71f19f0d93a3bd587d530458c 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -222,6 +222,6 @@ static struct comedi_driver pcm3724_driver = { }; module_comedi_driver(pcm3724_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Advantech PCM-3724 Digital I/O board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index fe5449bb17160e88810be7c20a317fb2718887b8..eec89a0afb2fbf6bb98600091903acd74fb8797d 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -144,6 +144,6 @@ static struct comedi_driver pcmad_driver = { }; module_comedi_driver(pcmad_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 33e463b193a164465f60715967ae34520b88fc17..14ab1f0d1e9f01cf49c8adcb84b441a5fd536243 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -160,6 +160,6 @@ static struct comedi_driver pcmda12_driver = { }; module_comedi_driver(pcmda12_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 72af1776f785de0d8916a5354c7d125f142b9592..24a9568d3378830a30865d165ba71ba6abc38c58 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -772,6 +772,6 @@ static struct comedi_driver pcmmio_driver = { }; module_comedi_driver(pcmmio_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Winsystems PCM-MIO PC/104 board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 743fb226e2e4ba3303981f1e23215bfeb14d3f1e..7e1fc6ffb48c1d264293af59c00361ccf98f6f7e 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -619,6 +619,6 @@ static struct comedi_driver pcmuio_driver = { }; module_comedi_driver(pcmuio_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/plx9052.h b/drivers/staging/comedi/drivers/plx9052.h index 8ec5a5f2837d939ec800ef75b8357941b54703f0..e68a7afef02545a442686dac469296336df44f72 100644 --- a/drivers/staging/comedi/drivers/plx9052.h +++ b/drivers/staging/comedi/drivers/plx9052.h @@ -2,7 +2,7 @@ /* * Definitions for the PLX-9052 PCI interface chip * - * Copyright (C) 2002 MEV Ltd. + * Copyright (C) 2002 MEV Ltd. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 6daaacf7a26a77e364574f07d8a910da8b1c1304..1b1efa4d31f68d153451bbfab43e7f371a1ae4fa 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -7,7 +7,7 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * http://www.comedi.org/ + * https://www.comedi.org/ * * Documentation for the DAQP PCMCIA cards can be found on Quatech's site: * ftp://ftp.quatech.com/Manuals/daqp-208.pdf diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 8c04af09be2cdd05f8a2b18ea43bab0d66294cc8..2d99a648b054721830b131aa90fcd237973cfef6 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1360,6 +1360,6 @@ static struct pci_driver rtd520_pci_driver = { }; module_comedi_pci_driver(rtd520_driver, rtd520_pci_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index f7c320c89ee6ab4fcf068deb24349bb697a25bd4..327fd93b8b12fdbc78a4345c9178499dbfea0212 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -353,5 +353,5 @@ static struct comedi_driver rti800_driver = { module_comedi_driver(rti800_driver); MODULE_DESCRIPTION("Comedi: RTI-800 Multifunction Analog/Digital board"); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index c6cf92bfff73f8abfece791192c8dfc80fb5ce46..195e2b1ac4c14974a877ea8f8f47b968e8692a2a 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -115,6 +115,6 @@ static struct comedi_driver rti802_driver = { }; module_comedi_driver(rti802_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi driver for Analog Devices RTI-802 board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 5d567ae78f28e86943ea49efc7cb78ef119542ce..085cf5b449e5b6199d54131c25a4a98f66cf988d 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -400,7 +400,7 @@ static int s526_gpct_winsn(struct comedi_device *dev, if ((data[1] <= data[0]) || !data[0]) return -EINVAL; /* to write the PULSE_WIDTH */ - /* fall through */ + fallthrough; case INSN_CONFIG_GPCT_QUADRATURE_ENCODER: case INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR: s526_gpct_write(dev, chan, data[0]); @@ -624,6 +624,6 @@ static struct comedi_driver s526_driver = { }; module_comedi_driver(s526_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 084a8e7b9fc2141f9e2a67aa7114aa2cac921933..e7aba937d896790eb26589ae89eca6299cbbdaa8 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2130,13 +2130,15 @@ static int s626_allocate_dma_buffers(struct comedi_device *dev) void *addr; dma_addr_t appdma; - addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma); + addr = dma_alloc_coherent(&pcidev->dev, S626_DMABUF_SIZE, &appdma, + GFP_KERNEL); if (!addr) return -ENOMEM; devpriv->ana_buf.logical_base = addr; devpriv->ana_buf.physical_base = appdma; - addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma); + addr = dma_alloc_coherent(&pcidev->dev, S626_DMABUF_SIZE, &appdma, + GFP_KERNEL); if (!addr) return -ENOMEM; devpriv->rps_buf.logical_base = addr; @@ -2154,13 +2156,13 @@ static void s626_free_dma_buffers(struct comedi_device *dev) return; if (devpriv->rps_buf.logical_base) - pci_free_consistent(pcidev, S626_DMABUF_SIZE, - devpriv->rps_buf.logical_base, - devpriv->rps_buf.physical_base); + dma_free_coherent(&pcidev->dev, S626_DMABUF_SIZE, + devpriv->rps_buf.logical_base, + devpriv->rps_buf.physical_base); if (devpriv->ana_buf.logical_base) - pci_free_consistent(pcidev, S626_DMABUF_SIZE, - devpriv->ana_buf.logical_base, - devpriv->ana_buf.physical_base); + dma_free_coherent(&pcidev->dev, S626_DMABUF_SIZE, + devpriv->ana_buf.logical_base, + devpriv->ana_buf.physical_base); } static int s626_initialize(struct comedi_device *dev) diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index 0628060e42cafa777af3ccc2b7b9e43d20b463ee..016d315aa584b999ddf3978884284b01db9b6fc5 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -175,6 +175,6 @@ static struct comedi_driver dnp_driver = { }; module_comedi_driver(dnp_driver); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/tests/ni_routes_test.c b/drivers/staging/comedi/drivers/tests/ni_routes_test.c index f809051820ac773f640b207eaf9fe826da06547b..eaefaf596a376b642174954abdfe0c0465eaa58b 100644 --- a/drivers/staging/comedi/drivers/tests/ni_routes_test.c +++ b/drivers/staging/comedi/drivers/tests/ni_routes_test.c @@ -607,7 +607,7 @@ static void __exit ni_routes_unittest_exit(void) { } module_init(ni_routes_unittest); module_exit(ni_routes_unittest_exit); -MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_AUTHOR("Comedi https://www.comedi.org"); MODULE_DESCRIPTION("Comedi unit-tests for ni_routes module"); MODULE_LICENSE("GPL"); /* **** END simple module entry/exit functions **** */ diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h index 5e1339daa7c7deec09db702301b85d449d32d763..f100d503bd17e80977b55ae8802f6326d1c6c6c7 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h @@ -69,6 +69,10 @@ #define DPSW_CMDID_FDB_SET_LEARNING_MODE DPSW_CMD_ID(0x088) #define DPSW_CMDID_FDB_DUMP DPSW_CMD_ID(0x08A) +#define DPSW_CMDID_IF_GET_PORT_MAC_ADDR DPSW_CMD_ID(0x0A7) +#define DPSW_CMDID_IF_GET_PRIMARY_MAC_ADDR DPSW_CMD_ID(0x0A8) +#define DPSW_CMDID_IF_SET_PRIMARY_MAC_ADDR DPSW_CMD_ID(0x0A9) + /* Macros for accessing command fields smaller than 1byte */ #define DPSW_MASK(field) \ GENMASK(DPSW_##field##_SHIFT + DPSW_##field##_SIZE - 1, \ @@ -369,4 +373,14 @@ struct dpsw_rsp_get_api_version { __le16 version_minor; }; +struct dpsw_rsp_if_get_mac_addr { + __le16 pad; + u8 mac_addr[6]; +}; + +struct dpsw_cmd_if_set_mac_addr { + __le16 if_id; + u8 mac_addr[6]; +}; + #endif /* __FSL_DPSW_CMD_H */ diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c index 56b0fa789a67642f3c79fbd5f75e17fef109ff6a..f8bfe779bd30fdd74b48be18367ecb07ec6d4657 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c @@ -1214,3 +1214,109 @@ int dpsw_get_api_version(struct fsl_mc_io *mc_io, return 0; } + +/** + * dpsw_if_get_port_mac_addr() + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPSW object + * @if_id: Interface Identifier + * @mac_addr: MAC address of the physical port, if any, otherwise 0 + * + * Return: Completion status. '0' on Success; Error code otherwise. + */ +int dpsw_if_get_port_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u16 if_id, u8 mac_addr[6]) +{ + struct dpsw_rsp_if_get_mac_addr *rsp_params; + struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if *cmd_params; + int err, i; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_PORT_MAC_ADDR, + cmd_flags, + token); + cmd_params = (struct dpsw_cmd_if *)cmd.params; + cmd_params->if_id = cpu_to_le16(if_id); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + rsp_params = (struct dpsw_rsp_if_get_mac_addr *)cmd.params; + for (i = 0; i < 6; i++) + mac_addr[5 - i] = rsp_params->mac_addr[i]; + + return 0; +} + +/** + * dpsw_if_get_primary_mac_addr() + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPSW object + * @if_id: Interface Identifier + * @mac_addr: MAC address of the physical port, if any, otherwise 0 + * + * Return: Completion status. '0' on Success; Error code otherwise. + */ +int dpsw_if_get_primary_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, + u16 token, u16 if_id, u8 mac_addr[6]) +{ + struct dpsw_rsp_if_get_mac_addr *rsp_params; + struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if *cmd_params; + int err, i; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_PRIMARY_MAC_ADDR, + cmd_flags, + token); + cmd_params = (struct dpsw_cmd_if *)cmd.params; + cmd_params->if_id = cpu_to_le16(if_id); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + rsp_params = (struct dpsw_rsp_if_get_mac_addr *)cmd.params; + for (i = 0; i < 6; i++) + mac_addr[5 - i] = rsp_params->mac_addr[i]; + + return 0; +} + +/** + * dpsw_if_set_primary_mac_addr() + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPSW object + * @if_id: Interface Identifier + * @mac_addr: MAC address of the physical port, if any, otherwise 0 + * + * Return: Completion status. '0' on Success; Error code otherwise. + */ +int dpsw_if_set_primary_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, + u16 token, u16 if_id, u8 mac_addr[6]) +{ + struct dpsw_cmd_if_set_mac_addr *cmd_params; + struct fsl_mc_command cmd = { 0 }; + int i; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_PRIMARY_MAC_ADDR, + cmd_flags, + token); + cmd_params = (struct dpsw_cmd_if_set_mac_addr *)cmd.params; + cmd_params->if_id = cpu_to_le16(if_id); + for (i = 0; i < 6; i++) + cmd_params->mac_addr[i] = mac_addr[5 - i]; + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h index 25b45850925c11f4667e158dbf08b94433a3fab5..ab63ee4f5cb7c5e171ffd8ddb2d397daedf396ff 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h @@ -580,4 +580,13 @@ int dpsw_get_api_version(struct fsl_mc_io *mc_io, u16 *major_ver, u16 *minor_ver); +int dpsw_if_get_port_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u16 if_id, u8 mac_addr[6]); + +int dpsw_if_get_primary_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, + u16 token, u16 if_id, u8 mac_addr[6]); + +int dpsw_if_set_primary_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, + u16 token, u16 if_id, u8 mac_addr[6]); + #endif /* __FSL_DPSW_H */ diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 546ad376df99fa762614ade735f9a22b332ed4c2..316fd9afd461d4b36800cd4ce72b2aec2db07cac 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -43,12 +43,31 @@ static int ethsw_add_vlan(struct ethsw_core *ethsw, u16 vid) return 0; } +static bool ethsw_port_is_up(struct ethsw_port_priv *port_priv) +{ + struct net_device *netdev = port_priv->netdev; + struct dpsw_link_state state; + int err; + + err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0, + port_priv->ethsw_data->dpsw_handle, + port_priv->idx, &state); + if (err) { + netdev_err(netdev, "dpsw_if_get_link_state() err %d\n", err); + return true; + } + + WARN_ONCE(state.up > 1, "Garbage read into link_state"); + + return state.up ? true : false; +} + static int ethsw_port_set_pvid(struct ethsw_port_priv *port_priv, u16 pvid) { struct ethsw_core *ethsw = port_priv->ethsw_data; struct net_device *netdev = port_priv->netdev; struct dpsw_tci_cfg tci_cfg = { 0 }; - bool is_oper; + bool up; int err, ret; err = dpsw_if_get_tci(ethsw->mc_io, 0, ethsw->dpsw_handle, @@ -61,8 +80,8 @@ static int ethsw_port_set_pvid(struct ethsw_port_priv *port_priv, u16 pvid) tci_cfg.vlan_id = pvid; /* Interface needs to be down to change PVID */ - is_oper = netif_oper_up(netdev); - if (is_oper) { + up = ethsw_port_is_up(port_priv); + if (up) { err = dpsw_if_disable(ethsw->mc_io, 0, ethsw->dpsw_handle, port_priv->idx); @@ -85,7 +104,7 @@ static int ethsw_port_set_pvid(struct ethsw_port_priv *port_priv, u16 pvid) port_priv->pvid = pvid; set_tci_error: - if (is_oper) { + if (up) { ret = dpsw_if_enable(ethsw->mc_io, 0, ethsw->dpsw_handle, port_priv->idx); @@ -183,21 +202,26 @@ static int ethsw_port_set_flood(struct ethsw_port_priv *port_priv, bool enable) static int ethsw_port_set_stp_state(struct ethsw_port_priv *port_priv, u8 state) { struct dpsw_stp_cfg stp_cfg = { - .vlan_id = DEFAULT_VLAN_ID, .state = state, }; int err; + u16 vid; - if (!netif_oper_up(port_priv->netdev) || state == port_priv->stp_state) + if (!netif_running(port_priv->netdev) || state == port_priv->stp_state) return 0; /* Nothing to do */ - err = dpsw_if_set_stp(port_priv->ethsw_data->mc_io, 0, - port_priv->ethsw_data->dpsw_handle, - port_priv->idx, &stp_cfg); - if (err) { - netdev_err(port_priv->netdev, - "dpsw_if_set_stp err %d\n", err); - return err; + for (vid = 0; vid <= VLAN_VID_MASK; vid++) { + if (port_priv->vlans[vid] & ETHSW_VLAN_MEMBER) { + stp_cfg.vlan_id = vid; + err = dpsw_if_set_stp(port_priv->ethsw_data->mc_io, 0, + port_priv->ethsw_data->dpsw_handle, + port_priv->idx, &stp_cfg); + if (err) { + netdev_err(port_priv->netdev, + "dpsw_if_set_stp err %d\n", err); + return err; + } + } } port_priv->stp_state = state; @@ -445,6 +469,12 @@ static int port_carrier_state_sync(struct net_device *netdev) struct dpsw_link_state state; int err; + /* Interrupts are received even though no one issued an 'ifconfig up' + * on the switch interface. Ignore these link state update interrupts + */ + if (!netif_running(netdev)) + return 0; + err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0, port_priv->ethsw_data->dpsw_handle, port_priv->idx, &state); @@ -462,6 +492,7 @@ static int port_carrier_state_sync(struct net_device *netdev) netif_carrier_off(netdev); port_priv->link_state = state.up; } + return 0; } @@ -473,6 +504,13 @@ static int port_open(struct net_device *netdev) /* No need to allow Tx as control interface is disabled */ netif_tx_stop_all_queues(netdev); + /* Explicitly set carrier off, otherwise + * netif_carrier_ok() will return true and cause 'ip link show' + * to report the LOWER_UP flag, even though the link + * notification wasn't even received. + */ + netif_carrier_off(netdev); + err = dpsw_if_enable(port_priv->ethsw_data->mc_io, 0, port_priv->ethsw_data->dpsw_handle, port_priv->idx); @@ -677,6 +715,46 @@ err_map: return err; } +static int ethsw_port_set_mac_addr(struct ethsw_port_priv *port_priv) +{ + struct ethsw_core *ethsw = port_priv->ethsw_data; + struct net_device *net_dev = port_priv->netdev; + struct device *dev = net_dev->dev.parent; + u8 mac_addr[ETH_ALEN]; + int err; + + if (!(ethsw->features & ETHSW_FEATURE_MAC_ADDR)) + return 0; + + /* Get firmware address, if any */ + err = dpsw_if_get_port_mac_addr(ethsw->mc_io, 0, ethsw->dpsw_handle, + port_priv->idx, mac_addr); + if (err) { + dev_err(dev, "dpsw_if_get_port_mac_addr() failed\n"); + return err; + } + + /* First check if firmware has any address configured by bootloader */ + if (!is_zero_ether_addr(mac_addr)) { + memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len); + } else { + /* No MAC address configured, fill in net_dev->dev_addr + * with a random one + */ + eth_hw_addr_random(net_dev); + dev_dbg_once(dev, "device(s) have all-zero hwaddr, replaced with random\n"); + + /* Override NET_ADDR_RANDOM set by eth_hw_addr_random(); for all + * practical purposes, this will be our "permanent" mac address, + * at least until the next reboot. This move will also permit + * register_netdevice() to properly fill up net_dev->perm_addr. + */ + net_dev->addr_assign_type = NET_ADDR_PERM; + } + + return 0; +} + static const struct net_device_ops ethsw_port_ops = { .ndo_open = port_open, .ndo_stop = port_stop, @@ -695,12 +773,28 @@ static const struct net_device_ops ethsw_port_ops = { .ndo_get_phys_port_name = port_get_phys_name, }; +static bool ethsw_port_dev_check(const struct net_device *netdev, + struct notifier_block *nb) +{ + struct ethsw_port_priv *port_priv = netdev_priv(netdev); + + if (netdev->netdev_ops == ðsw_port_ops && + (!nb || &port_priv->ethsw_data->port_nb == nb || + &port_priv->ethsw_data->port_switchdev_nb == nb || + &port_priv->ethsw_data->port_switchdevb_nb == nb)) + return true; + + return false; +} + static void ethsw_links_state_update(struct ethsw_core *ethsw) { int i; - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) + for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { port_carrier_state_sync(ethsw->ports[i]->netdev); + ethsw_port_set_mac_addr(ethsw->ports[i]); + } } static irqreturn_t ethsw_irq0_handler_thread(int irq_num, void *arg) @@ -885,10 +979,27 @@ static int port_vlans_add(struct net_device *netdev, struct switchdev_trans *trans) { struct ethsw_port_priv *port_priv = netdev_priv(netdev); - int vid, err = 0; + struct ethsw_core *ethsw = port_priv->ethsw_data; + struct dpsw_attr *attr = ðsw->sw_attr; + int vid, err = 0, new_vlans = 0; + + if (switchdev_trans_ph_prepare(trans)) { + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) + if (!port_priv->ethsw_data->vlans[vid]) + new_vlans++; + + /* Check if there is space for a new VLAN */ + err = dpsw_get_attributes(ethsw->mc_io, 0, ethsw->dpsw_handle, + ðsw->sw_attr); + if (err) { + netdev_err(netdev, "dpsw_get_attributes err %d\n", err); + return err; + } + if (attr->max_vlans - attr->num_vlans < new_vlans) + return -ENOSPC; - if (switchdev_trans_ph_prepare(trans)) return 0; + } for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { if (!port_priv->ethsw_data->vlans[vid]) { @@ -1112,6 +1223,9 @@ static int port_bridge_join(struct net_device *netdev, { struct ethsw_port_priv *port_priv = netdev_priv(netdev); struct ethsw_core *ethsw = port_priv->ethsw_data; + struct ethsw_port_priv *other_port_priv; + struct net_device *other_dev; + struct list_head *iter; int i, err; for (i = 0; i < ethsw->sw_attr.num_ifs; i++) @@ -1122,6 +1236,18 @@ static int port_bridge_join(struct net_device *netdev, return -EINVAL; } + netdev_for_each_lower_dev(upper_dev, other_dev, iter) { + if (!ethsw_port_dev_check(other_dev, NULL)) + continue; + + other_port_priv = netdev_priv(other_dev); + if (other_port_priv->ethsw_data != port_priv->ethsw_data) { + netdev_err(netdev, + "Interface from a different DPSW is in the bridge already!\n"); + return -EINVAL; + } + } + /* Enable flooding */ err = ethsw_port_set_flood(port_priv, 1); if (!err) @@ -1143,12 +1269,7 @@ static int port_bridge_leave(struct net_device *netdev) return err; } -static bool ethsw_port_dev_check(const struct net_device *netdev) -{ - return netdev->netdev_ops == ðsw_port_ops; -} - -static int port_netdevice_event(struct notifier_block *unused, +static int port_netdevice_event(struct notifier_block *nb, unsigned long event, void *ptr) { struct net_device *netdev = netdev_notifier_info_to_dev(ptr); @@ -1156,7 +1277,7 @@ static int port_netdevice_event(struct notifier_block *unused, struct net_device *upper_dev; int err = 0; - if (!ethsw_port_dev_check(netdev)) + if (!ethsw_port_dev_check(netdev, nb)) return NOTIFY_DONE; /* Handle just upper dev link/unlink for the moment */ @@ -1224,7 +1345,7 @@ static void ethsw_switchdev_event_work(struct work_struct *work) } /* Called under rcu_read_lock() */ -static int port_switchdev_event(struct notifier_block *unused, +static int port_switchdev_event(struct notifier_block *nb, unsigned long event, void *ptr) { struct net_device *dev = switchdev_notifier_info_to_dev(ptr); @@ -1233,7 +1354,7 @@ static int port_switchdev_event(struct notifier_block *unused, struct switchdev_notifier_fdb_info *fdb_info = ptr; struct ethsw_core *ethsw = port_priv->ethsw_data; - if (!ethsw_port_dev_check(dev)) + if (!ethsw_port_dev_check(dev, nb)) return NOTIFY_DONE; if (event == SWITCHDEV_PORT_ATTR_SET) @@ -1297,16 +1418,16 @@ ethsw_switchdev_port_obj_event(unsigned long event, struct net_device *netdev, return notifier_from_errno(err); } -static int port_switchdev_blocking_event(struct notifier_block *unused, +static int port_switchdev_blocking_event(struct notifier_block *nb, unsigned long event, void *ptr) { struct net_device *dev = switchdev_notifier_info_to_dev(ptr); - if (!ethsw_port_dev_check(dev)) + if (!ethsw_port_dev_check(dev, nb)) return NOTIFY_DONE; switch (event) { - case SWITCHDEV_PORT_OBJ_ADD: /* fall through */ + case SWITCHDEV_PORT_OBJ_ADD: case SWITCHDEV_PORT_OBJ_DEL: return ethsw_switchdev_port_obj_event(event, dev, ptr); case SWITCHDEV_PORT_ATTR_SET: @@ -1351,13 +1472,21 @@ err_switchdev_nb: return err; } +static void ethsw_detect_features(struct ethsw_core *ethsw) +{ + ethsw->features = 0; + + if (ethsw->major > 8 || (ethsw->major == 8 && ethsw->minor >= 6)) + ethsw->features |= ETHSW_FEATURE_MAC_ADDR; +} + static int ethsw_init(struct fsl_mc_device *sw_dev) { struct device *dev = &sw_dev->dev; struct ethsw_core *ethsw = dev_get_drvdata(dev); - u16 version_major, version_minor, i; struct dpsw_stp_cfg stp_cfg; int err; + u16 i; ethsw->dev_id = sw_dev->obj_desc.id; @@ -1375,25 +1504,27 @@ static int ethsw_init(struct fsl_mc_device *sw_dev) } err = dpsw_get_api_version(ethsw->mc_io, 0, - &version_major, - &version_minor); + ðsw->major, + ðsw->minor); if (err) { dev_err(dev, "dpsw_get_api_version err %d\n", err); goto err_close; } /* Minimum supported DPSW version check */ - if (version_major < DPSW_MIN_VER_MAJOR || - (version_major == DPSW_MIN_VER_MAJOR && - version_minor < DPSW_MIN_VER_MINOR)) { + if (ethsw->major < DPSW_MIN_VER_MAJOR || + (ethsw->major == DPSW_MIN_VER_MAJOR && + ethsw->minor < DPSW_MIN_VER_MINOR)) { dev_err(dev, "DPSW version %d:%d not supported. Use %d.%d or greater.\n", - version_major, - version_minor, + ethsw->major, + ethsw->minor, DPSW_MIN_VER_MAJOR, DPSW_MIN_VER_MINOR); err = -ENOTSUPP; goto err_close; } + ethsw_detect_features(ethsw); + err = dpsw_reset(ethsw->mc_io, 0, ethsw->dpsw_handle); if (err) { dev_err(dev, "dpsw_reset err %d\n", err); @@ -1533,8 +1664,6 @@ static int ethsw_remove(struct fsl_mc_device *sw_dev) ethsw_teardown_irqs(sw_dev); - destroy_workqueue(ethsw->workqueue); - dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle); for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { @@ -1545,6 +1674,9 @@ static int ethsw_remove(struct fsl_mc_device *sw_dev) kfree(ethsw->ports); ethsw_takedown(sw_dev); + + destroy_workqueue(ethsw->workqueue); + fsl_mc_portal_free(ethsw->mc_io); kfree(ethsw); @@ -1589,6 +1721,10 @@ static int ethsw_probe_port(struct ethsw_core *ethsw, u16 port_idx) if (err) goto err_port_probe; + err = ethsw_port_set_mac_addr(port_priv); + if (err) + goto err_port_probe; + err = register_netdev(port_netdev); if (err < 0) { dev_err(dev, "register_netdev error %d\n", err); @@ -1659,6 +1795,10 @@ static int ethsw_probe(struct fsl_mc_device *sw_dev) goto err_free_ports; } + /* Make sure the switch ports are disabled at probe time */ + for (i = 0; i < ethsw->sw_attr.num_ifs; i++) + dpsw_if_disable(ethsw->mc_io, 0, ethsw->dpsw_handle, i); + /* Setup IRQs */ err = ethsw_setup_irqs(sw_dev); if (err) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h index a0244f7d50034d05dd684d65c508f3b5a83d1bc2..d136dbdcaffa6ee88370daf88b1fcdccc8877af1 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h @@ -37,6 +37,8 @@ #define ETHSW_MAX_FRAME_LENGTH (DPAA2_MFL - VLAN_ETH_HLEN - ETH_FCS_LEN) #define ETHSW_L2_MAX_FRM(mtu) ((mtu) + VLAN_ETH_HLEN + ETH_FCS_LEN) +#define ETHSW_FEATURE_MAC_ADDR BIT(0) + extern const struct ethtool_ops ethsw_port_ethtool_ops; struct ethsw_core; @@ -61,6 +63,8 @@ struct ethsw_core { struct fsl_mc_io *mc_io; u16 dpsw_handle; struct dpsw_attr sw_attr; + u16 major, minor; + unsigned long features; int dev_id; struct ethsw_port_priv **ports; diff --git a/drivers/staging/gasket/gasket_core.c b/drivers/staging/gasket/gasket_core.c index 67325fbaf7605af34a8fc7a28991e402f73df0a9..28dab302183bcf24e9bce8b7c843827aaa4cd802 100644 --- a/drivers/staging/gasket/gasket_core.c +++ b/drivers/staging/gasket/gasket_core.c @@ -261,6 +261,7 @@ static int gasket_map_pci_bar(struct gasket_dev *gasket_dev, int bar_num) const struct gasket_driver_desc *driver_desc = internal_desc->driver_desc; ulong desc_bytes = driver_desc->bar_descriptions[bar_num].size; + struct gasket_bar_data *data; int ret; if (desc_bytes == 0) @@ -270,31 +271,32 @@ static int gasket_map_pci_bar(struct gasket_dev *gasket_dev, int bar_num) /* not PCI: skip this entry */ return 0; } + + data = &gasket_dev->bar_data[bar_num]; + /* * pci_resource_start and pci_resource_len return a "resource_size_t", * which is safely castable to ulong (which itself is the arg to * request_mem_region). */ - gasket_dev->bar_data[bar_num].phys_base = + data->phys_base = (ulong)pci_resource_start(gasket_dev->pci_dev, bar_num); - if (!gasket_dev->bar_data[bar_num].phys_base) { + if (!data->phys_base) { dev_err(gasket_dev->dev, "Cannot get BAR%u base address\n", bar_num); return -EINVAL; } - gasket_dev->bar_data[bar_num].length_bytes = + data->length_bytes = (ulong)pci_resource_len(gasket_dev->pci_dev, bar_num); - if (gasket_dev->bar_data[bar_num].length_bytes < desc_bytes) { + if (data->length_bytes < desc_bytes) { dev_err(gasket_dev->dev, "PCI BAR %u space is too small: %lu; expected >= %lu\n", - bar_num, gasket_dev->bar_data[bar_num].length_bytes, - desc_bytes); + bar_num, data->length_bytes, desc_bytes); return -ENOMEM; } - if (!request_mem_region(gasket_dev->bar_data[bar_num].phys_base, - gasket_dev->bar_data[bar_num].length_bytes, + if (!request_mem_region(data->phys_base, data->length_bytes, gasket_dev->dev_info.name)) { dev_err(gasket_dev->dev, "Cannot get BAR %d memory region %p\n", @@ -302,10 +304,8 @@ static int gasket_map_pci_bar(struct gasket_dev *gasket_dev, int bar_num) return -EINVAL; } - gasket_dev->bar_data[bar_num].virt_base = - ioremap(gasket_dev->bar_data[bar_num].phys_base, - gasket_dev->bar_data[bar_num].length_bytes); - if (!gasket_dev->bar_data[bar_num].virt_base) { + data->virt_base = ioremap(data->phys_base, data->length_bytes); + if (!data->virt_base) { dev_err(gasket_dev->dev, "Cannot remap BAR %d memory region %p\n", bar_num, &gasket_dev->pci_dev->resource[bar_num]); @@ -319,9 +319,8 @@ static int gasket_map_pci_bar(struct gasket_dev *gasket_dev, int bar_num) return 0; fail: - iounmap(gasket_dev->bar_data[bar_num].virt_base); - release_mem_region(gasket_dev->bar_data[bar_num].phys_base, - gasket_dev->bar_data[bar_num].length_bytes); + iounmap(data->virt_base); + release_mem_region(data->phys_base, data->length_bytes); return ret; } diff --git a/drivers/staging/gasket/gasket_page_table.c b/drivers/staging/gasket/gasket_page_table.c index f3dbe0fe2a67fc25d38e2774b4b9a09f8a98c0bd..6f6273c83822c7cc23667344536f41f110079908 100644 --- a/drivers/staging/gasket/gasket_page_table.c +++ b/drivers/staging/gasket/gasket_page_table.c @@ -449,7 +449,7 @@ static bool gasket_release_page(struct page *page) if (!PageReserved(page)) SetPageDirty(page); - put_page(page); + unpin_user_page(page); return true; } @@ -486,12 +486,12 @@ static int gasket_perform_mapping(struct gasket_page_table *pg_tbl, ptes[i].dma_addr = pg_tbl->coherent_pages[0].paddr + off + i * PAGE_SIZE; } else { - ret = get_user_pages_fast(page_addr - offset, 1, + ret = pin_user_pages_fast(page_addr - offset, 1, FOLL_WRITE, &page); if (ret <= 0) { dev_err(pg_tbl->device, - "get user pages failed for addr=0x%lx, offset=0x%lx [ret=%d]\n", + "pin user pages failed for addr=0x%lx, offset=0x%lx [ret=%d]\n", page_addr, offset, ret); return ret ? ret : -ENOMEM; } diff --git a/drivers/staging/gasket/gasket_sysfs.h b/drivers/staging/gasket/gasket_sysfs.h index ab5aa351d55500bcbd7b9dfa167e7cad015c660a..d5e167dfbe76013e1baafc443c2ab301859cd99f 100644 --- a/drivers/staging/gasket/gasket_sysfs.h +++ b/drivers/staging/gasket/gasket_sysfs.h @@ -71,7 +71,7 @@ struct gasket_sysfs_attribute { #define GASKET_SYSFS_RO(_name, _show_function, _attr_type) \ { \ - .attr = __ATTR(_name, S_IRUGO, _show_function, NULL), \ + .attr = __ATTR(_name, 0444, _show_function, NULL), \ .data.attr_type = _attr_type \ } diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index eb309190f5bef7be6d8d94aeeebb909b4c7e0d37..571f47d394843f66d441b3d7e25dfd2b752a09cf 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -784,7 +784,7 @@ static int gdm_lte_receive_pkt(struct phy_dev *phy_dev, char *buf, int len) return index; dev = phy_dev->dev[index]; gdm_lte_pdn_table(dev, buf, len); - /* Fall through */ + fallthrough; default: ret = gdm_lte_event_send(dev, buf, len); break; diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig index 9389e7a922fa67a5830fa9c50df31be20a316b8e..927cfa4bc9898cddaa56242003c5ca1448325faa 100644 --- a/drivers/staging/greybus/Kconfig +++ b/drivers/staging/greybus/Kconfig @@ -3,7 +3,7 @@ if GREYBUS config GREYBUS_AUDIO tristate "Greybus Audio Class driver" - depends on SOUND + depends on SOUND && SND_SOC help Select this option if you have a device that follows the Greybus Audio Class specification. @@ -11,6 +11,18 @@ config GREYBUS_AUDIO To compile this code as a module, chose M here: the module will be called gb-audio.ko +config GREYBUS_AUDIO_APB_CODEC + tristate "Greybus APBridge Audio codec driver" + depends on SND_SOC && GREYBUS_AUDIO + help + Select this option if you have a Toshiba APB device that has I2S + ports and acts as a Greybus "Dummy codec". This device is a + bridge from an APB-I2S port to a Unipro network. + + To compile this code as a module, chose M here: the module + will be called gb-audio-codec.ko + + config GREYBUS_BOOTROM tristate "Greybus Bootrom Class driver" help diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 627e44f2a983cdb9f4b39352405110bc50a3d0a2..7c5e896223344a8ae8f139ec1bb37d07c01daf18 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -28,7 +28,7 @@ obj-$(CONFIG_GREYBUS_VIBRATOR) += gb-vibrator.o # Greybus Audio is a bunch of modules gb-audio-module-y := audio_module.o audio_topology.o -gb-audio-codec-y := audio_codec.o +gb-audio-codec-y := audio_codec.o audio_helper.o gb-audio-gb-y := audio_gb.o gb-audio-apbridgea-y := audio_apbridgea.o gb-audio-manager-y := audio_manager.o audio_manager_module.o @@ -40,8 +40,8 @@ gb-audio-manager-y := audio_manager.o audio_manager_module.o #ccflags-y += -DGB_AUDIO_MANAGER_SYSFS #endif -obj-$(CONFIG_GREYBUS_AUDIO_MSM8994) += gb-audio-codec.o -obj-$(CONFIG_GREYBUS_AUDIO_MSM8994) += gb-audio-module.o +obj-$(CONFIG_GREYBUS_AUDIO_APB_CODEC) += gb-audio-codec.o +obj-$(CONFIG_GREYBUS_AUDIO_APB_CODEC) += gb-audio-module.o obj-$(CONFIG_GREYBUS_AUDIO) += gb-audio-gb.o obj-$(CONFIG_GREYBUS_AUDIO) += gb-audio-apbridgea.o obj-$(CONFIG_GREYBUS_AUDIO) += gb-audio-manager.o diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 08746c85dea6dbd372f987eb376813d2207e75aa..74538f8c5fa433997d25590a0bf31e363d216f40 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -14,6 +14,7 @@ #include "audio_codec.h" #include "audio_apbridgea.h" #include "audio_manager.h" +#include "audio_helper.h" static struct gbaudio_codec_info *gbcodec; @@ -709,34 +710,58 @@ static struct snd_soc_dai_driver gbaudio_dai[] = { }; static int gbaudio_init_jack(struct gbaudio_module_info *module, - struct snd_soc_codec *codec) + struct snd_soc_card *card) { int ret; + struct gbaudio_jack *jack, *n; + struct snd_soc_jack_pin *headset, *button; if (!module->jack_mask) return 0; snprintf(module->jack_name, NAME_SIZE, "GB %d Headset Jack", module->dev_id); - ret = snd_soc_jack_new(codec, module->jack_name, module->jack_mask, - &module->headset_jack); + + headset = devm_kzalloc(module->dev, sizeof(*headset), GFP_KERNEL); + if (!headset) + return -ENOMEM; + + headset->pin = module->jack_name; + headset->mask = module->jack_mask; + ret = snd_soc_card_jack_new(card, module->jack_name, module->jack_mask, + &module->headset.jack, headset, 1); if (ret) { dev_err(module->dev, "Failed to create new jack\n"); return ret; } + /* Add to module's jack list */ + list_add(&module->headset.list, &module->jack_list); + if (!module->button_mask) return 0; snprintf(module->button_name, NAME_SIZE, "GB %d Button Jack", module->dev_id); - ret = snd_soc_jack_new(codec, module->button_name, module->button_mask, - &module->button_jack); + button = devm_kzalloc(module->dev, sizeof(*button), GFP_KERNEL); + if (!button) { + ret = -ENOMEM; + goto free_jacks; + } + + button->pin = module->button_name; + button->mask = module->button_mask; + ret = snd_soc_card_jack_new(card, module->button_name, + module->button_mask, &module->button.jack, + button, 1); if (ret) { dev_err(module->dev, "Failed to create button jack\n"); - return ret; + goto free_jacks; } + /* Add to module's jack list */ + list_add(&module->button.list, &module->jack_list); + /* * Currently, max 4 buttons are supported with following key mapping * BTN_0 = KEY_MEDIA @@ -746,64 +771,72 @@ static int gbaudio_init_jack(struct gbaudio_module_info *module, */ if (module->button_mask & SND_JACK_BTN_0) { - ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_0, + ret = snd_jack_set_key(module->button.jack.jack, SND_JACK_BTN_0, KEY_MEDIA); if (ret) { dev_err(module->dev, "Failed to set BTN_0\n"); - return ret; + goto free_jacks; } } if (module->button_mask & SND_JACK_BTN_1) { - ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_1, + ret = snd_jack_set_key(module->button.jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); if (ret) { dev_err(module->dev, "Failed to set BTN_1\n"); - return ret; + goto free_jacks; } } if (module->button_mask & SND_JACK_BTN_2) { - ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_2, + ret = snd_jack_set_key(module->button.jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); if (ret) { dev_err(module->dev, "Failed to set BTN_2\n"); - return ret; + goto free_jacks; } } if (module->button_mask & SND_JACK_BTN_3) { - ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_3, + ret = snd_jack_set_key(module->button.jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); if (ret) { dev_err(module->dev, "Failed to set BTN_0\n"); - return ret; + goto free_jacks; } } /* FIXME * verify if this is really required set_bit(INPUT_PROP_NO_DUMMY_RELEASE, - module->button_jack.jack->input_dev->propbit); + module->button.jack.jack->input_dev->propbit); */ return 0; + +free_jacks: + list_for_each_entry_safe(jack, n, &module->jack_list, list) { + snd_device_free(card->snd_card, jack->jack.jack); + list_del(&jack->list); + } + + return ret; } int gbaudio_register_module(struct gbaudio_module_info *module) { int ret; - struct snd_soc_codec *codec; + struct snd_soc_component *comp; struct snd_card *card; - struct snd_soc_jack *jack = NULL; + struct gbaudio_jack *jack = NULL; if (!gbcodec) { dev_err(module->dev, "GB Codec not yet probed\n"); return -EAGAIN; } - codec = gbcodec->codec; - card = codec->card->snd_card; + comp = gbcodec->component; + card = comp->card->snd_card; down_write(&card->controls_rwsem); @@ -815,36 +848,34 @@ int gbaudio_register_module(struct gbaudio_module_info *module) return -EINVAL; } - ret = gbaudio_init_jack(module, codec); + ret = gbaudio_init_jack(module, comp->card); if (ret) { up_write(&card->controls_rwsem); return ret; } if (module->dapm_widgets) - snd_soc_dapm_new_controls(&codec->dapm, module->dapm_widgets, + snd_soc_dapm_new_controls(&comp->dapm, module->dapm_widgets, module->num_dapm_widgets); if (module->controls) - snd_soc_add_codec_controls(codec, module->controls, - module->num_controls); + snd_soc_add_component_controls(comp, module->controls, + module->num_controls); if (module->dapm_routes) - snd_soc_dapm_add_routes(&codec->dapm, module->dapm_routes, + snd_soc_dapm_add_routes(&comp->dapm, module->dapm_routes, module->num_dapm_routes); /* card already instantiated, create widgets here only */ - if (codec->card->instantiated) { - snd_soc_dapm_link_component_dai_widgets(codec->card, - &codec->dapm); + if (comp->card->instantiated) { + gbaudio_dapm_link_component_dai_widgets(comp->card, + &comp->dapm); #ifdef CONFIG_SND_JACK /* * register jack devices for this module * from codec->jack_list */ - list_for_each_entry(jack, &codec->jack_list, list) { - if ((jack == &module->headset_jack) || - (jack == &module->button_jack)) - snd_device_register(codec->card->snd_card, - jack->jack); + list_for_each_entry(jack, &module->jack_list, list) { + snd_device_register(comp->card->snd_card, + jack->jack.jack); } #endif } @@ -853,9 +884,9 @@ int gbaudio_register_module(struct gbaudio_module_info *module) list_add(&module->list, &gbcodec->module_list); mutex_unlock(&gbcodec->lock); - if (codec->card->instantiated) - ret = snd_soc_dapm_new_widgets(&codec->dapm); - dev_dbg(codec->dev, "Registered %s module\n", module->name); + if (comp->card->instantiated) + ret = snd_soc_dapm_new_widgets(comp->card); + dev_dbg(comp->dev, "Registered %s module\n", module->name); up_write(&card->controls_rwsem); return ret; @@ -926,126 +957,127 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) void gbaudio_unregister_module(struct gbaudio_module_info *module) { - struct snd_soc_codec *codec = gbcodec->codec; - struct snd_card *card = codec->card->snd_card; - struct snd_soc_jack *jack, *next_j; + struct snd_soc_component *comp = gbcodec->component; + struct snd_card *card = comp->card->snd_card; + struct gbaudio_jack *jack, *n; int mask; - dev_dbg(codec->dev, "Unregister %s module\n", module->name); + dev_dbg(comp->dev, "Unregister %s module\n", module->name); down_write(&card->controls_rwsem); mutex_lock(&gbcodec->lock); gbaudio_codec_cleanup(module); list_del(&module->list); - dev_dbg(codec->dev, "Process Unregister %s module\n", module->name); + dev_dbg(comp->dev, "Process Unregister %s module\n", module->name); mutex_unlock(&gbcodec->lock); #ifdef CONFIG_SND_JACK - /* free jack devices for this module from codec->jack_list */ - list_for_each_entry_safe(jack, next_j, &codec->jack_list, list) { - if (jack == &module->headset_jack) + /* free jack devices for this module jack_list */ + list_for_each_entry_safe(jack, n, &module->jack_list, list) { + if (jack == &module->headset) mask = GBCODEC_JACK_MASK; - else if (jack == &module->button_jack) + else if (jack == &module->button) mask = GBCODEC_JACK_BUTTON_MASK; else mask = 0; if (mask) { dev_dbg(module->dev, "Report %s removal\n", - jack->jack->id); - snd_soc_jack_report(jack, 0, mask); - snd_device_free(codec->card->snd_card, jack->jack); + jack->jack.jack->id); + snd_soc_jack_report(&jack->jack, 0, mask); + snd_device_free(comp->card->snd_card, + jack->jack.jack); list_del(&jack->list); } } #endif if (module->dapm_routes) { - dev_dbg(codec->dev, "Removing %d routes\n", + dev_dbg(comp->dev, "Removing %d routes\n", module->num_dapm_routes); - snd_soc_dapm_del_routes(&codec->dapm, module->dapm_routes, + snd_soc_dapm_del_routes(&comp->dapm, module->dapm_routes, module->num_dapm_routes); } if (module->controls) { - dev_dbg(codec->dev, "Removing %d controls\n", + dev_dbg(comp->dev, "Removing %d controls\n", module->num_controls); - snd_soc_remove_codec_controls(codec, module->controls, - module->num_controls); + /* release control semaphore */ + up_write(&card->controls_rwsem); + gbaudio_remove_component_controls(comp, module->controls, + module->num_controls); + down_write(&card->controls_rwsem); } if (module->dapm_widgets) { - dev_dbg(codec->dev, "Removing %d widgets\n", + dev_dbg(comp->dev, "Removing %d widgets\n", module->num_dapm_widgets); - snd_soc_dapm_free_controls(&codec->dapm, module->dapm_widgets, + gbaudio_dapm_free_controls(&comp->dapm, module->dapm_widgets, module->num_dapm_widgets); } - dev_dbg(codec->dev, "Unregistered %s module\n", module->name); + dev_dbg(comp->dev, "Unregistered %s module\n", module->name); up_write(&card->controls_rwsem); } EXPORT_SYMBOL(gbaudio_unregister_module); /* - * codec driver ops + * component driver ops */ -static int gbcodec_probe(struct snd_soc_codec *codec) +static int gbcodec_probe(struct snd_soc_component *comp) { int i; struct gbaudio_codec_info *info; struct gbaudio_codec_dai *dai; - info = devm_kzalloc(codec->dev, sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(comp->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - info->dev = codec->dev; + info->dev = comp->dev; INIT_LIST_HEAD(&info->module_list); mutex_init(&info->lock); INIT_LIST_HEAD(&info->dai_list); /* init dai_list used to maintain runtime stream info */ for (i = 0; i < ARRAY_SIZE(gbaudio_dai); i++) { - dai = devm_kzalloc(codec->dev, sizeof(*dai), GFP_KERNEL); + dai = devm_kzalloc(comp->dev, sizeof(*dai), GFP_KERNEL); if (!dai) return -ENOMEM; dai->id = gbaudio_dai[i].id; list_add(&dai->list, &info->dai_list); } - info->codec = codec; - snd_soc_codec_set_drvdata(codec, info); + info->component = comp; + snd_soc_component_set_drvdata(comp, info); gbcodec = info; - device_init_wakeup(codec->dev, 1); + device_init_wakeup(comp->dev, 1); return 0; } -static int gbcodec_remove(struct snd_soc_codec *codec) +static void gbcodec_remove(struct snd_soc_component *comp) { /* Empty function for now */ - return 0; + return; } -static int gbcodec_write(struct snd_soc_codec *codec, unsigned int reg, +static int gbcodec_write(struct snd_soc_component *comp, unsigned int reg, unsigned int value) { return 0; } -static unsigned int gbcodec_read(struct snd_soc_codec *codec, +static unsigned int gbcodec_read(struct snd_soc_component *comp, unsigned int reg) { return 0; } -static struct snd_soc_codec_driver soc_codec_dev_gbaudio = { +static const struct snd_soc_component_driver soc_codec_dev_gbaudio = { .probe = gbcodec_probe, .remove = gbcodec_remove, .read = gbcodec_read, .write = gbcodec_write, - - .idle_bias_off = true, - .ignore_pmdown_time = 1, }; #ifdef CONFIG_PM @@ -1069,13 +1101,13 @@ static const struct dev_pm_ops gbaudio_codec_pm_ops = { static int gbaudio_codec_probe(struct platform_device *pdev) { - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_gbaudio, + return devm_snd_soc_register_component(&pdev->dev, + &soc_codec_dev_gbaudio, gbaudio_dai, ARRAY_SIZE(gbaudio_dai)); } static int gbaudio_codec_remove(struct platform_device *pdev) { - snd_soc_unregister_codec(&pdev->dev); return 0; } diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index cb5d271da1a5431ef87afcb53a38054703cd0939..ce15e800e6074d546d2427e6215bccc8cb9ab0bb 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -66,7 +66,7 @@ struct gbaudio_codec_dai { struct gbaudio_codec_info { struct device *dev; - struct snd_soc_codec *codec; + struct snd_soc_component *component; struct list_head module_list; /* to maintain runtime stream params for each DAI */ struct list_head dai_list; @@ -106,6 +106,11 @@ enum gbaudio_module_state { GBAUDIO_MODULE_ON, }; +struct gbaudio_jack { + struct snd_soc_jack jack; + struct list_head list; +}; + struct gbaudio_module_info { /* module info */ struct device *dev; @@ -130,8 +135,8 @@ struct gbaudio_module_info { int jack_mask; int button_mask; int button_status; - struct snd_soc_jack headset_jack; - struct snd_soc_jack button_jack; + struct gbaudio_jack headset; + struct gbaudio_jack button; /* connection info */ struct gb_connection *mgmt_connection; @@ -155,6 +160,7 @@ struct gbaudio_module_info { struct list_head widget_list; struct list_head ctl_list; struct list_head widget_ctl_list; + struct list_head jack_list; struct gb_audio_topology *topology; }; diff --git a/drivers/staging/greybus/audio_helper.c b/drivers/staging/greybus/audio_helper.c new file mode 100644 index 0000000000000000000000000000000000000000..8b100a71f02ef09919fcb38acf561b006f98b14a --- /dev/null +++ b/drivers/staging/greybus/audio_helper.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus Audio Sound SoC helper APIs + */ + +#include +#include +#include +#include +#include "audio_helper.h" + +#define gbaudio_dapm_for_each_direction(dir) \ + for ((dir) = SND_SOC_DAPM_DIR_IN; (dir) <= SND_SOC_DAPM_DIR_OUT; \ + (dir)++) + +static void gbaudio_dapm_link_dai_widget(struct snd_soc_dapm_widget *dai_w, + struct snd_soc_card *card) +{ + struct snd_soc_dapm_widget *w; + struct snd_soc_dapm_widget *src, *sink; + struct snd_soc_dai *dai = dai_w->priv; + + /* ...find all widgets with the same stream and link them */ + list_for_each_entry(w, &card->widgets, list) { + if (w->dapm != dai_w->dapm) + continue; + + switch (w->id) { + case snd_soc_dapm_dai_in: + case snd_soc_dapm_dai_out: + continue; + default: + break; + } + + if (!w->sname || !strstr(w->sname, dai_w->sname)) + continue; + + /* + * check if widget is already linked, + * if (w->linked) + * return; + */ + + if (dai_w->id == snd_soc_dapm_dai_in) { + src = dai_w; + sink = w; + } else { + src = w; + sink = dai_w; + } + dev_dbg(dai->dev, "%s -> %s\n", src->name, sink->name); + /* Add the DAPM path and set widget's linked status + * snd_soc_dapm_add_path(w->dapm, src, sink, NULL, NULL); + * w->linked = 1; + */ + } +} + +int gbaudio_dapm_link_component_dai_widgets(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm) +{ + struct snd_soc_dapm_widget *dai_w; + + /* For each DAI widget... */ + list_for_each_entry(dai_w, &card->widgets, list) { + if (dai_w->dapm != dapm) + continue; + switch (dai_w->id) { + case snd_soc_dapm_dai_in: + case snd_soc_dapm_dai_out: + break; + default: + continue; + } + gbaudio_dapm_link_dai_widget(dai_w, card); + } + + return 0; +} + +static void gbaudio_dapm_free_path(struct snd_soc_dapm_path *path) +{ + list_del(&path->list_node[SND_SOC_DAPM_DIR_IN]); + list_del(&path->list_node[SND_SOC_DAPM_DIR_OUT]); + list_del(&path->list_kcontrol); + list_del(&path->list); + kfree(path); +} + +static void gbaudio_dapm_free_widget(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dapm_path *p, *next_p; + enum snd_soc_dapm_direction dir; + + list_del(&w->list); + /* + * remove source and sink paths associated to this widget. + * While removing the path, remove reference to it from both + * source and sink widgets so that path is removed only once. + */ + gbaudio_dapm_for_each_direction(dir) { + snd_soc_dapm_widget_for_each_path_safe(w, dir, p, next_p) + gbaudio_dapm_free_path(p); + } + + kfree(w->kcontrols); + kfree_const(w->name); + kfree_const(w->sname); + kfree(w); +} + +int gbaudio_dapm_free_controls(struct snd_soc_dapm_context *dapm, + const struct snd_soc_dapm_widget *widget, + int num) +{ + int i; + struct snd_soc_dapm_widget *w, *next_w; +#ifdef CONFIG_DEBUG_FS + struct dentry *parent = dapm->debugfs_dapm; + struct dentry *debugfs_w = NULL; +#endif + + mutex_lock(&dapm->card->dapm_mutex); + for (i = 0; i < num; i++) { + /* below logic can be optimized to identify widget pointer */ + list_for_each_entry_safe(w, next_w, &dapm->card->widgets, + list) { + if (w->dapm != dapm) + continue; + if (!strcmp(w->name, widget->name)) + break; + w = NULL; + } + if (!w) { + dev_err(dapm->dev, "%s: widget not found\n", + widget->name); + return -EINVAL; + } + widget++; +#ifdef CONFIG_DEBUG_FS + if (!parent) + debugfs_w = debugfs_lookup(w->name, parent); + debugfs_remove(debugfs_w); + debugfs_w = NULL; +#endif + gbaudio_dapm_free_widget(w); + } + mutex_unlock(&dapm->card->dapm_mutex); + return 0; +} + +static int gbaudio_remove_controls(struct snd_card *card, struct device *dev, + const struct snd_kcontrol_new *controls, + int num_controls, const char *prefix) +{ + int i, err; + + for (i = 0; i < num_controls; i++) { + const struct snd_kcontrol_new *control = &controls[i]; + struct snd_ctl_elem_id id; + struct snd_kcontrol *kctl; + + if (prefix) + snprintf(id.name, sizeof(id.name), "%s %s", prefix, + control->name); + else + strlcpy(id.name, control->name, sizeof(id.name)); + id.numid = 0; + id.iface = control->iface; + id.device = control->device; + id.subdevice = control->subdevice; + id.index = control->index; + kctl = snd_ctl_find_id(card, &id); + if (!kctl) { + dev_err(dev, "%d: Failed to find %s\n", err, + control->name); + continue; + } + err = snd_ctl_remove(card, kctl); + if (err < 0) { + dev_err(dev, "%d: Failed to remove %s\n", err, + control->name); + continue; + } + } + return 0; +} + +int gbaudio_remove_component_controls(struct snd_soc_component *component, + const struct snd_kcontrol_new *controls, + unsigned int num_controls) +{ + struct snd_card *card = component->card->snd_card; + + return gbaudio_remove_controls(card, component->dev, controls, + num_controls, component->name_prefix); +} diff --git a/drivers/staging/greybus/audio_helper.h b/drivers/staging/greybus/audio_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..5cf1c6d7d3ea4643e868b261520112872f898925 --- /dev/null +++ b/drivers/staging/greybus/audio_helper.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus Audio Sound SoC helper APIs + */ + +#ifndef __LINUX_GBAUDIO_HELPER_H +#define __LINUX_GBAUDIO_HELPER_H + +int gbaudio_dapm_link_component_dai_widgets(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm); +int gbaudio_dapm_free_controls(struct snd_soc_dapm_context *dapm, + const struct snd_soc_dapm_widget *widget, + int num); +int gbaudio_remove_component_controls(struct snd_soc_component *component, + const struct snd_kcontrol_new *controls, + unsigned int num_controls); +#endif diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 300a2b4f3fc78e11d53c7240e547019eb303e4ed..16f60256adb2bbbd89905de5f192a7666c4b377c 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -21,8 +21,8 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, struct gb_audio_jack_event_request *req) { int report; - struct snd_jack *jack = module->headset_jack.jack; - struct snd_jack *btn_jack = module->button_jack.jack; + struct snd_jack *jack = module->headset.jack.jack; + struct snd_jack *btn_jack = module->button.jack.jack; if (!jack) { dev_err_ratelimited(module->dev, @@ -38,11 +38,11 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, if (req->event == GB_AUDIO_JACK_EVENT_REMOVAL) { module->jack_type = 0; if (btn_jack && module->button_status) { - snd_soc_jack_report(&module->button_jack, 0, + snd_soc_jack_report(&module->button.jack, 0, module->button_mask); module->button_status = 0; } - snd_soc_jack_report(&module->headset_jack, 0, + snd_soc_jack_report(&module->headset.jack, 0, module->jack_mask); return 0; } @@ -61,7 +61,7 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, module->jack_type, report); module->jack_type = report; - snd_soc_jack_report(&module->headset_jack, report, module->jack_mask); + snd_soc_jack_report(&module->headset.jack, report, module->jack_mask); return 0; } @@ -70,7 +70,7 @@ static int gbaudio_request_button(struct gbaudio_module_info *module, struct gb_audio_button_event_request *req) { int soc_button_id, report; - struct snd_jack *btn_jack = module->button_jack.jack; + struct snd_jack *btn_jack = module->button.jack.jack; if (!btn_jack) { dev_err_ratelimited(module->dev, @@ -124,7 +124,7 @@ static int gbaudio_request_button(struct gbaudio_module_info *module, module->button_status = report; - snd_soc_jack_report(&module->button_jack, report, module->button_mask); + snd_soc_jack_report(&module->button.jack, report, module->button_mask); return 0; } @@ -258,6 +258,7 @@ static int gb_audio_probe(struct gb_bundle *bundle, INIT_LIST_HEAD(&gbmodule->widget_list); INIT_LIST_HEAD(&gbmodule->ctl_list); INIT_LIST_HEAD(&gbmodule->widget_ctl_list); + INIT_LIST_HEAD(&gbmodule->jack_list); gbmodule->dev = dev; snprintf(gbmodule->name, NAME_SIZE, "%s.%s", dev->driver->name, dev_name(dev)); diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 4ac30accf226ae9185d04d1c8c04bc22100d4202..2f9fdbdcd547017b8704b7839f8cb33f658ab110 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -5,8 +5,8 @@ * Copyright 2015-2016 Linaro Ltd. */ +#include #include "audio_codec.h" -#include "greybus_protocols.h" #define GBAUDIO_INVALID_ID 0xFF @@ -28,14 +28,16 @@ static struct gbaudio_module_info *find_gb_module( struct gbaudio_codec_info *codec, char const *name) { - int dev_id, ret; + int dev_id; char begin[NAME_SIZE]; struct gbaudio_module_info *module; if (!name) return NULL; - ret = sscanf(name, "%s %d", begin, &dev_id); + if (sscanf(name, "%s %d", begin, &dev_id) != 2) + return NULL; + dev_dbg(codec->dev, "%s:Find module#%d\n", __func__, dev_id); mutex_lock(&codec->lock); @@ -165,15 +167,15 @@ static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_info *info; struct gbaudio_module_info *module; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct gbaudio_codec_info *gbcodec = snd_soc_component_get_drvdata(comp); - dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + dev_dbg(comp->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; if (!info) { - dev_err(codec->dev, "NULL info for %s\n", uinfo->id.name); + dev_err(comp->dev, "NULL info for %s\n", uinfo->id.name); return -EINVAL; } @@ -201,7 +203,7 @@ static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol, strlcpy(uinfo->value.enumerated.name, name, NAME_SIZE); break; default: - dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n", + dev_err(comp->dev, "Invalid type: %d for %s:kcontrol\n", info->type, kcontrol->id.name); break; } @@ -216,11 +218,11 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; struct gbaudio_module_info *module; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct gbaudio_codec_info *gb = snd_soc_component_get_drvdata(comp); struct gb_bundle *bundle; - dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + dev_dbg(comp->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); module = find_gb_module(gb, kcontrol->id.name); if (!module) return -EINVAL; @@ -239,7 +241,7 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, gb_pm_runtime_put_autosuspend(bundle); if (ret) { - dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + dev_err_ratelimited(comp->dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); return ret; } @@ -262,7 +264,7 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, le32_to_cpu(gbvalue.value.enumerated_item[1]); break; default: - dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n", + dev_err(comp->dev, "Invalid type: %d for %s:kcontrol\n", info->type, kcontrol->id.name); ret = -EINVAL; break; @@ -278,11 +280,11 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; struct gbaudio_module_info *module; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct gbaudio_codec_info *gb = snd_soc_component_get_drvdata(comp); struct gb_bundle *bundle; - dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + dev_dbg(comp->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); module = find_gb_module(gb, kcontrol->id.name); if (!module) return -EINVAL; @@ -309,7 +311,7 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, cpu_to_le32(ucontrol->value.enumerated.item[1]); break; default: - dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n", + dev_err(comp->dev, "Invalid type: %d for %s:kcontrol\n", info->type, kcontrol->id.name); ret = -EINVAL; break; @@ -328,7 +330,7 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, gb_pm_runtime_put_autosuspend(bundle); if (ret) { - dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + dev_err_ratelimited(comp->dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); } @@ -352,11 +354,7 @@ static int gbcodec_mixer_dapm_ctl_info(struct snd_kcontrol *kcontrol, int platform_max, platform_min; struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_info *info; - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; - dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -381,23 +379,21 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int ret; - struct gb_audio_ctl_elem_info *info; struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; struct gbaudio_module_info *module; struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct device *codec_dev = widget->dapm->dev; + struct gbaudio_codec_info *gb = dev_get_drvdata(codec_dev); struct gb_bundle *bundle; - dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + dev_dbg(codec_dev, "Entered %s:%s\n", __func__, kcontrol->id.name); module = find_gb_module(gb, kcontrol->id.name); if (!module) return -EINVAL; data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; - info = (struct gb_audio_ctl_elem_info *)data->info; bundle = to_gb_bundle(module->dev); if (data->vcount == 2) @@ -415,7 +411,7 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, gb_pm_runtime_put_autosuspend(bundle); if (ret) { - dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + dev_err_ratelimited(codec_dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); return ret; } @@ -437,11 +433,11 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, struct gbaudio_module_info *module; struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct device *codec_dev = widget->dapm->dev; + struct gbaudio_codec_info *gb = dev_get_drvdata(codec_dev); struct gb_bundle *bundle; - dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + dev_dbg(codec_dev, "Entered %s:%s\n", __func__, kcontrol->id.name); module = find_gb_module(gb, kcontrol->id.name); if (!module) return -EINVAL; @@ -464,11 +460,8 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, if (gbvalue.value.integer_value[0] != val) { for (wi = 0; wi < wlist->num_widgets; wi++) { widget = wlist->widgets[wi]; - - widget->value = val; - widget->dapm->update = NULL; - snd_soc_dapm_mixer_update_power(widget, kcontrol, - connect); + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, + connect, NULL); } gbvalue.value.integer_value[0] = cpu_to_le32(ucontrol->value.integer.value[0]); @@ -484,7 +477,7 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, gb_pm_runtime_put_autosuspend(bundle); if (ret) { - dev_err_ratelimited(codec->dev, + dev_err_ratelimited(codec_dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); return ret; @@ -553,11 +546,11 @@ static int gbcodec_enum_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int ret, ctl_id; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct gbaudio_codec_info *gb = snd_soc_component_get_drvdata(comp); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct gb_audio_ctl_elem_value gbvalue; struct gbaudio_module_info *module; - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); struct gb_bundle *bundle; module = find_gb_module(gb, kcontrol->id.name); @@ -580,7 +573,7 @@ static int gbcodec_enum_ctl_get(struct snd_kcontrol *kcontrol, gb_pm_runtime_put_autosuspend(bundle); if (ret) { - dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + dev_err_ratelimited(comp->dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); return ret; } @@ -598,11 +591,11 @@ static int gbcodec_enum_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int ret, ctl_id; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct gbaudio_codec_info *gb = snd_soc_component_get_drvdata(comp); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct gb_audio_ctl_elem_value gbvalue; struct gbaudio_module_info *module; - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); struct gb_bundle *bundle; module = find_gb_module(gb, kcontrol->id.name); @@ -613,13 +606,13 @@ static int gbcodec_enum_ctl_put(struct snd_kcontrol *kcontrol, if (ctl_id < 0) return -EINVAL; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] > e->items - 1) return -EINVAL; gbvalue.value.enumerated_item[0] = cpu_to_le32(ucontrol->value.enumerated.item[0]); if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] > e->items - 1) return -EINVAL; gbvalue.value.enumerated_item[1] = cpu_to_le32(ucontrol->value.enumerated.item[1]); @@ -637,8 +630,8 @@ static int gbcodec_enum_ctl_put(struct snd_kcontrol *kcontrol, gb_pm_runtime_put_autosuspend(bundle); if (ret) { - dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, - __func__, kcontrol->id.name); + dev_err_ratelimited(comp->dev, "%d:Error in %s for %s\n", + ret, __func__, kcontrol->id.name); } return ret; @@ -659,13 +652,13 @@ static int gbaudio_tplg_create_enum_kctl(struct gbaudio_module_info *gb, gb_enum = &ctl->info.value.enumerated; /* since count=1, and reg is dummy */ - gbe->max = le32_to_cpu(gb_enum->items); + gbe->items = le32_to_cpu(gb_enum->items); gbe->texts = gb_generate_enum_strings(gb, gb_enum); /* debug enum info */ - dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gbe->max, + dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gbe->items, le16_to_cpu(gb_enum->names_length)); - for (i = 0; i < gbe->max; i++) + for (i = 0; i < gbe->items; i++) dev_dbg(gb->dev, "src[%d]: %s\n", i, gbe->texts[i]); *kctl = (struct snd_kcontrol_new) @@ -720,8 +713,8 @@ static int gbcodec_enum_dapm_ctl_get(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct gbaudio_module_info *module; struct gb_audio_ctl_elem_value gbvalue; - struct snd_soc_codec *codec = widget->codec; - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct device *codec_dev = widget->dapm->dev; + struct gbaudio_codec_info *gb = dev_get_drvdata(codec_dev); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct gb_bundle *bundle; @@ -745,7 +738,7 @@ static int gbcodec_enum_dapm_ctl_get(struct snd_kcontrol *kcontrol, gb_pm_runtime_put_autosuspend(bundle); if (ret) { - dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + dev_err_ratelimited(codec_dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); return ret; } @@ -768,12 +761,12 @@ static int gbcodec_enum_dapm_ctl_put(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct gb_audio_ctl_elem_value gbvalue; struct gbaudio_module_info *module; - struct snd_soc_codec *codec = widget->codec; - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct device *codec_dev = widget->dapm->dev; + struct gbaudio_codec_info *gb = dev_get_drvdata(codec_dev); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct gb_bundle *bundle; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] > e->items - 1) return -EINVAL; module = find_gb_module(gb, kcontrol->id.name); @@ -797,7 +790,7 @@ static int gbcodec_enum_dapm_ctl_put(struct snd_kcontrol *kcontrol, gb_pm_runtime_put_autosuspend(bundle); if (ret) { - dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + dev_err_ratelimited(codec_dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); return ret; } @@ -814,7 +807,7 @@ static int gbcodec_enum_dapm_ctl_put(struct snd_kcontrol *kcontrol, } if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] > e->items - 1) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; mask |= e->mask << e->shift_r; @@ -837,16 +830,14 @@ static int gbcodec_enum_dapm_ctl_put(struct snd_kcontrol *kcontrol, gb_pm_runtime_put_autosuspend(bundle); if (ret) { - dev_err_ratelimited(codec->dev, + dev_err_ratelimited(codec_dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); } for (wi = 0; wi < wlist->num_widgets; wi++) { widget = wlist->widgets[wi]; - - widget->value = val; - widget->dapm->update = NULL; - snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e); + snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, + val, e, NULL); } } @@ -868,13 +859,13 @@ static int gbaudio_tplg_create_enum_ctl(struct gbaudio_module_info *gb, gb_enum = &ctl->info.value.enumerated; /* since count=1, and reg is dummy */ - gbe->max = le32_to_cpu(gb_enum->items); + gbe->items = le32_to_cpu(gb_enum->items); gbe->texts = gb_generate_enum_strings(gb, gb_enum); /* debug enum info */ - dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gbe->max, + dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gbe->items, le16_to_cpu(gb_enum->names_length)); - for (i = 0; i < gbe->max; i++) + for (i = 0; i < gbe->items; i++) dev_dbg(gb->dev, "src[%d]: %s\n", i, gbe->texts[i]); *kctl = (struct snd_kcontrol_new) @@ -935,12 +926,12 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, { int wid; int ret; - struct snd_soc_codec *codec = w->codec; - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + struct device *codec_dev = w->dapm->dev; + struct gbaudio_codec_info *gbcodec = dev_get_drvdata(codec_dev); struct gbaudio_module_info *module; struct gb_bundle *bundle; - dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event); + dev_dbg(codec_dev, "%s %s %d\n", __func__, w->name, event); /* Find relevant module */ module = find_gb_module(gbcodec, w->name); @@ -950,7 +941,7 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, /* map name to widget id */ wid = gbaudio_map_widgetname(module, w->name); if (wid < 0) { - dev_err(codec->dev, "Invalid widget name:%s\n", w->name); + dev_err(codec_dev, "Invalid widget name:%s\n", w->name); return -EINVAL; } @@ -973,7 +964,7 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, break; } if (ret) - dev_err_ratelimited(codec->dev, + dev_err_ratelimited(codec_dev, "%d: widget, event:%d failed:%d\n", wid, event, ret); diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 36d99f9e419ef57b717db7591530d74c65505198..7e6347fe93f9922e8f06ab7db3a70158d28813f8 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -504,6 +504,7 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev, struct gb_connection *connection; struct gb_gpio_controller *ggc; struct gpio_chip *gpio; + struct gpio_irq_chip *girq; struct irq_chip *irqc; int ret; @@ -561,6 +562,15 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev, gpio->ngpio = ggc->line_max + 1; gpio->can_sleep = true; + girq = &gpio->irq; + girq->chip = irqc; + /* The event comes from the outside so no parent handler */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_level_irq; + ret = gb_connection_enable(connection); if (ret) goto exit_line_free; @@ -571,18 +581,9 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev, goto exit_line_free; } - ret = gpiochip_irqchip_add(gpio, irqc, 0, handle_level_irq, - IRQ_TYPE_NONE); - if (ret) { - dev_err(&gbphy_dev->dev, "failed to add irq chip: %d\n", ret); - goto exit_gpiochip_remove; - } - gbphy_runtime_put_autosuspend(gbphy_dev); return 0; -exit_gpiochip_remove: - gpiochip_remove(gpio); exit_line_free: kfree(ggc->lines); exit_connection_disable: diff --git a/drivers/staging/gs_fpgaboot/README b/drivers/staging/gs_fpgaboot/README index 8d793c1769b045eb0d333546782dadc4c04047c6..b85a76849fc4af878a8944f5f7ed1945114c6237 100644 --- a/drivers/staging/gs_fpgaboot/README +++ b/drivers/staging/gs_fpgaboot/README @@ -65,6 +65,6 @@ TABLE OF CONTENTS. 6. REFERENCE 1. Xilinx APP NOTE XAPP583: - http://www.xilinx.com/support/documentation/application_notes/xapp583-fpga-configuration.pdf + https://www.xilinx.com/support/documentation/application_notes/xapp583-fpga-configuration.pdf 2. bitstream file info: http://home.earthlink.net/~davesullins/software/bitinfo.html diff --git a/drivers/staging/iio/Documentation/device.txt b/drivers/staging/iio/Documentation/device.txt index ec42544a46aa6503d903bdd8ac999c891291b195..0d1275b1eb3ff4add17e873fb8fbaf918c57ecf8 100644 --- a/drivers/staging/iio/Documentation/device.txt +++ b/drivers/staging/iio/Documentation/device.txt @@ -8,7 +8,7 @@ The crucial structure for device drivers in iio is iio_dev. First allocate one using: -struct iio_dev *indio_dev = iio_device_alloc(sizeof(struct chip_state)); +struct iio_dev *indio_dev = iio_device_alloc(parent, sizeof(struct chip_state)); where chip_state is a structure of local state data for this instance of the chip. @@ -16,8 +16,6 @@ That data can be accessed using iio_priv(struct iio_dev *). Then fill in the following: -- indio_dev->dev.parent - Struct device associated with the underlying hardware. - indio_dev->name Name of the device being driven - made available as the name attribute in sysfs. diff --git a/drivers/staging/iio/accel/adis16203.c b/drivers/staging/iio/accel/adis16203.c index fef52d9b53467db9118fb4a53b8621304824343c..c7798908ef0e4d5c038daf05714828b8da66bddf 100644 --- a/drivers/staging/iio/accel/adis16203.c +++ b/drivers/staging/iio/accel/adis16203.c @@ -277,7 +277,6 @@ static int adis16203_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; indio_dev->channels = adis16203_channels; indio_dev->num_channels = ARRAY_SIZE(adis16203_channels); indio_dev->info = &adis16203_info; diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c index 8bd35c6c56a1bfa04c9858d2c7d77173d7e84f55..38ec40b458c90215f3cca3b91aafe171e2717622 100644 --- a/drivers/staging/iio/accel/adis16240.c +++ b/drivers/staging/iio/accel/adis16240.c @@ -400,7 +400,6 @@ static int adis16240_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16240_info; indio_dev->channels = adis16240_channels; indio_dev->num_channels = ARRAY_SIZE(adis16240_channels); diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index bef6bd1295eac60402d5716242d9a8d77d1998a1..fef0055b89909fc0454870e602cecad237554873 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -978,7 +978,6 @@ static int ad7280_probe(struct spi_device *spi) st->readback_delay_us += 5; /* Add tWAIT */ indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; indio_dev->modes = INDIO_DIRECT_MODE; ret = ad7280_channel_init(st); diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c index a9985a7f81990f965ae6de0c320961a44650a5c6..6c14d7bcdd6750908e9a53302d48df5abb7bdbbf 100644 --- a/drivers/staging/iio/adc/ad7816.c +++ b/drivers/staging/iio/adc/ad7816.c @@ -394,7 +394,6 @@ static int ad7816_probe(struct spi_device *spi_dev) } indio_dev->name = spi_get_device_id(spi_dev)->name; - indio_dev->dev.parent = &spi_dev->dev; indio_dev->info = &ad7816_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 9cb3d0e42c38cae6e399adb77d104523e381fa77..ccbafcaaf27e57bb2c047f8f7cf26fc67c58f4af 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -2171,7 +2171,6 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus, if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) chip->int_mask |= ADT7516_AIN_INT_MASK; - indio_dev->dev.parent = dev; if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) indio_dev->info = &adt7516_info; else diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index f4954d85553efa3eb7911408ac400f3b05c51088..48132ab157ef80686aac6045ae22a04765a0da37 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -590,8 +590,6 @@ static int ad7150_probe(struct i2c_client *client, indio_dev->name = id->name; indio_dev->channels = ad7150_channels; indio_dev->num_channels = ARRAY_SIZE(ad7150_channels); - /* Establish that the iio_dev is a child of the i2c device */ - indio_dev->dev.parent = &client->dev; indio_dev->info = &ad7150_info; diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 21527d84f9408cb737a6157e14d5c09c89f0731a..dfd71e99e872ed27c089496a1b9826b9a0fe6a62 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -693,9 +693,7 @@ static int ad7746_probe(struct i2c_client *client, chip->client = client; chip->capdac_set = -1; - /* Establish that the iio_dev is a child of the i2c device */ indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->info = &ad7746_info; indio_dev->channels = ad7746_channels; if (id->driver_data == 7746) diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index 74308a2e72dbec4d1a41bd9305d71d4f51ec8cd2..447937e04ebdc55028d8064946af18bc5f26c4b8 100644 --- a/drivers/staging/iio/frequency/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -348,7 +348,6 @@ static int ad9832_probe(struct spi_device *spi) st->spi = spi; mutex_init(&st->lock); - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad9832_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index 23026978a5a5f5f12b42508551ab1d0b875127df..77f77a2b2e0545c0747f13b86753cbd0c6d6adf0 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -431,7 +431,6 @@ static int ad9834_probe(struct spi_device *spi) st->spi = spi; st->devid = spi_get_device_id(spi)->driver_data; st->reg = reg; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; switch (st->devid) { case ID_AD9833: diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index c468355b0848fd4498f771fb0d57258b1d0d0eca..dba78896ea8f28506979ffa22afc1d38c5105bad 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -759,7 +759,6 @@ static int ad5933_probe(struct i2c_client *client, INIT_DELAYED_WORK(&st->work, ad5933_work); st->poll_time_jiffies = msecs_to_jiffies(AD5933_POLL_TIME_ms); - indio_dev->dev.parent = &client->dev; indio_dev->info = &ad5933_info; indio_dev->name = id->name; indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE); diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index ed404355ea4c6f9978c941a953a014dd21f4f4fe..74adb82f37c30f30e692f2858e93e938ece95f47 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -671,7 +671,6 @@ static int ad2s1210_probe(struct spi_device *spi) st->resolution = 12; st->fexcit = AD2S1210_DEF_EXCIT; - indio_dev->dev.parent = &spi->dev; indio_dev->info = &ad2s1210_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ad2s1210_channels; diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c index 89753463e9268cfb5f04da5f09ae00661cadec0e..dd716edd9b1b3b2d6047e62b09f7b5dfc64884c5 100644 --- a/drivers/staging/kpc2000/kpc_dma/fileops.c +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c @@ -35,7 +35,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv, unsigned long iov_base, size_t iov_len) { unsigned int i = 0; - long rv = 0; + int rv = 0, nr_pages = 0; struct kpc_dma_device *ldev; struct aio_cb_data *acd; DECLARE_COMPLETION_ONSTACK(done); @@ -76,25 +76,30 @@ static int kpc_dma_transfer(struct dev_private_data *priv, // Lock the user buffer pages in memory, and hold on to the page pointers (for the sglist) mmap_read_lock(current->mm); /* get memory map semaphore */ - rv = get_user_pages(iov_base, acd->page_count, FOLL_TOUCH | FOLL_WRITE | FOLL_GET, acd->user_pages, NULL); + rv = pin_user_pages(iov_base, acd->page_count, FOLL_TOUCH | FOLL_WRITE, acd->user_pages, NULL); mmap_read_unlock(current->mm); /* release the semaphore */ if (rv != acd->page_count) { - dev_err(&priv->ldev->pldev->dev, "Couldn't get_user_pages (%ld)\n", rv); - goto err_get_user_pages; + nr_pages = rv; + if (rv > 0) + rv = -EFAULT; + + dev_err(&priv->ldev->pldev->dev, "Couldn't pin_user_pages (%d)\n", rv); + goto unpin_pages; } + nr_pages = acd->page_count; // Allocate and setup the sg_table (scatterlist entries) rv = sg_alloc_table_from_pages(&acd->sgt, acd->user_pages, acd->page_count, iov_base & (PAGE_SIZE - 1), iov_len, GFP_KERNEL); if (rv) { - dev_err(&priv->ldev->pldev->dev, "Couldn't alloc sg_table (%ld)\n", rv); - goto err_alloc_sg_table; + dev_err(&priv->ldev->pldev->dev, "Couldn't alloc sg_table (%d)\n", rv); + goto unpin_pages; } // Setup the DMA mapping for all the sg entries acd->mapped_entry_count = dma_map_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, ldev->dir); if (acd->mapped_entry_count <= 0) { dev_err(&priv->ldev->pldev->dev, "Couldn't dma_map_sg (%d)\n", acd->mapped_entry_count); - goto err_dma_map_sg; + goto free_table; } // Calculate how many descriptors are actually needed for this transfer. @@ -186,17 +191,16 @@ static int kpc_dma_transfer(struct dev_private_data *priv, err_descr_too_many: unlock_engine(ldev); dma_unmap_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, ldev->dir); + free_table: sg_free_table(&acd->sgt); - err_dma_map_sg: - err_alloc_sg_table: - for (i = 0 ; i < acd->page_count ; i++) - put_page(acd->user_pages[i]); - err_get_user_pages: + unpin_pages: + if (nr_pages > 0) + unpin_user_pages(acd->user_pages, nr_pages); kfree(acd->user_pages); err_alloc_userpages: kfree(acd); - dev_dbg(&priv->ldev->pldev->dev, "%s returning with error %ld\n", __func__, rv); + dev_dbg(&priv->ldev->pldev->dev, "%s returning with error %d\n", __func__, rv); return rv; } @@ -210,15 +214,14 @@ void transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags) BUG_ON(!acd->ldev); BUG_ON(!acd->ldev->pldev); + dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir); + for (i = 0 ; i < acd->page_count ; i++) { if (!PageReserved(acd->user_pages[i])) - set_page_dirty(acd->user_pages[i]); + set_page_dirty_lock(acd->user_pages[i]); } - dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir); - - for (i = 0 ; i < acd->page_count ; i++) - put_page(acd->user_pages[i]); + unpin_user_pages(acd->user_pages, acd->page_count); sg_free_table(&acd->sgt); diff --git a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c b/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c index c3b30551e0ca3a35687fb817c1788ee46f396685..624d47bae4d1a8b78bfd691f7e5b709d2ccce575 100644 --- a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c +++ b/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c @@ -140,6 +140,7 @@ int kpc_dma_probe(struct platform_device *pldev) dev = MKDEV(assigned_major_num, pldev->id); ldev->kpc_dma_dev = device_create(kpc_dma_class, &pldev->dev, dev, ldev, "kpc_dma%d", pldev->id); if (IS_ERR(ldev->kpc_dma_dev)) { + rv = PTR_ERR(ldev->kpc_dma_dev); dev_err(&ldev->pldev->dev, "%s: device_create failed: %d\n", __func__, rv); goto err_kfree; } diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 2666f9e30c155006a5d68b749dbe7d53c7b69997..b10a92ae2067b6bcb9c6d85b597923d825004bea 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -161,7 +161,7 @@ int get_current_ap(struct ks_wlan_private *priv, struct link_ap_info *ap_info) wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL); } netdev_dbg(priv->net_dev, "Link AP\n" - "- bssid=%02X:%02X:%02X:%02X:%02X:%02X\n" + "- bssid=%pM\n" "- essid=%s\n" "- rate_set=%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X\n" "- channel=%d\n" @@ -172,8 +172,7 @@ int get_current_ap(struct ks_wlan_private *priv, struct link_ap_info *ap_info) "- rsn.size=%d\n" "- ext_rate_set_size=%d\n" "- rate_set_size=%d\n", - ap->bssid[0], ap->bssid[1], ap->bssid[2], - ap->bssid[3], ap->bssid[4], ap->bssid[5], + ap->bssid, &ap->ssid.body[0], ap->rate_set.body[0], ap->rate_set.body[1], ap->rate_set.body[2], ap->rate_set.body[3], @@ -439,11 +438,7 @@ void hostif_data_indication(struct ks_wlan_private *priv) /* source address check */ if (ether_addr_equal(&priv->eth_addr[0], eth_hdr->h_source)) { netdev_err(priv->net_dev, "invalid : source is own mac address !!\n"); - netdev_err(priv->net_dev, - "eth_hdrernet->h_dest=%02X:%02X:%02X:%02X:%02X:%02X\n", - eth_hdr->h_source[0], eth_hdr->h_source[1], - eth_hdr->h_source[2], eth_hdr->h_source[3], - eth_hdr->h_source[4], eth_hdr->h_source[5]); + netdev_err(priv->net_dev, "eth_hdrernet->h_dest=%pM\n", eth_hdr->h_source); priv->nstats.rx_errors++; return; } diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index 211dd4a11cac509281bad3b9d9df10db1e5276e9..dc09cc6e1c4784ac6b3c95ca06ee576f2348ac53 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -46,7 +46,7 @@ struct wep_key { */ static int ks_wlan_open(struct net_device *dev); static void ks_wlan_tx_timeout(struct net_device *dev, unsigned int txqueue); -static int ks_wlan_start_xmit(struct sk_buff *skb, struct net_device *dev); +static netdev_tx_t ks_wlan_start_xmit(struct sk_buff *skb, struct net_device *dev); static int ks_wlan_close(struct net_device *dev); static void ks_wlan_set_rx_mode(struct net_device *dev); static struct net_device_stats *ks_wlan_get_stats(struct net_device *dev); @@ -426,16 +426,16 @@ static int ks_wlan_set_rate(struct net_device *dev, priv->reg.rate_set.body[3] = TX_RATE_11M; i++; - /* fall through */ + fallthrough; case 5500000: priv->reg.rate_set.body[2] = TX_RATE_5M; i++; - /* fall through */ + fallthrough; case 2000000: priv->reg.rate_set.body[1] = TX_RATE_2M | BASIC_RATE; i++; - /* fall through */ + fallthrough; case 1000000: priv->reg.rate_set.body[0] = TX_RATE_1M | BASIC_RATE; @@ -491,17 +491,17 @@ static int ks_wlan_set_rate(struct net_device *dev, priv->reg.rate_set.body[11] = TX_RATE_54M; i++; - /* fall through */ + fallthrough; case 48000000: priv->reg.rate_set.body[10] = TX_RATE_48M; i++; - /* fall through */ + fallthrough; case 36000000: priv->reg.rate_set.body[9] = TX_RATE_36M; i++; - /* fall through */ + fallthrough; case 24000000: case 18000000: case 12000000: @@ -578,17 +578,17 @@ static int ks_wlan_set_rate(struct net_device *dev, TX_RATE_6M | BASIC_RATE; i++; } - /* fall through */ + fallthrough; case 5500000: priv->reg.rate_set.body[2] = TX_RATE_5M | BASIC_RATE; i++; - /* fall through */ + fallthrough; case 2000000: priv->reg.rate_set.body[1] = TX_RATE_2M | BASIC_RATE; i++; - /* fall through */ + fallthrough; case 1000000: priv->reg.rate_set.body[0] = TX_RATE_1M | BASIC_RATE; @@ -2511,7 +2511,7 @@ void ks_wlan_tx_timeout(struct net_device *dev, unsigned int txqueue) } static -int ks_wlan_start_xmit(struct sk_buff *skb, struct net_device *dev) +netdev_tx_t ks_wlan_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ks_wlan_private *priv = netdev_priv(dev); int ret; diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index c5a99f750abecc2f19386bbb094cb954d1346d10..c35fb34fae79dd0ed9b2b677647292eb4d27e1b3 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -30,6 +30,4 @@ source "drivers/staging/most/dim2/Kconfig" source "drivers/staging/most/i2c/Kconfig" -source "drivers/staging/most/usb/Kconfig" - endif diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile index a803a98654a8ea872bbccec46ed04662157cf033..7c10b84ebac0d7eb7c17488d34f11961c79e76e1 100644 --- a/drivers/staging/most/Makefile +++ b/drivers/staging/most/Makefile @@ -6,4 +6,3 @@ obj-$(CONFIG_MOST_SOUND) += sound/ obj-$(CONFIG_MOST_VIDEO) += video/ obj-$(CONFIG_MOST_DIM2) += dim2/ obj-$(CONFIG_MOST_I2C) += i2c/ -obj-$(CONFIG_MOST_USB) += usb/ diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index cc1e3dea196d4fa385b40fa3e007f44e6fba1ec2..044880760b584382fa247cde56d9cabd11cc6a8c 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -5,7 +5,6 @@ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include #include @@ -67,19 +66,16 @@ static struct comp_channel *get_channel(struct most_interface *iface, int id) { struct comp_channel *c, *tmp; unsigned long flags; - int found_channel = 0; spin_lock_irqsave(&ch_list_lock, flags); list_for_each_entry_safe(c, tmp, &channel_list, list) { if ((c->iface == iface) && (c->channel_id == id)) { - found_channel = 1; - break; + spin_unlock_irqrestore(&ch_list_lock, flags); + return c; } } spin_unlock_irqrestore(&ch_list_lock, flags); - if (!found_channel) - return NULL; - return c; + return NULL; } static void stop_channel(struct comp_channel *c) @@ -129,19 +125,16 @@ static int comp_open(struct inode *inode, struct file *filp) ((filp->f_flags & O_ACCMODE) != O_RDONLY)) || ((c->cfg->direction == MOST_CH_TX) && ((filp->f_flags & O_ACCMODE) != O_WRONLY))) { - pr_info("WARN: Access flags mismatch\n"); return -EACCES; } mutex_lock(&c->io_mutex); if (!c->dev) { - pr_info("WARN: Device is destroyed\n"); mutex_unlock(&c->io_mutex); return -ENODEV; } if (c->access_ref) { - pr_info("WARN: Device is busy\n"); mutex_unlock(&c->io_mutex); return -EBUSY; } @@ -328,14 +321,9 @@ static int comp_disconnect_channel(struct most_interface *iface, int channel_id) { struct comp_channel *c; - if (!iface) { - pr_info("Bad interface pointer\n"); - return -EINVAL; - } - c = get_channel(iface, channel_id); if (!c) - return -ENXIO; + return -EINVAL; mutex_lock(&c->io_mutex); spin_lock(&c->unlink); @@ -369,7 +357,7 @@ static int comp_rx_completion(struct mbo *mbo) c = get_channel(mbo->ifp, mbo->hdm_channel_id); if (!c) - return -ENXIO; + return -EINVAL; spin_lock(&c->unlink); if (!c->access_ref || !c->dev) { @@ -380,7 +368,7 @@ static int comp_rx_completion(struct mbo *mbo) spin_unlock(&c->unlink); #ifdef DEBUG_MESG if (kfifo_is_full(&c->fifo)) - pr_info("WARN: Fifo is full\n"); + dev_warn(c->dev, "Fifo is full\n"); #endif wake_up_interruptible(&c->wq); return 0; @@ -397,18 +385,15 @@ static int comp_tx_completion(struct most_interface *iface, int channel_id) { struct comp_channel *c; - if (!iface) { - pr_info("Bad interface pointer\n"); + c = get_channel(iface, channel_id); + if (!c) return -EINVAL; - } + if ((channel_id < 0) || (channel_id >= iface->num_channels)) { - pr_info("Channel ID out of range\n"); + dev_warn(c->dev, "Channel ID out of range\n"); return -EINVAL; } - c = get_channel(iface, channel_id); - if (!c) - return -ENXIO; wake_up_interruptible(&c->wq); return 0; } @@ -432,10 +417,9 @@ static int comp_probe(struct most_interface *iface, int channel_id, int retval; int current_minor; - if ((!iface) || (!cfg) || (!name)) { - pr_info("Probing component with bad arguments"); + if (!cfg || !name) return -EINVAL; - } + c = get_channel(iface, channel_id); if (c) return -EEXIST; @@ -474,7 +458,6 @@ static int comp_probe(struct most_interface *iface, int channel_id, if (IS_ERR(c->dev)) { retval = PTR_ERR(c->dev); - pr_info("failed to create new device node %s\n", name); goto err_free_kfifo_and_del_list; } kobject_uevent(&c->dev->kobj, KOBJ_ADD); @@ -507,13 +490,9 @@ static int __init mod_init(void) { int err; - pr_info("init()\n"); - comp.class = class_create(THIS_MODULE, "most_cdev"); - if (IS_ERR(comp.class)) { - pr_info("No udev support.\n"); + if (IS_ERR(comp.class)) return PTR_ERR(comp.class); - } INIT_LIST_HEAD(&channel_list); spin_lock_init(&ch_list_lock); @@ -545,8 +524,6 @@ static void __exit mod_exit(void) { struct comp_channel *c, *tmp; - pr_info("exit module\n"); - most_deregister_configfs_subsys(&comp.cc); most_deregister_component(&comp.cc); diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index 830f089f1a88ec8599a7d5064bd01914fea200dd..b6fecb06a0e60e02b60e6b98ec34a49bb4a4207a 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -564,13 +564,11 @@ static void on_netinfo(struct most_interface *iface, if (m && is_valid_ether_addr(m)) { if (!is_valid_ether_addr(dev->dev_addr)) { - netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n", - m[0], m[1], m[2], m[3], m[4], m[5]); + netdev_info(dev, "set mac %pM\n", m); ether_addr_copy(dev->dev_addr, m); netif_dormant_off(dev); } else if (!ether_addr_equal(dev->dev_addr, m)) { - netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n", - m[0], m[1], m[2], m[3], m[4], m[5]); + netdev_warn(dev, "reject mac %pM\n", m); } } diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 1527f410af2bc3ab145593a372f778f2404555e8..8a449ab9bdce4616de39402ee2c2f6b845eb74f1 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -50,10 +50,8 @@ struct channel { unsigned int period_pos; unsigned int buffer_pos; bool is_stream_running; - struct task_struct *playback_task; wait_queue_head_t playback_waitq; - void (*copy_fn)(void *alsa, void *most, unsigned int bytes); }; @@ -176,7 +174,6 @@ static struct channel *get_channel(struct most_interface *iface, if ((channel->iface == iface) && (channel->id == channel_id)) return channel; } - return NULL; } @@ -220,7 +217,6 @@ static bool copy_data(struct channel *channel, struct mbo *mbo) channel->period_pos -= runtime->period_size; return true; } - return false; } @@ -260,7 +256,6 @@ static int playback_thread(void *data) if (period_elapsed) snd_pcm_period_elapsed(channel->substream); } - return 0; } @@ -278,6 +273,7 @@ static int pcm_open(struct snd_pcm_substream *substream) struct channel *channel = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct most_channel_config *cfg = channel->cfg; + int ret; channel->substream = substream; @@ -290,11 +286,12 @@ static int pcm_open(struct snd_pcm_substream *substream) } } - if (most_start_channel(channel->iface, channel->id, &comp)) { + ret = most_start_channel(channel->iface, channel->id, &comp); + if (ret) { pr_err("most_start_channel() failed!\n"); if (cfg->direction == MOST_CH_TX) kthread_stop(channel->playback_task); - return -EBUSY; + return ret; } runtime->hw = channel->pcm_hardware; @@ -318,7 +315,6 @@ static int pcm_close(struct snd_pcm_substream *substream) if (channel->cfg->direction == MOST_CH_TX) kthread_stop(channel->playback_task); most_stop_channel(channel->iface, channel->id, &comp); - return 0; } @@ -360,14 +356,10 @@ static int pcm_prepare(struct snd_pcm_substream *substream) channel->copy_fn = most_to_alsa_copy32; } - if (!channel->copy_fn) { - pr_err("unsupported format\n"); + if (!channel->copy_fn) return -EINVAL; - } - channel->period_pos = 0; channel->buffer_pos = 0; - return 0; } @@ -396,7 +388,6 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) return 0; default: - pr_info("%s(), invalid\n", __func__); return -EINVAL; } return 0; @@ -442,12 +433,11 @@ static int split_arg_list(char *buf, u16 *ch_num, char **sample_res) *sample_res = strsep(&buf, ".\n"); if (!*sample_res) goto err; - return 0; err: pr_err("Bad PCM format\n"); - return -EIO; + return -EINVAL; } static const struct sample_resolution_info { @@ -472,7 +462,7 @@ static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw, goto found; } pr_err("Unsupported PCM format\n"); - return -EIO; + return -EINVAL; found: if (!ch_num) { @@ -541,9 +531,6 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id, char *sample_res; char arg_list_cpy[STRING_SIZE]; - if (!iface) - return -EINVAL; - if (cfg->data_type != MOST_CH_SYNC) { pr_err("Incompatible channel type\n"); return -EINVAL; @@ -583,7 +570,7 @@ skip_adpt_alloc: if (get_channel(iface, channel_id)) { pr_err("channel (%s:%d) is already linked\n", iface->description, channel_id); - return -EINVAL; + return -EEXIST; } if (cfg->direction == MOST_CH_TX) { @@ -620,7 +607,6 @@ skip_adpt_alloc: strscpy(pcm->name, device_name, sizeof(pcm->name)); snd_pcm_set_ops(pcm, direction, &pcm_ops); snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0); - return 0; err_free_adpt: @@ -664,11 +650,8 @@ static int audio_disconnect_channel(struct most_interface *iface, struct sound_adapter *adpt = iface->priv; channel = get_channel(iface, channel_id); - if (!channel) { - pr_err("sound_disconnect_channel(), invalid channel %d\n", - channel_id); + if (!channel) return -EINVAL; - } list_del(&channel->list); @@ -692,20 +675,13 @@ static int audio_rx_completion(struct mbo *mbo) struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id); bool period_elapsed = false; - if (!channel) { - pr_err("sound_rx_completion(), invalid channel %d\n", - mbo->hdm_channel_id); + if (!channel) return -EINVAL; - } - if (channel->is_stream_running) period_elapsed = copy_data(channel, mbo); - most_put_mbo(mbo); - if (period_elapsed) snd_pcm_period_elapsed(channel->substream); - return 0; } @@ -724,14 +700,10 @@ static int audio_tx_completion(struct most_interface *iface, int channel_id) { struct channel *channel = get_channel(iface, channel_id); - if (!channel) { - pr_err("sound_tx_completion(), invalid channel %d\n", - channel_id); + if (!channel) return -EINVAL; - } wake_up_interruptible(&channel->playback_waitq); - return 0; } @@ -752,25 +724,23 @@ static int __init audio_init(void) { int ret; - pr_info("init()\n"); - INIT_LIST_HEAD(&adpt_list); ret = most_register_component(&comp); - if (ret) + if (ret) { pr_err("Failed to register %s\n", comp.name); + return ret; + } ret = most_register_configfs_subsys(&comp); if (ret) { pr_err("Failed to register %s configfs subsys\n", comp.name); most_deregister_component(&comp); } - return ret; } static void __exit audio_exit(void) { - pr_info("exit()\n"); most_deregister_configfs_subsys(&comp); most_deregister_component(&comp); } diff --git a/drivers/staging/most/usb/Kconfig b/drivers/staging/most/usb/Kconfig deleted file mode 100644 index 75dc25c0e0e5125a1e0701a921b896aafd8405ca..0000000000000000000000000000000000000000 --- a/drivers/staging/most/usb/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# MOST USB configuration -# - -config MOST_USB - tristate "USB" - depends on USB && NET - help - Say Y here if you want to connect via USB to network transceiver. - This device driver depends on the networking AIM. - - To compile this driver as a module, choose M here: the - module will be called most_usb. diff --git a/drivers/staging/most/usb/Makefile b/drivers/staging/most/usb/Makefile deleted file mode 100644 index c2b207339aec05537ac1999d4cee6c6099f3bc22..0000000000000000000000000000000000000000 --- a/drivers/staging/most/usb/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_MOST_USB) += most_usb.o - -most_usb-objs := usb.o diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index 204fcdfc022fff34e1fe9457fdefcf30932ff0b0..69ea61faf8fa0ce6973c2f943ee1308470e3677d 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -355,7 +355,7 @@ static void xlr_stats(struct net_device *ndev, struct rtnl_link_stats64 *stats) stats->rx_missed_errors); stats->tx_aborted_errors = xlr_nae_rdreg(priv->base_addr, - TX_EXCESSIVE_COLLISION_PACKET_COUNTER); + TX_EXCESSIVE_COLLISION_PACKET_COUNTER); stats->tx_carrier_errors = xlr_nae_rdreg(priv->base_addr, TX_DROP_FRAME_COUNTER); stats->tx_fifo_errors = xlr_nae_rdreg(priv->base_addr, diff --git a/drivers/staging/nvec/README b/drivers/staging/nvec/README index 0e2d5c4c875fb37f18e70c30000f778e4c1c0373..510e6933f40226973eb30290e7f8292ad404f55d 100644 --- a/drivers/staging/nvec/README +++ b/drivers/staging/nvec/README @@ -10,5 +10,5 @@ but the source code[1] of the published nvec reference drivers can be a guide. This driver is currently only used by the AC100 project[2], but it is likely, that other Tegra boards (not yet mainlined, if ever) also use it. -[1] e.g. http://nv-tegra.nvidia.com/gitweb/?p=linux-2.6.git;a=tree;f=arch/arm/mach-tegra/nvec;hb=android-tegra-2.6.32 +[1] e.g. https://nv-tegra.nvidia.com/gitweb/?p=linux-2.6.git;a=tree;f=arch/arm/mach-tegra/nvec;hb=android-tegra-2.6.32 [2] http://gitorious.org/ac100, http://launchpad.net/ac100 diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index ef9e767b0e2e5464197dd2475240a3f81a54c1a3..c060374a3da2c41d6b18edd03f7de82cdfb0f89a 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h @@ -22,19 +22,19 @@ #define __ETHERNET_DEFINES_H__ #ifdef CONFIG_NETFILTER -#define REUSE_SKBUFFS_WITHOUT_FREE 0 +#define REUSE_SKBUFFS_WITHOUT_FREE 0 #else -#define REUSE_SKBUFFS_WITHOUT_FREE 1 +#define REUSE_SKBUFFS_WITHOUT_FREE 1 #endif -#define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0) +#define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0) /* Maximum number of SKBs to try to free per xmit packet. */ -#define MAX_OUT_QUEUE_DEPTH 1000 +#define MAX_OUT_QUEUE_DEPTH 1000 #define FAU_TOTAL_TX_TO_CLEAN (CVMX_FAU_REG_END - sizeof(u32)) #define FAU_NUM_PACKET_BUFFERS_TO_FREE (FAU_TOTAL_TX_TO_CLEAN - sizeof(u32)) -#define TOTAL_NUMBER_OF_PORTS (CVMX_PIP_NUM_INPUT_PORTS + 1) +#define TOTAL_NUMBER_OF_PORTS (CVMX_PIP_NUM_INPUT_PORTS + 1) #endif /* __ETHERNET_DEFINES_H__ */ diff --git a/drivers/staging/octeon/octeon-stubs.h b/drivers/staging/octeon/octeon-stubs.h index d06743504f2b63fa7bd0dc647bed7fd529dd020b..3f8e5713b8a850f06f9f15de63431105dc1f8442 100644 --- a/drivers/staging/octeon/octeon-stubs.h +++ b/drivers/staging/octeon/octeon-stubs.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE 512 #ifndef XKPHYS_TO_PHYS diff --git a/drivers/staging/qlge/qlge.h b/drivers/staging/qlge/qlge.h index fc8c5ca8935dcc38684505ca3bda48b5f7ba342c..483ce04789ed05a5c8c6153ec53fde6ec7713b87 100644 --- a/drivers/staging/qlge/qlge.h +++ b/drivers/staging/qlge/qlge.h @@ -2057,8 +2057,8 @@ enum { }; struct nic_operations { - int (*get_flash) (struct ql_adapter *); - int (*port_initialize) (struct ql_adapter *); + int (*get_flash)(struct ql_adapter *qdev); + int (*port_initialize)(struct ql_adapter *qdev); }; /* @@ -2224,6 +2224,7 @@ static inline void ql_write_db_reg_relaxed(u32 val, void __iomem *addr) static inline u32 ql_read_sh_reg(__le32 *addr) { u32 reg; + reg = le32_to_cpu(*addr); rmb(); return reg; @@ -2275,7 +2276,7 @@ int ql_mb_set_port_cfg(struct ql_adapter *qdev); int ql_wait_fifo_empty(struct ql_adapter *qdev); void ql_get_dump(struct ql_adapter *qdev, void *buff); netdev_tx_t ql_lb_send(struct sk_buff *skb, struct net_device *ndev); -void ql_check_lb_frame(struct ql_adapter *, struct sk_buff *); +void ql_check_lb_frame(struct ql_adapter *qdev, struct sk_buff *skb); int ql_own_firmware(struct ql_adapter *qdev); int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget); diff --git a/drivers/staging/qlge/qlge_dbg.c b/drivers/staging/qlge/qlge_dbg.c index 0588896879073c7aa62b577ae4f127e9d6e38a01..a55bf0b3e9dccf37668759ab9959da3ffbd32db2 100644 --- a/drivers/staging/qlge/qlge_dbg.c +++ b/drivers/staging/qlge/qlge_dbg.c @@ -42,9 +42,9 @@ static int ql_wait_other_func_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 err_bit) { u32 temp; - int count = 10; + int count; - while (count) { + for (count = 10; count; count--) { temp = ql_read_other_func_reg(qdev, reg); /* check for errors */ @@ -53,7 +53,6 @@ static int ql_wait_other_func_reg_rdy(struct ql_adapter *qdev, u32 reg, else if (temp & bit) return 0; mdelay(10); - count--; } return -1; } @@ -647,7 +646,7 @@ static void ql_get_mac_protocol_registers(struct ql_adapter *qdev, u32 *buf) max_offset = MAC_ADDR_MAX_MGMT_TU_DP_WCOUNT; break; default: - pr_err("Bad type!!! 0x%08x\n", type); + netdev_err(qdev->ndev, "Bad type!!! 0x%08x\n", type); max_index = 0; max_offset = 0; break; @@ -1299,7 +1298,7 @@ void ql_get_dump(struct ql_adapter *qdev, void *buff) * If the dump has already been taken and is stored * in our internal buffer and if force dump is set then * just start the spool to dump it to the log file - * and also, take a snapshot of the general regs to + * and also, take a snapshot of the general regs * to the user's buffer or else take complete dump * to the user's buffer if force is not set. */ @@ -1335,9 +1334,8 @@ static void ql_dump_intr_states(struct ql_adapter *qdev) for (i = 0; i < qdev->intr_count; i++) { ql_write32(qdev, INTR_EN, qdev->intr_context[i].intr_read_mask); value = ql_read32(qdev, INTR_EN); - pr_err("%s: Interrupt %d is %s\n", - qdev->ndev->name, i, - (value & INTR_EN_EN ? "enabled" : "disabled")); + netdev_err(qdev->ndev, "Interrupt %d is %s\n", i, + (value & INTR_EN_EN ? "enabled" : "disabled")); } } @@ -1345,13 +1343,14 @@ static void ql_dump_intr_states(struct ql_adapter *qdev) do { \ u32 data; \ ql_read_xgmac_reg(qdev, reg, &data); \ - pr_err("%s: %s = 0x%.08x\n", qdev->ndev->name, #reg, data); \ + netdev_err(qdev->ndev, "%s = 0x%.08x\n", #reg, data); \ } while (0) void ql_dump_xgmac_control_regs(struct ql_adapter *qdev) { if (ql_sem_spinlock(qdev, qdev->xg_sem_mask)) { - pr_err("%s: Couldn't get xgmac sem\n", __func__); + netdev_err(qdev->ndev, "%s: Couldn't get xgmac sem\n", + __func__); return; } DUMP_XGMAC(qdev, PAUSE_SRC_LO); @@ -1388,27 +1387,28 @@ static void ql_dump_cam_entries(struct ql_adapter *qdev) return; for (i = 0; i < 4; i++) { if (ql_get_mac_addr_reg(qdev, MAC_ADDR_TYPE_CAM_MAC, i, value)) { - pr_err("%s: Failed read of mac index register\n", - __func__); - return; - } else { - if (value[0]) - pr_err("%s: CAM index %d CAM Lookup Lower = 0x%.08x:%.08x, Output = 0x%.08x\n", - qdev->ndev->name, i, value[1], value[0], - value[2]); + netdev_err(qdev->ndev, + "%s: Failed read of mac index register\n", + __func__); + break; } + if (value[0]) + netdev_err(qdev->ndev, + "CAM index %d CAM Lookup Lower = 0x%.08x:%.08x, Output = 0x%.08x\n", + i, value[1], value[0], value[2]); } for (i = 0; i < 32; i++) { if (ql_get_mac_addr_reg (qdev, MAC_ADDR_TYPE_MULTI_MAC, i, value)) { - pr_err("%s: Failed read of mac index register\n", - __func__); - return; - } else { - if (value[0]) - pr_err("%s: MCAST index %d CAM Lookup Lower = 0x%.08x:%.08x\n", - qdev->ndev->name, i, value[1], value[0]); + netdev_err(qdev->ndev, + "%s: Failed read of mac index register\n", + __func__); + break; } + if (value[0]) + netdev_err(qdev->ndev, + "MCAST index %d CAM Lookup Lower = 0x%.08x:%.08x\n", + i, value[1], value[0]); } ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); } @@ -1424,24 +1424,25 @@ void ql_dump_routing_entries(struct ql_adapter *qdev) for (i = 0; i < 16; i++) { value = 0; if (ql_get_routing_reg(qdev, i, &value)) { - pr_err("%s: Failed read of routing index register\n", - __func__); - return; - } else { - if (value) - pr_err("%s: Routing Mask %d = 0x%.08x\n", - qdev->ndev->name, i, value); + netdev_err(qdev->ndev, + "%s: Failed read of routing index register\n", + __func__); + break; } + if (value) + netdev_err(qdev->ndev, + "%s: Routing Mask %d = 0x%.08x\n", + i, value); } ql_sem_unlock(qdev, SEM_RT_IDX_MASK); } #define DUMP_REG(qdev, reg) \ - pr_err("%-32s= 0x%x\n", #reg, ql_read32(qdev, reg)) + netdev_err(qdev->ndev, "%-32s= 0x%x\n", #reg, ql_read32(qdev, reg)) void ql_dump_regs(struct ql_adapter *qdev) { - pr_err("reg dump for function #%d\n", qdev->func); + netdev_err(qdev->ndev, "reg dump for function #%d\n", qdev->func); DUMP_REG(qdev, SYS); DUMP_REG(qdev, RST_FO); DUMP_REG(qdev, FSC); @@ -1506,11 +1507,12 @@ void ql_dump_regs(struct ql_adapter *qdev) #ifdef QL_STAT_DUMP #define DUMP_STAT(qdev, stat) \ - pr_err("%s = %ld\n", #stat, (unsigned long)(qdev)->nic_stats.stat) + netdev_err(qdev->ndev, "%s = %ld\n", #stat, \ + (unsigned long)(qdev)->nic_stats.stat) void ql_dump_stat(struct ql_adapter *qdev) { - pr_err("%s: Enter\n", __func__); + netdev_err(qdev->ndev, "%s: Enter\n", __func__); DUMP_STAT(qdev, tx_pkts); DUMP_STAT(qdev, tx_bytes); DUMP_STAT(qdev, tx_mcast_pkts); @@ -1559,11 +1561,12 @@ void ql_dump_stat(struct ql_adapter *qdev) #ifdef QL_DEV_DUMP #define DUMP_QDEV_FIELD(qdev, type, field) \ - pr_err("qdev->%-24s = " type "\n", #field, (qdev)->field) + netdev_err(qdev->ndev, "qdev->%-24s = " type "\n", #field, (qdev)->field) #define DUMP_QDEV_DMA_FIELD(qdev, field) \ - pr_err("qdev->%-24s = %llx\n", #field, (unsigned long long)qdev->field) + netdev_err(qdev->ndev, "qdev->%-24s = %llx\n", #field, \ + (unsigned long long)qdev->field) #define DUMP_QDEV_ARRAY(qdev, type, array, index, field) \ - pr_err("%s[%d].%s = " type "\n", \ + netdev_err(qdev->ndev, "%s[%d].%s = " type "\n", \ #array, index, #field, (qdev)->array[index].field) void ql_dump_qdev(struct ql_adapter *qdev) { @@ -1614,99 +1617,100 @@ void ql_dump_qdev(struct ql_adapter *qdev) #ifdef QL_CB_DUMP void ql_dump_wqicb(struct wqicb *wqicb) { - pr_err("Dumping wqicb stuff...\n"); - pr_err("wqicb->len = 0x%x\n", le16_to_cpu(wqicb->len)); - pr_err("wqicb->flags = %x\n", le16_to_cpu(wqicb->flags)); - pr_err("wqicb->cq_id_rss = %d\n", - le16_to_cpu(wqicb->cq_id_rss)); - pr_err("wqicb->rid = 0x%x\n", le16_to_cpu(wqicb->rid)); - pr_err("wqicb->wq_addr = 0x%llx\n", - (unsigned long long)le64_to_cpu(wqicb->addr)); - pr_err("wqicb->wq_cnsmr_idx_addr = 0x%llx\n", - (unsigned long long)le64_to_cpu(wqicb->cnsmr_idx_addr)); + netdev_err(qdev->ndev, "Dumping wqicb stuff...\n"); + netdev_err(qdev->ndev, "wqicb->len = 0x%x\n", le16_to_cpu(wqicb->len)); + netdev_err(qdev->ndev, "wqicb->flags = %x\n", + le16_to_cpu(wqicb->flags)); + netdev_err(qdev->ndev, "wqicb->cq_id_rss = %d\n", + le16_to_cpu(wqicb->cq_id_rss)); + netdev_err(qdev->ndev, "wqicb->rid = 0x%x\n", le16_to_cpu(wqicb->rid)); + netdev_err(qdev->ndev, "wqicb->wq_addr = 0x%llx\n", + (unsigned long long)le64_to_cpu(wqicb->addr)); + netdev_err(qdev->ndev, "wqicb->wq_cnsmr_idx_addr = 0x%llx\n", + (unsigned long long)le64_to_cpu(wqicb->cnsmr_idx_addr)); } void ql_dump_tx_ring(struct tx_ring *tx_ring) { if (!tx_ring) return; - pr_err("===================== Dumping tx_ring %d ===============\n", - tx_ring->wq_id); - pr_err("tx_ring->base = %p\n", tx_ring->wq_base); - pr_err("tx_ring->base_dma = 0x%llx\n", - (unsigned long long)tx_ring->wq_base_dma); - pr_err("tx_ring->cnsmr_idx_sh_reg, addr = 0x%p, value = %d\n", - tx_ring->cnsmr_idx_sh_reg, - tx_ring->cnsmr_idx_sh_reg + netdev_err(qdev->ndev, "===================== Dumping tx_ring %d ===============\n", + tx_ring->wq_id); + netdev_err(qdev->ndev, "tx_ring->base = %p\n", tx_ring->wq_base); + netdev_err(qdev->ndev, "tx_ring->base_dma = 0x%llx\n", + (unsigned long long)tx_ring->wq_base_dma); + netdev_err(qdev->ndev, "tx_ring->cnsmr_idx_sh_reg, addr = 0x%p, value = %d\n", + tx_ring->cnsmr_idx_sh_reg, + tx_ring->cnsmr_idx_sh_reg ? ql_read_sh_reg(tx_ring->cnsmr_idx_sh_reg) : 0); - pr_err("tx_ring->size = %d\n", tx_ring->wq_size); - pr_err("tx_ring->len = %d\n", tx_ring->wq_len); - pr_err("tx_ring->prod_idx_db_reg = %p\n", tx_ring->prod_idx_db_reg); - pr_err("tx_ring->valid_db_reg = %p\n", tx_ring->valid_db_reg); - pr_err("tx_ring->prod_idx = %d\n", tx_ring->prod_idx); - pr_err("tx_ring->cq_id = %d\n", tx_ring->cq_id); - pr_err("tx_ring->wq_id = %d\n", tx_ring->wq_id); - pr_err("tx_ring->q = %p\n", tx_ring->q); - pr_err("tx_ring->tx_count = %d\n", atomic_read(&tx_ring->tx_count)); + netdev_err(qdev->ndev, "tx_ring->size = %d\n", tx_ring->wq_size); + netdev_err(qdev->ndev, "tx_ring->len = %d\n", tx_ring->wq_len); + netdev_err(qdev->ndev, "tx_ring->prod_idx_db_reg = %p\n", tx_ring->prod_idx_db_reg); + netdev_err(qdev->ndev, "tx_ring->valid_db_reg = %p\n", tx_ring->valid_db_reg); + netdev_err(qdev->ndev, "tx_ring->prod_idx = %d\n", tx_ring->prod_idx); + netdev_err(qdev->ndev, "tx_ring->cq_id = %d\n", tx_ring->cq_id); + netdev_err(qdev->ndev, "tx_ring->wq_id = %d\n", tx_ring->wq_id); + netdev_err(qdev->ndev, "tx_ring->q = %p\n", tx_ring->q); + netdev_err(qdev->ndev, "tx_ring->tx_count = %d\n", atomic_read(&tx_ring->tx_count)); } void ql_dump_ricb(struct ricb *ricb) { int i; - pr_err("===================== Dumping ricb ===============\n"); - pr_err("Dumping ricb stuff...\n"); - - pr_err("ricb->base_cq = %d\n", ricb->base_cq & 0x1f); - pr_err("ricb->flags = %s%s%s%s%s%s%s%s%s\n", - ricb->base_cq & RSS_L4K ? "RSS_L4K " : "", - ricb->flags & RSS_L6K ? "RSS_L6K " : "", - ricb->flags & RSS_LI ? "RSS_LI " : "", - ricb->flags & RSS_LB ? "RSS_LB " : "", - ricb->flags & RSS_LM ? "RSS_LM " : "", - ricb->flags & RSS_RI4 ? "RSS_RI4 " : "", - ricb->flags & RSS_RT4 ? "RSS_RT4 " : "", - ricb->flags & RSS_RI6 ? "RSS_RI6 " : "", - ricb->flags & RSS_RT6 ? "RSS_RT6 " : ""); - pr_err("ricb->mask = 0x%.04x\n", le16_to_cpu(ricb->mask)); + netdev_err(qdev->ndev, "===================== Dumping ricb ===============\n"); + netdev_err(qdev->ndev, "Dumping ricb stuff...\n"); + + netdev_err(qdev->ndev, "ricb->base_cq = %d\n", ricb->base_cq & 0x1f); + netdev_err(qdev->ndev, "ricb->flags = %s%s%s%s%s%s%s%s%s\n", + ricb->base_cq & RSS_L4K ? "RSS_L4K " : "", + ricb->flags & RSS_L6K ? "RSS_L6K " : "", + ricb->flags & RSS_LI ? "RSS_LI " : "", + ricb->flags & RSS_LB ? "RSS_LB " : "", + ricb->flags & RSS_LM ? "RSS_LM " : "", + ricb->flags & RSS_RI4 ? "RSS_RI4 " : "", + ricb->flags & RSS_RT4 ? "RSS_RT4 " : "", + ricb->flags & RSS_RI6 ? "RSS_RI6 " : "", + ricb->flags & RSS_RT6 ? "RSS_RT6 " : ""); + netdev_err(qdev->ndev, "ricb->mask = 0x%.04x\n", le16_to_cpu(ricb->mask)); for (i = 0; i < 16; i++) - pr_err("ricb->hash_cq_id[%d] = 0x%.08x\n", i, - le32_to_cpu(ricb->hash_cq_id[i])); + netdev_err(qdev->ndev, "ricb->hash_cq_id[%d] = 0x%.08x\n", i, + le32_to_cpu(ricb->hash_cq_id[i])); for (i = 0; i < 10; i++) - pr_err("ricb->ipv6_hash_key[%d] = 0x%.08x\n", i, - le32_to_cpu(ricb->ipv6_hash_key[i])); + netdev_err(qdev->ndev, "ricb->ipv6_hash_key[%d] = 0x%.08x\n", i, + le32_to_cpu(ricb->ipv6_hash_key[i])); for (i = 0; i < 4; i++) - pr_err("ricb->ipv4_hash_key[%d] = 0x%.08x\n", i, - le32_to_cpu(ricb->ipv4_hash_key[i])); + netdev_err(qdev->ndev, "ricb->ipv4_hash_key[%d] = 0x%.08x\n", i, + le32_to_cpu(ricb->ipv4_hash_key[i])); } void ql_dump_cqicb(struct cqicb *cqicb) { - pr_err("Dumping cqicb stuff...\n"); - - pr_err("cqicb->msix_vect = %d\n", cqicb->msix_vect); - pr_err("cqicb->flags = %x\n", cqicb->flags); - pr_err("cqicb->len = %d\n", le16_to_cpu(cqicb->len)); - pr_err("cqicb->addr = 0x%llx\n", - (unsigned long long)le64_to_cpu(cqicb->addr)); - pr_err("cqicb->prod_idx_addr = 0x%llx\n", - (unsigned long long)le64_to_cpu(cqicb->prod_idx_addr)); - pr_err("cqicb->pkt_delay = 0x%.04x\n", - le16_to_cpu(cqicb->pkt_delay)); - pr_err("cqicb->irq_delay = 0x%.04x\n", - le16_to_cpu(cqicb->irq_delay)); - pr_err("cqicb->lbq_addr = 0x%llx\n", - (unsigned long long)le64_to_cpu(cqicb->lbq_addr)); - pr_err("cqicb->lbq_buf_size = 0x%.04x\n", - le16_to_cpu(cqicb->lbq_buf_size)); - pr_err("cqicb->lbq_len = 0x%.04x\n", - le16_to_cpu(cqicb->lbq_len)); - pr_err("cqicb->sbq_addr = 0x%llx\n", - (unsigned long long)le64_to_cpu(cqicb->sbq_addr)); - pr_err("cqicb->sbq_buf_size = 0x%.04x\n", - le16_to_cpu(cqicb->sbq_buf_size)); - pr_err("cqicb->sbq_len = 0x%.04x\n", - le16_to_cpu(cqicb->sbq_len)); + netdev_err(qdev->ndev, "Dumping cqicb stuff...\n"); + + netdev_err(qdev->ndev, "cqicb->msix_vect = %d\n", cqicb->msix_vect); + netdev_err(qdev->ndev, "cqicb->flags = %x\n", cqicb->flags); + netdev_err(qdev->ndev, "cqicb->len = %d\n", le16_to_cpu(cqicb->len)); + netdev_err(qdev->ndev, "cqicb->addr = 0x%llx\n", + (unsigned long long)le64_to_cpu(cqicb->addr)); + netdev_err(qdev->ndev, "cqicb->prod_idx_addr = 0x%llx\n", + (unsigned long long)le64_to_cpu(cqicb->prod_idx_addr)); + netdev_err(qdev->ndev, "cqicb->pkt_delay = 0x%.04x\n", + le16_to_cpu(cqicb->pkt_delay)); + netdev_err(qdev->ndev, "cqicb->irq_delay = 0x%.04x\n", + le16_to_cpu(cqicb->irq_delay)); + netdev_err(qdev->ndev, "cqicb->lbq_addr = 0x%llx\n", + (unsigned long long)le64_to_cpu(cqicb->lbq_addr)); + netdev_err(qdev->ndev, "cqicb->lbq_buf_size = 0x%.04x\n", + le16_to_cpu(cqicb->lbq_buf_size)); + netdev_err(qdev->ndev, "cqicb->lbq_len = 0x%.04x\n", + le16_to_cpu(cqicb->lbq_len)); + netdev_err(qdev->ndev, "cqicb->sbq_addr = 0x%llx\n", + (unsigned long long)le64_to_cpu(cqicb->sbq_addr)); + netdev_err(qdev->ndev, "cqicb->sbq_buf_size = 0x%.04x\n", + le16_to_cpu(cqicb->sbq_buf_size)); + netdev_err(qdev->ndev, "cqicb->sbq_len = 0x%.04x\n", + le16_to_cpu(cqicb->sbq_len)); } static const char *qlge_rx_ring_type_name(struct rx_ring *rx_ring) @@ -1723,71 +1727,73 @@ void ql_dump_rx_ring(struct rx_ring *rx_ring) { if (!rx_ring) return; - pr_err("===================== Dumping rx_ring %d ===============\n", - rx_ring->cq_id); - pr_err("Dumping rx_ring %d, type = %s\n", rx_ring->cq_id, - qlge_rx_ring_type_name(rx_ring)); - pr_err("rx_ring->cqicb = %p\n", &rx_ring->cqicb); - pr_err("rx_ring->cq_base = %p\n", rx_ring->cq_base); - pr_err("rx_ring->cq_base_dma = %llx\n", - (unsigned long long)rx_ring->cq_base_dma); - pr_err("rx_ring->cq_size = %d\n", rx_ring->cq_size); - pr_err("rx_ring->cq_len = %d\n", rx_ring->cq_len); - pr_err("rx_ring->prod_idx_sh_reg, addr = 0x%p, value = %d\n", - rx_ring->prod_idx_sh_reg, - rx_ring->prod_idx_sh_reg - ? ql_read_sh_reg(rx_ring->prod_idx_sh_reg) : 0); - pr_err("rx_ring->prod_idx_sh_reg_dma = %llx\n", - (unsigned long long)rx_ring->prod_idx_sh_reg_dma); - pr_err("rx_ring->cnsmr_idx_db_reg = %p\n", - rx_ring->cnsmr_idx_db_reg); - pr_err("rx_ring->cnsmr_idx = %d\n", rx_ring->cnsmr_idx); - pr_err("rx_ring->curr_entry = %p\n", rx_ring->curr_entry); - pr_err("rx_ring->valid_db_reg = %p\n", rx_ring->valid_db_reg); - - pr_err("rx_ring->lbq.base = %p\n", rx_ring->lbq.base); - pr_err("rx_ring->lbq.base_dma = %llx\n", - (unsigned long long)rx_ring->lbq.base_dma); - pr_err("rx_ring->lbq.base_indirect = %p\n", - rx_ring->lbq.base_indirect); - pr_err("rx_ring->lbq.base_indirect_dma = %llx\n", - (unsigned long long)rx_ring->lbq.base_indirect_dma); - pr_err("rx_ring->lbq = %p\n", rx_ring->lbq.queue); - pr_err("rx_ring->lbq.prod_idx_db_reg = %p\n", - rx_ring->lbq.prod_idx_db_reg); - pr_err("rx_ring->lbq.next_to_use = %d\n", rx_ring->lbq.next_to_use); - pr_err("rx_ring->lbq.next_to_clean = %d\n", rx_ring->lbq.next_to_clean); - - pr_err("rx_ring->sbq.base = %p\n", rx_ring->sbq.base); - pr_err("rx_ring->sbq.base_dma = %llx\n", - (unsigned long long)rx_ring->sbq.base_dma); - pr_err("rx_ring->sbq.base_indirect = %p\n", - rx_ring->sbq.base_indirect); - pr_err("rx_ring->sbq.base_indirect_dma = %llx\n", - (unsigned long long)rx_ring->sbq.base_indirect_dma); - pr_err("rx_ring->sbq = %p\n", rx_ring->sbq.queue); - pr_err("rx_ring->sbq.prod_idx_db_reg addr = %p\n", - rx_ring->sbq.prod_idx_db_reg); - pr_err("rx_ring->sbq.next_to_use = %d\n", rx_ring->sbq.next_to_use); - pr_err("rx_ring->sbq.next_to_clean = %d\n", rx_ring->sbq.next_to_clean); - pr_err("rx_ring->cq_id = %d\n", rx_ring->cq_id); - pr_err("rx_ring->irq = %d\n", rx_ring->irq); - pr_err("rx_ring->cpu = %d\n", rx_ring->cpu); - pr_err("rx_ring->qdev = %p\n", rx_ring->qdev); + netdev_err(qdev->ndev, + "===================== Dumping rx_ring %d ===============\n", + rx_ring->cq_id); + netdev_err(qdev->ndev, + "Dumping rx_ring %d, type = %s\n", rx_ring->cq_id, + qlge_rx_ring_type_name(rx_ring)); + netdev_err(qdev->ndev, "rx_ring->cqicb = %p\n", &rx_ring->cqicb); + netdev_err(qdev->ndev, "rx_ring->cq_base = %p\n", rx_ring->cq_base); + netdev_err(qdev->ndev, "rx_ring->cq_base_dma = %llx\n", + (unsigned long long)rx_ring->cq_base_dma); + netdev_err(qdev->ndev, "rx_ring->cq_size = %d\n", rx_ring->cq_size); + netdev_err(qdev->ndev, "rx_ring->cq_len = %d\n", rx_ring->cq_len); + netdev_err(qdev->ndev, + "rx_ring->prod_idx_sh_reg, addr = 0x%p, value = %d\n", + rx_ring->prod_idx_sh_reg, + rx_ring->prod_idx_sh_reg ? ql_read_sh_reg(rx_ring->prod_idx_sh_reg) : 0); + netdev_err(qdev->ndev, "rx_ring->prod_idx_sh_reg_dma = %llx\n", + (unsigned long long)rx_ring->prod_idx_sh_reg_dma); + netdev_err(qdev->ndev, "rx_ring->cnsmr_idx_db_reg = %p\n", + rx_ring->cnsmr_idx_db_reg); + netdev_err(qdev->ndev, "rx_ring->cnsmr_idx = %d\n", rx_ring->cnsmr_idx); + netdev_err(qdev->ndev, "rx_ring->curr_entry = %p\n", rx_ring->curr_entry); + netdev_err(qdev->ndev, "rx_ring->valid_db_reg = %p\n", rx_ring->valid_db_reg); + + netdev_err(qdev->ndev, "rx_ring->lbq.base = %p\n", rx_ring->lbq.base); + netdev_err(qdev->ndev, "rx_ring->lbq.base_dma = %llx\n", + (unsigned long long)rx_ring->lbq.base_dma); + netdev_err(qdev->ndev, "rx_ring->lbq.base_indirect = %p\n", + rx_ring->lbq.base_indirect); + netdev_err(qdev->ndev, "rx_ring->lbq.base_indirect_dma = %llx\n", + (unsigned long long)rx_ring->lbq.base_indirect_dma); + netdev_err(qdev->ndev, "rx_ring->lbq = %p\n", rx_ring->lbq.queue); + netdev_err(qdev->ndev, "rx_ring->lbq.prod_idx_db_reg = %p\n", + rx_ring->lbq.prod_idx_db_reg); + netdev_err(qdev->ndev, "rx_ring->lbq.next_to_use = %d\n", rx_ring->lbq.next_to_use); + netdev_err(qdev->ndev, "rx_ring->lbq.next_to_clean = %d\n", rx_ring->lbq.next_to_clean); + + netdev_err(qdev->ndev, "rx_ring->sbq.base = %p\n", rx_ring->sbq.base); + netdev_err(qdev->ndev, "rx_ring->sbq.base_dma = %llx\n", + (unsigned long long)rx_ring->sbq.base_dma); + netdev_err(qdev->ndev, "rx_ring->sbq.base_indirect = %p\n", + rx_ring->sbq.base_indirect); + netdev_err(qdev->ndev, "rx_ring->sbq.base_indirect_dma = %llx\n", + (unsigned long long)rx_ring->sbq.base_indirect_dma); + netdev_err(qdev->ndev, "rx_ring->sbq = %p\n", rx_ring->sbq.queue); + netdev_err(qdev->ndev, "rx_ring->sbq.prod_idx_db_reg addr = %p\n", + rx_ring->sbq.prod_idx_db_reg); + netdev_err(qdev->ndev, "rx_ring->sbq.next_to_use = %d\n", rx_ring->sbq.next_to_use); + netdev_err(qdev->ndev, "rx_ring->sbq.next_to_clean = %d\n", rx_ring->sbq.next_to_clean); + netdev_err(qdev->ndev, "rx_ring->cq_id = %d\n", rx_ring->cq_id); + netdev_err(qdev->ndev, "rx_ring->irq = %d\n", rx_ring->irq); + netdev_err(qdev->ndev, "rx_ring->cpu = %d\n", rx_ring->cpu); + netdev_err(qdev->ndev, "rx_ring->qdev = %p\n", rx_ring->qdev); } void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id) { void *ptr; - pr_err("%s: Enter\n", __func__); + netdev_err(qdev->ndev, "%s: Enter\n", __func__); ptr = kmalloc(size, GFP_ATOMIC); if (!ptr) return; if (ql_write_cfg(qdev, ptr, size, bit, q_id)) { - pr_err("%s: Failed to upload control block!\n", __func__); + netdev_err(qdev->ndev, "%s: Failed to upload control block!\n", __func__); goto fail_it; } switch (bit) { @@ -1801,7 +1807,7 @@ void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id) ql_dump_ricb((struct ricb *)ptr); break; default: - pr_err("%s: Invalid bit value = %x\n", __func__, bit); + netdev_err(qdev->ndev, "%s: Invalid bit value = %x\n", __func__, bit); break; } fail_it: @@ -1812,29 +1818,29 @@ fail_it: #ifdef QL_OB_DUMP void ql_dump_tx_desc(struct tx_buf_desc *tbd) { - pr_err("tbd->addr = 0x%llx\n", - le64_to_cpu((u64) tbd->addr)); - pr_err("tbd->len = %d\n", - le32_to_cpu(tbd->len & TX_DESC_LEN_MASK)); - pr_err("tbd->flags = %s %s\n", - tbd->len & TX_DESC_C ? "C" : ".", - tbd->len & TX_DESC_E ? "E" : "."); + netdev_err(qdev->ndev, "tbd->addr = 0x%llx\n", + le64_to_cpu((u64)tbd->addr)); + netdev_err(qdev->ndev, "tbd->len = %d\n", + le32_to_cpu(tbd->len & TX_DESC_LEN_MASK)); + netdev_err(qdev->ndev, "tbd->flags = %s %s\n", + tbd->len & TX_DESC_C ? "C" : ".", + tbd->len & TX_DESC_E ? "E" : "."); tbd++; - pr_err("tbd->addr = 0x%llx\n", - le64_to_cpu((u64) tbd->addr)); - pr_err("tbd->len = %d\n", - le32_to_cpu(tbd->len & TX_DESC_LEN_MASK)); - pr_err("tbd->flags = %s %s\n", - tbd->len & TX_DESC_C ? "C" : ".", - tbd->len & TX_DESC_E ? "E" : "."); + netdev_err(qdev->ndev, "tbd->addr = 0x%llx\n", + le64_to_cpu((u64)tbd->addr)); + netdev_err(qdev->ndev, "tbd->len = %d\n", + le32_to_cpu(tbd->len & TX_DESC_LEN_MASK)); + netdev_err(qdev->ndev, "tbd->flags = %s %s\n", + tbd->len & TX_DESC_C ? "C" : ".", + tbd->len & TX_DESC_E ? "E" : "."); tbd++; - pr_err("tbd->addr = 0x%llx\n", - le64_to_cpu((u64) tbd->addr)); - pr_err("tbd->len = %d\n", - le32_to_cpu(tbd->len & TX_DESC_LEN_MASK)); - pr_err("tbd->flags = %s %s\n", - tbd->len & TX_DESC_C ? "C" : ".", - tbd->len & TX_DESC_E ? "E" : "."); + netdev_err(qdev->ndev, "tbd->addr = 0x%llx\n", + le64_to_cpu((u64)tbd->addr)); + netdev_err(qdev->ndev, "tbd->len = %d\n", + le32_to_cpu(tbd->len & TX_DESC_LEN_MASK)); + netdev_err(qdev->ndev, "tbd->flags = %s %s\n", + tbd->len & TX_DESC_C ? "C" : ".", + tbd->len & TX_DESC_E ? "E" : "."); } void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb) @@ -1844,39 +1850,39 @@ void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb) struct tx_buf_desc *tbd; u16 frame_len; - pr_err("%s\n", __func__); - pr_err("opcode = %s\n", - (ob_mac_iocb->opcode == OPCODE_OB_MAC_IOCB) ? "MAC" : "TSO"); - pr_err("flags1 = %s %s %s %s %s\n", - ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_OI ? "OI" : "", - ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_I ? "I" : "", - ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_D ? "D" : "", - ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_IP4 ? "IP4" : "", - ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_IP6 ? "IP6" : ""); - pr_err("flags2 = %s %s %s\n", - ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_LSO ? "LSO" : "", - ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_UC ? "UC" : "", - ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_TC ? "TC" : ""); - pr_err("flags3 = %s %s %s\n", - ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_IC ? "IC" : "", - ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_DFP ? "DFP" : "", - ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_V ? "V" : ""); - pr_err("tid = %x\n", ob_mac_iocb->tid); - pr_err("txq_idx = %d\n", ob_mac_iocb->txq_idx); - pr_err("vlan_tci = %x\n", ob_mac_tso_iocb->vlan_tci); + netdev_err(qdev->ndev, "%s\n", __func__); + netdev_err(qdev->ndev, "opcode = %s\n", + (ob_mac_iocb->opcode == OPCODE_OB_MAC_IOCB) ? "MAC" : "TSO"); + netdev_err(qdev->ndev, "flags1 = %s %s %s %s %s\n", + ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_OI ? "OI" : "", + ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_I ? "I" : "", + ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_D ? "D" : "", + ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_IP4 ? "IP4" : "", + ob_mac_tso_iocb->flags1 & OB_MAC_TSO_IOCB_IP6 ? "IP6" : ""); + netdev_err(qdev->ndev, "flags2 = %s %s %s\n", + ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_LSO ? "LSO" : "", + ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_UC ? "UC" : "", + ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_TC ? "TC" : ""); + netdev_err(qdev->ndev, "flags3 = %s %s %s\n", + ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_IC ? "IC" : "", + ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_DFP ? "DFP" : "", + ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_V ? "V" : ""); + netdev_err(qdev->ndev, "tid = %x\n", ob_mac_iocb->tid); + netdev_err(qdev->ndev, "txq_idx = %d\n", ob_mac_iocb->txq_idx); + netdev_err(qdev->ndev, "vlan_tci = %x\n", ob_mac_tso_iocb->vlan_tci); if (ob_mac_iocb->opcode == OPCODE_OB_MAC_TSO_IOCB) { - pr_err("frame_len = %d\n", - le32_to_cpu(ob_mac_tso_iocb->frame_len)); - pr_err("mss = %d\n", - le16_to_cpu(ob_mac_tso_iocb->mss)); - pr_err("prot_hdr_len = %d\n", - le16_to_cpu(ob_mac_tso_iocb->total_hdrs_len)); - pr_err("hdr_offset = 0x%.04x\n", - le16_to_cpu(ob_mac_tso_iocb->net_trans_offset)); + netdev_err(qdev->ndev, "frame_len = %d\n", + le32_to_cpu(ob_mac_tso_iocb->frame_len)); + netdev_err(qdev->ndev, "mss = %d\n", + le16_to_cpu(ob_mac_tso_iocb->mss)); + netdev_err(qdev->ndev, "prot_hdr_len = %d\n", + le16_to_cpu(ob_mac_tso_iocb->total_hdrs_len)); + netdev_err(qdev->ndev, "hdr_offset = 0x%.04x\n", + le16_to_cpu(ob_mac_tso_iocb->net_trans_offset)); frame_len = le32_to_cpu(ob_mac_tso_iocb->frame_len); } else { - pr_err("frame_len = %d\n", - le16_to_cpu(ob_mac_iocb->frame_len)); + netdev_err(qdev->ndev, "frame_len = %d\n", + le16_to_cpu(ob_mac_iocb->frame_len)); frame_len = le16_to_cpu(ob_mac_iocb->frame_len); } tbd = &ob_mac_iocb->tbd[0]; @@ -1885,98 +1891,98 @@ void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb) void ql_dump_ob_mac_rsp(struct ob_mac_iocb_rsp *ob_mac_rsp) { - pr_err("%s\n", __func__); - pr_err("opcode = %d\n", ob_mac_rsp->opcode); - pr_err("flags = %s %s %s %s %s %s %s\n", - ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_OI ? "OI" : ".", - ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_I ? "I" : ".", - ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_E ? "E" : ".", - ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_S ? "S" : ".", - ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_L ? "L" : ".", - ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_P ? "P" : ".", - ob_mac_rsp->flags2 & OB_MAC_IOCB_RSP_B ? "B" : "."); - pr_err("tid = %x\n", ob_mac_rsp->tid); + netdev_err(qdev->ndev, "%s\n", __func__); + netdev_err(qdev->ndev, "opcode = %d\n", ob_mac_rsp->opcode); + netdev_err(qdev->ndev, "flags = %s %s %s %s %s %s %s\n", + ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_OI ? + "OI" : ".", ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_I ? "I" : ".", + ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_E ? "E" : ".", + ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_S ? "S" : ".", + ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_L ? "L" : ".", + ob_mac_rsp->flags1 & OB_MAC_IOCB_RSP_P ? "P" : ".", + ob_mac_rsp->flags2 & OB_MAC_IOCB_RSP_B ? "B" : "."); + netdev_err(qdev->ndev, "tid = %x\n", ob_mac_rsp->tid); } #endif #ifdef QL_IB_DUMP void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp) { - pr_err("%s\n", __func__); - pr_err("opcode = 0x%x\n", ib_mac_rsp->opcode); - pr_err("flags1 = %s%s%s%s%s%s\n", - ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_OI ? "OI " : "", - ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_I ? "I " : "", - ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_TE ? "TE " : "", - ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_NU ? "NU " : "", - ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_IE ? "IE " : "", - ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_B ? "B " : ""); + netdev_err(qdev->ndev, "%s\n", __func__); + netdev_err(qdev->ndev, "opcode = 0x%x\n", ib_mac_rsp->opcode); + netdev_err(qdev->ndev, "flags1 = %s%s%s%s%s%s\n", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_OI ? "OI " : "", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_I ? "I " : "", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_TE ? "TE " : "", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_NU ? "NU " : "", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_IE ? "IE " : "", + ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_B ? "B " : ""); if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) - pr_err("%s%s%s Multicast\n", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_HASH ? "Hash" : "", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_REG ? "Registered" : "", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); - - pr_err("flags2 = %s%s%s%s%s\n", - (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) ? "P " : "", - (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ? "V " : "", - (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) ? "U " : "", - (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) ? "T " : "", - (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_FO) ? "FO " : ""); + netdev_err(qdev->ndev, "%s%s%s Multicast\n", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_HASH ? "Hash" : "", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_REG ? "Registered" : "", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); + + netdev_err(qdev->ndev, "flags2 = %s%s%s%s%s\n", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) ? "P " : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ? "V " : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) ? "U " : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) ? "T " : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_FO) ? "FO " : ""); if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) - pr_err("%s%s%s%s%s error\n", - (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == - IB_MAC_IOCB_RSP_ERR_OVERSIZE ? "oversize" : "", - (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == - IB_MAC_IOCB_RSP_ERR_UNDERSIZE ? "undersize" : "", - (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == - IB_MAC_IOCB_RSP_ERR_PREAMBLE ? "preamble" : "", - (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == - IB_MAC_IOCB_RSP_ERR_FRAME_LEN ? "frame length" : "", - (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == - IB_MAC_IOCB_RSP_ERR_CRC ? "CRC" : ""); - - pr_err("flags3 = %s%s\n", - ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DS ? "DS " : "", - ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL ? "DL " : ""); + netdev_err(qdev->ndev, "%s%s%s%s%s error\n", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == + IB_MAC_IOCB_RSP_ERR_OVERSIZE ? "oversize" : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == + IB_MAC_IOCB_RSP_ERR_UNDERSIZE ? "undersize" : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == + IB_MAC_IOCB_RSP_ERR_PREAMBLE ? "preamble" : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == + IB_MAC_IOCB_RSP_ERR_FRAME_LEN ? "frame length" : "", + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) == + IB_MAC_IOCB_RSP_ERR_CRC ? "CRC" : ""); + + netdev_err(qdev->ndev, "flags3 = %s%s\n", + ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DS ? "DS " : "", + ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL ? "DL " : ""); if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) - pr_err("RSS flags = %s%s%s%s\n", - ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == - IB_MAC_IOCB_RSP_M_IPV4) ? "IPv4 RSS" : "", - ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == - IB_MAC_IOCB_RSP_M_IPV6) ? "IPv6 RSS " : "", - ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == - IB_MAC_IOCB_RSP_M_TCP_V4) ? "TCP/IPv4 RSS" : "", - ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == - IB_MAC_IOCB_RSP_M_TCP_V6) ? "TCP/IPv6 RSS" : ""); - - pr_err("data_len = %d\n", - le32_to_cpu(ib_mac_rsp->data_len)); - pr_err("data_addr = 0x%llx\n", - (unsigned long long)le64_to_cpu(ib_mac_rsp->data_addr)); + netdev_err(qdev->ndev, "RSS flags = %s%s%s%s\n", + ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == + IB_MAC_IOCB_RSP_M_IPV4) ? "IPv4 RSS" : "", + ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == + IB_MAC_IOCB_RSP_M_IPV6) ? "IPv6 RSS " : "", + ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == + IB_MAC_IOCB_RSP_M_TCP_V4) ? "TCP/IPv4 RSS" : "", + ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) == + IB_MAC_IOCB_RSP_M_TCP_V6) ? "TCP/IPv6 RSS" : ""); + + netdev_err(qdev->ndev, "data_len = %d\n", + le32_to_cpu(ib_mac_rsp->data_len)); + netdev_err(qdev->ndev, "data_addr = 0x%llx\n", + (unsigned long long)le64_to_cpu(ib_mac_rsp->data_addr)); if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) - pr_err("rss = %x\n", - le32_to_cpu(ib_mac_rsp->rss)); + netdev_err(qdev->ndev, "rss = %x\n", + le32_to_cpu(ib_mac_rsp->rss)); if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) - pr_err("vlan_id = %x\n", - le16_to_cpu(ib_mac_rsp->vlan_id)); + netdev_err(qdev->ndev, "vlan_id = %x\n", + le16_to_cpu(ib_mac_rsp->vlan_id)); - pr_err("flags4 = %s%s%s\n", - ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV ? "HV " : "", - ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS ? "HS " : "", - ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HL ? "HL " : ""); + netdev_err(qdev->ndev, "flags4 = %s%s%s\n", + ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV ? "HV " : "", + ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS ? "HS " : "", + ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HL ? "HL " : ""); if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) { - pr_err("hdr length = %d\n", - le32_to_cpu(ib_mac_rsp->hdr_len)); - pr_err("hdr addr = 0x%llx\n", - (unsigned long long)le64_to_cpu(ib_mac_rsp->hdr_addr)); + netdev_err(qdev->ndev, "hdr length = %d\n", + le32_to_cpu(ib_mac_rsp->hdr_len)); + netdev_err(qdev->ndev, "hdr addr = 0x%llx\n", + (unsigned long long)le64_to_cpu(ib_mac_rsp->hdr_addr)); } } #endif diff --git a/drivers/staging/qlge/qlge_ethtool.c b/drivers/staging/qlge/qlge_ethtool.c index 949abd53a7a92b1f618a34f962ff577d2f6bb343..d44b2dae92139a6f4c51f3818715ec3a79088456 100644 --- a/drivers/staging/qlge/qlge_ethtool.c +++ b/drivers/staging/qlge/qlge_ethtool.c @@ -516,8 +516,8 @@ static void ql_create_lb_frame(struct sk_buff *skb, memset(skb->data, 0xFF, frame_size); frame_size &= ~1; memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); - memset(&skb->data[frame_size / 2 + 10], 0xBE, 1); - memset(&skb->data[frame_size / 2 + 12], 0xAF, 1); + skb->data[frame_size / 2 + 10] = (unsigned char)0xBE; + skb->data[frame_size / 2 + 12] = (unsigned char)0xAF; } void ql_check_lb_frame(struct ql_adapter *qdev, @@ -528,8 +528,8 @@ void ql_check_lb_frame(struct ql_adapter *qdev, if ((*(skb->data + 3) == 0xFF) && (*(skb->data + frame_size / 2 + 10) == 0xBE) && (*(skb->data + frame_size / 2 + 12) == 0xAF)) { - atomic_dec(&qdev->lb_count); - return; + atomic_dec(&qdev->lb_count); + return; } } diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index 402edaeffe12d6d9f05d03a698fbb0cde21788b1..44ef00f1f8ee3490d09dcd6a282f7dabbd7e205b 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -687,7 +687,7 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) size = sizeof(struct flash_params_8000) / sizeof(u32); for (i = 0; i < size; i++, p++) { - status = ql_read_flash_word(qdev, i+offset, p); + status = ql_read_flash_word(qdev, i + offset, p); if (status) { netif_err(qdev, ifup, qdev->ndev, "Error reading flash.\n"); @@ -750,7 +750,7 @@ static int ql_get_8012_flash_params(struct ql_adapter *qdev) return -ETIMEDOUT; for (i = 0; i < size; i++, p++) { - status = ql_read_flash_word(qdev, i+offset, p); + status = ql_read_flash_word(qdev, i + offset, p); if (status) { netif_err(qdev, ifup, qdev->ndev, "Error reading flash.\n"); @@ -1528,7 +1528,7 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, struct iphdr *iph = (struct iphdr *)((u8 *)addr + hlen); if (!(iph->frag_off & - htons(IP_MF|IP_OFFSET))) { + htons(IP_MF | IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, @@ -1635,7 +1635,7 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, struct iphdr *iph = (struct iphdr *)skb->data; if (!(iph->frag_off & - htons(IP_MF|IP_OFFSET))) { + htons(IP_MF | IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, @@ -1924,7 +1924,7 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, struct iphdr *iph = (struct iphdr *)skb->data; if (!(iph->frag_off & - htons(IP_MF|IP_OFFSET))) { + htons(IP_MF | IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "TCP checksum done!\n"); @@ -3181,7 +3181,7 @@ static void ql_enable_msix(struct ql_adapter *qdev) msi: qdev->intr_count = 1; if (qlge_irq_type == MSI_IRQ) { - if (!pci_enable_msi(qdev->pdev)) { + if (pci_alloc_irq_vectors(qdev->pdev, 1, 1, PCI_IRQ_MSI) >= 0) { set_bit(QL_MSI_ENABLED, &qdev->flags); netif_info(qdev, ifup, qdev->ndev, "Running with MSI interrupts.\n"); @@ -3244,7 +3244,8 @@ static void ql_set_irq_mask(struct ql_adapter *qdev, struct intr_context *ctx) */ ctx->irq_mask = (1 << qdev->rx_ring[vect].cq_id); /* Add the TX ring(s) serviced by this vector - * to the mask. */ + * to the mask. + */ for (j = 0; j < tx_rings_per_vector; j++) { ctx->irq_mask |= (1 << qdev->rx_ring[qdev->rss_ring_count + @@ -3777,10 +3778,10 @@ static int ql_wol(struct ql_adapter *qdev) "Failed to set magic packet on %s.\n", qdev->ndev->name); return status; - } else - netif_info(qdev, drv, qdev->ndev, - "Enabled magic packet successfully on %s.\n", - qdev->ndev->name); + } + netif_info(qdev, drv, qdev->ndev, + "Enabled magic packet successfully on %s.\n", + qdev->ndev->name); wol |= MB_WOL_MAGIC_PKT; } @@ -4547,7 +4548,7 @@ static void ql_timer(struct timer_list *t) return; } - mod_timer(&qdev->timer, jiffies + (5*HZ)); + mod_timer(&qdev->timer, jiffies + (5 * HZ)); } static int qlge_probe(struct pci_dev *pdev, @@ -4619,7 +4620,7 @@ static int qlge_probe(struct pci_dev *pdev, * the bus goes dead */ timer_setup(&qdev->timer, ql_timer, TIMER_DEFERRABLE); - mod_timer(&qdev->timer, jiffies + (5*HZ)); + mod_timer(&qdev->timer, jiffies + (5 * HZ)); ql_link_off(qdev); ql_display_dev_info(ndev); atomic_set(&qdev->lb_count, 0); @@ -4753,7 +4754,7 @@ static void qlge_io_resume(struct pci_dev *pdev) netif_err(qdev, ifup, qdev->ndev, "Device was not running prior to EEH.\n"); } - mod_timer(&qdev->timer, jiffies + (5*HZ)); + mod_timer(&qdev->timer, jiffies + (5 * HZ)); netif_device_attach(ndev); } @@ -4763,9 +4764,9 @@ static const struct pci_error_handlers qlge_err_handler = { .resume = qlge_io_resume, }; -static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused qlge_suspend(struct device *dev_d) { - struct net_device *ndev = pci_get_drvdata(pdev); + struct net_device *ndev = dev_get_drvdata(dev_d); struct ql_adapter *qdev = netdev_priv(ndev); int err; @@ -4779,35 +4780,19 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) } ql_wol(qdev); - err = pci_save_state(pdev); - if (err) - return err; - - pci_disable_device(pdev); - - pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } -#ifdef CONFIG_PM -static int qlge_resume(struct pci_dev *pdev) +static int __maybe_unused qlge_resume(struct device *dev_d) { - struct net_device *ndev = pci_get_drvdata(pdev); + struct net_device *ndev = dev_get_drvdata(dev_d); struct ql_adapter *qdev = netdev_priv(ndev); int err; - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - err = pci_enable_device(pdev); - if (err) { - netif_err(qdev, ifup, qdev->ndev, "Cannot enable PCI device from suspend\n"); - return err; - } - pci_set_master(pdev); + pci_set_master(to_pci_dev(dev_d)); - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); + device_wakeup_disable(dev_d); if (netif_running(ndev)) { err = ql_adapter_up(qdev); @@ -4815,27 +4800,25 @@ static int qlge_resume(struct pci_dev *pdev) return err; } - mod_timer(&qdev->timer, jiffies + (5*HZ)); + mod_timer(&qdev->timer, jiffies + (5 * HZ)); netif_device_attach(ndev); return 0; } -#endif /* CONFIG_PM */ static void qlge_shutdown(struct pci_dev *pdev) { - qlge_suspend(pdev, PMSG_SUSPEND); + qlge_suspend(&pdev->dev); } +static SIMPLE_DEV_PM_OPS(qlge_pm_ops, qlge_suspend, qlge_resume); + static struct pci_driver qlge_driver = { .name = DRV_NAME, .id_table = qlge_pci_tbl, .probe = qlge_probe, .remove = qlge_remove, -#ifdef CONFIG_PM - .suspend = qlge_suspend, - .resume = qlge_resume, -#endif + .driver.pm = &qlge_pm_ops, .shutdown = qlge_shutdown, .err_handler = &qlge_err_handler }; diff --git a/drivers/staging/qlge/qlge_mpi.c b/drivers/staging/qlge/qlge_mpi.c index 60c08d9cc0348b2f1d482285be700982a2fd5dc6..e85c6ab538df1c7eb74ccb28275ad3e62659b811 100644 --- a/drivers/staging/qlge/qlge_mpi.c +++ b/drivers/staging/qlge/qlge_mpi.c @@ -17,36 +17,34 @@ int ql_unpause_mpi_risc(struct ql_adapter *qdev) int ql_pause_mpi_risc(struct ql_adapter *qdev) { u32 tmp; - int count = UDELAY_COUNT; + int count; /* Pause the RISC */ ql_write32(qdev, CSR, CSR_CMD_SET_PAUSE); - do { + for (count = UDELAY_COUNT; count; count--) { tmp = ql_read32(qdev, CSR); if (tmp & CSR_RP) break; mdelay(UDELAY_DELAY); - count--; - } while (count); + } return (count == 0) ? -ETIMEDOUT : 0; } int ql_hard_reset_mpi_risc(struct ql_adapter *qdev) { u32 tmp; - int count = UDELAY_COUNT; + int count; /* Reset the RISC */ ql_write32(qdev, CSR, CSR_CMD_SET_RST); - do { + for (count = UDELAY_COUNT; count; count--) { tmp = ql_read32(qdev, CSR); if (tmp & CSR_RR) { ql_write32(qdev, CSR, CSR_CMD_CLR_RST); break; } mdelay(UDELAY_DELAY); - count--; - } while (count); + } return (count == 0) ? -ETIMEDOUT : 0; } @@ -147,15 +145,15 @@ static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp) */ static int ql_wait_mbx_cmd_cmplt(struct ql_adapter *qdev) { - int count = 100; + int count; u32 value; - do { + for (count = 100; count; count--) { value = ql_read32(qdev, STS); if (value & STS_PI) return 0; mdelay(UDELAY_DELAY); /* 100ms */ - } while (--count); + } return -ETIMEDOUT; } @@ -276,8 +274,8 @@ static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) netif_err(qdev, ifup, qdev->ndev, "Failed to init CAM/Routing tables.\n"); return; - } else - clear_bit(QL_CAM_RT_SET, &qdev->flags); + } + clear_bit(QL_CAM_RT_SET, &qdev->flags); } /* Queue up a worker to check the frame @@ -389,7 +387,8 @@ static void ql_init_fw_done(struct ql_adapter *qdev, struct mbox_params *mbcp) * This can get called iteratively from the mpi_work thread * when events arrive via an interrupt. * It also gets called when a mailbox command is polling for - * it's completion. */ + * it's completion. + */ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp) { int status; @@ -520,7 +519,7 @@ end: * changed when a mailbox command is waiting * for a response and an AEN arrives and * is handled. - * */ + */ mbcp->out_count = orig_count; return status; } @@ -555,7 +554,8 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) * here because some AEN might arrive while * we're waiting for the mailbox command to * complete. If more than 5 seconds expire we can - * assume something is wrong. */ + * assume something is wrong. + */ count = jiffies + HZ * MAILBOX_TIMEOUT; do { /* Wait for the interrupt to come in. */ @@ -786,8 +786,9 @@ int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, char *my_buf; dma_addr_t buf_dma; - my_buf = pci_alloc_consistent(qdev->pdev, word_count * sizeof(u32), - &buf_dma); + my_buf = dma_alloc_coherent(&qdev->pdev->dev, + word_count * sizeof(u32), &buf_dma, + GFP_ATOMIC); if (!my_buf) return -EIO; @@ -795,8 +796,8 @@ int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, if (!status) memcpy(buf, my_buf, word_count * sizeof(u32)); - pci_free_consistent(qdev->pdev, word_count * sizeof(u32), my_buf, - buf_dma); + dma_free_coherent(&qdev->pdev->dev, word_count * sizeof(u32), my_buf, + buf_dma); return status; } @@ -911,10 +912,10 @@ int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol) static int ql_idc_wait(struct ql_adapter *qdev) { int status = -ETIMEDOUT; - long wait_time = 1 * HZ; struct mbox_params *mbcp = &qdev->idc_mbc; + long wait_time; - do { + for (wait_time = 1 * HZ; wait_time;) { /* Wait here for the command to complete * via the IDC process. */ @@ -944,7 +945,7 @@ static int ql_idc_wait(struct ql_adapter *qdev) status = -EIO; break; } - } while (wait_time); + } return status; } @@ -1077,18 +1078,18 @@ static int ql_mb_get_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 *control) int ql_wait_fifo_empty(struct ql_adapter *qdev) { - int count = 5; + int count; u32 mgmnt_fifo_empty; u32 nic_fifo_empty; - do { + for (count = 6; count; count--) { nic_fifo_empty = ql_read32(qdev, STS) & STS_NFE; ql_mb_get_mgmnt_traffic_ctl(qdev, &mgmnt_fifo_empty); mgmnt_fifo_empty &= MB_GET_MPI_TFK_FIFO_EMPTY; if (nic_fifo_empty && mgmnt_fifo_empty) return 0; msleep(100); - } while (count-- > 0); + } return -ETIMEDOUT; } @@ -1173,12 +1174,12 @@ void ql_mpi_idc_work(struct work_struct *work) case MB_CMD_PORT_RESET: case MB_CMD_STOP_FW: ql_link_off(qdev); - /* Fall through */ + fallthrough; case MB_CMD_SET_PORT_CFG: /* Signal the resulting link up AEN * that the frame routing and mac addr * needs to be set. - * */ + */ set_bit(QL_CAM_RT_SET, &qdev->flags); /* Do ACK if required */ if (timeout) { @@ -1206,7 +1207,7 @@ void ql_mpi_idc_work(struct work_struct *work) */ ql_link_off(qdev); set_bit(QL_CAM_RT_SET, &qdev->flags); - /* Fall through. */ + fallthrough; case MB_CMD_IOP_DVR_START: case MB_CMD_IOP_FLASH_ACC: case MB_CMD_IOP_CORE_DUMP_MPI: diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index 817793b9aff27eced19325822f37be5c56c20feb..41535441f82c7a448001c08419545d866f5e8b56 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -535,7 +535,7 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) /* bwmode */ if (le16_to_cpu(phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & - IEEE80211_HT_CAP_SUP_WIDTH) { + IEEE80211_HT_CAP_SUP_WIDTH_20_40) { phtpriv_sta->bwmode = pmlmeext->cur_bwmode; phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; } @@ -925,12 +925,12 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2)); + pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07 << 2)); else - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00); + pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00); /* set Max Rx AMPDU size to 64K */ - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & 0x03); + pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_FACTOR & 0x03); pht_cap->mcs.rx_mask[0] = 0xff; pht_cap->mcs.rx_mask[1] = 0x0; @@ -1307,7 +1307,7 @@ static int rtw_ht_operation_update(struct adapter *padapter) (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)) new_op_mode = OP_MODE_MIXED; else if ((le16_to_cpu(phtpriv_ap->ht_cap.cap_info) & - IEEE80211_HT_CAP_SUP_WIDTH) && + IEEE80211_HT_CAP_SUP_WIDTH_20_40) && pmlmepriv->num_sta_ht_20mhz) new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED; else if (pmlmepriv->olbc_ht) @@ -1457,7 +1457,7 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) pmlmepriv->num_sta_ht_no_gf); } - if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) { + if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH_20_40) == 0) { if (!psta->ht_20mhz_set) { psta->ht_20mhz_set = 1; pmlmepriv->num_sta_ht_20mhz++; diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index f69e9453ad458dd06172ba8c8b4d8aaa45ef2874..a97d500810716538644843b9efa4b9af0190dc16 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -229,7 +229,7 @@ _next: * LOCKED pmlmepriv->lock */ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num, - struct rtw_ieee80211_channel *ch, int ch_num) + struct rtw_ieee80211_channel *ch, int ch_num) { u8 res = _FAIL; struct cmd_obj *ph2c; @@ -449,7 +449,7 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) { /* rtw_restructure_ht_ie */ rtw_restructure_ht_ie(padapter, &pnetwork->network.ies[0], &psecnetwork->ies[0], - pnetwork->network.ie_length, &psecnetwork->ie_length); + pnetwork->network.ie_length, &psecnetwork->ie_length); } } diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c index d0e41f2ef1ce8cc6316e81d1f3e111397687a2ab..fcc8bd1011e1370112e70b1becc6e5e3a64646d9 100644 --- a/drivers/staging/rtl8188eu/core/rtw_debug.c +++ b/drivers/staging/rtl8188eu/core/rtw_debug.c @@ -10,8 +10,8 @@ #include int proc_get_drv_version(char *page, char **start, - off_t offset, int count, - int *eof, void *data) + off_t offset, int count, + int *eof, void *data) { int len = 0; @@ -22,15 +22,15 @@ int proc_get_drv_version(char *page, char **start, } int proc_get_write_reg(char *page, char **start, - off_t offset, int count, - int *eof, void *data) + off_t offset, int count, + int *eof, void *data) { *eof = 1; return 0; } int proc_set_write_reg(struct file *file, const char __user *buffer, - unsigned long count, void *data) + unsigned long count, void *data) { struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); @@ -71,8 +71,8 @@ static u32 proc_get_read_addr = 0xeeeeeeee; static u32 proc_get_read_len = 0x4; int proc_get_read_reg(char *page, char **start, - off_t offset, int count, - int *eof, void *data) + off_t offset, int count, + int *eof, void *data) { struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); @@ -104,7 +104,7 @@ int proc_get_read_reg(char *page, char **start, } int proc_set_read_reg(struct file *file, const char __user *buffer, - unsigned long count, void *data) + unsigned long count, void *data) { char tmp[16]; u32 addr, len; @@ -131,8 +131,8 @@ int proc_set_read_reg(struct file *file, const char __user *buffer, } int proc_get_adapter_state(char *page, char **start, - off_t offset, int count, - int *eof, void *data) + off_t offset, int count, + int *eof, void *data) { struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index caf600eba03be6b82998332a195f611c074941fa..b80273611fb83b60c52d25e4157c62d9e3e33907 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -139,9 +139,11 @@ u8 *rtw_set_ie return pbuf + len + 2; } -/*---------------------------------------------------------------------------- -index: the information element id index, limit is the limit for search ------------------------------------------------------------------------------*/ +/* + * ---------------------------------------------------------------------------- + * index: the information element id index, limit is the limit for search + * ---------------------------------------------------------------------------- + */ u8 *rtw_get_ie(u8 *pbuf, int index, uint *len, int limit) { int tmp, i; @@ -379,8 +381,8 @@ int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwis left -= 2; if (count == 0 || left < count * WPA_SELECTOR_LEN) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), " - "count %u left %u", __func__, count, left)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), count %u left %u", + __func__, count, left)); return _FAIL; } @@ -446,8 +448,8 @@ int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwi left -= 2; if (count == 0 || left < count * RSN_SELECTOR_LEN) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), " - "count %u left %u", __func__, count, left)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), count %u left %u", + __func__, count, left)); return _FAIL; } @@ -492,23 +494,23 @@ void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie authmode = in_ie[cnt]; if ((authmode == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("\n rtw_get_wpa_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n", - sec_idx, in_ie[cnt + 1] + 2)); - - if (wpa_ie) { - memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - for (i = 0; i < (in_ie[cnt + 1] + 2); i += 8) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n", - wpa_ie[i], wpa_ie[i + 1], wpa_ie[i + 2], wpa_ie[i + 3], wpa_ie[i + 4], - wpa_ie[i + 5], wpa_ie[i + 6], wpa_ie[i + 7])); - } + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, + ("\n rtw_get_wpa_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n", + sec_idx, in_ie[cnt + 1] + 2)); + + if (wpa_ie) { + memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); + + for (i = 0; i < (in_ie[cnt + 1] + 2); i += 8) { + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, + ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n", + wpa_ie[i], wpa_ie[i + 1], wpa_ie[i + 2], wpa_ie[i + 3], wpa_ie[i + 4], + wpa_ie[i + 5], wpa_ie[i + 6], wpa_ie[i + 7])); } + } - *wpa_len = in_ie[cnt + 1] + 2; - cnt += in_ie[cnt + 1] + 2; /* get next */ + *wpa_len = in_ie[cnt + 1] + 2; + cnt += in_ie[cnt + 1] + 2; /* get next */ } else { if (authmode == _WPA2_IE_ID_) { RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, @@ -675,14 +677,15 @@ u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 } static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, - struct rtw_ieee802_11_elems *elems, - int show_errors) + struct rtw_ieee802_11_elems *elems, int show_errors) { unsigned int oui; - /* first 3 bytes in vendor specific information element are the IEEE + /* + * first 3 bytes in vendor specific information element are the IEEE * OUI of the vendor. The following byte is used a vendor specific - * sub-type. */ + * sub-type. + */ if (elen < 4) { if (show_errors) { DBG_88E("short vendor specific information element ignored (len=%lu)\n", @@ -694,12 +697,16 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, oui = RTW_GET_BE24(pos); switch (oui) { case OUI_MICROSOFT: - /* Microsoft/Wi-Fi information elements are further typed and - * subtyped */ + /* + * Microsoft/Wi-Fi information elements are further typed and + * subtyped + */ switch (pos[3]) { case 1: - /* Microsoft OUI (00:50:F2) with OUI Type 1: - * real WPA information element */ + /* + * Microsoft OUI (00:50:F2) with OUI Type 1: + * real WPA information element + */ elems->wpa_ie = pos; elems->wpa_ie_len = elen; break; @@ -766,8 +773,8 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, * Returns: Parsing result */ enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len, - struct rtw_ieee802_11_elems *elems, - int show_errors) + struct rtw_ieee802_11_elems *elems, + int show_errors) { uint left = len; u8 *pos = start; @@ -921,8 +928,10 @@ static int rtw_get_cipher_info(struct wlan_network *pnetwork) pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; pnetwork->BcnInfo.group_cipher = group_cipher; pnetwork->BcnInfo.is_8021x = is8021x; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d", - __func__, pnetwork->BcnInfo.pairwise_cipher, pnetwork->BcnInfo.is_8021x)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, + ("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d", + __func__, pnetwork->BcnInfo.pairwise_cipher, + pnetwork->BcnInfo.is_8021x)); ret = _SUCCESS; } } else { @@ -935,8 +944,8 @@ static int rtw_get_cipher_info(struct wlan_network *pnetwork) pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; pnetwork->BcnInfo.group_cipher = group_cipher; pnetwork->BcnInfo.is_8021x = is8021x; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d," - "pnetwork->group_cipher is %d, is_8021x is %d", __func__, pnetwork->BcnInfo.pairwise_cipher, + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_8021x is %d", + __func__, pnetwork->BcnInfo.pairwise_cipher, pnetwork->BcnInfo.group_cipher, pnetwork->BcnInfo.is_8021x)); ret = _SUCCESS; } @@ -978,10 +987,10 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork) if (bencrypt) pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP; } - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n", - pnetwork->BcnInfo.encryp_protocol)); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n", - pnetwork->BcnInfo.encryp_protocol)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->encryp_protocol is %x\n", + __func__, pnetwork->BcnInfo.encryp_protocol)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->encryp_protocol is %x\n", + __func__, pnetwork->BcnInfo.encryp_protocol)); rtw_get_cipher_info(pnetwork); /* get bwmode and ch_offset */ diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c index 7d56767cdff6d050a68060908a01ac736fa5343d..26e5193cfd6cd342258c90944e8e86a329e7a291 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c +++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c @@ -25,7 +25,7 @@ u8 rtw_do_join(struct adapter *padapter) phead = get_list_head(queue); plist = phead->next; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("\n rtw_do_join: phead = %p; plist = %p\n\n\n", phead, plist)); + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("\n %s: phead = %p; plist = %p\n\n\n", __func__, phead, plist)); pmlmepriv->cur_network.join_res = -2; @@ -44,12 +44,12 @@ u8 rtw_do_join(struct adapter *padapter) if (!pmlmepriv->LinkDetectInfo.bBusyTraffic || pmlmepriv->to_roaming > 0) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("rtw_do_join(): site survey if scanned_queue is empty\n.")); + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("%s: site survey if scanned_queue is empty\n.", __func__)); /* submit site_survey_cmd */ ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0); if (ret != _SUCCESS) { pmlmepriv->to_join = false; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("rtw_do_join(): site survey return error\n.")); + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("%s: site survey return error\n.", __func__)); } } else { pmlmepriv->to_join = false; @@ -306,14 +306,14 @@ exit: } u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter, - enum ndis_802_11_network_infra networktype) + enum ndis_802_11_network_infra networktype) { struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_network *cur_network = &pmlmepriv->cur_network; enum ndis_802_11_network_infra *pold_state = &cur_network->network.InfrastructureMode; RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_, - ("+rtw_set_802_11_infrastructure_mode: old =%d new =%d fw_state = 0x%08x\n", + ("+%s: old =%d new =%d fw_state = 0x%08x\n", __func__, *pold_state, networktype, get_fwstate(pmlmepriv))); if (*pold_state != networktype) { @@ -343,7 +343,7 @@ u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter, *pold_state == Ndis802_11IBSS) { if (check_fwstate(pmlmepriv, _FW_LINKED)) rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether issue dis-assoc_cmd or not */ - } + } *pold_state = networktype; @@ -496,7 +496,7 @@ u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep) break; } RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - ("rtw_set_802_11_add_wep:before memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x keyid =%x\n", + ("%s:before memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x keyid =%x\n", __func__, wep->KeyLength, wep->KeyIndex, keyid)); memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0], @@ -507,7 +507,7 @@ u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep) psecuritypriv->dot11PrivacyKeyIndex = keyid; RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - ("rtw_set_802_11_add_wep:security key material : %x %x %x %x %x %x %x %x %x %x %x %x %x\n", + ("%s:security key material : %x %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__, psecuritypriv->dot11DefKey[keyid].skey[0], psecuritypriv->dot11DefKey[keyid].skey[1], psecuritypriv->dot11DefKey[keyid].skey[2], diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 9de2d421f6b1793e967a1fea22cc52eb05e5b61c..d334dc3359148ff90e4165eaaa63789dacbd98de 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -334,7 +334,7 @@ struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue) } void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src, - struct adapter *padapter, bool update_ie) + struct adapter *padapter, bool update_ie) { long rssi_ori = dst->Rssi; u8 sq_smp = src->PhyInfo.SignalQuality; @@ -646,7 +646,7 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf) s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv); if (s_ret == _SUCCESS) { mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT)); + jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT)); } else if (s_ret == 2) { /* there is no need to wait for join */ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); rtw_indicate_connect(adapter); @@ -1729,9 +1729,11 @@ int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_ if ((ndisauthmode == Ndis802_11AuthModeWPA) || (ndisauthmode == Ndis802_11AuthModeWPAPSK)) authmode = _WPA_IE_ID_; - if ((ndisauthmode == Ndis802_11AuthModeWPA2) || + else if ((ndisauthmode == Ndis802_11AuthModeWPA2) || (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) authmode = _WPA2_IE_ID_; + else + authmode = 0x0; if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) { memcpy(out_ie + ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len); @@ -1882,7 +1884,7 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ memset(&ht_cap, 0, sizeof(struct ieee80211_ht_cap)); - ht_cap.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH | + ht_cap.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_TX_STBC | @@ -1900,9 +1902,9 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ ht_cap.ampdu_params_info = max_rx_ampdu_factor & 0x03; if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_) - ht_cap.ampdu_params_info |= IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2); + ht_cap.ampdu_params_info |= IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07 << 2); else - ht_cap.ampdu_params_info |= IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00; + ht_cap.ampdu_params_info |= IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00; rtw_set_ie(out_ie + out_len, _HT_CAPABILITY_IE_, sizeof(struct ieee80211_ht_cap), diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 8d035f67ef6135efad840e0e68e2e51dff689388..98b1ba2e489f09514d05f0af7697429bf94c51c0 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -370,7 +370,7 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) pframe += (cur_network->ie_length + len_diff); pattrib->pktlen += (cur_network->ie_length + len_diff); wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, - pattrib->pktlen - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen); + pattrib->pktlen - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen); if (wps_ie && wps_ielen > 0) rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); if (sr != 0) @@ -870,7 +870,7 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, pattrib->last_txcmdsz = pattrib->pktlen; - rtw_wep_encrypt(padapter, (u8 *)pmgntframe); + rtw_wep_encrypt(padapter, pmgntframe); DBG_88E("%s\n", __func__); dump_mgntframe(padapter, pmgntframe); } @@ -1932,12 +1932,12 @@ static void site_survey(struct adapter *padapter) if (pmlmeext->sitesurvey_res.ssid[i].ssid_length) { /* todo: to issue two probe req??? */ issue_probereq(padapter, - &pmlmeext->sitesurvey_res.ssid[i], - NULL, false); + &pmlmeext->sitesurvey_res.ssid[i], + NULL, false); /* msleep(SURVEY_TO>>1); */ issue_probereq(padapter, - &pmlmeext->sitesurvey_res.ssid[i], - NULL, false); + &pmlmeext->sitesurvey_res.ssid[i], + NULL, false); } } @@ -2522,7 +2522,7 @@ static unsigned int OnProbeReq(struct adapter *padapter, return _SUCCESS; p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, &ielen, - len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); + len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); /* check (wildcard) SSID */ if (p) { @@ -2759,7 +2759,7 @@ static unsigned int OnAuth(struct adapter *padapter, DBG_88E("checking for challenging txt...\n"); p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, &ie_len, - len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); + len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); if (!p || ie_len <= 0) { DBG_88E("auth rejected because challenge failure!(1)\n"); @@ -2853,7 +2853,7 @@ static unsigned int OnAuthClient(struct adapter *padapter, if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { /* legendary shared system */ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, &len, - pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); + pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); if (!p) goto authclnt_fail; @@ -2966,7 +2966,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, /* now we should check all the fields... */ /* checking SSID */ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len, - pkt_len - WLAN_HDR_A3_LEN - ie_offset); + pkt_len - WLAN_HDR_A3_LEN - ie_offset); if (!p || ie_len == 0) { /* broadcast ssid, however it is not allowed in assocreq */ @@ -2999,7 +2999,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, supportRateNum = ie_len; p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len, - pkt_len - WLAN_HDR_A3_LEN - ie_offset); + pkt_len - WLAN_HDR_A3_LEN - ie_offset); if (p) { if (supportRateNum <= sizeof(supportRate)) { memcpy(supportRate + supportRateNum, @@ -3913,8 +3913,7 @@ static void init_mlme_ext_priv_value(struct adapter *padapter) } static int has_channel(struct rt_channel_info *channel_set, - u8 chanset_size, - u8 chan) + u8 chanset_size, u8 chan) { int i; @@ -4133,7 +4132,7 @@ void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame) ptable->func = &OnAuth; else ptable->func = &OnAuthClient; - /* fall through */ + fallthrough; case WIFI_ASSOCREQ: case WIFI_REASSOCREQ: case WIFI_PROBEREQ: @@ -4671,18 +4670,15 @@ void linked_status_chk(struct adapter *padapter) } else { if (rx_chk != _SUCCESS) { if (pmlmeext->retry == 0) { - issue_probereq(padapter, - &pmlmeinfo->network.ssid, - pmlmeinfo->network.MacAddress, - false); - issue_probereq(padapter, - &pmlmeinfo->network.ssid, - pmlmeinfo->network.MacAddress, - false); - issue_probereq(padapter, - &pmlmeinfo->network.ssid, - pmlmeinfo->network.MacAddress, - false); + issue_probereq(padapter, &pmlmeinfo->network.ssid, + pmlmeinfo->network.MacAddress, + false); + issue_probereq(padapter, &pmlmeinfo->network.ssid, + pmlmeinfo->network.MacAddress, + false); + issue_probereq(padapter, &pmlmeinfo->network.ssid, + pmlmeinfo->network.MacAddress, + false); } } @@ -5330,7 +5326,7 @@ u8 set_tx_beacon_cmd(struct adapter *padapter) } ptxBeacon_parm = kmemdup(&pmlmeinfo->network, - sizeof(struct wlan_bssid_ex), GFP_ATOMIC); + sizeof(struct wlan_bssid_ex), GFP_ATOMIC); if (!ptxBeacon_parm) { kfree(ph2c); res = _FAIL; diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c index c000382c96d9d09ab8cb760dc7a271e0202e75dd..39ca97411fd5d652d04230b455283b79d5c23a6f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c @@ -205,10 +205,10 @@ static bool rtw_pwr_unassociated_idle(struct adapter *adapter) if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies)) return false; - if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) || - check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) || + if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE | WIFI_SITE_MONITOR) || + check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS) || check_fwstate(pmlmepriv, WIFI_AP_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)) + check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE)) return false; return true; @@ -249,7 +249,7 @@ void rtw_ps_processor(struct adapter *padapter) if (!rtw_pwr_unassociated_idle(padapter)) goto exit; - if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0)) { + if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts % 4) == 0)) { DBG_88E("==>%s .fw_state(%x)\n", __func__, get_fwstate(pmlmepriv)); pwrpriv->change_rfpwrstate = rf_off; @@ -264,7 +264,7 @@ static void pwr_state_check_handler(struct timer_list *t) { struct adapter *padapter = from_timer(padapter, t, - pwrctrlpriv.pwr_state_check_timer); + pwrctrlpriv.pwr_state_check_timer); rtw_ps_cmd(padapter); } diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index a036ef104198e76ecec2d33b23c27eb085f23bec..5fe7a0458dd217081b52c68ee54aafcfa39396d3 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -15,6 +15,7 @@ #include #include #include +#include #define ETHERNET_HEADER_SIZE 14 /* Ethernet Header Length */ #define LLC_HEADER_SIZE 6 /* LLC Header Length */ @@ -22,15 +23,6 @@ static u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37}; static u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3}; -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static u8 rtw_bridge_tunnel_header[] = { - 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 -}; - -static u8 rtw_rfc1042_header[] = { - 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 -}; - static void rtw_signal_stat_timer_hdl(struct timer_list *t); void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv) @@ -67,7 +59,7 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) INIT_LIST_HEAD(&precvframe->list); list_add_tail(&precvframe->list, - &precvpriv->free_recv_queue.queue); + &precvpriv->free_recv_queue.queue); precvframe->pkt = NULL; @@ -163,12 +155,12 @@ int rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue) } /* -caller : defrag ; recvframe_chk_defrag in recv_thread (passive) -pframequeue: defrag_queue : will be accessed in recv_thread (passive) - -using spinlock to protect - -*/ + * caller : defrag ; recvframe_chk_defrag in recv_thread (passive) + * pframequeue: defrag_queue : will be accessed in recv_thread (passive) + * + * using spinlock to protect + * + */ void rtw_free_recvframe_queue(struct __queue *pframequeue, struct __queue *pfree_recv_queue) { @@ -252,10 +244,10 @@ static int recvframe_chkmic(struct adapter *adapter, } /* icv_len included the mic code */ - datalen = precvframe->pkt->len-prxattrib->hdrlen - - prxattrib->iv_len-prxattrib->icv_len-8; + datalen = precvframe->pkt->len - prxattrib->hdrlen - + prxattrib->iv_len - prxattrib->icv_len - 8; pframe = precvframe->pkt->data; - payload = pframe+prxattrib->hdrlen+prxattrib->iv_len; + payload = pframe + prxattrib->hdrlen + prxattrib->iv_len; RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n prxattrib->iv_len=%d prxattrib->icv_len=%d\n", prxattrib->iv_len, prxattrib->icv_len)); rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0], @@ -266,7 +258,7 @@ static int recvframe_chkmic(struct adapter *adapter, bmic_err = false; for (i = 0; i < 8; i++) { - if (miccode[i] != *(pframemic+i)) { + if (miccode[i] != *(pframemic + i)) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: miccode[%d](%02x)!=*(pframemic+%d)(%02x) ", __func__, i, miccode[i], i, *(pframemic + i))); @@ -277,14 +269,14 @@ static int recvframe_chkmic(struct adapter *adapter, if (bmic_err) { RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n *(pframemic-8)-*(pframemic-1)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", - *(pframemic-8), *(pframemic-7), *(pframemic-6), - *(pframemic-5), *(pframemic-4), *(pframemic-3), - *(pframemic-2), *(pframemic-1))); + *(pframemic - 8), *(pframemic - 7), *(pframemic - 6), + *(pframemic - 5), *(pframemic - 4), *(pframemic - 3), + *(pframemic - 2), *(pframemic - 1))); RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n *(pframemic-16)-*(pframemic-9)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", - *(pframemic-16), *(pframemic-15), *(pframemic-14), - *(pframemic-13), *(pframemic-12), *(pframemic-11), - *(pframemic-10), *(pframemic-9))); + *(pframemic - 16), *(pframemic - 15), *(pframemic - 14), + *(pframemic - 13), *(pframemic - 12), *(pframemic - 11), + *(pframemic - 10), *(pframemic - 9))); { uint i; @@ -295,14 +287,14 @@ static int recvframe_chkmic(struct adapter *adapter, RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x", - *(precvframe->pkt->data+i), - *(precvframe->pkt->data+i+1), - *(precvframe->pkt->data+i+2), - *(precvframe->pkt->data+i+3), - *(precvframe->pkt->data+i+4), - *(precvframe->pkt->data+i+5), - *(precvframe->pkt->data+i+6), - *(precvframe->pkt->data+i+7))); + *(precvframe->pkt->data + i), + *(precvframe->pkt->data + i + 1), + *(precvframe->pkt->data + i + 2), + *(precvframe->pkt->data + i + 3), + *(precvframe->pkt->data + i + 4), + *(precvframe->pkt->data + i + 5), + *(precvframe->pkt->data + i + 6), + *(precvframe->pkt->data + i + 7))); } RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, @@ -392,13 +384,13 @@ static struct recv_frame *decryptor(struct adapter *padapter, switch (prxattrib->encrypt) { case _WEP40_: case _WEP104_: - res = rtw_wep_decrypt(padapter, (u8 *)precv_frame); + res = rtw_wep_decrypt(padapter, precv_frame); break; case _TKIP_: - res = rtw_tkip_decrypt(padapter, (u8 *)precv_frame); + res = rtw_tkip_decrypt(padapter, precv_frame); break; case _AES_: - res = rtw_aes_decrypt(padapter, (u8 *)precv_frame); + res = rtw_aes_decrypt(padapter, precv_frame); break; default: break; @@ -496,7 +488,7 @@ static int recv_decache(struct recv_frame *precv_frame, u8 bretry, { int tid = precv_frame->attrib.priority; - u16 seq_ctrl = ((precv_frame->attrib.seq_num&0xffff) << 4) | + u16 seq_ctrl = ((precv_frame->attrib.seq_num & 0xffff) << 4) | (precv_frame->attrib.frag_num & 0xf); if (tid > 15) { @@ -561,29 +553,29 @@ static void process_wmmps_data(struct adapter *padapter, if (!psta->qos_option) return; - if (!(psta->qos_info&0xf)) + if (!(psta->qos_info & 0xf)) return; - if (psta->state&WIFI_SLEEP_STATE) { + if (psta->state & WIFI_SLEEP_STATE) { u8 wmmps_ac = 0; switch (pattrib->priority) { case 1: case 2: - wmmps_ac = psta->uapsd_bk&BIT(1); + wmmps_ac = psta->uapsd_bk & BIT(1); break; case 4: case 5: - wmmps_ac = psta->uapsd_vi&BIT(1); + wmmps_ac = psta->uapsd_vi & BIT(1); break; case 6: case 7: - wmmps_ac = psta->uapsd_vo&BIT(1); + wmmps_ac = psta->uapsd_vo & BIT(1); break; case 0: case 3: default: - wmmps_ac = psta->uapsd_be&BIT(1); + wmmps_ac = psta->uapsd_be & BIT(1); break; } @@ -679,8 +671,8 @@ static int sta2sta_data_frame(struct adapter *adapter, if (mcast) { /* For AP mode, if DA == MCAST, then BSSID should be also MCAST */ if (!is_multicast_ether_addr(pattrib->bssid)) { - ret = _FAIL; - goto exit; + ret = _FAIL; + goto exit; } } else { /* not mc-frame */ /* For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID */ @@ -710,10 +702,9 @@ exit: return ret; } -static int ap2sta_data_frame( - struct adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta) +static int ap2sta_data_frame(struct adapter *adapter, + struct recv_frame *precv_frame, + struct sta_info **psta) { u8 *ptr = precv_frame->pkt->data; struct rx_pkt_attrib *pattrib = &precv_frame->attrib; @@ -892,20 +883,20 @@ static int validate_recv_ctrl_frame(struct adapter *padapter, switch (pattrib->priority) { case 1: case 2: - wmmps_ac = psta->uapsd_bk&BIT(0); + wmmps_ac = psta->uapsd_bk & BIT(0); break; case 4: case 5: - wmmps_ac = psta->uapsd_vi&BIT(0); + wmmps_ac = psta->uapsd_vi & BIT(0); break; case 6: case 7: - wmmps_ac = psta->uapsd_vo&BIT(0); + wmmps_ac = psta->uapsd_vo & BIT(0); break; case 0: case 3: default: - wmmps_ac = psta->uapsd_be&BIT(0); + wmmps_ac = psta->uapsd_be & BIT(0); break; } @@ -918,7 +909,7 @@ static int validate_recv_ctrl_frame(struct adapter *padapter, psta->state ^= WIFI_STA_ALIVE_CHK_STATE; } - if ((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) { + if ((psta->state & WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap & BIT(psta->aid))) { struct list_head *xmitframe_plist, *xmitframe_phead; struct xmit_frame *pxmitframe = NULL; @@ -956,7 +947,7 @@ static int validate_recv_ctrl_frame(struct adapter *padapter, update_beacon(padapter, _TIM_IE_, NULL, false); } } else { - if (pstapriv->tim_bitmap&BIT(psta->aid)) { + if (pstapriv->tim_bitmap & BIT(psta->aid)) { if (psta->sleepq_len == 0) { DBG_88E("no buffered packets to xmit\n"); @@ -1192,21 +1183,21 @@ static int validate_recv_frame(struct adapter *adapter, if (_drv_err_ <= GlobalDebugLevel) { pr_info(DRIVER_PREFIX "#############################\n"); print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, - 16, 1, ptr, 64, false); + 16, 1, ptr, 64, false); pr_info(DRIVER_PREFIX "#############################\n"); } } else if (bDumpRxPkt == 2) { if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_MGT_TYPE)) { pr_info(DRIVER_PREFIX "#############################\n"); print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, - 16, 1, ptr, 64, false); + 16, 1, ptr, 64, false); pr_info(DRIVER_PREFIX "#############################\n"); } } else if (bDumpRxPkt == 3) { if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_DATA_TYPE)) { pr_info(DRIVER_PREFIX "#############################\n"); print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, - 16, 1, ptr, 64, false); + 16, 1, ptr, 64, false); pr_info(DRIVER_PREFIX "#############################\n"); } } @@ -1274,13 +1265,13 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe) if (pattrib->encrypt) skb_trim(precvframe->pkt, precvframe->pkt->len - pattrib->icv_len); - psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen + pattrib->iv_len); - psnap_type = ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE; + psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen + pattrib->iv_len); + psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE; /* convert hdr + possible LLC headers into Ethernet header */ - if ((!memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) && + if ((!memcmp(psnap, rfc1042_header, SNAP_SIZE) && memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) && memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2)) || - !memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)) { + !memcmp(psnap, bridge_tunnel_header, SNAP_SIZE)) { /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */ bsnaphdr = true; } else { @@ -1294,7 +1285,7 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe) RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n===pattrib->hdrlen: %x, pattrib->iv_len:%x===\n\n", pattrib->hdrlen, pattrib->iv_len)); - memcpy(&be_tmp, ptr+rmv_len, 2); + memcpy(&be_tmp, ptr + rmv_len, 2); eth_type = ntohs(be_tmp); /* pattrib->ether_type */ pattrib->eth_type = eth_type; @@ -1543,7 +1534,7 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe) pdata += nSubframe_Length; a_len -= nSubframe_Length; if (a_len != 0) { - padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4-1)); + padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4 - 1)); if (padding_len == 4) padding_len = 0; @@ -1560,9 +1551,9 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe) /* convert hdr + possible LLC headers into Ethernet header */ eth_type = get_unaligned_be16(&sub_skb->data[6]); if (sub_skb->len >= 8 && - ((!memcmp(sub_skb->data, rtw_rfc1042_header, SNAP_SIZE) && + ((!memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) && eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || - !memcmp(sub_skb->data, rtw_bridge_tunnel_header, SNAP_SIZE))) { + !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) { /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */ skb_pull(sub_skb, SNAP_SIZE); memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN); diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index 435c0fbec54ab8e1efab3336a63ae7bdbc3acab6..78a8ac60bf3df3338c590a767f944cedb1f29bb0 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -80,9 +80,9 @@ static u32 crc32_table[256]; static u8 crc32_reverseBit(u8 data) { - return (u8)((data<<7)&0x80) | ((data<<5)&0x40) | ((data<<3)&0x20) | - ((data<<1)&0x10) | ((data>>1)&0x08) | ((data>>3)&0x04) | - ((data>>5)&0x02) | ((data>>7)&0x01); + return (u8)((data << 7) & 0x80) | ((data << 5) & 0x40) | ((data << 3) & 0x20) | + ((data << 1) & 0x10) | ((data >> 1) & 0x08) | ((data >> 3) & 0x04) | + ((data >> 5) & 0x02) | ((data >> 7) & 0x01); } static void crc32_init(void) @@ -129,12 +129,12 @@ static __le32 getcrc32(u8 *buf, int len) /* Need to consider the fragment situation */ -void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe) +void rtw_wep_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) { int curfragnum, length; u8 *pframe; u8 hw_hdr_offset = 0; - struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib; + struct pkt_attrib *pattrib = &pxmitframe->attrib; struct security_priv *psecuritypriv = &padapter->securitypriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; const int keyindex = psecuritypriv->dot11PrivacyKeyIndex; @@ -142,16 +142,16 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe) struct sk_buff *skb; struct lib80211_crypto_ops *crypto_ops; - if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) + if (pxmitframe->buf_addr == NULL) return; if ((pattrib->encrypt != _WEP40_) && (pattrib->encrypt != _WEP104_)) return; hw_hdr_offset = TXDESC_SIZE + - (((struct xmit_frame *)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ); + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ); - pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset; + pframe = pxmitframe->buf_addr + hw_hdr_offset; crypto_ops = lib80211_get_crypto_ops("WEP"); @@ -198,13 +198,13 @@ free_crypto_private: crypto_ops->deinit(crypto_private); } -int rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe) +int rtw_wep_decrypt(struct adapter *padapter, struct recv_frame *precvframe) { - struct rx_pkt_attrib *prxattrib = &(((struct recv_frame *)precvframe)->attrib); + struct rx_pkt_attrib *prxattrib = &precvframe->attrib; if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) { struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sk_buff *skb = ((struct recv_frame *)precvframe)->pkt; + struct sk_buff *skb = precvframe->pkt; u8 *pframe = skb->data; void *crypto_private = NULL; int status = _SUCCESS; @@ -260,7 +260,7 @@ static u32 secmicgetuint32(u8 *p) u32 res = 0; for (i = 0; i < 4; i++) - res |= ((u32)(*p++)) << (8*i); + res |= ((u32)(*p++)) << (8 * i); return res; } @@ -296,7 +296,7 @@ void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key) void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b) { /* Append the byte to our word-sized buffer */ - pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM); + pmicdata->M |= ((unsigned long)b) << (8 * pmicdata->nBytesInM); pmicdata->nBytesInM++; /* Process the word if it is full. */ if (pmicdata->nBytesInM >= 4) { @@ -337,7 +337,7 @@ void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst) rtw_secmicappendbyte(pmicdata, 0); /* The appendByte function has already computed the result. */ secmicputuint32(dst, pmicdata->L); - secmicputuint32(dst+4, pmicdata->R); + secmicputuint32(dst + 4, pmicdata->R); /* Reset to the empty message. */ secmicclear(pmicdata); } @@ -351,15 +351,15 @@ void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_cod priority[0] = pri; /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */ - if (header[1]&1) { /* ToDS == 1 */ + if (header[1] & 1) { /* ToDS == 1 */ rtw_secmicappend(&micdata, &header[16], 6); /* DA */ - if (header[1]&2) /* From Ds == 1 */ + if (header[1] & 2) /* From Ds == 1 */ rtw_secmicappend(&micdata, &header[24], 6); else rtw_secmicappend(&micdata, &header[10], 6); } else { /* ToDS == 0 */ rtw_secmicappend(&micdata, &header[4], 6); /* DA */ - if (header[1]&2) /* From Ds == 1 */ + if (header[1] & 2) /* From Ds == 1 */ rtw_secmicappend(&micdata, &header[16], 6); else rtw_secmicappend(&micdata, &header[10], 6); @@ -382,7 +382,7 @@ void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_cod #define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8)) /* select the Nth 16-bit word of the temporal key unsigned char array TK[] */ -#define TK16(N) Mk16(tk[2*(N)+1], tk[2*(N)]) +#define TK16(N) Mk16(tk[2 * (N) + 1], tk[2 * (N)]) /* S-box lookup: 16 bits --> 16 bits */ #define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)]) @@ -497,11 +497,11 @@ static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32) /* Now compute an unbalanced Feistel cipher with 80-bit block */ /* size on the 80-bit block P1K[], using the 128-bit key TK[] */ for (i = 0; i < PHASE1_LOOP_CNT; i++) { /* Each add operation here is mod 2**16 */ - p1k[0] += _S_(p1k[4] ^ TK16((i&1)+0)); - p1k[1] += _S_(p1k[0] ^ TK16((i&1)+2)); - p1k[2] += _S_(p1k[1] ^ TK16((i&1)+4)); - p1k[3] += _S_(p1k[2] ^ TK16((i&1)+6)); - p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0)); + p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0)); + p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2)); + p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4)); + p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6)); + p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0)); p1k[4] += (unsigned short)i; /* avoid "slide attacks" */ } } @@ -566,13 +566,13 @@ static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16) /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */ for (i = 0; i < 6; i++) { - rc4key[4+2*i] = Lo8(PPK[i]); - rc4key[5+2*i] = Hi8(PPK[i]); + rc4key[4 + 2 * i] = Lo8(PPK[i]); + rc4key[5 + 2 * i] = Hi8(PPK[i]); } } /* The hlen isn't include the IV */ -u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) +u32 rtw_tkip_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) { /* exclude ICV */ u16 pnl; u32 pnh; @@ -586,17 +586,17 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) u8 *pframe, *payload, *iv, *prwskey; union pn48 dot11txpn; struct sta_info *stainfo; - struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib; + struct pkt_attrib *pattrib = &pxmitframe->attrib; struct security_priv *psecuritypriv = &padapter->securitypriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; u32 res = _SUCCESS; - if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) + if (pxmitframe->buf_addr == NULL) return _FAIL; hw_hdr_offset = TXDESC_SIZE + - (((struct xmit_frame *)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ); - pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset; + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ); + pframe = pxmitframe->buf_addr + hw_hdr_offset; /* 4 start to encrypt each fragment */ if (pattrib->encrypt == _TKIP_) { if (pattrib->psta) @@ -613,18 +613,18 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) prwskey = &stainfo->dot118021x_UncstKey.skey[0]; for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - iv = pframe+pattrib->hdrlen; - payload = pframe+pattrib->iv_len+pattrib->hdrlen; + iv = pframe + pattrib->hdrlen; + payload = pframe + pattrib->iv_len + pattrib->hdrlen; GET_TKIP_PN(iv, dot11txpn); pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val>>16); + pnh = (u32)(dot11txpn.val >> 16); phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh); phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl); - if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */ - length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; + if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */ + length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("pattrib->iv_len=%x, pattrib->icv_len=%x\n", pattrib->iv_len, pattrib->icv_len)); @@ -632,13 +632,13 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) arcfour_init(&mycontext, rc4key, 16); arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload+length, crc, 4); + arcfour_encrypt(&mycontext, payload + length, crc, 4); } else { - length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; + length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/ arcfour_init(&mycontext, rc4key, 16); arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload+length, crc, 4); + arcfour_encrypt(&mycontext, payload + length, crc, 4); pframe += pxmitpriv->frag_len; pframe = (u8 *)round_up((size_t)(pframe), 4); @@ -653,7 +653,7 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) } /* The hlen isn't include the IV */ -u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe) +u32 rtw_tkip_decrypt(struct adapter *padapter, struct recv_frame *precvframe) { /* exclude ICV */ u16 pnl; u32 pnh; @@ -666,12 +666,12 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe) u8 *pframe, *payload, *iv, *prwskey; union pn48 dot11txpn; struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &((struct recv_frame *)precvframe)->attrib; + struct rx_pkt_attrib *prxattrib = &precvframe->attrib; struct security_priv *psecuritypriv = &padapter->securitypriv; u32 res = _SUCCESS; - pframe = (unsigned char *)((struct recv_frame *)precvframe)->pkt->data; + pframe = (unsigned char *)precvframe->pkt->data; /* 4 start to decrypt recvframe */ if (prxattrib->encrypt == _TKIP_) { @@ -689,14 +689,14 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe) prwskey = &stainfo->dot118021x_UncstKey.skey[0]; } - iv = pframe+prxattrib->hdrlen; - payload = pframe+prxattrib->iv_len+prxattrib->hdrlen; - length = ((struct recv_frame *)precvframe)->pkt->len-prxattrib->hdrlen-prxattrib->iv_len; + iv = pframe + prxattrib->hdrlen; + payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; + length = precvframe->pkt->len - prxattrib->hdrlen - prxattrib->iv_len; GET_TKIP_PN(iv, dot11txpn); pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val>>16); + pnh = (u32)(dot11txpn.val >> 16); phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh); phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl); @@ -706,19 +706,19 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe) arcfour_init(&mycontext, rc4key, 16); arcfour_encrypt(&mycontext, payload, payload, length); - *((__le32 *)crc) = getcrc32(payload, length-4); + *((__le32 *)crc) = getcrc32(payload, length - 4); - if (crc[3] != payload[length-1] || - crc[2] != payload[length-2] || - crc[1] != payload[length-3] || - crc[0] != payload[length-4]) { + if (crc[3] != payload[length - 1] || + crc[2] != payload[length - 2] || + crc[1] != payload[length - 3] || + crc[0] != payload[length - 4]) { RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_wep_decrypt:icv error crc (%4ph)!=payload (%4ph)\n", - &crc, &payload[length-4])); + &crc, &payload[length - 4])); res = _FAIL; } } else { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt: stainfo==NULL!!!\n")); + RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo==NULL!!!\n", __func__)); res = _FAIL; } } @@ -734,7 +734,7 @@ exit: /******** SBOX Table *********/ /*****************************/ -static u8 sbox_table[256] = { +static const u8 sbox_table[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, @@ -817,7 +817,7 @@ static void next_key(u8 *key, int round) { u8 rcon; u8 sbox_key[4]; - u8 rcon_table[12] = { + static const u8 rcon_table[12] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x36, 0x36 }; @@ -840,6 +840,7 @@ static void next_key(u8 *key, int round) static void byte_sub(u8 *in, u8 *out) { int i; + for (i = 0; i < 16; i++) out[i] = sbox(in[i]); } @@ -900,7 +901,7 @@ static void mix_column(u8 *in, u8 *out) for (i = 3; i > 0; i--) { /* logical shift left 1 bit */ andf7[i] = andf7[i] << 1; - if ((andf7[i-1] & 0x80) == 0x80) + if ((andf7[i - 1] & 0x80) == 0x80) andf7[i] = (andf7[i] | 0x01); } andf7[0] = andf7[0] << 1; @@ -1025,7 +1026,7 @@ static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, int if (!qc_exists && a4_exists) { for (i = 0; i < 6; i++) - mic_header2[8+i] = mpdu[24+i]; /* A4 */ + mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ } if (qc_exists && !a4_exists) { @@ -1035,7 +1036,7 @@ static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, int if (qc_exists && a4_exists) { for (i = 0; i < 6; i++) - mic_header2[8+i] = mpdu[24+i]; /* A4 */ + mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ mic_header2[14] = mpdu[30] & 0x0f; mic_header2[15] = mpdu[31] & 0x00; @@ -1128,11 +1129,11 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) } pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen+1]; - pn_vector[2] = pframe[hdrlen+4]; - pn_vector[3] = pframe[hdrlen+5]; - pn_vector[4] = pframe[hdrlen+6]; - pn_vector[5] = pframe[hdrlen+7]; + pn_vector[1] = pframe[hdrlen + 1]; + pn_vector[2] = pframe[hdrlen + 4]; + pn_vector[3] = pframe[hdrlen + 5]; + pn_vector[4] = pframe[hdrlen + 6]; + pn_vector[5] = pframe[hdrlen + 7]; construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector); @@ -1174,11 +1175,11 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) /* Insert MIC into payload */ for (j = 0; j < 8; j++) - pframe[payload_index+j] = mic[j]; + pframe[payload_index + j] = mic[j]; payload_index = hdrlen + 8; for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, i+1); + construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, i + 1); aes128k128d(key, ctr_preload, aes_out); bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); for (j = 0; j < 16; j++) @@ -1187,12 +1188,12 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) if (payload_remainder > 0) { /* If there is a short final block, then pad it,*/ /* encrypt it and copy the unpadded part back */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, num_blocks+1); + construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, num_blocks + 1); for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index+j]; + padded_buffer[j] = pframe[payload_index + j]; aes128k128d(key, ctr_preload, aes_out); bitwise_xor(aes_out, padded_buffer, chain_buffer); for (j = 0; j < payload_remainder; j++) @@ -1204,7 +1205,7 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; for (j = 0; j < 8; j++) - padded_buffer[j] = pframe[j+hdrlen+8+plen]; + padded_buffer[j] = pframe[j + hdrlen + 8 + plen]; aes128k128d(key, ctr_preload, aes_out); bitwise_xor(aes_out, padded_buffer, chain_buffer); @@ -1213,7 +1214,7 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) return _SUCCESS; } -u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe) +u32 rtw_aes_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) { /* exclude ICV */ /*static*/ @@ -1224,20 +1225,20 @@ u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe) u8 *pframe, *prwskey; /* *payload,*iv */ u8 hw_hdr_offset = 0; struct sta_info *stainfo; - struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib; + struct pkt_attrib *pattrib = &pxmitframe->attrib; struct security_priv *psecuritypriv = &padapter->securitypriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; /* uint offset = 0; */ u32 res = _SUCCESS; - if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) + if (pxmitframe->buf_addr == NULL) return _FAIL; hw_hdr_offset = TXDESC_SIZE + - (((struct xmit_frame *)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ); + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ); - pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset; + pframe = pxmitframe->buf_addr + hw_hdr_offset; /* 4 start to encrypt each fragment */ if (pattrib->encrypt == _AES_) { @@ -1254,12 +1255,12 @@ u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe) else prwskey = &stainfo->dot118021x_UncstKey.skey[0]; for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */ - length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; + if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */ + length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; aes_cipher(prwskey, pattrib->hdrlen, pframe, length); } else { - length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; + length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; aes_cipher(prwskey, pattrib->hdrlen, pframe, length); pframe += pxmitpriv->frag_len; @@ -1275,9 +1276,9 @@ u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe) return res; } -u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe) +u32 rtw_aes_decrypt(struct adapter *padapter, struct recv_frame *precvframe) { - struct rx_pkt_attrib *prxattrib = &((struct recv_frame *)precvframe)->attrib; + struct rx_pkt_attrib *prxattrib = &precvframe->attrib; u32 res = _SUCCESS; /* 4 start to encrypt each fragment */ @@ -1287,7 +1288,7 @@ u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe) if (stainfo != NULL) { int key_idx; const int key_length = 16, iv_len = 8, icv_len = 8; - struct sk_buff *skb = ((struct recv_frame *)precvframe)->pkt; + struct sk_buff *skb = precvframe->pkt; void *crypto_private = NULL; u8 *key, *pframe = skb->data; struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("CCMP"); diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c index 73f2cb5ebaa6cb4da0a7e9007c65e7004b6be20f..3c03141e25b14ee4398b0a2fa11f6184d9345624 100644 --- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c +++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c @@ -112,7 +112,7 @@ u32 _rtw_init_sta_priv(struct sta_priv *pstapriv) inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta) { - int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info); + int offset = (((u8 *)sta) - stapriv->pstainfo_buf) / sizeof(struct sta_info); if (!stainfo_offset_valid(offset)) DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset); diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 6df873e4c2ed7d1b706979f5b2908f725b1d091b..be843fd2461a317935964738638a9ba34ab5c62b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -967,7 +967,7 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) pbuf = rtw_get_wpa_ie(&bssid->ies[12], &wpa_ielen, bssid->ie_length - 12); if (pbuf && (wpa_ielen > 0)) { - if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x)) { + if (rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x) == _SUCCESS) { RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", __func__, pairwise_cipher, group_cipher, is_8021x)); @@ -977,7 +977,7 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) bssid->ie_length - 12); if (pbuf && (wpa_ielen > 0)) { - if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x)) { + if (rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x) == _SUCCESS) { RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_802x is %d\n", __func__, pairwise_cipher, group_cipher, is_8021x)); diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index 258531bc140894d1e57e7cbca1a483f8b2fc0b24..314790fea1ae001215cd9343d8bb070d8b6e7013 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -49,8 +49,8 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) spin_lock_init(&pxmitpriv->lock); /* - Please insert all the queue initializaiton using _rtw_init_queue below - */ + * Please insert all the queue initializaiton using _rtw_init_queue below + */ pxmitpriv->adapter = padapter; @@ -63,10 +63,10 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) _rtw_init_queue(&pxmitpriv->free_xmit_queue); /* - Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME, - and initialize free_xmit_frame below. - Please also apply free_txobj to link_up all the xmit_frames... - */ + * Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME, + * and initialize free_xmit_frame below. + * Please also apply free_txobj to link_up all the xmit_frames... + */ pxmitpriv->pallocated_frame_buf = vzalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4); @@ -124,10 +124,10 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) pxmitbuf->ext_tag = false; /* Tx buf allocation may fail sometimes, so sleep and retry. */ - res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); + res = rtw_os_xmit_resource_alloc(pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); if (res == _FAIL) { msleep(10); - res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); + res = rtw_os_xmit_resource_alloc(pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); if (res == _FAIL) goto exit; } @@ -162,7 +162,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) pxmitbuf->padapter = padapter; pxmitbuf->ext_tag = true; - res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ); + res = rtw_os_xmit_resource_alloc(pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ); if (res == _FAIL) { res = _FAIL; goto exit; @@ -713,13 +713,13 @@ static s32 xmitframe_swencrypt(struct adapter *padapter, struct xmit_frame *pxmi switch (pattrib->encrypt) { case _WEP40_: case _WEP104_: - rtw_wep_encrypt(padapter, (u8 *)pxmitframe); + rtw_wep_encrypt(padapter, pxmitframe); break; case _TKIP_: - rtw_tkip_encrypt(padapter, (u8 *)pxmitframe); + rtw_tkip_encrypt(padapter, pxmitframe); break; case _AES_: - rtw_aes_encrypt(padapter, (u8 *)pxmitframe); + rtw_aes_encrypt(padapter, pxmitframe); break; default: break; @@ -893,17 +893,17 @@ s32 rtw_txframes_sta_ac_pending(struct adapter *padapter, struct pkt_attrib *pat } /* - -This sub-routine will perform all the following: - -1. remove 802.3 header. -2. create wlan_header, based on the info in pxmitframe -3. append sta's iv/ext-iv -4. append LLC -5. move frag chunk from pframe to pxmitframe->mem -6. apply sw-encrypt, if necessary. - -*/ + * + * This sub-routine will perform all the following: + * + * 1. remove 802.3 header. + * 2. create wlan_header, based on the info in pxmitframe + * 3. append sta's iv/ext-iv + * 4. append LLC + * 5. move frag chunk from pframe to pxmitframe->mem + * 6. apply sw-encrypt, if necessary. + * + */ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct xmit_frame *pxmitframe) { s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz; @@ -1233,25 +1233,25 @@ s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) } /* -Calling context: -1. OS_TXENTRY -2. RXENTRY (rx_thread or RX_ISR/RX_CallBack) - -If we turn on USE_RXTHREAD, then, no need for critical section. -Otherwise, we must use _enter/_exit critical to protect free_xmit_queue... - -Must be very very cautious... - -*/ + * Calling context: + * 1. OS_TXENTRY + * 2. RXENTRY (rx_thread or RX_ISR/RX_CallBack) + * + * If we turn on USE_RXTHREAD, then, no need for critical section. + * Otherwise, we must use _enter/_exit critical to protect free_xmit_queue... + * + * Must be very very cautious... + * + */ struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv) /* _queue *pfree_xmit_queue) */ { /* - Please remember to use all the osdep_service api, - and lock/unlock or _enter/_exit critical to protect - pfree_xmit_queue - */ + * Please remember to use all the osdep_service api, + * and lock/unlock or _enter/_exit critical to protect + * pfree_xmit_queue + */ struct xmit_frame *pxframe; struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 740004d71a15871c619494fb651c52462098b1f7..2baef9a285c021ad1c2bb02c5daa4a87e533edaf 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -145,7 +145,7 @@ void rtw_hal_set_odm_var(struct adapter *Adapter, enum hal_odm_variable eVariabl } else { DBG_88E("### Clean STA_(%d) info\n", psta->mac_id); ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, NULL); - } + } } break; case HAL_ODM_P2P_STATE: diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c index 1cf8cff9a2a4d9416ed15e34974ad910b15c3d9f..7badfc2e45df58fdb434f4b4e838018ffc95acf5 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -16,10 +16,10 @@ #include -int rtw_hal_init_recv_priv(struct adapter *padapter) +int rtw_hal_init_recv_priv(struct adapter *padapter) { - struct recv_priv *precvpriv = &padapter->recvpriv; - int i, res = _SUCCESS; + struct recv_priv *precvpriv = &padapter->recvpriv; + int i, res = _SUCCESS; struct recv_buf *precvbuf; tasklet_init(&precvpriv->recv_tasklet, rtl8188eu_recv_tasklet, @@ -33,7 +33,7 @@ int rtw_hal_init_recv_priv(struct adapter *padapter) if (!precvpriv->precv_buf) { res = _FAIL; RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("alloc recv_buf fail!\n")); + ("alloc recv_buf fail!\n")); goto exit; } precvbuf = precvpriv->precv_buf; @@ -54,11 +54,11 @@ int rtw_hal_init_recv_priv(struct adapter *padapter) for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) { pskb = __netdev_alloc_skb(padapter->pnetdev, - MAX_RECVBUF_SZ, GFP_KERNEL); + MAX_RECVBUF_SZ, GFP_KERNEL); if (pskb) { kmemleak_not_leak(pskb); skb_queue_tail(&precvpriv->free_recv_skb_queue, - pskb); + pskb); } pskb = NULL; } @@ -69,9 +69,9 @@ exit: void rtw_hal_free_recv_priv(struct adapter *padapter) { - int i; - struct recv_buf *precvbuf; - struct recv_priv *precvpriv = &padapter->recvpriv; + int i; + struct recv_buf *precvbuf; + struct recv_priv *precvpriv = &padapter->recvpriv; precvbuf = precvpriv->precv_buf; @@ -88,7 +88,7 @@ void rtw_hal_free_recv_priv(struct adapter *padapter) if (skb_queue_len(&precvpriv->free_recv_skb_queue)) DBG_88E(KERN_WARNING "free_recv_skb_queue not empty, %d\n", - skb_queue_len(&precvpriv->free_recv_skb_queue)); + skb_queue_len(&precvpriv->free_recv_skb_queue)); skb_queue_purge(&precvpriv->free_recv_skb_queue); } diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 16a57b31a439145705cde5ba04e0e58ccc6235fb..114638f6f7194256f2bcc8e76dd5d837c2c082ba 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1728,7 +1728,7 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) switch (variable) { case HW_VAR_BASIC_RATE: *((u16 *)(val)) = Adapter->HalData->BasicRateSet; - /* fall through */ + fallthrough; case HW_VAR_TXPAUSE: val[0] = usb_read8(Adapter, REG_TXPAUSE); break; diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 35c0946bc65d7c056e8f71af174f9bde245537b3..0a3acb378d6dc1b3a5f97d7cb52b364bc0a9d277 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -10,7 +10,6 @@ ------------------------------------------------------------------------------*/ - #ifndef __DRV_TYPES_H__ #define __DRV_TYPES_H__ diff --git a/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h b/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h index 0c5b2b0948f54c4b029d72dfea4cced46cd0a92d..a1055ceb7206a3c40143f77244fb9e911c6cfe65 100644 --- a/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h +++ b/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h @@ -7,8 +7,6 @@ #ifndef __INC_HAL8188EPHYCFG_H__ #define __INC_HAL8188EPHYCFG_H__ - -/*--------------------------Define Parameters-------------------------------*/ #define LOOP_LIMIT 5 #define MAX_STALL_TIME 50 /* us */ #define AntennaDiversityValue 0x80 @@ -17,11 +15,6 @@ #define MAX_AGGR_NUM 0x07 - -/*--------------------------Define Parameters-------------------------------*/ - - -/*------------------------------Define structure----------------------------*/ enum sw_chnl_cmd_id { CmdID_End, CmdID_SetTxPowerLevel, @@ -145,22 +138,6 @@ struct bb_reg_def { */ }; -/*------------------------------Define structure----------------------------*/ - - -/*------------------------Export global variable----------------------------*/ -/*------------------------Export global variable----------------------------*/ - - -/*------------------------Export Marco Definition---------------------------*/ -/*------------------------Export Marco Definition---------------------------*/ - - -/*--------------------------Exported Function prototype---------------------*/ -/* */ -/* BB and RF register read/write */ -/* */ - /* Read initi reg value for tx power setting. */ void rtl8192c_PHY_GetHWRegOriginalValue(struct adapter *adapter); @@ -181,8 +158,6 @@ void PHY_EnableHostClkReq(struct adapter *adapter); bool SetAntennaConfig92C(struct adapter *adapter, u8 defaultant); -/*--------------------------Exported Function prototype---------------------*/ - #define PHY_SetMacReg PHY_SetBBReg #define SIC_HW_SUPPORT 0 diff --git a/drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h b/drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h index 5b59c25e4c8a56c026a2e2b9f4d67b2dcef13082..646647feae85036aa02e78ae3b598e5e133ad8e1 100644 --- a/drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h +++ b/drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h @@ -28,24 +28,24 @@ #define GET_TX_RPT2_DESC_PKT_LEN_88E(__pRxStatusDesc) \ LE_BITS_TO_4BYTE(__pRxStatusDesc, 0, 9) #define GET_TX_RPT2_DESC_MACID_VALID_1_88E(__pRxStatusDesc) \ - LE_BITS_TO_4BYTE(__pRxStatusDesc+16, 0, 32) + LE_BITS_TO_4BYTE(__pRxStatusDesc + 16, 0, 32) #define GET_TX_RPT2_DESC_MACID_VALID_2_88E(__pRxStatusDesc) \ - LE_BITS_TO_4BYTE(__pRxStatusDesc+20, 0, 32) + LE_BITS_TO_4BYTE(__pRxStatusDesc + 20, 0, 32) #define GET_TX_REPORT_TYPE1_RERTY_0(__pAddr) \ LE_BITS_TO_4BYTE(__pAddr, 0, 16) #define GET_TX_REPORT_TYPE1_RERTY_1(__pAddr) \ - LE_BITS_TO_1BYTE(__pAddr+2, 0, 8) + LE_BITS_TO_1BYTE(__pAddr + 2, 0, 8) #define GET_TX_REPORT_TYPE1_RERTY_2(__pAddr) \ - LE_BITS_TO_1BYTE(__pAddr+3, 0, 8) + LE_BITS_TO_1BYTE(__pAddr + 3, 0, 8) #define GET_TX_REPORT_TYPE1_RERTY_3(__pAddr) \ - LE_BITS_TO_1BYTE(__pAddr+4, 0, 8) + LE_BITS_TO_1BYTE(__pAddr + 4, 0, 8) #define GET_TX_REPORT_TYPE1_RERTY_4(__pAddr) \ - LE_BITS_TO_1BYTE(__pAddr+4+1, 0, 8) + LE_BITS_TO_1BYTE(__pAddr + 4 + 1, 0, 8) #define GET_TX_REPORT_TYPE1_DROP_0(__pAddr) \ - LE_BITS_TO_1BYTE(__pAddr+4+2, 0, 8) + LE_BITS_TO_1BYTE(__pAddr + 4 + 2, 0, 8) #define GET_TX_REPORT_TYPE1_DROP_1(__pAddr) \ - LE_BITS_TO_1BYTE(__pAddr+4+3, 0, 8) + LE_BITS_TO_1BYTE(__pAddr + 4 + 3, 0, 8) /* End rate adaptive define */ diff --git a/drivers/staging/rtl8188eu/include/hal_com.h b/drivers/staging/rtl8188eu/include/hal_com.h index 93cbbe7ba1fd645a447999d07a9accf93d8b5d58..c2019772bef081fc06577b04c99b4d28f63d4ede 100644 --- a/drivers/staging/rtl8188eu/include/hal_com.h +++ b/drivers/staging/rtl8188eu/include/hal_com.h @@ -81,7 +81,7 @@ #define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M | \ RATR_24M | RATR_36M | RATR_48M | RATR_54M) #define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \ - RATR_MCS3 | RATR_MCS4 | RATR_MCS5|RATR_MCS6 | \ + RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | RATR_MCS6 | \ RATR_MCS7) #define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \ RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \ @@ -137,7 +137,6 @@ #include "HalVerDef.h" void dump_chip_info(struct HAL_VERSION ChipVersion); - /* return the final channel plan decision */ u8 hal_com_get_channel_plan(u8 hw_channel_plan, u8 sw_channel_plan, u8 def_channel_plan, bool load_fail); diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index 75f0ebe0faf56afecc824495b9f5fea63a8470e2..83218e7ec0a9fa2b7b1ccc658fb4e181b09eb249 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -90,7 +90,6 @@ enum { #define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6 #define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7 - #define IEEE_CRYPT_ALG_NAME_LEN 16 #define WPA_CIPHER_NONE BIT(0) @@ -99,8 +98,6 @@ enum { #define WPA_CIPHER_TKIP BIT(3) #define WPA_CIPHER_CCMP BIT(4) - - #define WPA_SELECTOR_LEN 4 extern u8 RTW_WPA_OUI_TYPE[]; extern u8 WPA_AUTH_KEY_MGMT_NONE[]; @@ -113,7 +110,6 @@ extern u8 WPA_CIPHER_SUITE_WRAP[]; extern u8 WPA_CIPHER_SUITE_CCMP[]; extern u8 WPA_CIPHER_SUITE_WEP104[]; - #define RSN_HEADER_LEN 4 #define RSN_SELECTOR_LEN 4 @@ -192,7 +188,6 @@ enum NETWORK_TYPE { #define IsSupportedTxMCS(NetType) \ ((NetType) & (WIRELESS_11_24N | WIRELESS_11_5N) ? true : false) - struct ieee_param { u32 cmd; u8 sta_addr[ETH_ALEN]; @@ -270,11 +265,9 @@ struct sta_data { * WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ - #define IEEE80211_HLEN 30 #define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) - /* this is stolen from ipw2200 driver */ #define IEEE_IBSS_MAC_HASH_SIZE 31 @@ -297,7 +290,6 @@ enum eap_type { #define RTW_IEEE80211_SCTL_FRAG 0x000F #define RTW_IEEE80211_SCTL_SEQ 0xFFF0 - #define RTW_ERP_INFO_NON_ERP_PRESENT BIT(0) #define RTW_ERP_INFO_USE_PROTECTION BIT(1) #define RTW_ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) @@ -354,7 +346,6 @@ struct ieee80211_snap_hdr { #define IEEE80211_CCK_RATE_LEN 4 #define IEEE80211_NUM_OFDM_RATESLEN 8 - #define IEEE80211_CCK_RATE_1MB 0x02 #define IEEE80211_CCK_RATE_2MB 0x04 #define IEEE80211_CCK_RATE_5MB 0x0B @@ -613,7 +604,6 @@ enum rtw_ieee80211_back_parties { #define WME_TSPEC_DIRECTION_DOWNLINK 1 #define WME_TSPEC_DIRECTION_BI_DIRECTIONAL 3 - #define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */ #define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */ @@ -758,7 +748,6 @@ uint rtw_get_rateset_len(u8 *rateset); struct registry_priv; int rtw_generate_ie(struct registry_priv *pregistrypriv); - int rtw_get_bit_value_from_ieee_value(u8 val); bool rtw_is_cckrates_included(u8 *rate); diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h index 9d39fe13626a351e0a9e362505ea3dd0db121eb0..d814ce492424ef0a45bcffa0a593c1f4f7a3fb8c 100644 --- a/drivers/staging/rtl8188eu/include/odm.h +++ b/drivers/staging/rtl8188eu/include/odm.h @@ -5,7 +5,6 @@ * ******************************************************************************/ - #ifndef __HALDMOUTSRC_H__ #define __HALDMOUTSRC_H__ @@ -41,7 +40,6 @@ #define DPK_DELTA_MAPPING_NUM 13 #define index_mapping_HP_NUM 15 - /* */ /* 3 PSD Handler */ /* 3============================================================ */ @@ -244,7 +242,7 @@ struct odm_rate_adapt { #define AVG_THERMAL_NUM 8 #define IQK_Matrix_REG_NUM 8 -#define IQK_Matrix_Settings_NUM 1+24+21 +#define IQK_Matrix_Settings_NUM (1 + 24 + 21) #define DM_Type_ByFWi 0 #define DM_Type_ByDriver 1 @@ -913,7 +911,6 @@ enum dm_dig_op { #define DM_SCAN_RSSI_TH 0x14 /* scan return issue for LC */ - #define DM_false_ALARM_THRESH_LOW 400 #define DM_false_ALARM_THRESH_HIGH 1000 @@ -991,7 +988,6 @@ enum dm_dig_op { /* 3 BB Power Save */ /* 3=========================================================== */ - enum dm_1r_cca { CCA_1R = 0, CCA_2R = 1, diff --git a/drivers/staging/rtl8188eu/include/odm_debug.h b/drivers/staging/rtl8188eu/include/odm_debug.h index 7ab2483bdacc039994617495d4615139528ecbb6..857c64b8d2f4ee7d3e7f04702a9b62ece6fa15e9 100644 --- a/drivers/staging/rtl8188eu/include/odm_debug.h +++ b/drivers/staging/rtl8188eu/include/odm_debug.h @@ -5,11 +5,9 @@ * ******************************************************************************/ - #ifndef __ODM_DBG_H__ #define __ODM_DBG_H__ - /* */ /* Define the debug levels */ /* */ diff --git a/drivers/staging/rtl8188eu/include/odm_types.h b/drivers/staging/rtl8188eu/include/odm_types.h index 7255f7afff7a35e74c6bdbc4d35e9ba0d4dc313b..2b207f09b56b5021b7558edfdc353b3d1354eaa5 100644 --- a/drivers/staging/rtl8188eu/include/odm_types.h +++ b/drivers/staging/rtl8188eu/include/odm_types.h @@ -15,10 +15,10 @@ enum HAL_STATUS { }; #define SET_TX_DESC_ANTSEL_A_88E(__pTxDesc, __Value) \ - SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 24, 1, __Value) + SET_BITS_TO_LE_4BYTE(__pTxDesc + 8, 24, 1, __Value) #define SET_TX_DESC_ANTSEL_B_88E(__pTxDesc, __Value) \ - SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 25, 1, __Value) + SET_BITS_TO_LE_4BYTE(__pTxDesc + 8, 25, 1, __Value) #define SET_TX_DESC_ANTSEL_C_88E(__pTxDesc, __Value) \ - SET_BITS_TO_LE_4BYTE(__pTxDesc+28, 29, 1, __Value) + SET_BITS_TO_LE_4BYTE(__pTxDesc + 28, 29, 1, __Value) #endif /* __ODM_TYPES_H__ */ diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index 0d3e4a6e7e8559bd11553a6b7ee335b1ce70a94c..b44d602e954a194e4b65a55f438e5b5122964f71 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -71,8 +71,11 @@ struct rtw_netdev_priv_indicator { }; struct net_device *rtw_alloc_etherdev_with_old_priv(void *old_priv); -#define rtw_netdev_priv(netdev) \ - (((struct rtw_netdev_priv_indicator *)netdev_priv(netdev))->priv) +static inline struct adapter *rtw_netdev_priv(struct net_device *netdev) +{ + return ((struct rtw_netdev_priv_indicator *)netdev_priv(netdev))->priv; +} + void rtw_free_netdev(struct net_device *netdev); #define FUNC_NDEV_FMT "%s(%s)" @@ -82,7 +85,7 @@ void rtw_free_netdev(struct net_device *netdev); /* Macros for handling unaligned memory accesses */ -#define RTW_GET_BE24(a) ((((u32)(a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ +#define RTW_GET_BE24(a) ((((u32)(a)[0]) << 16) | (((u32)(a)[1]) << 8) | \ ((u32)(a)[2])) void rtw_buf_free(u8 **buf, u32 *buf_len); diff --git a/drivers/staging/rtl8188eu/include/pwrseq.h b/drivers/staging/rtl8188eu/include/pwrseq.h index aa58db5fbd80877433a8216e44c7d08b604055ad..c4b76064476f5d759d79cdedaa1789485f060463 100644 --- a/drivers/staging/rtl8188eu/include/pwrseq.h +++ b/drivers/staging/rtl8188eu/include/pwrseq.h @@ -43,7 +43,6 @@ #define RTL8188E_TRANS_LPS_TO_ACT_STEPS 15 #define RTL8188E_TRANS_END_STEPS 1 - #define RTL8188E_TRANS_CARDEMU_TO_ACT \ /* format * { offset, cut_msk, cmd, msk, value @@ -179,7 +178,6 @@ {0x0553, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(5), BIT(5)}, \ /*Respond TxOK to scheduler*/ - #define RTL8188E_TRANS_LPS_TO_ACT \ /* format * { offset, cut_msk, cmd, msk, @@ -213,7 +211,6 @@ */ \ {0xFFFF, PWR_CUT_ALL_MSK, PWR_CMD_END, 0, 0}, - extern struct wl_pwr_cfg rtl8188E_power_on_flow [RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS + RTL8188E_TRANS_END_STEPS]; extern struct wl_pwr_cfg rtl8188E_radio_off_flow diff --git a/drivers/staging/rtl8188eu/include/pwrseqcmd.h b/drivers/staging/rtl8188eu/include/pwrseqcmd.h index 8c73322a03141ed9d9b5af29833f19da68b3052c..05f117e2a1057dc5b3f6f0629e1aedfe72473033 100644 --- a/drivers/staging/rtl8188eu/include/pwrseqcmd.h +++ b/drivers/staging/rtl8188eu/include/pwrseqcmd.h @@ -27,7 +27,6 @@ #define PWR_CUT_G_MSK BIT(7) #define PWR_CUT_ALL_MSK 0xFF - enum pwrseq_cmd_delat_unit { PWRSEQ_DELAY_US, PWRSEQ_DELAY_MS, diff --git a/drivers/staging/rtl8188eu/include/recv_osdep.h b/drivers/staging/rtl8188eu/include/recv_osdep.h index d2341521cc8e5d3a16f572aa8eee795c5f32f7c4..3b771702810dfa7982c37efd8418daac449413c5 100644 --- a/drivers/staging/rtl8188eu/include/recv_osdep.h +++ b/drivers/staging/rtl8188eu/include/recv_osdep.h @@ -10,11 +10,9 @@ #include #include - int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter); void _rtw_free_recv_priv(struct recv_priv *precvpriv); - s32 rtw_recv_entry(struct recv_frame *precv_frame); int rtw_recv_indicatepkt(struct adapter *adapter, struct recv_frame *recv_frame); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index eb4655ecf6e0cbde06c47720c5fd3a175d49454e..6035c12ec5785f04893bfcf20f83066e6e74833a 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -7,7 +7,6 @@ #ifndef __RTL8188E_HAL_H__ #define __RTL8188E_HAL_H__ - /* include HAL Related header after HAL Related compiling flags */ #include "rtl8188e_spec.h" #include "hal8188e_phy_reg.h" @@ -46,7 +45,7 @@ #define Rtl8188E_NIC_LPS_LEAVE_FLOW rtl8188E_leave_lps_flow #define DRVINFO_SZ 4 /* unit is 8bytes */ -#define PageNum_128(_Len) (u32)(((_Len)>>7) + ((_Len) & 0x7F ? 1 : 0)) +#define PageNum_128(_Len) (u32)(((_Len) >> 7) + ((_Len) & 0x7F ? 1 : 0)) /* download firmware related data structure */ #define FW_8188E_SIZE 0x4000 /* 16384,16k */ @@ -55,11 +54,11 @@ #define MAX_PAGE_SIZE 4096 /* @ page : 4k bytes */ -#define IS_FW_HEADER_EXIST(_pFwHdr) \ - ((le16_to_cpu(_pFwHdr->signature)&0xFFF0) == 0x92C0 || \ - (le16_to_cpu(_pFwHdr->signature)&0xFFF0) == 0x88C0 || \ - (le16_to_cpu(_pFwHdr->signature)&0xFFF0) == 0x2300 || \ - (le16_to_cpu(_pFwHdr->signature)&0xFFF0) == 0x88E0) +#define IS_FW_HEADER_EXIST(_pFwHdr) \ + ((le16_to_cpu(_pFwHdr->signature) & 0xFFF0) == 0x92C0 || \ + (le16_to_cpu(_pFwHdr->signature) & 0xFFF0) == 0x88C0 || \ + (le16_to_cpu(_pFwHdr->signature) & 0xFFF0) == 0x2300 || \ + (le16_to_cpu(_pFwHdr->signature) & 0xFFF0) == 0x88E0) #define DRIVER_EARLY_INT_TIME 0x05 #define BCN_DMA_ATIME_INT_TIME 0x02 @@ -78,7 +77,6 @@ enum usb_rx_agg_mode { #define MAX_TX_REPORT_BUFFER_SIZE 0x0400 /* 1k */ - /* BK, BE, VI, VO, HCCA, MANAGEMENT, COMMAND, HIGH, BEACON. */ #define MAX_TX_QUEUE 9 @@ -106,7 +104,7 @@ enum usb_rx_agg_mode { (WMM_NORMAL_TX_TOTAL_PAGE_NUMBER + 1) /* 0xA9 */ /* Chip specific */ -#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) +#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3) #define CHIP_BONDING_92C_1T2R 0x1 #define CHIP_BONDING_88C_USB_MCARD 0x2 #define CHIP_BONDING_88C_USB_HP 0x1 @@ -246,7 +244,6 @@ struct hal_data_8188e { u8 CurrentBW2024GTxPwrIdx; u8 CurrentBW4024GTxPwrIdx; - /* Read/write are allow for following hardware information variables */ u8 framesync; u32 framesyncC34; @@ -285,7 +282,6 @@ struct hal_data_8188e { u8 AntDivCfg; u8 TRxAntDivType; - u8 bDumpRxPkt;/* for debug */ u8 bDumpTxPkt;/* for debug */ u8 FwRsvdPageStartOffset; /* Reserve page start offset except @@ -335,7 +331,6 @@ void Hal_GetChnlGroup88E(u8 chnl, u8 *group); void _8051Reset88E(struct adapter *padapter); void rtl8188e_InitializeFirmwareVars(struct adapter *padapter); - s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy); /* EFuse */ diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h index be30c9434a29ceee09dae04df69b29042c5fc22e..55cce1f6bd7738a0805141fa884dca21578d76d2 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h @@ -18,7 +18,6 @@ #define RXPKT_BUF_SELECT 0xA5 #define DISABLE_TRXPKT_BUF_ACCESS 0x0 - /* 0x0000h ~ 0x00FFh System Configuration */ #define REG_SYS_ISO_CTRL 0x0000 #define REG_SYS_FUNC_EN 0x0002 diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h index c6c2ad20d9cfc5cd6ada09602fddd2d203e68a9c..85efa41c83504e1e88b0eea10eb34850f8e61ebc 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h @@ -30,11 +30,11 @@ #define SET_EARLYMODE_LEN2_1(__pAddr, __Value) \ SET_BITS_TO_LE_4BYTE(__pAddr, 28, 4, __Value) #define SET_EARLYMODE_LEN2_2(__pAddr, __Value) \ - SET_BITS_TO_LE_4BYTE(__pAddr+4, 0, 8, __Value) + SET_BITS_TO_LE_4BYTE(__pAddr + 4, 0, 8, __Value) #define SET_EARLYMODE_LEN3(__pAddr, __Value) \ - SET_BITS_TO_LE_4BYTE(__pAddr+4, 8, 12, __Value) + SET_BITS_TO_LE_4BYTE(__pAddr + 4, 8, 12, __Value) #define SET_EARLYMODE_LEN4(__pAddr, __Value) \ - SET_BITS_TO_LE_4BYTE(__pAddr+4, 20, 12, __Value) + SET_BITS_TO_LE_4BYTE(__pAddr + 4, 20, 12, __Value) /* */ /* defined for TX DESC Operation */ @@ -50,7 +50,6 @@ #define FSG BIT(27) #define OWN BIT(31) - /* OFFSET 4 */ #define PKT_OFFSET_SZ 0 #define QSEL_SHT 8 @@ -101,7 +100,7 @@ enum TXDESC_SC { #define txdesc_set_ccx_sw_88e(txdesc, value) \ do { \ - ((struct txdesc_88e *)(txdesc))->sw1 = (((value)>>8) & 0x0f); \ + ((struct txdesc_88e *)(txdesc))->sw1 = (((value) >> 8) & 0x0f); \ ((struct txdesc_88e *)(txdesc))->sw0 = ((value) & 0xff); \ } while (0) @@ -139,9 +138,9 @@ struct txrpt_ccx_88e { u8 sw0; }; -#define txrpt_ccx_sw_88e(txrpt_ccx) ((txrpt_ccx)->sw0 + ((txrpt_ccx)->sw1<<8)) +#define txrpt_ccx_sw_88e(txrpt_ccx) ((txrpt_ccx)->sw0 + ((txrpt_ccx)->sw1 << 8)) #define txrpt_ccx_qtime_88e(txrpt_ccx) \ - ((txrpt_ccx)->ccx_qtime0+((txrpt_ccx)->ccx_qtime1<<8)) + ((txrpt_ccx)->ccx_qtime0 + ((txrpt_ccx)->ccx_qtime1 << 8)) void rtl8188e_fill_fake_txdesc(struct adapter *padapter, u8 *pDesc, u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull); diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h index fa5e212fc9e0f1aedf6f01d0e99e1f4a7fd68bd3..002a797c6d0a7447f7453b4f2af22cc65168e3a7 100644 --- a/drivers/staging/rtl8188eu/include/rtw_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtw_cmd.h @@ -115,7 +115,7 @@ struct setopmode_parm { */ #define RTW_SSID_SCAN_AMOUNT 9 /* for WEXT_CSCAN_AMOUNT 9 */ -#define RTW_CHANNEL_SCAN_AMOUNT (14+37) +#define RTW_CHANNEL_SCAN_AMOUNT (14 + 37) struct sitesurvey_parm { int scan_mode; /* active: 1, passive: 0 */ u8 ssid_num; diff --git a/drivers/staging/rtl8188eu/include/rtw_debug.h b/drivers/staging/rtl8188eu/include/rtw_debug.h index 9840e596feaa8a4979a2e946d6d33ec6f388caee..1fdf16124a0d5803b1f016f78e6056a74214bd16 100644 --- a/drivers/staging/rtl8188eu/include/rtw_debug.h +++ b/drivers/staging/rtl8188eu/include/rtw_debug.h @@ -21,7 +21,6 @@ #define _drv_info_ 8 #define _drv_debug_ 9 - #define _module_rtl871x_xmit_c_ BIT(0) #define _module_xmit_osdep_c_ BIT(1) #define _module_rtl871x_recv_c_ BIT(2) diff --git a/drivers/staging/rtl8188eu/include/rtw_efuse.h b/drivers/staging/rtl8188eu/include/rtw_efuse.h index 7a9c8ff0daa976931ca57bbaf975ed059b615298..5926fc9b5e6b85cc8dfe32b1b4e79e80d8be2ce9 100644 --- a/drivers/staging/rtl8188eu/include/rtw_efuse.h +++ b/drivers/staging/rtl8188eu/include/rtw_efuse.h @@ -44,7 +44,7 @@ /* The following is for BT Efuse definition */ #define EFUSE_BT_MAX_MAP_LEN 1024 #define EFUSE_MAX_BANK 4 -#define EFUSE_MAX_BT_BANK (EFUSE_MAX_BANK-1) +#define EFUSE_MAX_BT_BANK (EFUSE_MAX_BANK - 1) /*--------------------------Define Parameters-------------------------------*/ #define EFUSE_MAX_WORD_UNIT 4 diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl.h b/drivers/staging/rtl8188eu/include/rtw_ioctl.h index 5d773c84f11bf54d24f542ff142e36fe3a8fe112..f681f9ebeafe2ed713c6b11ca4f1d39a5b71e8e2 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ioctl.h +++ b/drivers/staging/rtl8188eu/include/rtw_ioctl.h @@ -10,7 +10,6 @@ #include #include - #ifndef OID_802_11_CAPABILITY #define OID_802_11_CAPABILITY 0x0d010122 #endif @@ -19,7 +18,6 @@ #define OID_802_11_PMKID 0x0d010123 #endif - /* For DDK-defined OIDs */ #define OID_NDIS_SEG1 0x00010100 #define OID_NDIS_SEG2 0x00010200 diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h b/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h index 0be99f6d75ba4c9a80d4b1d9597a55ca4ef1cd64..7078f8252fa082188e9d3532a64abfab4ee57d85 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h +++ b/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h @@ -9,7 +9,6 @@ #include - typedef u8 NDIS_802_11_PMKID_VALUE[16]; u8 rtw_set_802_11_authentication_mode(struct adapter *adapt, diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index d70780c8fd621e88b2aa6f37789732fd419d349b..565bfe46256cb4e0d8e7166ab4fc61bc106668c8 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -11,7 +11,6 @@ #include #include - /* Commented by Albert 20101105 */ /* Increase the SURVEY_TO value from 100 to 150 ( 100ms to 150ms ) */ /* The Realtek 8188CE SoftAP will spend around 100ms to send the probe response after receiving the probe request. */ @@ -66,7 +65,6 @@ #define _HW_STATE_STATION_ 0x02 #define _HW_STATE_AP_ 0x03 - #define _1M_RATE_ 0 #define _2M_RATE_ 1 #define _5M_RATE_ 2 @@ -681,7 +679,6 @@ enum rtw_c2h_event { MAX_C2HEVT }; - #ifdef _RTW_MLME_EXT_C_ static struct fwevent wlanevents[] = { diff --git a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h index 404634999e35481bf61a7db81970bcfabe3713ac..06062643c868c34531be1c616f96fb660811cbb4 100644 --- a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h +++ b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h @@ -84,7 +84,7 @@ struct reportpwrstate_parm { unsigned short rsvd; }; -#define LPS_DELAY_TIME 1*HZ /* 1 sec */ +#define LPS_DELAY_TIME 1 * HZ /* 1 sec */ #define EXE_PWR_NONE 0x01 #define EXE_PWR_IPS 0x02 diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index 8fc500496f922e071eb74abe8458c3cbdc94f8f0..b281b9e7fcea0656db33198390bbe5c16dfc053a 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -10,11 +10,10 @@ #include #include - #define NR_RECVFRAME 256 #define RXFRAME_ALIGN 8 -#define RXFRAME_ALIGN_SZ (1<>(32-(n))) & ((1UL << (n)) - 1))) -#define ROR32(A, n) ROL32((A), 32-(n)) +#define ROL32(A, n) (((A) << (n)) | (((A) >> (32 - (n))) & ((1UL << (n)) - 1))) +#define ROR32(A, n) ROL32((A), 32 - (n)) struct mic_data { u32 K0, K1; /* Key */ @@ -278,12 +275,12 @@ static const unsigned long K[64] = { /* Various logical functions */ #define RORc(x, y) \ - (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y)&31)) | \ - ((unsigned long)(x) << (unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) + (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \ + ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL) #define Ch(x, y, z) (z ^ (x & (y ^ z))) #define Maj(x, y, z) (((x | y) & z) | (x & y)) #define S(x, n) RORc((x), (n)) -#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define R(x, n) (((x) & 0xFFFFFFFFUL) >> (n)) #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) @@ -295,11 +292,11 @@ void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nBytes); void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst); void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *Miccode, u8 priority); -u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe); -u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe); -void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe); -u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe); -u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe); -int rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe); +u32 rtw_aes_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe); +u32 rtw_tkip_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe); +void rtw_wep_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe); +u32 rtw_aes_decrypt(struct adapter *padapter, struct recv_frame *precvframe); +u32 rtw_tkip_decrypt(struct adapter *padapter, struct recv_frame *precvframe); +int rtw_wep_decrypt(struct adapter *padapter, struct recv_frame *precvframe); #endif /* __RTL871X_SECURITY_H_ */ diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/rtl8188eu/include/rtw_xmit.h index b9f11ef327e75a68219d63ab1324766501c88c4e..456fd52717f355d4fd278c478ca00e6eec7f390a 100644 --- a/drivers/staging/rtl8188eu/include/rtw_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtw_xmit.h @@ -42,22 +42,21 @@ do {\ pattrib_iv[0] = dot11txpn._byte_.TSC0;\ pattrib_iv[1] = dot11txpn._byte_.TSC1;\ pattrib_iv[2] = dot11txpn._byte_.TSC2;\ - pattrib_iv[3] = ((keyidx & 0x3)<<6);\ - dot11txpn.val = (dot11txpn.val == 0xffffff) ? 0 : (dot11txpn.val+1);\ + pattrib_iv[3] = ((keyidx & 0x3) << 6);\ + dot11txpn.val = (dot11txpn.val == 0xffffff) ? 0 : (dot11txpn.val + 1);\ } while (0) - #define TKIP_IV(pattrib_iv, dot11txpn, keyidx)\ do {\ pattrib_iv[0] = dot11txpn._byte_.TSC1;\ pattrib_iv[1] = (dot11txpn._byte_.TSC1 | 0x20) & 0x7f;\ pattrib_iv[2] = dot11txpn._byte_.TSC0;\ - pattrib_iv[3] = BIT(5) | ((keyidx & 0x3)<<6);\ + pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6);\ pattrib_iv[4] = dot11txpn._byte_.TSC2;\ pattrib_iv[5] = dot11txpn._byte_.TSC3;\ pattrib_iv[6] = dot11txpn._byte_.TSC4;\ pattrib_iv[7] = dot11txpn._byte_.TSC5;\ - dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val+1);\ + dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val + 1);\ } while (0) #define AES_IV(pattrib_iv, dot11txpn, keyidx)\ @@ -65,12 +64,12 @@ do { \ pattrib_iv[0] = dot11txpn._byte_.TSC0; \ pattrib_iv[1] = dot11txpn._byte_.TSC1; \ pattrib_iv[2] = 0; \ - pattrib_iv[3] = BIT(5) | ((keyidx & 0x3)<<6); \ + pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6); \ pattrib_iv[4] = dot11txpn._byte_.TSC2; \ pattrib_iv[5] = dot11txpn._byte_.TSC3; \ pattrib_iv[6] = dot11txpn._byte_.TSC4; \ pattrib_iv[7] = dot11txpn._byte_.TSC5; \ - dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val+1);\ + dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val + 1);\ } while (0) #define HWXMIT_ENTRY 4 @@ -194,14 +193,9 @@ struct xmit_buf { void *priv_data; u16 ext_tag; /* 0: Normal xmitbuf, 1: extension xmitbuf. */ u16 flags; - u32 alloc_sz; u32 len; struct submit_ctx *sctx; - u32 ff_hwaddr; struct urb *pxmit_urb[8]; - dma_addr_t dma_transfer_addr; /* (in) dma addr for transfer_buffer */ - u8 bpending[8]; - int last[8]; }; struct xmit_frame { diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index d059240b836f64d5270edc18667447f6a3243bfa..217be809b937c380010dd83bae913645052b4924 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -35,7 +35,7 @@ enum WIFI_FRAME_TYPE { WIFI_MGT_TYPE = (0), WIFI_CTRL_TYPE = (BIT(2)), WIFI_DATA_TYPE = (BIT(3)), - WIFI_QOS_DATA_TYPE = (BIT(7)|BIT(3)), /* QoS Data */ + WIFI_QOS_DATA_TYPE = (BIT(7) | BIT(3)), /* QoS Data */ }; enum WIFI_FRAME_SUBTYPE { @@ -160,7 +160,6 @@ enum WIFI_REG_DOMAIN { #define get_tofr_ds(pframe) ((GetToDs(pframe) << 1) | GetFrDs(pframe)) - #define SetMFrag(pbuf) \ *(__le16 *)(pbuf) |= cpu_to_le16(_MORE_FRAG_) @@ -231,7 +230,6 @@ enum WIFI_REG_DOMAIN { #define SetDuration(pbuf, dur) \ *(__le16 *)((size_t)(pbuf) + 2) = cpu_to_le16(0xffff & (dur)) - #define SetPriority(pbuf, tid) \ *(__le16 *)(pbuf) |= cpu_to_le16(tid & 0xf) @@ -384,7 +382,6 @@ static inline int IsFrameTypeCtrl(unsigned char *pframe) #define _HT_ADD_INFO_IE_ 61 /* _HT_EXTRA_INFO_IE_ */ #define _WAPI_IE_ 68 - #define EID_BSSCoexistence 72 /* 20/40 BSS Coexistence */ #define EID_BSSIntolerantChlReport 73 #define _RIC_Descriptor_IE_ 75 @@ -452,15 +449,10 @@ static inline int IsFrameTypeCtrl(unsigned char *pframe) #define _WMM_IE_Length_ 7 /* for WMM STA */ #define _WMM_Para_Element_Length_ 24 - /*----------------------------------------------------------------------------- Below is the definition for 802.11n ------------------------------------------------------------------------------*/ -/* 802.11 BAR control masks */ -#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 -#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 - /** * struct rtw_ieee80211_ht_cap - HT additional information * @@ -507,53 +499,6 @@ enum ht_cap_ampdu_factor { MAX_AMPDU_FACTOR_64K = 3, }; -/* 802.11n HT capabilities masks */ -#define IEEE80211_HT_CAP_SUP_WIDTH 0x0002 -#define IEEE80211_HT_CAP_SM_PS 0x000C -#define IEEE80211_HT_CAP_GRN_FLD 0x0010 -#define IEEE80211_HT_CAP_SGI_20 0x0020 -#define IEEE80211_HT_CAP_SGI_40 0x0040 -#define IEEE80211_HT_CAP_TX_STBC 0x0080 -#define IEEE80211_HT_CAP_RX_STBC 0x0300 -#define IEEE80211_HT_CAP_DELAY_BA 0x0400 -#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 -#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 -/* 802.11n HT capability AMPDU settings */ -#define IEEE80211_HT_CAP_AMPDU_FACTOR 0x03 -#define IEEE80211_HT_CAP_AMPDU_DENSITY 0x1C -/* 802.11n HT capability MSC set */ -#define IEEE80211_SUPP_MCS_SET_UEQM 4 -#define IEEE80211_HT_CAP_MAX_STREAMS 4 -#define IEEE80211_SUPP_MCS_SET_LEN 10 -/* maximum streams the spec allows */ -#define IEEE80211_HT_CAP_MCS_TX_DEFINED 0x01 -#define IEEE80211_HT_CAP_MCS_TX_RX_DIFF 0x02 -#define IEEE80211_HT_CAP_MCS_TX_STREAMS 0x0C -#define IEEE80211_HT_CAP_MCS_TX_UEQM 0x10 -/* 802.11n HT IE masks */ -#define IEEE80211_HT_IE_CHA_SEC_OFFSET 0x03 -#define IEEE80211_HT_IE_CHA_SEC_NONE 0x00 -#define IEEE80211_HT_IE_CHA_SEC_ABOVE 0x01 -#define IEEE80211_HT_IE_CHA_SEC_BELOW 0x03 -#define IEEE80211_HT_IE_CHA_WIDTH 0x04 -#define IEEE80211_HT_IE_HT_PROTECTION 0x0003 -#define IEEE80211_HT_IE_NON_GF_STA_PRSNT 0x0004 -#define IEEE80211_HT_IE_NON_HT_STA_PRSNT 0x0010 - -/* block-ack parameters */ -#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 -#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C -#define RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFC0 -#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 -#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 - -/* - * A-PMDU buffer sizes - * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) - */ -#define IEEE80211_MIN_AMPDU_BUF 0x8 - - #define OP_MODE_PURE 0 #define OP_MODE_MAY_BE_LEGACY_STAS 1 #define OP_MODE_20MHZ_HT_STA_ASSOCED 2 diff --git a/drivers/staging/rtl8188eu/include/wlan_bssdef.h b/drivers/staging/rtl8188eu/include/wlan_bssdef.h index 8462c9c2fd391ec0c0a470208c7fb5fa4b814b7d..2c184ce8746b7713e665b3db083351b2965b95e0 100644 --- a/drivers/staging/rtl8188eu/include/wlan_bssdef.h +++ b/drivers/staging/rtl8188eu/include/wlan_bssdef.h @@ -7,7 +7,6 @@ #ifndef __WLAN_BSSDEF_H__ #define __WLAN_BSSDEF_H__ - #define MAX_IE_SZ 768 #define NDIS_802_11_LENGTH_SSID 32 @@ -62,8 +61,6 @@ struct ndis_802_11_fixed_ie { u16 Capabilities; }; - - struct ndis_802_11_var_ie { u8 ElementID; u8 Length; @@ -149,7 +146,7 @@ enum ndis_802_11_status_type { #define MIC_CHECK_TIME 60000000 #ifndef Ndis802_11APMode -#define Ndis802_11APMode (Ndis802_11InfrastructureMax+1) +#define Ndis802_11APMode (Ndis802_11InfrastructureMax + 1) #endif struct wlan_phy_info { diff --git a/drivers/staging/rtl8188eu/include/xmit_osdep.h b/drivers/staging/rtl8188eu/include/xmit_osdep.h index 5283a6d537005f69ddc0b9a7d24365b5cd41d897..5fd8ca51f1563020143f554a88ea09268deb6474 100644 --- a/drivers/staging/rtl8188eu/include/xmit_osdep.h +++ b/drivers/staging/rtl8188eu/include/xmit_osdep.h @@ -22,8 +22,7 @@ int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev); void rtw_os_xmit_schedule(struct adapter *padapter); -int rtw_os_xmit_resource_alloc(struct adapter *padapter, - struct xmit_buf *pxmitbuf, u32 alloc_sz); +int rtw_os_xmit_resource_alloc(struct xmit_buf *pxmitbuf, u32 alloc_sz); void rtw_os_xmit_resource_free(struct xmit_buf *pxmitbuf); void rtw_os_pkt_complete(struct adapter *padapter, struct sk_buff *pkt); diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index d5968ef9f43d73ae15ff85adcb3b46c0c1552662..2e83d24fcb094c6218c6a53e0bad55bc7f108e9c 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -120,7 +120,7 @@ static char *translate_scan(struct adapter *padapter, start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid); /* parsing HT_CAP_IE */ - p = rtw_get_ie(&pnetwork->network.ies[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.ie_length-12); + p = rtw_get_ie(&pnetwork->network.ies[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.ie_length - 12); if (p && ht_ielen > 0) { struct ieee80211_ht_cap *pht_capie; @@ -129,7 +129,7 @@ static char *translate_scan(struct adapter *padapter, pht_capie = (struct ieee80211_ht_cap *)(p + 2); memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2); bw_40MHz = !!(le16_to_cpu(pht_capie->cap_info) & - IEEE80211_HT_CAP_SUP_WIDTH); + IEEE80211_HT_CAP_SUP_WIDTH_20_40); short_GI = !!(le16_to_cpu(pht_capie->cap_info) & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)); @@ -195,7 +195,7 @@ static char *translate_scan(struct adapter *padapter, p = custom; p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): "); while (pnetwork->network.SupportedRates[i] != 0) { - rate = pnetwork->network.SupportedRates[i]&0x7F; + rate = pnetwork->network.SupportedRates[i] & 0x7F; if (rate > max_rate) max_rate = rate; p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), @@ -204,14 +204,14 @@ static char *translate_scan(struct adapter *padapter, } if (ht_cap) { - if (mcs_rate&0x8000)/* MCS15 */ + if (mcs_rate & 0x8000)/* MCS15 */ max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130); - else if (mcs_rate&0x0080)/* MCS7 */ + else if (mcs_rate & 0x0080)/* MCS7 */ ; else/* default MCS7 */ max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65); - max_rate = max_rate*2;/* Mbps/2; */ + max_rate *= 2; /* Mbps/2; */ } iwe.cmd = SIOCGIWRATE; @@ -284,7 +284,7 @@ static char *translate_scan(struct adapter *padapter, iwe.u.data.length = (u16)wps_ielen; start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr); } - cnt += ie_ptr[cnt+1]+2; /* goto next */ + cnt += ie_ptr[cnt + 1] + 2; /* goto next */ } } @@ -512,7 +512,7 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie DBG_88E("\n wpa_ie(length:%d):\n", ielen); for (i = 0; i < ielen; i += 8) - DBG_88E("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]); + DBG_88E("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]); } if (ielen < RSN_HEADER_LEN) { @@ -586,7 +586,7 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie while (cnt < ielen) { eid = buf[cnt]; - if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt+2], wps_oui, 4))) { + if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt + 2], wps_oui, 4))) { DBG_88E("SET WPS_IE\n"); padapter->securitypriv.wps_ie_len = min(buf[cnt + 1] + 2, MAX_WPA_IE_LEN << 2); @@ -594,10 +594,10 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len); set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS); - cnt += buf[cnt+1]+2; + cnt += buf[cnt + 1] + 2; break; } - cnt += buf[cnt+1]+2; /* goto next */ + cnt += buf[cnt + 1] + 2; /* goto next */ } } } @@ -628,7 +628,7 @@ static int rtw_wx_get_name(struct net_device *dev, if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) { /* parsing HT_CAP_IE */ - p = rtw_get_ie(&pcur_bss->ies[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->ie_length-12); + p = rtw_get_ie(&pcur_bss->ies[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->ie_length - 12); if (p && ht_ielen > 0) ht_cap = true; @@ -782,7 +782,7 @@ static int rtw_wx_set_pmkid(struct net_device *dev, DBG_88E("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n"); memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN); psecuritypriv->PMKIDList[j].bUsed = true; - psecuritypriv->PMKIDIndex = j+1; + psecuritypriv->PMKIDIndex = j + 1; blInserted = true; break; } @@ -811,7 +811,7 @@ static int rtw_wx_set_pmkid(struct net_device *dev, psecuritypriv->PMKIDList[j].bUsed = false; break; } - } + } } else if (pPMK->cmd == IW_PMKSA_FLUSH) { DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n"); memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); @@ -1093,7 +1093,7 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a, goto exit; } - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) { + if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) { indicate_wx_scan_complete_event(padapter); goto exit; } @@ -1102,7 +1102,7 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a, /* the pmlmepriv->scan_interval is always equal to 3. */ /* So, the wpa_supplicant won't find out the WPS SoftAP. */ - memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT); + memset(ssid, 0, sizeof(struct ndis_802_11_ssid) * RTW_SSID_SCAN_AMOUNT); if (wrqu->data.length == sizeof(struct iw_scan_req)) { struct iw_scan_req *req = (struct iw_scan_req *)extra; @@ -1128,7 +1128,7 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a, if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE && !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) { int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE; - char *pos = extra+WEXT_CSCAN_HEADER_SIZE; + char *pos = extra + WEXT_CSCAN_HEADER_SIZE; char section; char sec_len; int ssid_index = 0; @@ -1239,7 +1239,7 @@ static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - wrqu->data.length = ev-extra; + wrqu->data.length = ev - extra; wrqu->data.flags = 0; exit: @@ -1395,7 +1395,7 @@ static int rtw_wx_set_rate(struct net_device *dev, ratevalue = 11; goto set_rate; } - target_rate = target_rate/100000; + target_rate /= 100000; switch (target_rate) { case 10: @@ -1890,7 +1890,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)) param->u.crypt.set_tx = 0; - param->u.crypt.idx = (pencoding->flags&0x00FF) - 1; + param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1; if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) memcpy(param->u.crypt.seq, pext->rx_seq, 8); @@ -1935,7 +1935,7 @@ static int wpa_set_param(struct net_device *dev, u8 name, u32 value) switch (name) { case IEEE_PARAM_WPA_ENABLED: padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */ - switch ((value)&0xff) { + switch (value & 0xff) { case 1: /* WPA */ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled; @@ -2407,7 +2407,7 @@ static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0)) pstapriv->max_num_sta = NUM_STA; - if (rtw_check_beacon_data(padapter, pbuf, (len-12-2)) == _SUCCESS)/* 12 = param header, 2:no packed */ + if (rtw_check_beacon_data(padapter, pbuf, len - 12 - 2) == _SUCCESS) /* 12 = param header, 2:no packed */ ret = 0; else ret = -EINVAL; @@ -2436,7 +2436,7 @@ static int rtw_add_sta(struct net_device *dev, struct ieee_param *param) DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr)); - if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE))) + if (!check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE))) return -EINVAL; if (is_broadcast_ether_addr(param->sta_addr)) @@ -2451,7 +2451,7 @@ static int rtw_add_sta(struct net_device *dev, struct ieee_param *param) memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16); /* check wmm cap. */ - if (WLAN_STA_WME&flags) + if (WLAN_STA_WME & flags) psta->qos_option = 1; else psta->qos_option = 0; @@ -2460,7 +2460,7 @@ static int rtw_add_sta(struct net_device *dev, struct ieee_param *param) psta->qos_option = 0; /* chec 802.11n ht cap. */ - if (WLAN_STA_HT&flags) { + if (WLAN_STA_HT & flags) { psta->htpriv.ht_option = true; psta->qos_option = 1; memcpy(&psta->htpriv.ht_cap, ¶m->u.add_sta.ht_cap, @@ -2620,7 +2620,7 @@ static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) return -EINVAL; - ie_len = len-12-2;/* 12 = param header, 2:no packed */ + ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */ kfree(pmlmepriv->wps_beacon_ie); pmlmepriv->wps_beacon_ie = NULL; @@ -2654,7 +2654,7 @@ static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *par if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) return -EINVAL; - ie_len = len-12-2;/* 12 = param header, 2:no packed */ + ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */ kfree(pmlmepriv->wps_probe_resp_ie); pmlmepriv->wps_probe_resp_ie = NULL; @@ -2683,7 +2683,7 @@ static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *par if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) return -EINVAL; - ie_len = len-12-2;/* 12 = param header, 2:no packed */ + ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */ kfree(pmlmepriv->wps_assoc_resp_ie); pmlmepriv->wps_assoc_resp_ie = NULL; @@ -3014,7 +3014,7 @@ int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ret = rtw_hostapd_ioctl(dev, &wrq->u.data); break; #endif /* CONFIG_88EU_AP_MODE */ - case (SIOCDEVPRIVATE+1): + case (SIOCDEVPRIVATE + 1): ret = rtw_android_priv_cmd(dev, rq, cmd); break; default: diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 3cd6da1f843d23a11a78ac512069392feb141dc4..a80c7f3b86d151139562c5e16c570bc649540324 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -400,7 +400,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) case -ENODEV: case -ESHUTDOWN: adapt->bSurpriseRemoved = true; - /* fall through */ + fallthrough; case -ENOENT: adapt->bDriverStopped = true; RT_TRACE(_module_hci_ops_os_c_, _drv_err_, diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c index 017e1d628461459c5cd546bd1330dfff9f08889e..a73313cf6a7570ab0a9864811df3a08c8a561ad6 100644 --- a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c @@ -14,8 +14,7 @@ #include #include -int rtw_os_xmit_resource_alloc(struct adapter *padapter, - struct xmit_buf *pxmitbuf, u32 alloc_sz) +int rtw_os_xmit_resource_alloc(struct xmit_buf *pxmitbuf, u32 alloc_sz) { int i; @@ -24,7 +23,6 @@ int rtw_os_xmit_resource_alloc(struct adapter *padapter, return _FAIL; pxmitbuf->pbuf = PTR_ALIGN(pxmitbuf->pallocated_buf, XMITBUF_ALIGN_SZ); - pxmitbuf->dma_transfer_addr = 0; for (i = 0; i < 8; i++) { pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL); diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index ddcd7885d190d7b9793d5a2f15293f5321aadc28..9f869fb3eaa89213c3b32aa7a10590df8fb3713d 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -1215,9 +1215,9 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, memset((u8 *)pdesc, 0, 12); - mapping = pci_map_single(priv->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(priv->pdev, mapping)) { + mapping = dma_map_single(&priv->pdev->dev, skb->data, skb->len, + DMA_TO_DEVICE); + if (dma_mapping_error(&priv->pdev->dev, mapping)) { netdev_err(dev, "%s(): DMA Mapping error\n", __func__); return; } @@ -1282,10 +1282,10 @@ void rtl92e_fill_tx_cmd_desc(struct net_device *dev, struct tx_desc_cmd *entry, struct cb_desc *cb_desc, struct sk_buff *skb) { struct r8192_priv *priv = rtllib_priv(dev); - dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); + dma_addr_t mapping = dma_map_single(&priv->pdev->dev, skb->data, + skb->len, DMA_TO_DEVICE); - if (pci_dma_mapping_error(priv->pdev, mapping)) + if (dma_mapping_error(&priv->pdev->dev, mapping)) netdev_err(dev, "%s(): DMA Mapping error\n", __func__); memset(entry, 0, 12); entry->LINIP = cb_desc->bLastIniPkt; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index a7cd4de65b2856ce15630180dab54d2cc3fdb798..fac58eebf263a476f581e5a09928df780eaa218a 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -63,13 +63,14 @@ static int _rtl92e_pci_probe(struct pci_dev *pdev, static void _rtl92e_pci_disconnect(struct pci_dev *pdev); static irqreturn_t _rtl92e_irq(int irq, void *netdev); +static SIMPLE_DEV_PM_OPS(rtl92e_pm_ops, rtl92e_suspend, rtl92e_resume); + static struct pci_driver rtl8192_pci_driver = { .name = DRV_NAME, /* Driver name */ .id_table = rtl8192_pci_id_tbl, /* PCI_ID table */ .probe = _rtl92e_pci_probe, /* probe fn */ .remove = _rtl92e_pci_disconnect, /* remove fn */ - .suspend = rtl92e_suspend, /* PM suspend fn */ - .resume = rtl92e_resume, /* PM resume fn */ + .driver.pm = &rtl92e_pm_ops, }; static short _rtl92e_is_tx_queue_empty(struct net_device *dev); @@ -1557,17 +1558,16 @@ static void _rtl92e_free_rx_ring(struct net_device *dev) if (!skb) continue; - pci_unmap_single(priv->pdev, - *((dma_addr_t *)skb->cb), - priv->rxbuffersize, PCI_DMA_FROMDEVICE); + dma_unmap_single(&priv->pdev->dev, + *((dma_addr_t *)skb->cb), + priv->rxbuffersize, DMA_FROM_DEVICE); kfree_skb(skb); } - pci_free_consistent(priv->pdev, - sizeof(*priv->rx_ring[rx_queue_idx]) * - priv->rxringcount, - priv->rx_ring[rx_queue_idx], - priv->rx_ring_dma[rx_queue_idx]); + dma_free_coherent(&priv->pdev->dev, + sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount, + priv->rx_ring[rx_queue_idx], + priv->rx_ring_dma[rx_queue_idx]); priv->rx_ring[rx_queue_idx] = NULL; } } @@ -1581,14 +1581,15 @@ static void _rtl92e_free_tx_ring(struct net_device *dev, unsigned int prio) struct tx_desc *entry = &ring->desc[ring->idx]; struct sk_buff *skb = __skb_dequeue(&ring->queue); - pci_unmap_single(priv->pdev, entry->TxBuffAddr, - skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(&priv->pdev->dev, entry->TxBuffAddr, + skb->len, DMA_TO_DEVICE); kfree_skb(skb); ring->idx = (ring->idx + 1) % ring->entries; } - pci_free_consistent(priv->pdev, sizeof(*ring->desc) * ring->entries, - ring->desc, ring->dma); + dma_free_coherent(&priv->pdev->dev, + sizeof(*ring->desc) * ring->entries, ring->desc, + ring->dma); ring->desc = NULL; } @@ -1675,8 +1676,8 @@ static void _rtl92e_tx_isr(struct net_device *dev, int prio) } skb = __skb_dequeue(&ring->queue); - pci_unmap_single(priv->pdev, entry->TxBuffAddr, - skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(&priv->pdev->dev, entry->TxBuffAddr, + skb->len, DMA_TO_DEVICE); kfree_skb(skb); } @@ -1781,9 +1782,10 @@ static short _rtl92e_alloc_rx_ring(struct net_device *dev) int i, rx_queue_idx; for (rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx++) { - priv->rx_ring[rx_queue_idx] = pci_zalloc_consistent(priv->pdev, - sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount, - &priv->rx_ring_dma[rx_queue_idx]); + priv->rx_ring[rx_queue_idx] = dma_alloc_coherent(&priv->pdev->dev, + sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount, + &priv->rx_ring_dma[rx_queue_idx], + GFP_ATOMIC); if (!priv->rx_ring[rx_queue_idx] || (unsigned long)priv->rx_ring[rx_queue_idx] & 0xFF) { netdev_warn(dev, "Cannot allocate RX ring\n"); @@ -1802,11 +1804,10 @@ static short _rtl92e_alloc_rx_ring(struct net_device *dev) skb->dev = dev; priv->rx_buf[rx_queue_idx][i] = skb; mapping = (dma_addr_t *)skb->cb; - *mapping = pci_map_single(priv->pdev, + *mapping = dma_map_single(&priv->pdev->dev, skb_tail_pointer_rsl(skb), - priv->rxbuffersize, - PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(priv->pdev, *mapping)) { + priv->rxbuffersize, DMA_FROM_DEVICE); + if (dma_mapping_error(&priv->pdev->dev, *mapping)) { dev_kfree_skb_any(skb); return -1; } @@ -1830,7 +1831,8 @@ static int _rtl92e_alloc_tx_ring(struct net_device *dev, unsigned int prio, dma_addr_t dma; int i; - ring = pci_zalloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma); + ring = dma_alloc_coherent(&priv->pdev->dev, sizeof(*ring) * entries, + &dma, GFP_ATOMIC); if (!ring || (unsigned long)ring & 0xFF) { netdev_warn(dev, "Cannot allocate TX ring (prio = %d)\n", prio); return -ENOMEM; @@ -1904,9 +1906,9 @@ void rtl92e_reset_desc_ring(struct net_device *dev) struct sk_buff *skb = __skb_dequeue(&ring->queue); - pci_unmap_single(priv->pdev, - entry->TxBuffAddr, - skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(&priv->pdev->dev, + entry->TxBuffAddr, skb->len, + DMA_TO_DEVICE); kfree_skb(skb); ring->idx = (ring->idx + 1) % ring->entries; } @@ -2027,10 +2029,8 @@ static void _rtl92e_rx_normal(struct net_device *dev) if (unlikely(!new_skb)) goto done; - pci_unmap_single(priv->pdev, - *((dma_addr_t *)skb->cb), - priv->rxbuffersize, - PCI_DMA_FROMDEVICE); + dma_unmap_single(&priv->pdev->dev, *((dma_addr_t *)skb->cb), + priv->rxbuffersize, DMA_FROM_DEVICE); skb_put(skb, pdesc->Length); skb_reserve(skb, stats.RxDrvInfoSize + @@ -2073,12 +2073,10 @@ static void _rtl92e_rx_normal(struct net_device *dev) priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]] = skb; - *((dma_addr_t *)skb->cb) = pci_map_single(priv->pdev, - skb_tail_pointer_rsl(skb), - priv->rxbuffersize, - PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(priv->pdev, - *((dma_addr_t *)skb->cb))) { + *((dma_addr_t *)skb->cb) = dma_map_single(&priv->pdev->dev, + skb_tail_pointer_rsl(skb), + priv->rxbuffersize, DMA_FROM_DEVICE); + if (dma_mapping_error(&priv->pdev->dev, *((dma_addr_t *)skb->cb))) { dev_kfree_skb_any(skb); return; } @@ -2416,8 +2414,8 @@ static int _rtl92e_pci_probe(struct pci_dev *pdev, pci_set_master(pdev); - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { + if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { + if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) { dev_info(&pdev->dev, "Unable to obtain 32bit DMA for consistent allocations\n"); goto err_pci_disable; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c index cd3e17b41d6fe9ddc88c43512ba3ec4c27a55e7c..5575186caebddd1d166765762c62914bce048179 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c @@ -10,9 +10,9 @@ #include "rtl_pm.h" -int rtl92e_suspend(struct pci_dev *pdev, pm_message_t state) +int rtl92e_suspend(struct device *dev_d) { - struct net_device *dev = pci_get_drvdata(pdev); + struct net_device *dev = dev_get_drvdata(dev_d); struct r8192_priv *priv = rtllib_priv(dev); u32 ulRegRead; @@ -46,40 +46,28 @@ int rtl92e_suspend(struct pci_dev *pdev, pm_message_t state) out_pci_suspend: netdev_info(dev, "WOL is %s\n", priv->rtllib->bSupportRemoteWakeUp ? "Supported" : "Not supported"); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), - priv->rtllib->bSupportRemoteWakeUp ? 1 : 0); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); + device_set_wakeup_enable(dev_d, priv->rtllib->bSupportRemoteWakeUp); mdelay(20); return 0; } -int rtl92e_resume(struct pci_dev *pdev) +int rtl92e_resume(struct device *dev_d) { - struct net_device *dev = pci_get_drvdata(pdev); + struct pci_dev *pdev = to_pci_dev(dev_d); + struct net_device *dev = dev_get_drvdata(dev_d); struct r8192_priv *priv = rtllib_priv(dev); - int err; u32 val; netdev_info(dev, "================>r8192E resume call.\n"); - pci_set_power_state(pdev, PCI_D0); - - err = pci_enable_device(pdev); - if (err) { - netdev_err(dev, "pci_enable_device failed on resume\n"); - return err; - } - pci_restore_state(pdev); pci_read_config_dword(pdev, 0x40, &val); if ((val & 0x0000ff00) != 0) pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - pci_enable_wake(pdev, PCI_D0, 0); + device_wakeup_disable(dev_d); if (priv->polling_timer_on == 0) rtl92e_check_rfctrl_gpio_timer(&priv->gpio_polling_timer); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h index e58f2bcdb1ddc7ac090701f2f26267802d085a34..fd86114959753fbe12fb8415edca21ac522aff78 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h @@ -10,7 +10,7 @@ #include #include -int rtl92e_suspend(struct pci_dev *dev, pm_message_t state); -int rtl92e_resume(struct pci_dev *dev); +int rtl92e_suspend(struct device *dev_d); +int rtl92e_resume(struct device *dev_d); #endif diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c index 0cbf4a1a326b3fa378f6430210d1adda090e0217..b60e2a109ce4da66ed63ae78c0969d53428a3e15 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c @@ -278,7 +278,7 @@ static int rtllib_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) int aad_len, ret; req = aead_request_alloc(key->tfm, GFP_ATOMIC); - if(!req) + if (!req) return -ENOMEM; aad_len = ccmp_init_iv_and_aad(hdr, pn, iv, aad); @@ -337,7 +337,7 @@ static int rtllib_ccmp_set_key(void *key, int len, u8 *seq, void *priv) } if (crypto_aead_setauthsize(data->tfm, CCMP_MIC_LEN) || crypto_aead_setkey(data->tfm, data->key, CCMP_TK_LEN)) - return -1; + return -1; } else if (len == 0) { data->key_set = 0; } else { diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c index 7e7df50164fb13944aa8f3ca72e48ad43b2a2bc2..aa26b2fd2774e4129b87143bb95804c7ee39a478 100644 --- a/drivers/staging/rtl8192e/rtllib_wx.c +++ b/drivers/staging/rtl8192e/rtllib_wx.c @@ -680,7 +680,7 @@ int rtllib_wx_set_mlme(struct rtllib_device *ieee, switch (mlme->cmd) { case IW_MLME_DEAUTH: deauth = true; - /* fall through */ + fallthrough; case IW_MLME_DISASSOC: if (deauth) netdev_info(ieee->dev, "disauth packet !\n"); diff --git a/drivers/staging/rtl8192u/copying b/drivers/staging/rtl8192u/copying deleted file mode 100644 index e90dfed1a31ed1c0c22befce22c6f37f9cf5f2bb..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8192u/copying +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c index a5a1b14f5a40c508f4690a63fc148237ac88ae73..c52540b734fd48dbba77927960c372a3c5224528 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c @@ -9,22 +9,6 @@ * * Copyright (c) 2002-2003, Jouni Malinen * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * * Contact Information: * James P. Ketrenos * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index fcfb9024a83f06850143d49a9d55e031ac739c28..6ec65187bef911e00c0bd9db7234064e4277fa05 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -2374,7 +2374,7 @@ static int rtl8192_read_eeprom_info(struct net_device *dev) ret = eprom_read(dev, (EEPROM_TX_PW_INDEX_CCK >> 1)); if (ret < 0) return ret; - priv->EEPROMTxPowerLevelCCK = ((u16)ret & 0xff) >> 8; + priv->EEPROMTxPowerLevelCCK = ((u16)ret & 0xff00) >> 8; } else priv->EEPROMTxPowerLevelCCK = 0x10; RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK); diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index c23e43b095d9b9382a72603c6927a7becec2652d..6b301acb584e3149844ed8795439f9b7d628f25b 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -2240,7 +2240,7 @@ static void dm_ctstoself(struct net_device *dev) unsigned long curTxOkCnt = 0; unsigned long curRxOkCnt = 0; - if (priv->ieee80211->bCTSToSelfEnable != true) { + if (!priv->ieee80211->bCTSToSelfEnable) { pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF; return; } @@ -2944,7 +2944,7 @@ static void dm_dynamic_txpower(struct net_device *dev) unsigned int txhipower_threshold = 0; unsigned int txlowpower_threshold = 0; - if (priv->ieee80211->bdynamic_txpower_enable != true) { + if (!priv->ieee80211->bdynamic_txpower_enable) { priv->bDynamicTxHighPower = false; priv->bDynamicTxLowPower = false; return; diff --git a/drivers/staging/rtl8712/Kconfig b/drivers/staging/rtl8712/Kconfig index c62747c90968cce91cc9483162749db2084085d9..8de26425225b380ed62cb224676a0b00445a8439 100644 --- a/drivers/staging/rtl8712/Kconfig +++ b/drivers/staging/rtl8712/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 config R8712U tristate "RealTek RTL8712U (RTL8192SU) Wireless LAN NIC driver" - depends on WLAN && USB + depends on WLAN && USB && CFG80211 select WIRELESS_EXT select WEXT_PRIV select FW_LOADER diff --git a/drivers/staging/rtl8712/basic_types.h b/drivers/staging/rtl8712/basic_types.h index 4ad7f35b1644a66347541bbec198e75b8c94406c..aecded87dd4c8733742c433f4111b009f9f82c27 100644 --- a/drivers/staging/rtl8712/basic_types.h +++ b/drivers/staging/rtl8712/basic_types.h @@ -14,14 +14,9 @@ #ifndef __BASIC_TYPES_H__ #define __BASIC_TYPES_H__ -#define SUCCESS 0 -#define FAIL (-1) - #include -#define SIZE_T __kernel_size_t #define sint signed int -#define FIELD_OFFSET(s, field) ((addr_t)&((s *)(0))->field) /* Should we extend this to be host_addr_t and target_addr_t for case: * host : x86_64 @@ -29,8 +24,5 @@ */ #define addr_t unsigned long -#define MEM_ALIGNMENT_OFFSET (sizeof(SIZE_T)) -#define MEM_ALIGNMENT_PADDING (sizeof(SIZE_T) - 1) - #endif /*__BASIC_TYPES_H__*/ diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index 40145c0338e458290891f9e36c35cf2622805a2c..715f1fe8b472639263c4b57928d9e3fdae8fa9ee 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -27,13 +27,12 @@ #include "usb_osintf.h" #define FWBUFF_ALIGN_SZ 512 -#define MAX_DUMP_FWSZ 49152 /*default = 49152 (48k)*/ +#define MAX_DUMP_FWSZ (48 * 1024) static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context) { struct _adapter *adapter = context; - complete(&adapter->rtl8712_fw_ready); if (!firmware) { struct usb_device *udev = adapter->dvobjpriv.pusbdev; struct usb_interface *usb_intf = adapter->pusb_intf; @@ -41,11 +40,13 @@ static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context) dev_err(&udev->dev, "r8712u: Firmware request failed\n"); usb_put_dev(udev); usb_set_intfdata(usb_intf, NULL); + complete(&adapter->rtl8712_fw_ready); return; } adapter->fw = firmware; /* firmware available - start netdev */ register_netdev(adapter->pnetdev); + complete(&adapter->rtl8712_fw_ready); } static const char firmware_file[] = "rtlwifi/rtl8712u.bin"; @@ -67,15 +68,13 @@ MODULE_FIRMWARE("rtlwifi/rtl8712u.bin"); static u32 rtl871x_open_fw(struct _adapter *adapter, const u8 **mappedfw) { - const struct firmware **raw = &adapter->fw; - if (adapter->fw->size > 200000) { - dev_err(&adapter->pnetdev->dev, "r8172u: Badfw->size of %d\n", - (int)adapter->fw->size); + dev_err(&adapter->pnetdev->dev, "r8712u: Bad fw->size of %zu\n", + adapter->fw->size); return 0; } - *mappedfw = (*raw)->data; - return (*raw)->size; + *mappedfw = adapter->fw->data; + return adapter->fw->size; } static void fill_fwpriv(struct _adapter *adapter, struct fw_priv *fwpriv) @@ -99,12 +98,12 @@ static void fill_fwpriv(struct _adapter *adapter, struct fw_priv *fwpriv) default: fwpriv->rf_config = RTL8712_RFC_1T2R; } - fwpriv->mp_mode = (regpriv->mp_mode == 1) ? 1 : 0; + fwpriv->mp_mode = (regpriv->mp_mode == 1); /* 0:off 1:on 2:auto */ fwpriv->vcs_type = regpriv->vrtl_carrier_sense; fwpriv->vcs_mode = regpriv->vcs_type; /* 1:RTS/CTS 2:CTS to self */ /* default enable turbo_mode */ - fwpriv->turbo_mode = ((regpriv->wifi_test == 1) ? 0 : 1); + fwpriv->turbo_mode = (regpriv->wifi_test != 1); fwpriv->low_power_mode = regpriv->low_power; } @@ -133,7 +132,7 @@ static u8 chk_fwhdr(struct fw_hdr *pfwhdr, u32 ulfilelength) if (pfwhdr->fw_priv_sz != sizeof(struct fw_priv)) return _FAIL; /* check fw_sz & image_fw_sz */ - fwhdrsz = FIELD_OFFSET(struct fw_hdr, fwpriv) + pfwhdr->fw_priv_sz; + fwhdrsz = offsetof(struct fw_hdr, fwpriv) + pfwhdr->fw_priv_sz; fw_sz = fwhdrsz + pfwhdr->img_IMEM_size + pfwhdr->img_SRAM_size + pfwhdr->dmem_size; if (fw_sz != ulfilelength) @@ -173,7 +172,7 @@ static u8 rtl8712_dl_fw(struct _adapter *adapter) txdesc = (struct tx_desc *)(tmpchar + FWBUFF_ALIGN_SZ - ((addr_t)(tmpchar) & (FWBUFF_ALIGN_SZ - 1))); payload = (u8 *)(txdesc) + txdscp_sz; - ptr = (u8 *)mappedfw + FIELD_OFFSET(struct fw_hdr, fwpriv) + + ptr = (u8 *)mappedfw + offsetof(struct fw_hdr, fwpriv) + fwhdr.fw_priv_sz; /* Download FirmWare */ /* 1. determine IMEM code size and Load IMEM Code Section */ @@ -343,7 +342,7 @@ uint rtl8712_hal_init(struct _adapter *padapter) /* Fix the RX FIFO issue(USB error) */ r8712_write8(padapter, 0x1025fe5C, r8712_read8(padapter, 0x1025fe5C) | BIT(7)); - for (i = 0; i < 6; i++) + for (i = 0; i < ETH_ALEN; i++) padapter->eeprompriv.mac_addr[i] = r8712_read8(padapter, MACID + i); return _SUCCESS; diff --git a/drivers/staging/rtl8712/ieee80211.h b/drivers/staging/rtl8712/ieee80211.h index dabaa8fd34fb83e1eb46b1fc2269bd4bb6055162..61eff7c5746b7d5396df204692e322c91b094b5b 100644 --- a/drivers/staging/rtl8712/ieee80211.h +++ b/drivers/staging/rtl8712/ieee80211.h @@ -14,14 +14,8 @@ #ifndef __IEEE80211_H #define __IEEE80211_H -#include "osdep_service.h" -#include "drv_types.h" -#include "wifi.h" -#include -#include +#include -#define MGMT_QUEUE_NUM 5 -#define ETH_ALEN 6 #define IEEE_CMD_SET_WPA_PARAM 1 #define IEEE_CMD_SET_WPA_IE 2 #define IEEE_CMD_SET_ENCRYPTION 3 @@ -102,162 +96,11 @@ struct ieee_param { } u; }; -#define IEEE80211_DATA_LEN 2304 -/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section - * 6.2.1.1.2. - * - * The figure in section 7.1.2 suggests a body size of up to 2312 - * bytes is allowed, which is a bit confusing, I suspect this - * represents the 2304 bytes of real data, plus a possible 8 bytes of - * WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) - */ - -#define IEEE80211_HLEN 30 -#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) - -/* this is stolen from ipw2200 driver */ -#define IEEE_IBSS_MAC_HASH_SIZE 31 - -struct ieee_ibss_seq { - u8 mac[ETH_ALEN]; - u16 seq_num; - u16 frag_num; - unsigned long packet_time; - struct list_head list; -}; - -struct ieee80211_hdr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctl; - u8 addr4[ETH_ALEN]; -} __packed __aligned(2); - -struct ieee80211_hdr_3addr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctl; -} __packed __aligned(2); - -struct ieee80211_hdr_qos { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctl; - u8 addr4[ETH_ALEN]; - __le16 qc; -} __packed __aligned(2); - -struct ieee80211_hdr_3addr_qos { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctl; - __le16 qc; -} __packed; - -struct eapol { - u8 snap[6]; - __be16 ethertype; - u8 version; - u8 type; - __le16 length; -} __packed; - -enum eap_type { - EAP_PACKET = 0, - EAPOL_START, - EAPOL_LOGOFF, - EAPOL_KEY, - EAPOL_ENCAP_ASF_ALERT -}; - -#define IEEE80211_3ADDR_LEN 24 -#define IEEE80211_4ADDR_LEN 30 -#define IEEE80211_FCS_LEN 4 - #define MIN_FRAG_THRESHOLD 256U #define MAX_FRAG_THRESHOLD 2346U -/* Frame control field constants */ -#define IEEE80211_FCTL_VERS 0x0002 -#define IEEE80211_FCTL_FTYPE 0x000c -#define IEEE80211_FCTL_STYPE 0x00f0 -#define IEEE80211_FCTL_TODS 0x0100 -#define IEEE80211_FCTL_FROMDS 0x0200 -#define IEEE80211_FCTL_MOREFRAGS 0x0400 -#define IEEE80211_FCTL_RETRY 0x0800 -#define IEEE80211_FCTL_PM 0x1000 -#define IEEE80211_FCTL_MOREDATA 0x2000 -#define IEEE80211_FCTL_WEP 0x4000 -#define IEEE80211_FCTL_ORDER 0x8000 - -#define IEEE80211_FTYPE_MGMT 0x0000 -#define IEEE80211_FTYPE_CTL 0x0004 -#define IEEE80211_FTYPE_DATA 0x0008 - -/* management */ -#define IEEE80211_STYPE_ASSOC_REQ 0x0000 -#define IEEE80211_STYPE_ASSOC_RESP 0x0010 -#define IEEE80211_STYPE_REASSOC_REQ 0x0020 -#define IEEE80211_STYPE_REASSOC_RESP 0x0030 -#define IEEE80211_STYPE_PROBE_REQ 0x0040 -#define IEEE80211_STYPE_PROBE_RESP 0x0050 -#define IEEE80211_STYPE_BEACON 0x0080 -#define IEEE80211_STYPE_ATIM 0x0090 -#define IEEE80211_STYPE_DISASSOC 0x00A0 -#define IEEE80211_STYPE_AUTH 0x00B0 -#define IEEE80211_STYPE_DEAUTH 0x00C0 - -/* control */ -#define IEEE80211_STYPE_PSPOLL 0x00A0 -#define IEEE80211_STYPE_RTS 0x00B0 -#define IEEE80211_STYPE_CTS 0x00C0 -#define IEEE80211_STYPE_ACK 0x00D0 -#define IEEE80211_STYPE_CFEND 0x00E0 -#define IEEE80211_STYPE_CFENDACK 0x00F0 - -/* data */ -#define IEEE80211_STYPE_DATA 0x0000 -#define IEEE80211_STYPE_DATA_CFACK 0x0010 -#define IEEE80211_STYPE_DATA_CFPOLL 0x0020 -#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 -#define IEEE80211_STYPE_NULLFUNC 0x0040 -#define IEEE80211_STYPE_CFACK 0x0050 -#define IEEE80211_STYPE_CFPOLL 0x0060 -#define IEEE80211_STYPE_CFACKPOLL 0x0070 -#define IEEE80211_QOS_DATAGRP 0x0080 - -#define IEEE80211_SCTL_FRAG 0x000F -#define IEEE80211_SCTL_SEQ 0xFFF0 - /* QoS,QOS */ #define NORMAL_ACK 0 -#define NO_ACK 1 -#define NON_EXPLICIT_ACK 2 -#define BLOCK_ACK 3 - -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ - -#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ - -#define ETH_P_ECONET 0x0018 - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW (ETH_P_ECONET + 1) -#endif /* IEEE 802.11 defines */ @@ -272,58 +115,6 @@ struct ieee80211_snap_hdr { #define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) -#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) -#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) - -#define WLAN_QC_GET_TID(qc) ((qc) & 0x0f) - -#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) -#define WLAN_GET_SEQ_SEQ(seq) ((seq) & IEEE80211_SCTL_SEQ) - -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 - -#define WLAN_AUTH_CHALLENGE_LEN 128 - -#define WLAN_CAPABILITY_BSS BIT(0) -#define WLAN_CAPABILITY_IBSS BIT(1) -#define WLAN_CAPABILITY_CF_POLLABLE BIT(2) -#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3) -#define WLAN_CAPABILITY_PRIVACY BIT(4) -#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5) -#define WLAN_CAPABILITY_PBCC BIT(6) -#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7) -#define WLAN_CAPABILITY_SHORT_SLOT BIT(10) - -/* Information Element IDs */ -#define WLAN_EID_SSID 0 -#define WLAN_EID_SUPP_RATES 1 -#define WLAN_EID_FH_PARAMS 2 -#define WLAN_EID_DS_PARAMS 3 -#define WLAN_EID_CF_PARAMS 4 -#define WLAN_EID_TIM 5 -#define WLAN_EID_IBSS_PARAMS 6 -#define WLAN_EID_CHALLENGE 16 -#define WLAN_EID_RSN 48 -#define WLAN_EID_GENERIC 221 - -#define IEEE80211_MGMT_HDR_LEN 24 -#define IEEE80211_DATA_HDR3_LEN 24 -#define IEEE80211_DATA_HDR4_LEN 30 - -#define IEEE80211_STATMASK_SIGNAL BIT(0) -#define IEEE80211_STATMASK_RSSI BIT(1) -#define IEEE80211_STATMASK_NOISE BIT(2) -#define IEEE80211_STATMASK_RATE BIT(3) -#define IEEE80211_STATMASK_WEMASK 0x7 - -#define IEEE80211_CCK_MODULATION BIT(0) -#define IEEE80211_OFDM_MODULATION BIT(1) - -#define IEEE80211_24GHZ_BAND BIT(0) -#define IEEE80211_52GHZ_BAND BIT(1) - #define IEEE80211_CCK_RATE_LEN 4 #define IEEE80211_NUM_OFDM_RATESLEN 8 @@ -331,7 +122,6 @@ struct ieee80211_snap_hdr { #define IEEE80211_CCK_RATE_2MB 0x04 #define IEEE80211_CCK_RATE_5MB 0x0B #define IEEE80211_CCK_RATE_11MB 0x16 -#define IEEE80211_OFDM_RATE_LEN 8 #define IEEE80211_OFDM_RATE_6MB 0x0C #define IEEE80211_OFDM_RATE_9MB 0x12 #define IEEE80211_OFDM_RATE_12MB 0x18 @@ -342,388 +132,16 @@ struct ieee80211_snap_hdr { #define IEEE80211_OFDM_RATE_54MB 0x6C #define IEEE80211_BASIC_RATE_MASK 0x80 -#define IEEE80211_CCK_RATE_1MB_MASK BIT(0) -#define IEEE80211_CCK_RATE_2MB_MASK BIT(1) -#define IEEE80211_CCK_RATE_5MB_MASK BIT(2) -#define IEEE80211_CCK_RATE_11MB_MASK BIT(3) -#define IEEE80211_OFDM_RATE_6MB_MASK BIT(4) -#define IEEE80211_OFDM_RATE_9MB_MASK BIT(5) -#define IEEE80211_OFDM_RATE_12MB_MASK BIT(6) -#define IEEE80211_OFDM_RATE_18MB_MASK BIT(7) -#define IEEE80211_OFDM_RATE_24MB_MASK BIT(8) -#define IEEE80211_OFDM_RATE_36MB_MASK BIT(9) -#define IEEE80211_OFDM_RATE_48MB_MASK BIT(10) -#define IEEE80211_OFDM_RATE_54MB_MASK BIT(11) - -#define IEEE80211_CCK_RATES_MASK 0x0000000F -#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ - IEEE80211_CCK_RATE_2MB_MASK) -#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ - IEEE80211_CCK_RATE_5MB_MASK | \ - IEEE80211_CCK_RATE_11MB_MASK) - -#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 -#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ - IEEE80211_OFDM_RATE_12MB_MASK | \ - IEEE80211_OFDM_RATE_24MB_MASK) -#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ - IEEE80211_OFDM_RATE_9MB_MASK | \ - IEEE80211_OFDM_RATE_18MB_MASK | \ - IEEE80211_OFDM_RATE_36MB_MASK | \ - IEEE80211_OFDM_RATE_48MB_MASK | \ - IEEE80211_OFDM_RATE_54MB_MASK) -#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ - IEEE80211_CCK_DEFAULT_RATES_MASK) - -#define IEEE80211_NUM_OFDM_RATES 8 -#define IEEE80211_NUM_CCK_RATES 4 -#define IEEE80211_OFDM_SHIFT_MASK_A 4 - -/* NOTE: This data is for statistical purposes; not all hardware provides this - * information for frames received. Not setting these will not cause - * any adverse affects. - */ -struct ieee80211_rx_stats { - s8 rssi; - u8 signal; - u8 noise; - u8 received_channel; - u16 rate; /* in 100 kbps */ - u8 mask; - u8 freq; - u16 len; -}; - -/* IEEE 802.11 requires that STA supports concurrent reception of at least - * three fragmented frames. This define can be increased to support more - * concurrent frames, but it should be noted that each entry can consume about - * 2 kB of RAM and increasing cache size will slow down frame reassembly. - */ -#define IEEE80211_FRAG_CACHE_LEN 4 - -struct ieee80211_frag_entry { - u32 first_frag_time; - uint seq; - uint last_frag; - uint qos; /*jackson*/ - uint tid; /*jackson*/ - struct sk_buff *skb; - u8 src_addr[ETH_ALEN]; - u8 dst_addr[ETH_ALEN]; -}; - -struct ieee80211_stats { - uint tx_unicast_frames; - uint tx_multicast_frames; - uint tx_fragments; - uint tx_unicast_octets; - uint tx_multicast_octets; - uint tx_deferred_transmissions; - uint tx_single_retry_frames; - uint tx_multiple_retry_frames; - uint tx_retry_limit_exceeded; - uint tx_discards; - uint rx_unicast_frames; - uint rx_multicast_frames; - uint rx_fragments; - uint rx_unicast_octets; - uint rx_multicast_octets; - uint rx_fcs_errors; - uint rx_discards_no_buffer; - uint tx_discards_wrong_sa; - uint rx_discards_undecryptable; - uint rx_message_in_msg_fragments; - uint rx_message_in_bad_msg_fragments; -}; - -struct ieee80211_softmac_stats { - uint rx_ass_ok; - uint rx_ass_err; - uint rx_probe_rq; - uint tx_probe_rs; - uint tx_beacons; - uint rx_auth_rq; - uint rx_auth_rs_ok; - uint rx_auth_rs_err; - uint tx_auth_rq; - uint no_auth_rs; - uint no_ass_rs; - uint tx_ass_rq; - uint rx_ass_rq; - uint tx_probe_rq; - uint reassoc; - uint swtxstop; - uint swtxawake; -}; - -#define SEC_KEY_1 BIT(0) -#define SEC_KEY_2 BIT(1) -#define SEC_KEY_3 BIT(2) -#define SEC_KEY_4 BIT(3) -#define SEC_ACTIVE_KEY BIT(4) -#define SEC_AUTH_MODE BIT(5) -#define SEC_UNICAST_GROUP BIT(6) -#define SEC_LEVEL BIT(7) -#define SEC_ENABLED BIT(8) - -#define SEC_LEVEL_0 0 /* None */ -#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ -#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ -#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ -#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ - #define WEP_KEYS 4 -#define WEP_KEY_LEN 13 - -struct ieee80211_security { - u16 active_key:2, - enabled:1, - auth_mode:2, - auth_algo:4, - unicast_uses_group:1; - u8 key_sizes[WEP_KEYS]; - u8 keys[WEP_KEYS][WEP_KEY_LEN]; - u8 level; - u16 flags; -} __packed; - -/* - * - * 802.11 data frame from AP - * - * ,-------------------------------------------------------------------. - * Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - * |------|------|---------|---------|---------|------|---------|------| - * Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | - * | | tion | (BSSID) | | | ence | data | | - * `-------------------------------------------------------------------' - * - * Total: 28-2340 bytes - * - */ - -struct ieee80211_header_data { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - __le16 seq_ctrl; -} __packed __aligned(2); -#define BEACON_PROBE_SSID_ID_POSITION 12 - -/* Management Frame Information Element Types */ -#define MFIE_TYPE_SSID 0 -#define MFIE_TYPE_RATES 1 -#define MFIE_TYPE_FH_SET 2 -#define MFIE_TYPE_DS_SET 3 -#define MFIE_TYPE_CF_SET 4 -#define MFIE_TYPE_TIM 5 -#define MFIE_TYPE_IBSS_SET 6 -#define MFIE_TYPE_CHALLENGE 16 -#define MFIE_TYPE_ERP 42 -#define MFIE_TYPE_RSN 48 -#define MFIE_TYPE_RATES_EX 50 -#define MFIE_TYPE_GENERIC 221 - -struct ieee80211_info_element_hdr { - u8 id; - u8 len; -} __packed; - -struct ieee80211_info_element { - u8 id; - u8 len; - u8 data[]; -} __packed; - -/* - * These are the data types that can make up management packets - * - __le16 auth_algorithm; - __le16 auth_sequence; - __le16 beacon_interval; - __le16 capability; - u8 current_ap[ETH_ALEN]; - __le16 listen_interval; - struct { - u16 association_id:14, reserved:2; - } __packed; - __le32 time_stamp[2]; - __le16 reason; - __le16 status; -*/ - -#define IEEE80211_DEFAULT_TX_ESSID "Penguin" -#define IEEE80211_DEFAULT_BASIC_RATE 10 - -struct ieee80211_authentication { - struct ieee80211_header_data header; - __le16 algorithm; - __le16 transaction; - __le16 status; -} __packed; - -struct ieee80211_probe_response { - struct ieee80211_header_data header; - __le32 time_stamp[2]; - __le16 beacon_interval; - __le16 capability; - struct ieee80211_info_element info_element; -} __packed; - -struct ieee80211_probe_request { - struct ieee80211_header_data header; -} __packed; - -struct ieee80211_assoc_request_frame { - struct ieee80211_hdr_3addr header; - __le16 capability; - __le16 listen_interval; - struct ieee80211_info_element_hdr info_element; -} __packed; - -struct ieee80211_assoc_response_frame { - struct ieee80211_hdr_3addr header; - __le16 capability; - __le16 status; - __le16 aid; -} __packed; - -struct ieee80211_txb { - u8 nr_frags; - u8 encrypted; - u16 reserved; - u16 frag_size; - u16 payload_size; - struct sk_buff *fragments[]; -}; - -/* SWEEP TABLE ENTRIES NUMBER*/ -#define MAX_SWEEP_TAB_ENTRIES 42 -#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 /* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs * only use 8, and then use extended rates for the remaining supported * rates. Other APs, however, stick all of their supported rates on the * main rates information element... */ #define MAX_RATES_LENGTH ((u8)12) -#define MAX_RATES_EX_LENGTH ((u8)16) -#define MAX_NETWORK_COUNT 128 -#define MAX_CHANNEL_NUMBER 161 -#define IEEE80211_SOFTMAC_SCAN_TIME 400 -/*(HZ / 2)*/ -#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2) - -#define CRC_LENGTH 4U - #define MAX_WPA_IE_LEN 128 -#define NETWORK_EMPTY_ESSID BIT(0) -#define NETWORK_HAS_OFDM BIT(1) -#define NETWORK_HAS_CCK BIT(2) - -#define IEEE80211_DTIM_MBCAST 4 -#define IEEE80211_DTIM_UCAST 2 -#define IEEE80211_DTIM_VALID 1 -#define IEEE80211_DTIM_INVALID 0 - -#define IEEE80211_PS_DISABLED 0 -#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST -#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST -#define IW_ESSID_MAX_SIZE 32 -/* - * join_res: - * -1: authentication fail - * -2: association fail - * > 0: TID - */ - -enum ieee80211_state { - /* the card is not linked at all */ - IEEE80211_NOLINK = 0, - /* IEEE80211_ASSOCIATING* are for BSS client mode - * the driver shall not perform RX filtering unless - * the state is LINKED. - * The driver shall just check for the state LINKED and - * defaults to NOLINK for ALL the other states (including - * LINKED_SCANNING) - */ - /* the association procedure will start (wq scheduling)*/ - IEEE80211_ASSOCIATING, - IEEE80211_ASSOCIATING_RETRY, - /* the association procedure is sending AUTH request*/ - IEEE80211_ASSOCIATING_AUTHENTICATING, - /* the association procedure has successfully authenticated - * and is sending association request - */ - IEEE80211_ASSOCIATING_AUTHENTICATED, - /* the link is ok. the card associated to a BSS or linked - * to a ibss cell or acting as an AP and creating the bss - */ - IEEE80211_LINKED, - /* same as LINKED, but the driver shall apply RX filter - * rules as we are in NO_LINK mode. As the card is still - * logically linked, but it is doing a syncro site survey - * then it will be back to LINKED state. - */ - IEEE80211_LINKED_SCANNING, -}; - -#define DEFAULT_MAX_SCAN_AGE (15 * HZ) -#define DEFAULT_FTS 2346 - -#define CFG_IEEE80211_RESERVE_FCS BIT(0) -#define CFG_IEEE80211_COMPUTE_FCS BIT(1) - -#define MAXTID 16 - -#define IEEE_A BIT(0) -#define IEEE_B BIT(1) -#define IEEE_G BIT(2) -#define IEEE_MODE_MASK (IEEE_A | IEEE_B | IEEE_G) - -static inline int ieee80211_is_empty_essid(const char *essid, int essid_len) -{ - /* Single white space is for Linksys APs */ - if (essid_len == 1 && essid[0] == ' ') - return 1; - /* Otherwise, if the entire essid is 0, we assume it is hidden */ - while (essid_len) { - essid_len--; - if (essid[essid_len] != '\0') - return 0; - } - return 1; -} - -static inline int ieee80211_get_hdrlen(u16 fc) -{ - int hdrlen = 24; - - switch (WLAN_FC_GET_TYPE(fc)) { - case IEEE80211_FTYPE_DATA: - if (fc & IEEE80211_QOS_DATAGRP) - hdrlen += 2; - if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) - hdrlen += 6; /* Addr4 */ - break; - case IEEE80211_FTYPE_CTL: - switch (WLAN_FC_GET_STYPE(fc)) { - case IEEE80211_STYPE_CTS: - case IEEE80211_STYPE_ACK: - hdrlen = 10; - break; - default: - hdrlen = 16; - break; - } - break; - } - return hdrlen; -} - struct registry_priv; u8 *r8712_set_ie(u8 *pbuf, sint index, uint len, u8 *source, uint *frlen); diff --git a/drivers/staging/rtl8712/osdep_intf.h b/drivers/staging/rtl8712/osdep_intf.h index 2cc25db1a91de84fce37991b199fade3a0612c23..9e75116c987ec32a518a8ece1829457180aee6a0 100644 --- a/drivers/staging/rtl8712/osdep_intf.h +++ b/drivers/staging/rtl8712/osdep_intf.h @@ -17,7 +17,7 @@ #include "osdep_service.h" #include "drv_types.h" -#define RND4(x) (((x >> 2) + (((x & 3) == 0) ? 0 : 1)) << 2) +#define RND4(x) (((x >> 2) + ((x & 3) != 0)) << 2) struct intf_priv { u8 *intf_dev; diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 116773943a2e910fea1139badd54beff30c6a872..d83f421acfc1ea0409cbbaf02ebd5ba462494c41 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -18,6 +18,7 @@ #include #include +#include #include "osdep_service.h" #include "drv_types.h" @@ -27,12 +28,6 @@ #include "usb_ops.h" #include "wifi.h" -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static u8 bridge_tunnel_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8}; - -/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -static u8 rfc1042_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; - static void recv_tasklet(unsigned long priv); void r8712_init_recv_priv(struct recv_priv *precvpriv, @@ -148,9 +143,8 @@ static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib, /*TODO: * Offset 0 */ - pattrib->bdecrypted = ((le32_to_cpu(prxstat->rxdw0) & BIT(27)) >> 27) - ? 0 : 1; - pattrib->crc_err = (le32_to_cpu(prxstat->rxdw0) & BIT(14)) >> 14; + pattrib->bdecrypted = (le32_to_cpu(prxstat->rxdw0) & BIT(27)) == 0; + pattrib->crc_err = (le32_to_cpu(prxstat->rxdw0) & BIT(14)) != 0; /*Offset 4*/ /*Offset 8*/ /*Offset 12*/ @@ -487,8 +481,7 @@ static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, plist = plist->next; else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) return false; - else - break; + break; } list_del_init(&(prframe->u.hdr.list)); list_add_tail(&(prframe->u.hdr.list), plist); @@ -1037,24 +1030,17 @@ static void recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) */ alloc_sz += 6; pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz); - if (pkt_copy) { - precvframe->u.hdr.pkt = pkt_copy; - skb_reserve(pkt_copy, 4 - ((addr_t)(pkt_copy->data) - % 4)); - skb_reserve(pkt_copy, shift_sz); - memcpy(pkt_copy->data, pbuf, tmp_len); - precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = - precvframe->u.hdr.rx_tail = pkt_copy->data; - precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz; - } else { - precvframe->u.hdr.pkt = skb_clone(pskb, GFP_ATOMIC); - if (!precvframe->u.hdr.pkt) - return; - precvframe->u.hdr.rx_head = pbuf; - precvframe->u.hdr.rx_data = pbuf; - precvframe->u.hdr.rx_tail = pbuf; - precvframe->u.hdr.rx_end = pbuf + alloc_sz; - } + if (!pkt_copy) + return; + + precvframe->u.hdr.pkt = pkt_copy; + skb_reserve(pkt_copy, 4 - ((addr_t)(pkt_copy->data) % 4)); + skb_reserve(pkt_copy, shift_sz); + memcpy(pkt_copy->data, pbuf, tmp_len); + precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = + precvframe->u.hdr.rx_tail = pkt_copy->data; + precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz; + recvframe_put(precvframe, tmp_len); recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); /* because the endian issue, driver avoid reference to the diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c index 26b618008fcfe731e77bb2b0e8ced6eb4346991e..c7523072a6607b838b011fd89f8f8a3e19539db4 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.c +++ b/drivers/staging/rtl8712/rtl871x_cmd.c @@ -168,14 +168,9 @@ void r8712_free_cmd_obj(struct cmd_obj *pcmd) kfree(pcmd); } -/* - * r8712_sitesurvey_cmd(~) - * ### NOTE:#### (!!!!) - * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, - * YOU SHOULD HAVE LOCKED pmlmepriv->lock - */ u8 r8712_sitesurvey_cmd(struct _adapter *padapter, struct ndis_802_11_ssid *pssid) + __must_hold(&padapter->mlmepriv.lock) { struct cmd_obj *ph2c; struct sitesurvey_parm *psurveyPara; diff --git a/drivers/staging/rtl8712/rtl871x_ht.h b/drivers/staging/rtl8712/rtl871x_ht.h index ebd78665775dd02862b9d20af703b0b0e67435be..4bcf5591c44dce5865b64a64f23442e459553918 100644 --- a/drivers/staging/rtl8712/rtl871x_ht.h +++ b/drivers/staging/rtl8712/rtl871x_ht.h @@ -26,7 +26,7 @@ struct ht_priv { unsigned int rx_ampdu_maxlen; /* for rx reordering ctrl win_sz, * updated when join_callback. */ - struct ieee80211_ht_cap ht_cap; + struct rtl_ieee80211_ht_cap ht_cap; }; #endif /*_RTL871X_HT_H_ */ diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index 363b82e3e7c6ee149ee78569337286e8ee8ff97a..df6ae855f3c137e3f4b0d0f635f824c215adae4e 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -211,11 +211,10 @@ static char *translate_scan(struct _adapter *padapter, char *start, char *stop) { struct iw_event iwe; - struct ieee80211_ht_cap *pht_capie; char *current_val; s8 *p; u32 i = 0, ht_ielen = 0; - u16 cap, ht_cap = false, mcs_rate; + u16 cap, ht_cap = false; u8 rssi; if ((pnetwork->network.Configuration.DSConfig < 1) || @@ -239,11 +238,8 @@ static char *translate_scan(struct _adapter *padapter, /* parsing HT_CAP_IE */ p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength - 12); - if (p && ht_ielen > 0) { + if (p && ht_ielen > 0) ht_cap = true; - pht_capie = (struct ieee80211_ht_cap *)(p + 2); - memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2); - } /* Add the protocol name */ iwe.cmd = SIOCGIWNAME; if (r8712_is_cckratesonly_included(pnetwork->network.rates)) { @@ -268,8 +264,8 @@ static char *translate_scan(struct _adapter *padapter, memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs), 2); le16_to_cpus(&cap); - if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) { - if (cap & WLAN_CAPABILITY_BSS) + if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_ESS)) { + if (cap & WLAN_CAPABILITY_ESS) iwe.u.mode = (u32)IW_MODE_MASTER; else iwe.u.mode = (u32)IW_MODE_ADHOC; @@ -410,7 +406,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, return -ENOMEM; pwep->KeyLength = wep_key_len; pwep->Length = wep_key_len + - FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial); + offsetof(struct NDIS_802_11_WEP, KeyMaterial); if (wep_key_len == 13) { padapter->securitypriv.PrivacyAlgrthm = _WEP104_; padapter->securitypriv.XGrpPrivacy = _WEP104_; @@ -1395,7 +1391,7 @@ static int r8711_wx_get_rate(struct net_device *dev, struct _adapter *padapter = netdev_priv(dev); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - struct ieee80211_ht_cap *pht_capie; + struct rtl_ieee80211_ht_cap *pht_capie; unsigned char rf_type = padapter->registrypriv.rf_config; int i; u8 *p; @@ -1411,10 +1407,10 @@ static int r8711_wx_get_rate(struct net_device *dev, pcur_bss->IELength - 12); if (p && ht_ielen > 0) { ht_cap = true; - pht_capie = (struct ieee80211_ht_cap *)(p + 2); + pht_capie = (struct rtl_ieee80211_ht_cap *)(p + 2); memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2); bw_40MHz = (le16_to_cpu(pht_capie->cap_info) & - IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0; + IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0; short_GI = (le16_to_cpu(pht_capie->cap_info) & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; @@ -1558,7 +1554,7 @@ static int r8711_wx_set_enc(struct net_device *dev, if (erq->length > 0) { wep.KeyLength = erq->length <= 5 ? 5 : 13; wep.Length = wep.KeyLength + - FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial); + offsetof(struct NDIS_802_11_WEP, KeyMaterial); } else { wep.KeyLength = 0; if (keyindex_provided == 1) { /* set key_id only, no given diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index cabdb3549a5a0ff45a2d626094ed400e785fd447..2ccd490322067ca786825f8b35194af5017ac61e 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -249,8 +249,8 @@ static int is_same_network(struct wlan_bssid_ex *src, src->Ssid.SsidLength))) && ((s_cap & WLAN_CAPABILITY_IBSS) == (d_cap & WLAN_CAPABILITY_IBSS)) && - ((s_cap & WLAN_CAPABILITY_BSS) == - (d_cap & WLAN_CAPABILITY_BSS)); + ((s_cap & WLAN_CAPABILITY_ESS) == + (d_cap & WLAN_CAPABILITY_ESS)); } @@ -264,13 +264,13 @@ struct wlan_network *r8712_get_oldest_wlan_network( phead = &scanned_queue->queue; plist = phead->next; while (1) { - if (end_of_queue_search(phead, plist) == true) + if (end_of_queue_search(phead, plist)) break; pwlan = container_of(plist, struct wlan_network, list); - if (pwlan->fixed != true) { - if (oldest == NULL || + if (!pwlan->fixed) { + if (!oldest || time_after((unsigned long)oldest->last_scanned, - (unsigned long)pwlan->last_scanned)) + (unsigned long)pwlan->last_scanned)) oldest = pwlan; } plist = plist->next; @@ -1643,7 +1643,7 @@ unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie, { u32 ielen, out_len; unsigned char *p; - struct ieee80211_ht_cap ht_capie; + struct rtl_ieee80211_ht_cap ht_capie; unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct qos_priv *pqospriv = &pmlmepriv->qospriv; @@ -1659,17 +1659,17 @@ unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie, pqospriv->qos_option = 1; } out_len = *pout_len; - memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap)); - ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH | + memset(&ht_capie, 0, sizeof(struct rtl_ieee80211_ht_cap)); + ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_MAX_AMSDU | IEEE80211_HT_CAP_DSSSCCK40); - ht_capie.ampdu_params_info = (IEEE80211_HT_CAP_AMPDU_FACTOR & - 0x03) | (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00); + ht_capie.ampdu_params_info = (IEEE80211_HT_AMPDU_PARM_FACTOR & + 0x03) | (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00); r8712_set_ie(out_ie + out_len, _HT_CAPABILITY_IE_, - sizeof(struct ieee80211_ht_cap), + sizeof(struct rtl_ieee80211_ht_cap), (unsigned char *)&ht_capie, pout_len); phtpriv->ht_option = 1; } @@ -1683,7 +1683,7 @@ static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len) int i; uint len; struct sta_info *bmc_sta, *psta; - struct ieee80211_ht_cap *pht_capie; + struct rtl_ieee80211_ht_cap *pht_capie; struct recv_reorder_ctrl *preorder_ctrl; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct ht_priv *phtpriv = &pmlmepriv->htpriv; @@ -1703,9 +1703,9 @@ static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len) &len, ie_len - sizeof(struct NDIS_802_11_FIXED_IEs)); if (p && len > 0) { - pht_capie = (struct ieee80211_ht_cap *)(p + 2); + pht_capie = (struct rtl_ieee80211_ht_cap *)(p + 2); max_ampdu_sz = (pht_capie->ampdu_params_info & - IEEE80211_HT_CAP_AMPDU_FACTOR); + IEEE80211_HT_AMPDU_PARM_FACTOR); /* max_ampdu_sz (kbytes); */ max_ampdu_sz = 1 << (max_ampdu_sz + 3); phtpriv->rx_ampdu_maxlen = max_ampdu_sz; diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index e5092b6da4bdcbfaf572b171a667235e4ec70103..c1bfd61824ef2d27d59d586316913fa027766bf9 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "osdep_service.h" #include "drv_types.h" @@ -35,12 +36,6 @@ static const u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37}; /* Datagram Delivery Protocol */ static const u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3}; -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static const u8 bridge_tunnel_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8}; - -/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -static const u8 rfc1042_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; - void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv) { memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv)); diff --git a/drivers/staging/rtl8712/rtl871x_recv.h b/drivers/staging/rtl8712/rtl871x_recv.h index e93f356ed2b0d2fa46e3626dd496c2cb40a53ec9..e83c256e14741f1b7e0def4247c5bca85ca04b6d 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.h +++ b/drivers/staging/rtl8712/rtl871x_recv.h @@ -12,8 +12,6 @@ #define MAX_SUBFRAME_COUNT 64 -#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) - /* for Rx reordering buffer control */ struct recv_reorder_ctrl { struct _adapter *padapter; diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c index 73e3d5ef3af27e2d4d9927f6416911c2494dea79..c05010d85212c003fde15626f8d8c73553e57d06 100644 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ b/drivers/staging/rtl8712/rtl871x_security.c @@ -762,7 +762,7 @@ static void next_key(u8 *key, sint round) { u8 rcon; u8 sbox_key[4]; - u8 rcon_table[12] = { + static const u8 rcon_table[12] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x36, 0x36 }; diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 2f0d0ffa6fae2c7487d40d9b88133764f700d96e..8b88fd5dc9a1d53a2f78fce0ebd9d55a7cb4d277 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -476,7 +476,7 @@ static int make_wlanhdr(struct _adapter *padapter, u8 *hdr, struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct qos_priv *pqospriv = &pmlmepriv->qospriv; - __le16 *fctrl = &pwlanhdr->frame_ctl; + __le16 *fctrl = &pwlanhdr->frame_control; u8 *bssid; memset(hdr, 0, WLANHDR_OFFSET); diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index a87562f632a7ff07a4f7fb405dbb66ad4764f0da..2fcd65260f4c18b1f9e2465aed024738a61acfc7 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -595,13 +595,17 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf) if (pnetdev) { struct _adapter *padapter = netdev_priv(pnetdev); - usb_set_intfdata(pusb_intf, NULL); - release_firmware(padapter->fw); /* never exit with a firmware callback pending */ wait_for_completion(&padapter->rtl8712_fw_ready); + pnetdev = usb_get_intfdata(pusb_intf); + usb_set_intfdata(pusb_intf, NULL); + if (!pnetdev) + goto firmware_load_fail; + release_firmware(padapter->fw); if (drvpriv.drv_registered) padapter->surprise_removed = true; - unregister_netdev(pnetdev); /* will call netdev_close() */ + if (pnetdev->reg_state != NETREG_UNINITIALIZED) + unregister_netdev(pnetdev); /* will call netdev_close() */ flush_scheduled_work(); udelay(1); /* Stop driver mlme relation timer */ @@ -614,6 +618,7 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf) */ usb_put_dev(udev); } +firmware_load_fail: /* If we didn't unplug usb dongle and remove/insert module, driver * fails on sitesurvey for the first time when device is up. * Reset usb port for sitesurvey fail issue. diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c index 0045da3bb69a61e63d7c6a98f38318fbe242d05f..9a04a752af13e01ce5a12ee313a9c9e7d3341ba7 100644 --- a/drivers/staging/rtl8712/usb_ops_linux.c +++ b/drivers/staging/rtl8712/usb_ops_linux.c @@ -225,7 +225,7 @@ static void r8712_usb_read_port_complete(struct urb *purb) padapter->driver_stopped = true; break; } - /* Fall through. */ + fallthrough; case -EPROTO: r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h index 91b65731fcaa871ee684c13b17d1ae2fa8cfca94..601d4ff607bc846a4cd5e4252e9dfd6702183e97 100644 --- a/drivers/staging/rtl8712/wifi.h +++ b/drivers/staging/rtl8712/wifi.h @@ -437,13 +437,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) *------------------------------------------------------------------------------ */ -/* block-ack parameters */ -#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 -#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C -#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFC0 -#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 -#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 - #define SetOrderBit(pbuf) ({ \ *(__le16 *)(pbuf) |= cpu_to_le16(_ORDER_); \ }) @@ -451,33 +444,14 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) #define GetOrderBit(pbuf) (((*(__le16 *)(pbuf)) & \ le16_to_cpu(_ORDER_)) != 0) -/** - * struct ieee80211_bar - HT Block Ack Request - * - * This structure refers to "HT BlockAckReq" as - * described in 802.11n draft section 7.2.1.7.1 - */ -struct ieee80211_bar { - __le16 frame_control; - __le16 duration; - unsigned char ra[6]; - unsigned char ta[6]; - __le16 control; - __le16 start_seq_num; -} __packed; - -/* 802.11 BAR control masks */ -#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 -#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 - /* - * struct ieee80211_ht_cap - HT capabilities + * struct rtl_ieee80211_ht_cap - HT capabilities * * This structure refers to "HT capabilities element" as * described in 802.11n draft section 7.3.2.52 */ -struct ieee80211_ht_cap { +struct rtl_ieee80211_ht_cap { __le16 cap_info; unsigned char ampdu_params_info; unsigned char supp_mcs_set[16]; @@ -487,7 +461,7 @@ struct ieee80211_ht_cap { } __packed; /** - * struct ieee80211_ht_cap - HT additional information + * struct ieee80211_ht_addt_info - HT additional information * * This structure refers to "HT information element" as * described in 802.11n draft section 7.3.2.53 @@ -500,49 +474,5 @@ struct ieee80211_ht_addt_info { unsigned char basic_set[16]; } __packed; -/* 802.11n HT capabilities masks */ -#define IEEE80211_HT_CAP_SUP_WIDTH 0x0002 -#define IEEE80211_HT_CAP_SM_PS 0x000C -#define IEEE80211_HT_CAP_GRN_FLD 0x0010 -#define IEEE80211_HT_CAP_SGI_20 0x0020 -#define IEEE80211_HT_CAP_SGI_40 0x0040 -#define IEEE80211_HT_CAP_TX_STBC 0x0080 -#define IEEE80211_HT_CAP_DELAY_BA 0x0400 -#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 -#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 -/* 802.11n HT capability AMPDU settings */ -#define IEEE80211_HT_CAP_AMPDU_FACTOR 0x03 -#define IEEE80211_HT_CAP_AMPDU_DENSITY 0x1C -/* 802.11n HT capability MSC set */ -#define IEEE80211_SUPP_MCS_SET_UEQM 4 -#define IEEE80211_HT_CAP_MAX_STREAMS 4 -#define IEEE80211_SUPP_MCS_SET_LEN 10 -/* maximum streams the spec allows */ -#define IEEE80211_HT_CAP_MCS_TX_DEFINED 0x01 -#define IEEE80211_HT_CAP_MCS_TX_RX_DIFF 0x02 -#define IEEE80211_HT_CAP_MCS_TX_STREAMS 0x0C -#define IEEE80211_HT_CAP_MCS_TX_UEQM 0x10 -/* 802.11n HT IE masks */ -#define IEEE80211_HT_IE_CHA_SEC_OFFSET 0x03 -#define IEEE80211_HT_IE_CHA_SEC_NONE 0x00 -#define IEEE80211_HT_IE_CHA_SEC_ABOVE 0x01 -#define IEEE80211_HT_IE_CHA_SEC_BELOW 0x03 -#define IEEE80211_HT_IE_CHA_WIDTH 0x04 -#define IEEE80211_HT_IE_HT_PROTECTION 0x0003 -#define IEEE80211_HT_IE_NON_GF_STA_PRSNT 0x0004 -#define IEEE80211_HT_IE_NON_HT_STA_PRSNT 0x0010 - -/* - * A-PMDU buffer sizes - * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) - */ -#define IEEE80211_MIN_AMPDU_BUF 0x8 - -/* Spatial Multiplexing Power Save Modes */ -#define WLAN_HT_CAP_SM_PS_STATIC 0 -#define WLAN_HT_CAP_SM_PS_DYNAMIC 1 -#define WLAN_HT_CAP_SM_PS_INVALID 2 -#define WLAN_HT_CAP_SM_PS_DISABLED 3 - #endif /* _WIFI_H_ */ diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index d6d7198dfe45ab39de29ee4fe14d27463e1f49ae..6db637701063029d705c6ce31fd52dab4f229fbf 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -568,7 +568,7 @@ void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame) ptable->func = &OnAuth; else ptable->func = &OnAuthClient; - /* fall through */ + fallthrough; case WIFI_ASSOCREQ: case WIFI_REASSOCREQ: _mgt_dispatcher(padapter, ptable, precv_frame); diff --git a/drivers/staging/rtl8723bs/core/rtw_security.c b/drivers/staging/rtl8723bs/core/rtw_security.c index 0f95009a30b6ffcb933920d3867e88994e005530..0f15c96183a0ce73c91269e3c802bb986a674847 100644 --- a/drivers/staging/rtl8723bs/core/rtw_security.c +++ b/drivers/staging/rtl8723bs/core/rtw_security.c @@ -10,7 +10,7 @@ #include #include -static const char *_security_type_str[] = { +static const char * const _security_type_str[] = { "N/A", "WEP40", "TKIP", @@ -842,7 +842,7 @@ exit: /******** SBOX Table *********/ /*****************************/ - static u8 sbox_table[256] = { + static const u8 sbox_table[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, @@ -957,7 +957,7 @@ static void next_key(u8 *key, sint round) { u8 rcon; u8 sbox_key[4]; - u8 rcon_table[12] = { + static const u8 rcon_table[12] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x36, 0x36 diff --git a/drivers/staging/rtl8723bs/include/HalPwrSeqCmd.h b/drivers/staging/rtl8723bs/include/HalPwrSeqCmd.h index 7040cfc507d8d2d759030cfacfe9ae19b0a07a5f..459f2f9d4bbbe14497d3ed12cf20830f50a24491 100644 --- a/drivers/staging/rtl8723bs/include/HalPwrSeqCmd.h +++ b/drivers/staging/rtl8723bs/include/HalPwrSeqCmd.h @@ -82,14 +82,12 @@ #define PWR_CUT_ALL_MSK 0xFF -typedef enum _PWRSEQ_CMD_DELAY_UNIT_ -{ +typedef enum _PWRSEQ_CMD_DELAY_UNIT_ { PWRSEQ_DELAY_US, PWRSEQ_DELAY_MS, } PWRSEQ_DELAY_UNIT; -typedef struct _WL_PWR_CFG_ -{ +typedef struct _WL_PWR_CFG_ { u16 offset; u8 cut_msk; u8 fab_msk:4; diff --git a/drivers/staging/rtl8723bs/include/HalVerDef.h b/drivers/staging/rtl8723bs/include/HalVerDef.h index c548fb126683bc21970f0de424868c9839bff8d1..b4744be2cbe171b19b92d77c5a860960b338afb9 100644 --- a/drivers/staging/rtl8723bs/include/HalVerDef.h +++ b/drivers/staging/rtl8723bs/include/HalVerDef.h @@ -8,8 +8,7 @@ #define __HAL_VERSION_DEF_H__ /* HAL_IC_TYPE_E */ -typedef enum tag_HAL_IC_Type_Definition -{ +typedef enum tag_HAL_IC_Type_Definition { CHIP_8192S = 0, CHIP_8188C = 1, CHIP_8192C = 2, @@ -23,16 +22,14 @@ typedef enum tag_HAL_IC_Type_Definition } HAL_IC_TYPE_E; /* HAL_CHIP_TYPE_E */ -typedef enum tag_HAL_CHIP_Type_Definition -{ +typedef enum tag_HAL_CHIP_Type_Definition { TEST_CHIP = 0, NORMAL_CHIP = 1, FPGA = 2, } HAL_CHIP_TYPE_E; /* HAL_CUT_VERSION_E */ -typedef enum tag_HAL_Cut_Version_Definition -{ +typedef enum tag_HAL_Cut_Version_Definition { A_CUT_VERSION = 0, B_CUT_VERSION = 1, C_CUT_VERSION = 2, @@ -47,15 +44,13 @@ typedef enum tag_HAL_Cut_Version_Definition } HAL_CUT_VERSION_E; /* HAL_Manufacturer */ -typedef enum tag_HAL_Manufacturer_Version_Definition -{ +typedef enum tag_HAL_Manufacturer_Version_Definition { CHIP_VENDOR_TSMC = 0, CHIP_VENDOR_UMC = 1, CHIP_VENDOR_SMIC = 2, } HAL_VENDOR_E; -typedef enum tag_HAL_RF_Type_Definition -{ +typedef enum tag_HAL_RF_Type_Definition { RF_TYPE_1T1R = 0, RF_TYPE_1T2R = 1, RF_TYPE_2T2R = 2, @@ -66,8 +61,7 @@ typedef enum tag_HAL_RF_Type_Definition RF_TYPE_4T4R = 7, } HAL_RF_TYPE_E; -typedef struct tag_HAL_VERSION -{ +typedef struct tag_HAL_VERSION { HAL_IC_TYPE_E ICType; HAL_CHIP_TYPE_E ChipType; HAL_CUT_VERSION_E CUTVersion; diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h index dba75216cbfe7886a0e7db2e60251d61d8dff845..c73f581aea064f77784c702df068308f32848bdf 100644 --- a/drivers/staging/rtl8723bs/include/drv_types.h +++ b/drivers/staging/rtl8723bs/include/drv_types.h @@ -86,8 +86,7 @@ struct specific_device_id { }; -struct registry_priv -{ +struct registry_priv { u8 chip_version; u8 rfintfs; u8 lbkmode; @@ -418,8 +417,7 @@ struct cam_entry_cache { ((u8 *)(x))[6], ((u8 *)(x))[7], ((u8 *)(x))[8], ((u8 *)(x))[9], ((u8 *)(x))[10], ((u8 *)(x))[11], \ ((u8 *)(x))[12], ((u8 *)(x))[13], ((u8 *)(x))[14], ((u8 *)(x))[15] -struct dvobj_priv -{ +struct dvobj_priv { /*-------- below is common data --------*/ struct adapter *if1; /* PRIMARY_ADAPTER */ struct adapter *if2; /* SECONDARY_ADAPTER */ diff --git a/drivers/staging/rtl8723bs/include/drv_types_sdio.h b/drivers/staging/rtl8723bs/include/drv_types_sdio.h index 09263ad27ce966a1e07c12f2fda1ee2ee49e903f..5e079838f59cbec286aa87c0c286f93bc12eff1e 100644 --- a/drivers/staging/rtl8723bs/include/drv_types_sdio.h +++ b/drivers/staging/rtl8723bs/include/drv_types_sdio.h @@ -16,8 +16,7 @@ #include #endif -struct sdio_data -{ +struct sdio_data { u8 func_number; u8 tx_block_mode; diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h index eb03813fdcb98ec0486c042d065556ba795400ec..29318b49c3ff36c82092435e0f75f17257cb5687 100644 --- a/drivers/staging/rtl8723bs/include/hal_btcoex.h +++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h @@ -11,8 +11,7 @@ /* Some variables can't get from outsrc BT-Coex, */ /* so we need to save here */ -typedef struct _BT_COEXIST -{ +typedef struct _BT_COEXIST { u8 bBtExist; u8 btTotalAntNum; u8 btChipType; diff --git a/drivers/staging/rtl8723bs/include/hal_com.h b/drivers/staging/rtl8723bs/include/hal_com.h index a46626d0509a89df446ce33d04dd2e8f6dc31a4c..fe7e2efce0e3a7dfbf0d9fda31e488506e6b49ca 100644 --- a/drivers/staging/rtl8723bs/include/hal_com.h +++ b/drivers/staging/rtl8723bs/include/hal_com.h @@ -288,8 +288,7 @@ void SetHalODMVar( bool bSet); #ifdef CONFIG_BACKGROUND_NOISE_MONITOR -struct noise_info -{ +struct noise_info { u8 bPauseDIG; u8 IGIValue; u32 max_time;/* ms */ diff --git a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h index 419ddb0733aa90ed6fc59dd529ff5769cd610a3a..ed3488a09d7982a106c8ee7b4ae4e366a3507ae8 100644 --- a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h +++ b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h @@ -8,11 +8,11 @@ #define __INC_HAL8723BPHYCFG_H__ /*--------------------------Define Parameters-------------------------------*/ -#define LOOP_LIMIT 5 -#define MAX_STALL_TIME 50 /* us */ +#define LOOP_LIMIT 5 +#define MAX_STALL_TIME 50 /* us */ #define AntennaDiversityValue 0x80 /* Adapter->bSoftwareAntennaDiversity ? 0x00:0x80) */ #define MAX_TXPWR_IDX_NMODE_92S 63 -#define Reset_Cnt_Limit 3 +#define Reset_Cnt_Limit 3 #define MAX_AGGR_NUM 0x07 @@ -25,37 +25,16 @@ /*------------------------------Define structure End----------------------------*/ /*--------------------------Exported Function prototype---------------------*/ -u32 -PHY_QueryBBReg_8723B( -struct adapter *Adapter, -u32 RegAddr, -u32 BitMask - ); - -void -PHY_SetBBReg_8723B( -struct adapter *Adapter, -u32 RegAddr, -u32 BitMask, -u32 Data - ); - -u32 -PHY_QueryRFReg_8723B( -struct adapter * Adapter, -u8 eRFPath, -u32 RegAddr, -u32 BitMask - ); - -void -PHY_SetRFReg_8723B( -struct adapter * Adapter, -u8 eRFPath, -u32 RegAddr, -u32 BitMask, -u32 Data - ); +u32 PHY_QueryBBReg_8723B(struct adapter *Adapter, u32 RegAddr, u32 BitMask); + +void PHY_SetBBReg_8723B(struct adapter *Adapter, u32 RegAddr, + u32 BitMask, u32 Data); + +u32 PHY_QueryRFReg_8723B(struct adapter *Adapter, u8 eRFPath, + u32 RegAddr, u32 BitMask); + +void PHY_SetRFReg_8723B(struct adapter *Adapter, u8 eRFPath, + u32 RegAddr, u32 BitMask, u32 Data); /* MAC/BB/RF HAL config */ int PHY_BBConfig8723B(struct adapter *Adapter); @@ -64,56 +43,25 @@ int PHY_RFConfig8723B(struct adapter *Adapter); s32 PHY_MACConfig8723B(struct adapter *padapter); -void -PHY_SetTxPowerIndex( -struct adapter * Adapter, -u32 PowerIndex, -u8 RFPath, -u8 Rate - ); - -u8 -PHY_GetTxPowerIndex( -struct adapter * padapter, -u8 RFPath, -u8 Rate, -enum CHANNEL_WIDTH BandWidth, -u8 Channel - ); - -void -PHY_GetTxPowerLevel8723B( -struct adapter * Adapter, - s32* powerlevel - ); - -void -PHY_SetTxPowerLevel8723B( -struct adapter * Adapter, -u8 channel - ); - -void -PHY_SetBWMode8723B( -struct adapter * Adapter, -enum CHANNEL_WIDTH Bandwidth, /* 20M or 40M */ -unsigned char Offset /* Upper, Lower, or Don't care */ -); - -void -PHY_SwChnl8723B(/* Call after initialization */ -struct adapter *Adapter, -u8 channel - ); - -void -PHY_SetSwChnlBWMode8723B( -struct adapter * Adapter, -u8 channel, -enum CHANNEL_WIDTH Bandwidth, -u8 Offset40, -u8 Offset80 -); +void PHY_SetTxPowerIndex(struct adapter *Adapter, u32 PowerIndex, + u8 RFPath, u8 Rate); + +u8 PHY_GetTxPowerIndex(struct adapter *padapter, u8 RFPath, u8 Rate, + enum CHANNEL_WIDTH BandWidth, u8 Channel); + +void PHY_GetTxPowerLevel8723B(struct adapter *Adapter, s32 *powerlevel); + +void PHY_SetTxPowerLevel8723B(struct adapter *Adapter, u8 channel); + +void PHY_SetBWMode8723B(struct adapter *Adapter, enum CHANNEL_WIDTH Bandwidth, + unsigned char Offset); + +/* Call after initialization */ +void PHY_SwChnl8723B(struct adapter *Adapter, u8 channel); + +void PHY_SetSwChnlBWMode8723B(struct adapter *Adapter, u8 channel, + enum CHANNEL_WIDTH Bandwidth, + u8 Offset40, u8 Offset80); /*--------------------------Exported Function prototype End---------------------*/ diff --git a/drivers/staging/rtl8723bs/include/ieee80211.h b/drivers/staging/rtl8723bs/include/ieee80211.h index 7243e656d5892227fb44d51253973e840ee26fd0..b7c4b1cf204e1fc24aeb973de22fa9a23b989b99 100644 --- a/drivers/staging/rtl8723bs/include/ieee80211.h +++ b/drivers/staging/rtl8723bs/include/ieee80211.h @@ -152,8 +152,7 @@ typedef enum _RATR_TABLE_MODE { } RATR_TABLE_MODE, *PRATR_TABLE_MODE; -enum NETWORK_TYPE -{ +enum NETWORK_TYPE { WIRELESS_INVALID = 0, /* Sub-Element */ WIRELESS_11B = BIT(0), /* tx: cck only , rx: cck only, hw: cck */ diff --git a/drivers/staging/rtl8723bs/include/ioctl_cfg80211.h b/drivers/staging/rtl8723bs/include/ioctl_cfg80211.h index 931599d8b08a0c16dd8d02eec258965c1a640c28..44d0a098265970c93cb8029f5c6a42e61e0e1bd1 100644 --- a/drivers/staging/rtl8723bs/include/ioctl_cfg80211.h +++ b/drivers/staging/rtl8723bs/include/ioctl_cfg80211.h @@ -61,8 +61,7 @@ struct rtw_wdev_nego_info { (nego_info)->conf_op_ch = 0; \ } while (0) -struct rtw_wdev_priv -{ +struct rtw_wdev_priv { struct wireless_dev *rtw_wdev; struct adapter *padapter; diff --git a/drivers/staging/rtl8723bs/include/osdep_service.h b/drivers/staging/rtl8723bs/include/osdep_service.h index 5f681899bbece5d59f544179987db98966a0f0fd..be34e279670b0b371c7d33c5cb6237e4ac4d1182 100644 --- a/drivers/staging/rtl8723bs/include/osdep_service.h +++ b/drivers/staging/rtl8723bs/include/osdep_service.h @@ -94,7 +94,6 @@ void _kfree(u8 *pbuf, u32 sz); struct sk_buff *_rtw_skb_alloc(u32 sz); struct sk_buff *_rtw_skb_copy(const struct sk_buff *skb); -struct sk_buff *_rtw_skb_clone(struct sk_buff *skb); int _rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb); #define rtw_malloc(sz) _rtw_malloc((sz)) @@ -103,9 +102,7 @@ int _rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb); #define rtw_skb_alloc(size) _rtw_skb_alloc((size)) #define rtw_skb_alloc_f(size, mstat_f) _rtw_skb_alloc((size)) #define rtw_skb_copy(skb) _rtw_skb_copy((skb)) -#define rtw_skb_clone(skb) _rtw_skb_clone((skb)) #define rtw_skb_copy_f(skb, mstat_f) _rtw_skb_copy((skb)) -#define rtw_skb_clone_f(skb, mstat_f) _rtw_skb_clone((skb)) #define rtw_netif_rx(ndev, skb) _rtw_netif_rx(ndev, skb) extern void _rtw_init_queue(struct __queue *pqueue); diff --git a/drivers/staging/rtl8723bs/include/rtl8192c_recv.h b/drivers/staging/rtl8723bs/include/rtl8192c_recv.h index c77d172de7d08b33dfc29b09b2bf8d6670e66edb..9664758e21bef34d7256ea452ce94d1435c43539 100644 --- a/drivers/staging/rtl8723bs/include/rtl8192c_recv.h +++ b/drivers/staging/rtl8723bs/include/rtl8192c_recv.h @@ -13,8 +13,7 @@ #define MAX_RECVBUF_SZ (10240) -struct phy_stat -{ +struct phy_stat { unsigned int phydw0; unsigned int phydw1; diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_recv.h b/drivers/staging/rtl8723bs/include/rtl8723b_recv.h index 31ae83f2557f9ff1410db4586c05828d325886d8..fad6749af7686640918c5f18bb9d007a42aec6ff 100644 --- a/drivers/staging/rtl8723bs/include/rtl8723b_recv.h +++ b/drivers/staging/rtl8723bs/include/rtl8723b_recv.h @@ -9,8 +9,7 @@ #include -typedef struct rxreport_8723b -{ +typedef struct rxreport_8723b { /* DWORD 0 */ u32 pktlen:14; u32 crc32:1; @@ -82,8 +81,7 @@ typedef struct rxreport_8723b u32 tsfl; } RXREPORT, *PRXREPORT; -typedef struct phystatus_8723b -{ +typedef struct phystatus_8723b { u32 rxgain_a:7; u32 trsw_a:1; u32 rxgain_b:7; diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h index 320ca65e5faa16554c6d375ae6ca93c8fac61794..243d36d9bc7bd88249f0185710c8f90b15b64622 100644 --- a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h +++ b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h @@ -59,8 +59,7 @@ /* */ /* defined for TX DESC Operation */ /* */ -typedef struct txdesc_8723b -{ +typedef struct txdesc_8723b { /* Offset 0 */ u32 pktlen:16; u32 offset:8; diff --git a/drivers/staging/rtl8723bs/include/rtw_cmd.h b/drivers/staging/rtl8723bs/include/rtw_cmd.h index 3e025a652e38f2d635b6879037a3a8b9f0e54cf9..56c77bc7ca815cdfd0b64e6e8506a709ae60c2e0 100644 --- a/drivers/staging/rtl8723bs/include/rtw_cmd.h +++ b/drivers/staging/rtl8723bs/include/rtw_cmd.h @@ -134,8 +134,7 @@ extern void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv); extern void rtw_free_evt_priv(struct evt_priv *pevtpriv); extern void rtw_evt_notify_isr(struct evt_priv *pevtpriv); -enum rtw_drvextra_cmd_id -{ +enum rtw_drvextra_cmd_id { NONE_WK_CID, DYNAMIC_CHK_WK_CID, DM_CTRL_WK_CID, @@ -159,8 +158,7 @@ enum rtw_drvextra_cmd_id MAX_WK_CID }; -enum LPS_CTRL_TYPE -{ +enum LPS_CTRL_TYPE { LPS_CTRL_SCAN = 0, LPS_CTRL_JOINBSS = 1, LPS_CTRL_CONNECT = 2, @@ -530,8 +528,7 @@ struct getrfintfs_parm { }; -struct Tx_Beacon_param -{ +struct Tx_Beacon_param { struct wlan_bssid_ex network; }; @@ -754,8 +751,7 @@ struct setassocrspextraie_parm { }; -struct addBaReq_parm -{ +struct addBaReq_parm { unsigned int tid; u8 addr[ETH_ALEN]; }; @@ -768,33 +764,28 @@ struct set_ch_parm { }; /*H2C Handler index: 59 */ -struct SetChannelPlan_param -{ +struct SetChannelPlan_param { u8 channel_plan; }; /*H2C Handler index: 60 */ -struct LedBlink_param -{ +struct LedBlink_param { void *pLed; }; /*H2C Handler index: 61 */ -struct SetChannelSwitch_param -{ +struct SetChannelSwitch_param { u8 new_ch_no; }; /*H2C Handler index: 62 */ -struct TDLSoption_param -{ +struct TDLSoption_param { u8 addr[ETH_ALEN]; u8 option; }; /*H2C Handler index: 64 */ -struct RunInThread_param -{ +struct RunInThread_param { void (*func)(void*); void *context; }; @@ -881,8 +872,7 @@ struct _cmd_callback { void (*callback)(struct adapter *padapter, struct cmd_obj *cmd); }; -enum rtw_h2c_cmd -{ +enum rtw_h2c_cmd { GEN_CMD_CODE(_Read_MACREG), /*0*/ GEN_CMD_CODE(_Write_MACREG), GEN_CMD_CODE(_Read_BBREG), diff --git a/drivers/staging/rtl8723bs/include/rtw_eeprom.h b/drivers/staging/rtl8723bs/include/rtw_eeprom.h index 704c6461333ad1e4441c037ef05c62cbfbc80823..78f34f6cebb4b8d7ae68e32bea34bf96968db96c 100644 --- a/drivers/staging/rtl8723bs/include/rtw_eeprom.h +++ b/drivers/staging/rtl8723bs/include/rtw_eeprom.h @@ -42,8 +42,7 @@ /* Besides, CustomerID of registry has precedence of that of EEPROM. */ /* defined below. 060703, by rcnjko. */ /* */ -typedef enum _RT_CUSTOMER_ID -{ +typedef enum _RT_CUSTOMER_ID { RT_CID_DEFAULT = 0, RT_CID_8187_ALPHA0 = 1, RT_CID_8187_SERCOMM_PS = 2, @@ -93,8 +92,7 @@ typedef enum _RT_CUSTOMER_ID RT_CID_DNI_BUFFALO = 46,/* add by page for NEC */ } RT_CUSTOMER_ID, *PRT_CUSTOMER_ID; -struct eeprom_priv -{ +struct eeprom_priv { u8 bautoload_fail_flag; u8 bloadfile_fail_flag; u8 bloadmac_fail_flag; diff --git a/drivers/staging/rtl8723bs/include/rtw_event.h b/drivers/staging/rtl8723bs/include/rtw_event.h index aeaabab780e5e9b35fe53b00dd62c93c1a7acdce..560521c80ace919809edbad35b859c00ef771fd2 100644 --- a/drivers/staging/rtl8723bs/include/rtw_event.h +++ b/drivers/staging/rtl8723bs/include/rtw_event.h @@ -60,13 +60,11 @@ struct stadel_event { int mac_id; }; -struct addba_event -{ +struct addba_event { unsigned int tid; }; -struct wmm_event -{ +struct wmm_event { unsigned char wmm; }; diff --git a/drivers/staging/rtl8723bs/include/rtw_ht.h b/drivers/staging/rtl8723bs/include/rtw_ht.h index 4c224c1283272ea35b8e9292741a23954e1e2be0..13489913f40b3c6fd2d57904b74a0462d02dff8c 100644 --- a/drivers/staging/rtl8723bs/include/rtw_ht.h +++ b/drivers/staging/rtl8723bs/include/rtw_ht.h @@ -8,8 +8,7 @@ #define _RTW_HT_H_ -struct ht_priv -{ +struct ht_priv { u8 ht_option; u8 ampdu_enable;/* for enable Tx A-MPDU */ u8 tx_amsdu_enable;/* for enable Tx A-MSDU */ diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme.h b/drivers/staging/rtl8723bs/include/rtw_mlme.h index 14e4bce28856d13ab26e78197d65927e7bc706be..cd98efccb32176ea7d4fc7af9ba274b05aa89dc4 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme.h @@ -101,8 +101,7 @@ enum DriverInterface { DRIVER_CFG80211 = 2 }; -enum SCAN_RESULT_TYPE -{ +enum SCAN_RESULT_TYPE { SCAN_RESULT_P2P_ONLY = 0, /* Will return all the P2P devices. */ SCAN_RESULT_ALL = 1, /* Will return all the scanned device, include AP. */ SCAN_RESULT_WFD_TYPE = 2 /* Will just return the correct WFD device. */ @@ -463,8 +462,7 @@ struct mlme_priv { void rtw_mlme_reset_auto_scan_int(struct adapter *adapter); -struct hostapd_priv -{ +struct hostapd_priv { struct adapter *padapter; }; diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h index 6c1ed6211c7ef195031a6614a8c93951dfc80c72..14583799039f20f065815e28b57ab890b8d332b0 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h @@ -115,8 +115,7 @@ extern unsigned char WMM_PARA_OUI[]; /* If you just wnat to customize the acitions(scan period or join actions) about one of the channel plan, */ /* customize them in RT_CHANNEL_INFO in the RT_CHANNEL_LIST. */ /* */ -typedef enum _RT_CHANNEL_DOMAIN -{ +typedef enum _RT_CHANNEL_DOMAIN { /* old channel plan mapping ===== */ RT_CHANNEL_DOMAIN_FCC = 0x00, RT_CHANNEL_DOMAIN_IC = 0x01, @@ -184,8 +183,7 @@ typedef enum _RT_CHANNEL_DOMAIN RT_CHANNEL_DOMAIN_REALTEK_DEFINE = 0x7F, } RT_CHANNEL_DOMAIN, *PRT_CHANNEL_DOMAIN; -typedef enum _RT_CHANNEL_DOMAIN_2G -{ +typedef enum _RT_CHANNEL_DOMAIN_2G { RT_CHANNEL_DOMAIN_2G_WORLD = 0x00, /* Worldwird 13 */ RT_CHANNEL_DOMAIN_2G_ETSI1 = 0x01, /* Europe */ RT_CHANNEL_DOMAIN_2G_FCC1 = 0x02, /* US */ @@ -197,8 +195,7 @@ typedef enum _RT_CHANNEL_DOMAIN_2G RT_CHANNEL_DOMAIN_2G_MAX, } RT_CHANNEL_DOMAIN_2G, *PRT_CHANNEL_DOMAIN_2G; -typedef enum _RT_CHANNEL_DOMAIN_5G -{ +typedef enum _RT_CHANNEL_DOMAIN_5G { RT_CHANNEL_DOMAIN_5G_NULL = 0x00, RT_CHANNEL_DOMAIN_5G_ETSI1 = 0x01, /* Europe */ RT_CHANNEL_DOMAIN_5G_ETSI2 = 0x02, /* Australia, New Zealand */ @@ -241,32 +238,27 @@ typedef enum _RT_CHANNEL_DOMAIN_5G #define rtw_is_channel_plan_valid(chplan) (chplan < RT_CHANNEL_DOMAIN_MAX || chplan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE) -typedef struct _RT_CHANNEL_PLAN -{ +typedef struct _RT_CHANNEL_PLAN { unsigned char Channel[MAX_CHANNEL_NUM]; unsigned char Len; } RT_CHANNEL_PLAN, *PRT_CHANNEL_PLAN; -typedef struct _RT_CHANNEL_PLAN_2G -{ +typedef struct _RT_CHANNEL_PLAN_2G { unsigned char Channel[MAX_CHANNEL_NUM_2G]; unsigned char Len; } RT_CHANNEL_PLAN_2G, *PRT_CHANNEL_PLAN_2G; -typedef struct _RT_CHANNEL_PLAN_5G -{ +typedef struct _RT_CHANNEL_PLAN_5G { unsigned char Channel[MAX_CHANNEL_NUM_5G]; unsigned char Len; } RT_CHANNEL_PLAN_5G, *PRT_CHANNEL_PLAN_5G; -typedef struct _RT_CHANNEL_PLAN_MAP -{ +typedef struct _RT_CHANNEL_PLAN_MAP { unsigned char Index2G; unsigned char Index5G; } RT_CHANNEL_PLAN_MAP, *PRT_CHANNEL_PLAN_MAP; -enum Associated_AP -{ +enum Associated_AP { atherosAP = 0, broadcomAP = 1, ciscoAP = 2, @@ -278,8 +270,7 @@ enum Associated_AP maxAP, }; -typedef enum _HT_IOT_PEER -{ +typedef enum _HT_IOT_PEER { HT_IOT_PEER_UNKNOWN = 0, HT_IOT_PEER_REALTEK = 1, HT_IOT_PEER_REALTEK_92SE = 2, @@ -302,8 +293,7 @@ typedef enum _HT_IOT_PEER } HT_IOT_PEER_E, *PHTIOT_PEER_E; -enum SCAN_STATE -{ +enum SCAN_STATE { SCAN_DISABLE = 0, SCAN_START = 1, SCAN_TXNULL = 2, @@ -324,8 +314,7 @@ struct action_handler { unsigned int (*func)(struct adapter *padapter, union recv_frame *precv_frame); }; -struct ss_res -{ +struct ss_res { int state; int bss_cnt; int channel_idx; @@ -355,8 +344,7 @@ struct ss_res #define WIFI_FW_LINKING_STATE (WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE | WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE) -struct FW_Sta_Info -{ +struct FW_Sta_Info { struct sta_info *psta; u32 status; u32 rx_pkt; @@ -382,8 +370,7 @@ struct FW_Sta_Info * 4. Back to channel 1 for 300 milliseconds * 5. ... and so on, till survey done. */ -struct mlme_ext_info -{ +struct mlme_ext_info { u32 state; u32 reauth_count; u32 reassoc_count; @@ -430,8 +417,7 @@ struct mlme_ext_info }; /* The channel information about this channel including joining, scanning, and power constraints. */ -typedef struct _RT_CHANNEL_INFO -{ +typedef struct _RT_CHANNEL_INFO { u8 ChannelNum; /* The channel number. */ RT_SCAN_TYPE ScanType; /* Scan type such as passive or active scan. */ } RT_CHANNEL_INFO, *PRT_CHANNEL_INFO; @@ -472,8 +458,7 @@ struct p2p_oper_class_map { enum { BW20, BW40PLUS, BW40MINUS } bw; }; -struct mlme_ext_priv -{ +struct mlme_ext_priv { struct adapter *padapter; u8 mlmeext_init; atomic_t event_seq; @@ -786,8 +771,7 @@ u8 run_in_thread_hdl(struct adapter *padapter, u8 *pbuf); #define GEN_DRV_CMD_HANDLER(size, cmd) {size, &cmd ## _hdl}, #define GEN_MLME_EXT_HANDLER(size, cmd) {size, cmd}, -struct C2HEvent_Header -{ +struct C2HEvent_Header { #ifdef __LITTLE_ENDIAN @@ -805,8 +789,7 @@ struct C2HEvent_Header void rtw_dummy_event_callback(struct adapter *adapter, u8 *pbuf); void rtw_fwdbg_event_callback(struct adapter *adapter, u8 *pbuf); -enum rtw_c2h_event -{ +enum rtw_c2h_event { GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/ GEN_EVT_CODE(_Read_BBREG), GEN_EVT_CODE(_Read_RFREG), diff --git a/drivers/staging/rtl8723bs/include/rtw_mp.h b/drivers/staging/rtl8723bs/include/rtw_mp.h index e5a801b405829c9fd2f24d20ab1337b26e3304b2..4d156eab029c5bf3ca47f0a0d48fb4fb70cdf42c 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mp.h +++ b/drivers/staging/rtl8723bs/include/rtw_mp.h @@ -10,8 +10,7 @@ #define MAX_MP_XMITBUF_SZ 2048 #define NR_MP_XMITFRAME 8 -struct mp_xmit_frame -{ +struct mp_xmit_frame { struct list_head list; struct pkt_attrib attrib; @@ -25,8 +24,7 @@ struct mp_xmit_frame uint mem[(MAX_MP_XMITBUF_SZ >> 2)]; }; -struct mp_wiparam -{ +struct mp_wiparam { u32 bcompleted; u32 act_type; u32 io_offset; @@ -35,8 +33,7 @@ struct mp_wiparam typedef void(*wi_act_func)(void* padapter); -struct mp_tx -{ +struct mp_tx { u8 stop; u32 count, sended; u8 payload; @@ -54,8 +51,7 @@ struct mp_tx #define MP_MAX_LINES_BYTES 256 typedef void (*MPT_WORK_ITEM_HANDLER)(void *Adapter); -typedef struct _MPT_CONTEXT -{ +typedef struct _MPT_CONTEXT { /* Indicate if we have started Mass Production Test. */ bool bMassProdTest; @@ -205,8 +201,7 @@ enum { MP_GET_TXPOWER_INX, }; -struct mp_priv -{ +struct mp_priv { struct adapter *papdater; /* Testing Flag */ diff --git a/drivers/staging/rtl8723bs/include/rtw_pwrctrl.h b/drivers/staging/rtl8723bs/include/rtw_pwrctrl.h index 2bc922ce5ae13781a56c0b9924b845288fdb4408..3d999540e239eaee0e999b9bcbe7278a3633293a 100644 --- a/drivers/staging/rtl8723bs/include/rtw_pwrctrl.h +++ b/drivers/staging/rtl8723bs/include/rtw_pwrctrl.h @@ -159,8 +159,7 @@ enum PS_DENY_REASON { }; #ifdef CONFIG_PNO_SUPPORT -struct pno_nlo_info -{ +struct pno_nlo_info { u32 fast_scan_period; /* Fast scan period */ u32 ssid_num; /* number of entry */ u32 slow_scan_period; /* slow scan period */ @@ -179,16 +178,14 @@ struct pno_ssid_list { struct pno_ssid node[MAX_PNO_LIST_COUNT]; }; -struct pno_scan_channel_info -{ +struct pno_scan_channel_info { u8 channel; u8 tx_power; u8 timeout; u8 active; /* set 1 means active scan, or pasivite scan. */ }; -struct pno_scan_info -{ +struct pno_scan_info { u8 enableRFE; /* Enable RFE */ u8 period_scan_time; /* exclusive with fast_scan_period and slow_scan_period */ u8 periodScan; /* exclusive with fast_scan_period and slow_scan_period */ @@ -202,8 +199,7 @@ struct pno_scan_info }; #endif /* CONFIG_PNO_SUPPORT */ -struct pwrctrl_priv -{ +struct pwrctrl_priv { struct mutex lock; volatile u8 rpwm; /* requested power state for fw */ volatile u8 cpwm; /* fw current power state. updated when 1. read from HCPWM 2. driver lowers power level */ diff --git a/drivers/staging/rtl8723bs/include/rtw_recv.h b/drivers/staging/rtl8723bs/include/rtw_recv.h index a851b818ef0ec76f48109c54db91b002e387f15b..60bf00f35caea4f4589ef0207d7ee0781f0d72c9 100644 --- a/drivers/staging/rtl8723bs/include/rtw_recv.h +++ b/drivers/staging/rtl8723bs/include/rtw_recv.h @@ -40,8 +40,7 @@ #define MAX_SUBFRAME_COUNT 64 /* for Rx reordering buffer control */ -struct recv_reorder_ctrl -{ +struct recv_reorder_ctrl { struct adapter *padapter; u8 enable; u16 indicate_seq;/* wstart_b, init_value = 0xffff */ @@ -112,8 +111,7 @@ struct phy_info { }; #ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA -struct rx_raw_rssi -{ +struct rx_raw_rssi { u8 data_rate; u8 pwdball; s8 pwr_all; @@ -292,8 +290,7 @@ struct sta_recv_priv { }; -struct recv_buf -{ +struct recv_buf { struct list_head list; _lock recvbuf_lock; @@ -331,8 +328,7 @@ struct recv_buf len = (unsigned int)(tail - data); */ -struct recv_frame_hdr -{ +struct recv_frame_hdr { struct list_head list; #ifndef CONFIG_BSD_RX_USE_MBUF struct sk_buff *pkt; diff --git a/drivers/staging/rtl8723bs/include/rtw_security.h b/drivers/staging/rtl8723bs/include/rtw_security.h index aa60b6f867dd061ce3b735a5fe46fff44dfd6a2d..514c0799c34bf4b366434ce4b4931807bc4c42d3 100644 --- a/drivers/staging/rtl8723bs/include/rtw_security.h +++ b/drivers/staging/rtl8723bs/include/rtw_security.h @@ -87,8 +87,7 @@ union Keytype { }; -typedef struct _RT_PMKID_LIST -{ +typedef struct _RT_PMKID_LIST { u8 bUsed; u8 Bssid[6]; u8 PMKID[16]; @@ -98,8 +97,7 @@ typedef struct _RT_PMKID_LIST } RT_PMKID_LIST, *PRT_PMKID_LIST; -struct security_priv -{ +struct security_priv { u32 dot11AuthAlgrthm; /* 802.11 auth, could be open, shared, 8021x and authswitch */ u32 dot11PrivacyAlgrthm; /* This specify the privacy for shared auth. algorithm. */ @@ -273,8 +271,7 @@ do {\ #define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1))) #define ROR32(A, n) ROL32((A), 32-(n)) -struct mic_data -{ +struct mic_data { u32 K0, K1; /* Key */ u32 L, R; /* Current state */ u32 M; /* Message accumulator (single word) */ diff --git a/drivers/staging/rtl8723bs/include/rtw_xmit.h b/drivers/staging/rtl8723bs/include/rtw_xmit.h index cd2be0056aa1abd23aae51113e882bcaf023426f..196e70865c00f06ce390ce0cc0daaa85a7bd9b9c 100644 --- a/drivers/staging/rtl8723bs/include/rtw_xmit.h +++ b/drivers/staging/rtl8723bs/include/rtw_xmit.h @@ -137,8 +137,7 @@ struct hw_xmit { }; /* reduce size */ -struct pkt_attrib -{ +struct pkt_attrib { u8 type; u8 subtype; u8 bswenc; @@ -246,8 +245,7 @@ int rtw_sctx_wait(struct submit_ctx *sctx, const char *msg); void rtw_sctx_done_err(struct submit_ctx **sctx, int status); void rtw_sctx_done(struct submit_ctx **sctx); -struct xmit_buf -{ +struct xmit_buf { struct list_head list; struct adapter *padapter; @@ -281,8 +279,7 @@ struct xmit_buf }; -struct xmit_frame -{ +struct xmit_frame { struct list_head list; struct pkt_attrib attrib; @@ -314,8 +311,7 @@ struct tx_servq { }; -struct sta_xmit_priv -{ +struct sta_xmit_priv { _lock lock; sint option; sint apsd_setting; /* When bit mask is on, the associated edca queue supports APSD. */ diff --git a/drivers/staging/rtl8723bs/include/wifi.h b/drivers/staging/rtl8723bs/include/wifi.h index 88a6e982ce0120bdca975451c74a5487e140252d..3a7dd2ed26a822774ac63ea94cfda5ad1d400ef3 100644 --- a/drivers/staging/rtl8723bs/include/wifi.h +++ b/drivers/staging/rtl8723bs/include/wifi.h @@ -657,11 +657,6 @@ struct rtw_ieee80211_bar { __le16 start_seq_num; } __attribute__((packed)); -/* 802.11 BAR control masks */ -#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 -#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 - - /** * struct rtw_ieee80211_ht_cap - HT capabilities * @@ -693,12 +688,9 @@ struct ieee80211_ht_addt_info { } __attribute__ ((packed)); -struct HT_caps_element -{ - union - { - struct - { +struct HT_caps_element { + union { + struct { __le16 HT_caps_info; unsigned char AMPDU_para; unsigned char MCS_rate[16]; @@ -710,29 +702,25 @@ struct HT_caps_element } u; } __attribute__ ((packed)); -struct HT_info_element -{ +struct HT_info_element { unsigned char primary_channel; unsigned char infos[5]; unsigned char MCS_rate[16]; } __attribute__ ((packed)); -struct AC_param -{ +struct AC_param { unsigned char ACI_AIFSN; unsigned char CW; __le16 TXOP_limit; } __attribute__ ((packed)); -struct WMM_para_element -{ +struct WMM_para_element { unsigned char QoS_info; unsigned char reserved; struct AC_param ac_param[4]; } __attribute__ ((packed)); -struct ADDBA_request -{ +struct ADDBA_request { unsigned char dialog_token; __le16 BA_para_set; __le16 BA_timeout_value; @@ -1095,8 +1083,7 @@ enum P2P_WPSINFO { #define P2P_PRIVATE_IOCTL_SET_LEN 64 -enum P2P_PROTO_WK_ID -{ +enum P2P_PROTO_WK_ID { P2P_FIND_PHASE_WK = 0, P2P_RESTORE_STATE_WK = 1, P2P_PRE_TX_PROVDISC_PROCESS_WK = 2, diff --git a/drivers/staging/rtl8723bs/include/wlan_bssdef.h b/drivers/staging/rtl8723bs/include/wlan_bssdef.h index 723fc5b546efae7decc0203f053200d3e17ca383..ea370b2bb8db35b5ee72b00994fec0d1326b47f5 100644 --- a/drivers/staging/rtl8723bs/include/wlan_bssdef.h +++ b/drivers/staging/rtl8723bs/include/wlan_bssdef.h @@ -127,8 +127,7 @@ struct ndis_801_11_ai_resfi { u16 AssociationId; }; -typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION -{ +typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION { u32 Length; u16 AvailableRequestFixedIEs; struct ndis_802_11_ai_reqfi RequestFixedIEs; @@ -146,8 +145,7 @@ enum NDIS_802_11_RELOAD_DEFAULTS { /* Key mapping keys require a BSSID */ -typedef struct _NDIS_802_11_KEY -{ +typedef struct _NDIS_802_11_KEY { u32 Length; /* Length of this structure */ u32 KeyIndex; u32 KeyLength; /* length of key in bytes */ @@ -156,8 +154,7 @@ typedef struct _NDIS_802_11_KEY u8 KeyMaterial[32]; /* variable length depending on above field */ } NDIS_802_11_KEY, *PNDIS_802_11_KEY; -typedef struct _NDIS_802_11_REMOVE_KEY -{ +typedef struct _NDIS_802_11_REMOVE_KEY { u32 Length; /* Length of this structure */ u32 KeyIndex; NDIS_802_11_MAC_ADDRESS BSSID; diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index 50a3c2c3a8d25ecaedc2bc57564894680c42e1ee..27f990a01a23fdcdaf2a9569ee9a592efab5d514 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -313,7 +313,7 @@ static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p) struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); struct sockaddr *addr = p; - if (padapter->bup == false) { + if (!padapter->bup) { /* DBG_871X("r8711_net_set_mac_address(), MAC =%x:%x:%x:%x:%x:%x\n", addr->sa_data[0], addr->sa_data[1], addr->sa_data[2], addr->sa_data[3], */ /* addr->sa_data[4], addr->sa_data[5]); */ memcpy(padapter->eeprompriv.mac_addr, addr->sa_data, ETH_ALEN); @@ -897,12 +897,12 @@ int _netdev_open(struct net_device *pnetdev) padapter->netif_up = true; - if (pwrctrlpriv->ps_flag == true) { + if (pwrctrlpriv->ps_flag) { padapter->net_closed = false; goto netdev_open_normal_process; } - if (padapter->bup == false) { + if (!padapter->bup) { padapter->bDriverStopped = false; padapter->bSurpriseRemoved = false; padapter->bCardDisableWOHSM = false; @@ -964,7 +964,7 @@ int netdev_open(struct net_device *pnetdev) struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); - if (pwrctrlpriv->bInSuspend == true) { + if (pwrctrlpriv->bInSuspend) { DBG_871X("+871x_drv - drv_open, bInSuspend =%d\n", pwrctrlpriv->bInSuspend); return 0; } @@ -1041,7 +1041,7 @@ void rtw_ips_dev_unload(struct adapter *padapter) DBG_871X("====> %s...\n", __func__); - if (padapter->bSurpriseRemoved == false) + if (!padapter->bSurpriseRemoved) rtw_hal_deinit(padapter); } @@ -1052,7 +1052,7 @@ static int pm_netdev_open(struct net_device *pnetdev, u8 bnormal) struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); - if (true == bnormal) { + if (bnormal) { if (mutex_lock_interruptible(&(adapter_to_dvobj(padapter)->hw_init_mutex)) == 0) { status = _netdev_open(pnetdev); mutex_unlock(&(adapter_to_dvobj(padapter)->hw_init_mutex)); @@ -1071,7 +1071,7 @@ static int netdev_close(struct net_device *pnetdev) RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+871x_drv - drv_close\n")); - if (pwrctl->bInternalAutoSuspend == true) { + if (pwrctl->bInternalAutoSuspend) { /* rtw_pwr_wakeup(padapter); */ if (pwrctl->rf_pwrstate == rf_off) pwrctl->ps_flag = true; @@ -1134,7 +1134,7 @@ void rtw_dev_unload(struct adapter *padapter) RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+%s\n", __func__)); - if (padapter->bup == true) { + if (padapter->bup) { DBG_871X("===> %s\n", __func__); padapter->bDriverStopped = true; @@ -1149,7 +1149,7 @@ void rtw_dev_unload(struct adapter *padapter) if (!pwrctl->bInternalAutoSuspend) rtw_stop_drv_threads(padapter); - while (atomic_read(&(pcmdpriv->cmdthd_running)) == true) { + while (atomic_read(&pcmdpriv->cmdthd_running)) { if (cnt > 5) { DBG_871X("stop cmdthd timeout\n"); break; @@ -1163,7 +1163,8 @@ void rtw_dev_unload(struct adapter *padapter) RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("@ %s: stop thread complete!\n", __func__)); /* check the status of IPS */ - if (rtw_hal_check_ips_status(padapter) == true || pwrctl->rf_pwrstate == rf_off) { /* check HW status and SW state */ + if (rtw_hal_check_ips_status(padapter) || pwrctl->rf_pwrstate == rf_off) { + /* check HW status and SW state */ DBG_871X_LEVEL(_drv_always_, "%s: driver in IPS-FWLPS\n", __func__); pdbgpriv->dbg_dev_unload_inIPS_cnt++; LeaveAllPowerSaveMode(padapter); @@ -1171,11 +1172,10 @@ void rtw_dev_unload(struct adapter *padapter) DBG_871X_LEVEL(_drv_always_, "%s: driver not in IPS\n", __func__); } - if (padapter->bSurpriseRemoved == false) { + if (!padapter->bSurpriseRemoved) { hal_btcoex_IpsNotify(padapter, pwrctl->ips_mode_req); #ifdef CONFIG_WOWLAN - if (pwrctl->bSupportRemoteWakeup == true && - pwrctl->wowlan_mode == true) { + if (pwrctl->bSupportRemoteWakeup && pwrctl->wowlan_mode) { DBG_871X_LEVEL(_drv_always_, "%s bSupportRemoteWakeup ==true do not run rtw_hal_deinit()\n", __func__); } else @@ -1235,7 +1235,7 @@ static int rtw_suspend_free_assoc_resource(struct adapter *padapter) if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) rtw_indicate_scan_done(padapter, 1); - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) { + if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { DBG_871X_LEVEL(_drv_always_, "%s: fw_under_linking\n", __func__); rtw_indicate_disconnect(padapter); } @@ -1259,7 +1259,7 @@ void rtw_suspend_wow(struct adapter *padapter) DBG_871X("wowlan_mode: %d\n", pwrpriv->wowlan_mode); DBG_871X("wowlan_pno_enable: %d\n", pwrpriv->wowlan_pno_enable); - if (pwrpriv->wowlan_mode == true) { + if (pwrpriv->wowlan_mode) { if (pnetdev) rtw_netif_stop_queue(pnetdev); /* 1. stop thread */ @@ -1283,8 +1283,7 @@ void rtw_suspend_wow(struct adapter *padapter) poidparam.subcode = WOWLAN_ENABLE; padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_WOWLAN, (u8 *)&poidparam); if (rtw_chk_roam_flags(padapter, RTW_ROAM_ON_RESUME)) { - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) - && check_fwstate(pmlmepriv, _FW_LINKED)) { + if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED)) { DBG_871X("%s %s(" MAC_FMT "), length:%d assoc_ssid.length:%d\n", __func__, pmlmepriv->cur_network.network.Ssid.Ssid, MAC_ARG(pmlmepriv->cur_network.network.MacAddress), @@ -1297,7 +1296,7 @@ void rtw_suspend_wow(struct adapter *padapter) DBG_871X_LEVEL(_drv_always_, "%s: wowmode suspending\n", __func__); - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) { + if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { DBG_871X_LEVEL(_drv_always_, "%s: fw_under_survey\n", __func__); rtw_indicate_scan_done(padapter, 1); clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY); @@ -1313,8 +1312,7 @@ void rtw_suspend_wow(struct adapter *padapter) DBG_871X_LEVEL(_drv_always_, "%s: pno: %d\n", __func__, pwrpriv->wowlan_pno_enable); else rtw_set_ps_mode(padapter, PS_MODE_DTIM, 0, 0, "WOWLAN"); - } - else { + } else { DBG_871X_LEVEL(_drv_always_, "%s: ### ERROR ### wowlan_mode =%d\n", __func__, pwrpriv->wowlan_mode); } DBG_871X("<== " FUNC_ADPT_FMT " exit....\n", FUNC_ADPT_ARG(padapter)); @@ -1385,10 +1383,8 @@ static void rtw_suspend_normal(struct adapter *padapter) rtw_suspend_free_assoc_resource(padapter); - if ((rtw_hal_check_ips_status(padapter) == true) - || (adapter_to_pwrctl(padapter)->rf_pwrstate == rf_off)) { + if ((rtw_hal_check_ips_status(padapter)) || (adapter_to_pwrctl(padapter)->rf_pwrstate == rf_off)) DBG_871X_LEVEL(_drv_always_, "%s: ### ERROR #### driver in IPS ####ERROR###!!!\n", __func__); - } rtw_dev_unload(padapter); @@ -1415,7 +1411,7 @@ int rtw_suspend_common(struct adapter *padapter) pwrpriv->bInSuspend = true; - while (pwrpriv->bips_processing == true) + while (pwrpriv->bips_processing) msleep(1); if ((!padapter->bup) || (padapter->bDriverStopped) || (padapter->bSurpriseRemoved)) { @@ -1433,24 +1429,24 @@ int rtw_suspend_common(struct adapter *padapter) rtw_stop_cmd_thread(padapter); /* wait for the latest FW to remove this condition. */ - if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { + if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { hal_btcoex_SuspendNotify(padapter, 0); DBG_871X("WIFI_AP_STATE\n"); - } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) { + } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { hal_btcoex_SuspendNotify(padapter, 1); DBG_871X("STATION\n"); } rtw_ps_deny_cancel(padapter, PS_DENY_SUSPEND); - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) { + if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { #ifdef CONFIG_WOWLAN if (check_fwstate(pmlmepriv, _FW_LINKED)) pwrpriv->wowlan_mode = true; - else if (pwrpriv->wowlan_pno_enable == true) + else if (pwrpriv->wowlan_pno_enable) pwrpriv->wowlan_mode |= pwrpriv->wowlan_pno_enable; - if (pwrpriv->wowlan_mode == true) + if (pwrpriv->wowlan_mode) rtw_suspend_wow(padapter); else rtw_suspend_normal(padapter); @@ -1458,7 +1454,7 @@ int rtw_suspend_common(struct adapter *padapter) #else /* CONFIG_WOWLAN */ rtw_suspend_normal(padapter); #endif /* CONFIG_WOWLAN */ - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { + } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { #ifdef CONFIG_AP_WOWLAN rtw_suspend_ap_wow(padapter); #else @@ -1513,7 +1509,7 @@ int rtw_resume_process_wow(struct adapter *padapter) pwrpriv->pno_in_resume = true; #endif - if (pwrpriv->wowlan_mode == true) { + if (pwrpriv->wowlan_mode) { rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, "WOWLAN"); pwrpriv->bFwCurrentInPSMode = false; @@ -1553,8 +1549,7 @@ int rtw_resume_process_wow(struct adapter *padapter) else rtw_netif_wake_queue(pnetdev); } - } - else { + } else { DBG_871X_LEVEL(_drv_always_, "%s: ### ERROR ### wowlan_mode =%d\n", __func__, pwrpriv->wowlan_mode); } @@ -1584,7 +1579,7 @@ int rtw_resume_process_wow(struct adapter *padapter) } } - if (pwrpriv->wowlan_mode == true) { + if (pwrpriv->wowlan_mode) { pwrpriv->bips_processing = false; _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000); } else { @@ -1730,7 +1725,6 @@ static int rtw_resume_process_normal(struct adapter *padapter) rtw_signal_process(padapter->pid[1], SIGUSR2); } - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { DBG_871X(FUNC_ADPT_FMT " fwstate:0x%08x - WIFI_STATION_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv)); @@ -1762,9 +1756,9 @@ int rtw_resume_common(struct adapter *padapter) DBG_871X_LEVEL(_drv_always_, "resume start\n"); DBG_871X("==> %s (%s:%d)\n", __func__, current->comm, current->pid); - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) { + if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { #ifdef CONFIG_WOWLAN - if (pwrpriv->wowlan_mode == true) + if (pwrpriv->wowlan_mode) rtw_resume_process_wow(padapter); else rtw_resume_process_normal(padapter); @@ -1772,7 +1766,7 @@ int rtw_resume_common(struct adapter *padapter) rtw_resume_process_normal(padapter); #endif - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { + } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { #ifdef CONFIG_AP_WOWLAN rtw_resume_process_ap_wow(padapter); #else diff --git a/drivers/staging/rtl8723bs/os_dep/osdep_service.c b/drivers/staging/rtl8723bs/os_dep/osdep_service.c index 4238209ec17562b883b0948503a53f5d085c8ab6..f61ad9200960dd8358c7e75004b614d72713af8d 100644 --- a/drivers/staging/rtl8723bs/os_dep/osdep_service.c +++ b/drivers/staging/rtl8723bs/os_dep/osdep_service.c @@ -47,11 +47,6 @@ inline struct sk_buff *_rtw_skb_copy(const struct sk_buff *skb) return skb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); } -inline struct sk_buff *_rtw_skb_clone(struct sk_buff *skb) -{ - return skb_clone(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); -} - inline int _rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb) { skb->dev = ndev; @@ -151,10 +146,8 @@ int rtw_change_ifname(struct adapter *padapter, const char *ifname) rereg_priv->old_pnetdev = cur_pnetdev; pnetdev = rtw_init_netdev(padapter); - if (!pnetdev) { - ret = -1; + if (!pnetdev) goto error; - } SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter))); @@ -175,9 +168,7 @@ int rtw_change_ifname(struct adapter *padapter, const char *ifname) return 0; error: - return -1; - } void rtw_buf_free(u8 **buf, u32 *buf_len) diff --git a/drivers/staging/rtl8723bs/os_dep/recv_linux.c b/drivers/staging/rtl8723bs/os_dep/recv_linux.c index eb4d1c3008fea63f53d5c6aeaf72d3dc1bd04c68..b2a1bbb30df65421a953183bb57e827273bdfe81 100644 --- a/drivers/staging/rtl8723bs/os_dep/recv_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/recv_linux.c @@ -110,7 +110,7 @@ void rtw_os_recv_indicate_pkt(struct adapter *padapter, _pkt *pkt, struct rx_pkt if (memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)) { if (bmcast) { psta = rtw_get_bcmc_stainfo(padapter); - pskb2 = rtw_skb_clone(pkt); + pskb2 = skb_clone(pkt, GFP_ATOMIC); } else { psta = rtw_get_stainfo(pstapriv, pattrib->dst); } diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index d53dd138a356bf086d2cdb723039d31bf1b2a35f..9001570a8c947e612db31ad52e0369a34837714f 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -2306,14 +2306,14 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) if (!segment->l2p_table) goto BUILD_FAIL; } - memset((u8 *)(segment->l2p_table), 0xff, table_size * 2); + memset((u8 *)(segment->l2p_table), 0xff, array_size(table_size, 2)); if (!segment->free_table) { - segment->free_table = vmalloc(MS_FREE_TABLE_CNT * 2); + segment->free_table = vmalloc(array_size(MS_FREE_TABLE_CNT, 2)); if (!segment->free_table) goto BUILD_FAIL; } - memset((u8 *)(segment->free_table), 0xff, MS_FREE_TABLE_CNT * 2); + memset((u8 *)(segment->free_table), 0xff, array_size(MS_FREE_TABLE_CNT, 2)); start = (u16)seg_no << 9; end = (u16)(seg_no + 1) << 9; diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index be0053c795b7acc3d4a9e4321e051304af69f9ff..898add4d1fc8817a9ba91d78e8a6df9c0a26a2ac 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -258,12 +258,12 @@ static int rtsx_acquire_irq(struct rtsx_dev *dev) return 0; } -#ifdef CONFIG_PM /* * power management */ -static int rtsx_suspend(struct pci_dev *pci, pm_message_t state) +static int __maybe_unused rtsx_suspend(struct device *dev_d) { + struct pci_dev *pci = to_pci_dev(dev_d); struct rtsx_dev *dev = pci_get_drvdata(pci); struct rtsx_chip *chip; @@ -283,12 +283,9 @@ static int rtsx_suspend(struct pci_dev *pci, pm_message_t state) } if (chip->msi_en) - pci_disable_msi(pci); + pci_free_irq_vectors(pci); - pci_save_state(pci); - pci_enable_wake(pci, pci_choose_state(pci, state), 1); - pci_disable_device(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); + device_wakeup_enable(dev_d); /* unlock the device pointers */ mutex_unlock(&dev->dev_mutex); @@ -296,8 +293,9 @@ static int rtsx_suspend(struct pci_dev *pci, pm_message_t state) return 0; } -static int rtsx_resume(struct pci_dev *pci) +static int __maybe_unused rtsx_resume(struct device *dev_d) { + struct pci_dev *pci = to_pci_dev(dev_d); struct rtsx_dev *dev = pci_get_drvdata(pci); struct rtsx_chip *chip; @@ -309,20 +307,10 @@ static int rtsx_resume(struct pci_dev *pci) /* lock the device pointers */ mutex_lock(&dev->dev_mutex); - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - dev_err(&dev->pci->dev, - "%s: pci_enable_device failed, disabling device\n", - CR_DRIVER_NAME); - /* unlock the device pointers */ - mutex_unlock(&dev->dev_mutex); - return -EIO; - } pci_set_master(pci); if (chip->msi_en) { - if (pci_enable_msi(pci) < 0) + if (pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) < 0) chip->msi_en = 0; } @@ -340,7 +328,6 @@ static int rtsx_resume(struct pci_dev *pci) return 0; } -#endif /* CONFIG_PM */ static void rtsx_shutdown(struct pci_dev *pci) { @@ -360,7 +347,7 @@ static void rtsx_shutdown(struct pci_dev *pci) } if (chip->msi_en) - pci_disable_msi(pci); + pci_free_irq_vectors(pci); pci_disable_device(pci); } @@ -607,7 +594,7 @@ static void rtsx_release_resources(struct rtsx_dev *dev) if (dev->irq > 0) free_irq(dev->irq, (void *)dev); if (dev->chip->msi_en) - pci_disable_msi(dev->pci); + pci_free_irq_vectors(dev->pci); if (dev->remap_addr) iounmap(dev->remap_addr); @@ -894,7 +881,7 @@ static int rtsx_probe(struct pci_dev *pci, dev_info(&pci->dev, "pci->irq = %d\n", pci->irq); if (dev->chip->msi_en) { - if (pci_enable_msi(pci) < 0) + if (pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) < 0) dev->chip->msi_en = 0; } @@ -965,13 +952,14 @@ irq_acquire_fail: dev->chip->host_cmds_ptr = NULL; dev->chip->host_sg_tbl_ptr = NULL; if (dev->chip->msi_en) - pci_disable_msi(dev->pci); + pci_free_irq_vectors(dev->pci); dma_alloc_fail: iounmap(dev->remap_addr); ioremap_fail: kfree(dev->chip); chip_alloc_fail: dev_err(&pci->dev, "%s failed\n", __func__); + scsi_host_put(host); scsi_host_alloc_fail: pci_release_regions(pci); return err; @@ -999,16 +987,15 @@ static const struct pci_device_id rtsx_ids[] = { MODULE_DEVICE_TABLE(pci, rtsx_ids); +static SIMPLE_DEV_PM_OPS(rtsx_pm_ops, rtsx_suspend, rtsx_resume); + /* pci_driver definition */ static struct pci_driver rtsx_driver = { .name = CR_DRIVER_NAME, .id_table = rtsx_ids, .probe = rtsx_probe, .remove = rtsx_remove, -#ifdef CONFIG_PM - .suspend = rtsx_suspend, - .resume = rtsx_resume, -#endif + .driver.pm = &rtsx_pm_ops, .shutdown = rtsx_shutdown, }; diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c index c6f9375468ebd553224ba9b309240ee886b86c0f..ee9ddc4eb94dfbe50fb40ccc0b5c927670282c26 100644 --- a/drivers/staging/rts5208/rtsx_chip.c +++ b/drivers/staging/rts5208/rtsx_chip.c @@ -1440,6 +1440,7 @@ int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, u16 aligned_addr = addr - offset; int dw_len, i, j; int retval; + size_t size; if (!buf) return STATUS_NOMEM; @@ -1451,11 +1452,12 @@ int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len); - data = vzalloc(array_size(dw_len, 4)); + size = array_size(dw_len, 4); + data = vzalloc(size); if (!data) return STATUS_NOMEM; - mask = vzalloc(array_size(dw_len, 4)); + mask = vzalloc(size); if (!mask) { vfree(data); return STATUS_NOMEM; @@ -1471,10 +1473,8 @@ int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, } } - print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, mask, - dw_len * 4); - print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, data, - dw_len * 4); + print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, mask, size); + print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, data, size); for (i = 0; i < dw_len; i++) { retval = rtsx_write_cfg_dw(chip, func, aligned_addr + i * 4, diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c index 5f1eefe80f1e69cf55b6f8c7e30d4d9746b1de9b..0027bcf638ad1fb5575f575e83ff271d1db627b1 100644 --- a/drivers/staging/rts5208/rtsx_transport.c +++ b/drivers/staging/rts5208/rtsx_transport.c @@ -678,7 +678,7 @@ static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, /* Wait for TRANS_OK_INT */ timeleft = wait_for_completion_interruptible_timeout(&trans_done, - msecs_to_jiffies(timeout)); + msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", __func__, __LINE__); diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index a1a82e59dfee181db277e4423d02e9a4085874f8..84fb585a5739bfdc2228481eef27c5cbfc77ee69 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -407,61 +407,29 @@ static inline unsigned int chan_to_field(unsigned int chan, return chan << bf->offset; } -#ifdef CONFIG_PM -static int lynxfb_suspend(struct pci_dev *pdev, pm_message_t mesg) +static int __maybe_unused lynxfb_suspend(struct device *dev) { struct fb_info *info; struct sm750_dev *sm750_dev; - int ret; - - if (mesg.event == pdev->dev.power.power_state.event) - return 0; - - ret = 0; - sm750_dev = pci_get_drvdata(pdev); - switch (mesg.event) { - case PM_EVENT_FREEZE: - case PM_EVENT_PRETHAW: - pdev->dev.power.power_state = mesg; - return 0; - } + sm750_dev = dev_get_drvdata(dev); console_lock(); - if (mesg.event & PM_EVENT_SLEEP) { - info = sm750_dev->fbinfo[0]; - if (info) - /* 1 means do suspend */ - fb_set_suspend(info, 1); - info = sm750_dev->fbinfo[1]; - if (info) - /* 1 means do suspend */ - fb_set_suspend(info, 1); - - ret = pci_save_state(pdev); - if (ret) { - dev_err(&pdev->dev, - "error:%d occurred in pci_save_state\n", ret); - goto lynxfb_suspend_err; - } - - ret = pci_set_power_state(pdev, pci_choose_state(pdev, mesg)); - if (ret) { - dev_err(&pdev->dev, - "error:%d occurred in pci_set_power_state\n", - ret); - goto lynxfb_suspend_err; - } - } - - pdev->dev.power.power_state = mesg; + info = sm750_dev->fbinfo[0]; + if (info) + /* 1 means do suspend */ + fb_set_suspend(info, 1); + info = sm750_dev->fbinfo[1]; + if (info) + /* 1 means do suspend */ + fb_set_suspend(info, 1); -lynxfb_suspend_err: console_unlock(); - return ret; + return 0; } -static int lynxfb_resume(struct pci_dev *pdev) +static int __maybe_unused lynxfb_resume(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct fb_info *info; struct sm750_dev *sm750_dev; @@ -469,32 +437,10 @@ static int lynxfb_resume(struct pci_dev *pdev) struct lynxfb_crtc *crtc; struct lynx_cursor *cursor; - int ret; - - ret = 0; sm750_dev = pci_get_drvdata(pdev); console_lock(); - ret = pci_set_power_state(pdev, PCI_D0); - if (ret) { - dev_err(&pdev->dev, - "error:%d occurred in pci_set_power_state\n", ret); - goto lynxfb_resume_err; - } - - if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) { - pci_restore_state(pdev); - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, - "error:%d occurred in pci_enable_device\n", - ret); - goto lynxfb_resume_err; - } - pci_set_master(pdev); - } - hw_sm750_inithw(sm750_dev, pdev); info = sm750_dev->fbinfo[0]; @@ -523,11 +469,9 @@ static int lynxfb_resume(struct pci_dev *pdev) pdev->dev.power.power_state.event = PM_EVENT_RESUME; -lynxfb_resume_err: console_unlock(); - return ret; + return 0; } -#endif static int lynxfb_ops_check_var(struct fb_var_screeninfo *var, struct fb_info *info) @@ -1210,15 +1154,14 @@ static const struct pci_device_id smi_pci_table[] = { MODULE_DEVICE_TABLE(pci, smi_pci_table); +static SIMPLE_DEV_PM_OPS(lynxfb_pm_ops, lynxfb_suspend, lynxfb_resume); + static struct pci_driver lynxfb_driver = { .name = "sm750fb", .id_table = smi_pci_table, .probe = lynxfb_pci_probe, .remove = lynxfb_pci_remove, -#ifdef CONFIG_PM - .suspend = lynxfb_suspend, - .resume = lynxfb_resume, -#endif + .driver.pm = &lynxfb_pm_ops, }; static int __init lynxfb_init(void) diff --git a/drivers/staging/speakup/TODO b/drivers/staging/speakup/TODO deleted file mode 100644 index 993410c3e531bc89edc522b0826d4e2c5f9453c4..0000000000000000000000000000000000000000 --- a/drivers/staging/speakup/TODO +++ /dev/null @@ -1,47 +0,0 @@ -Speakup project home: http://www.linux-speakup.org - -Mailing List: speakup@linux-speakup.org - -Speakup is a kernel based screen review package for the linux operating -system. It allows blind users to interact with applications on the -linux console by means of synthetic speech. - -Currently, speakup has several issues we know of. - -The first issue has to do with the way speakup communicates with serial -ports. Currently, we communicate directly with the hardware -ports. This however conflicts with the standard serial port drivers, -which poses various problems. This is also not working for modern hardware -such as PCI-based serial ports. Also, there is not a way we can -communicate with USB devices. The current serial port handling code is -in serialio.c in this directory. - -Some places are currently using in_atomic() because speakup functions -are called in various contexts, and a couple of things can't happen -in these cases. Pushing work to some worker thread would probably help, -as was already done for the serial port driving part. - -There is a duplication of the selection functions in selections.c. These -functions should get exported from drivers/char/selection.c (clear_selection -notably) and used from there instead. - -The kobjects may have to move to a more proper place in /sys. The -discussion on lkml resulted to putting speech synthesizers in the -"speech" class, and the speakup screen reader itself into -/sys/class/vtconsole/vtcon0/speakup, the nasty path being handled by -userland tools. - -Another issue seems to only happen on SMP systems. It seems -that text in the output buffer gets garbled because a lock is not set. -This bug happens regularly, but no one has been able to find a situation -which produces it consistently. - -Patches, suggestions, corrections, etc, are definitely welcome. - -We prefer that you contact us on the mailing list; however, if you do -not want to subscribe to a mailing list, send your email to all of the -following: - -w.d.hubbs@gmail.com, chris@the-brannons.com, kirk@reisers.ca and -samuel.thibault@ens-lyon.org. - diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 99c57ceeb357b90202cdbf7a3decaf92a8349100..7ae5306b92fedb9c5b37c4e5987f1802e0f6b6e2 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -305,7 +305,7 @@ static int forward_taskmgmt_command(enum task_mgmt_types tasktype, (struct visorhba_devdata *)scsidev->host->hostdata; int notifyresult = 0xffff; wait_queue_head_t notifyevent; - int scsicmd_id = 0; + int scsicmd_id; if (devdata->serverdown || devdata->serverchangingstate) return FAILED; @@ -1186,7 +1186,7 @@ static struct visor_driver visorhba_driver = { */ static int visorhba_init(void) { - int rc = -ENOMEM; + int rc; visorhba_debugfs_dir = debugfs_create_dir("visorhba", NULL); if (!visorhba_debugfs_dir) diff --git a/drivers/staging/vc04_services/Kconfig b/drivers/staging/vc04_services/Kconfig index 6baf9dd57f1f2b0b8a8d1313447b6895b4e1b209..4b886293f19838218b34fa8153ee5b6ba9b2ccf9 100644 --- a/drivers/staging/vc04_services/Kconfig +++ b/drivers/staging/vc04_services/Kconfig @@ -23,5 +23,7 @@ source "drivers/staging/vc04_services/bcm2835-audio/Kconfig" source "drivers/staging/vc04_services/bcm2835-camera/Kconfig" +source "drivers/staging/vc04_services/vchiq-mmal/Kconfig" + endif diff --git a/drivers/staging/vc04_services/Makefile b/drivers/staging/vc04_services/Makefile index 54d9e2f31916d35805429b17211d26e294279f72..7546d70116a04a2ba517f085986a132c10e19239 100644 --- a/drivers/staging/vc04_services/Makefile +++ b/drivers/staging/vc04_services/Makefile @@ -6,12 +6,11 @@ vchiq-objs := \ interface/vchiq_arm/vchiq_arm.o \ interface/vchiq_arm/vchiq_2835_arm.o \ interface/vchiq_arm/vchiq_debugfs.o \ - interface/vchiq_arm/vchiq_shim.o \ - interface/vchiq_arm/vchiq_util.o \ interface/vchiq_arm/vchiq_connected.o \ -obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/ -obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/ +obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/ +obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/ +obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/ -ccflags-y += -D__VCCOREVER__=0x04000000 +ccflags-y += -I $(srctree)/$(src)/include -D__VCCOREVER__=0x04000000 diff --git a/drivers/staging/vc04_services/bcm2835-audio/Makefile b/drivers/staging/vc04_services/bcm2835-audio/Makefile index 13fa6d7d9745b1de80d4f14245ae70d203353cc7..d59fe4dde615365af00b56e48d96c7888bd018cb 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/Makefile +++ b/drivers/staging/vc04_services/bcm2835-audio/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o -ccflags-y += -I $(srctree)/$(src)/.. -D__VCCOREVER__=0x04000000 +ccflags-y += -I $(srctree)/$(src)/../include -D__VCCOREVER__=0x04000000 diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c index 73144f1ce45efda405aaf4d14471ce1137c5230c..292fcee9d6f2d9e645b61d4dae9c412840be7f5e 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c @@ -9,7 +9,7 @@ struct bcm2835_audio_instance { struct device *dev; - struct vchi_service_handle *vchi_handle; + unsigned int service_handle; struct completion msg_avail_comp; struct mutex vchi_mutex; struct bcm2835_alsa_stream *alsa_stream; @@ -25,12 +25,12 @@ MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio"); static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance) { mutex_lock(&instance->vchi_mutex); - vchi_service_use(instance->vchi_handle); + vchiq_use_service(instance->service_handle); } static void bcm2835_audio_unlock(struct bcm2835_audio_instance *instance) { - vchi_service_release(instance->vchi_handle); + vchiq_release_service(instance->service_handle); mutex_unlock(&instance->vchi_mutex); } @@ -44,8 +44,8 @@ static int bcm2835_audio_send_msg_locked(struct bcm2835_audio_instance *instance init_completion(&instance->msg_avail_comp); } - status = vchi_queue_kernel_message(instance->vchi_handle, - m, sizeof(*m)); + status = vchiq_queue_kernel_message(instance->service_handle, + m, sizeof(*m)); if (status) { dev_err(instance->dev, "vchi message queue failed: %d, msg=%d\n", @@ -89,53 +89,51 @@ static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance, return bcm2835_audio_send_msg(instance, &m, wait); } -static void audio_vchi_callback(void *param, - const enum vchi_callback_reason reason, - void *msg_handle) +static enum vchiq_status audio_vchi_callback(enum vchiq_reason reason, + struct vchiq_header *header, + unsigned int handle, void *userdata) { - struct bcm2835_audio_instance *instance = param; - struct vc_audio_msg m; - int msg_len; - int status; - - if (reason != VCHI_CALLBACK_MSG_AVAILABLE) - return; + struct bcm2835_audio_instance *instance = vchiq_get_service_userdata(handle); + struct vc_audio_msg *m; - status = vchi_msg_dequeue(instance->vchi_handle, - &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE); - if (status) - return; + if (reason != VCHIQ_MESSAGE_AVAILABLE) + return VCHIQ_SUCCESS; - if (m.type == VC_AUDIO_MSG_TYPE_RESULT) { - instance->result = m.result.success; + m = (void *)header->data; + if (m->type == VC_AUDIO_MSG_TYPE_RESULT) { + instance->result = m->result.success; complete(&instance->msg_avail_comp); - } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) { - if (m.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 || - m.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2) + } else if (m->type == VC_AUDIO_MSG_TYPE_COMPLETE) { + if (m->complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 || + m->complete.cookie2 != VC_AUDIO_WRITE_COOKIE2) dev_err(instance->dev, "invalid cookie\n"); else bcm2835_playback_fifo(instance->alsa_stream, - m.complete.count); + m->complete.count); } else { - dev_err(instance->dev, "unexpected callback type=%d\n", m.type); + dev_err(instance->dev, "unexpected callback type=%d\n", m->type); } + + vchiq_release_message(handle, header); + return VCHIQ_SUCCESS; } static int -vc_vchi_audio_init(struct vchi_instance_handle *vchi_instance, +vc_vchi_audio_init(struct vchiq_instance *vchiq_instance, struct bcm2835_audio_instance *instance) { - struct service_creation params = { - .version = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER), - .service_id = VC_AUDIO_SERVER_NAME, + struct vchiq_service_params params = { + .version = VC_AUDIOSERV_VER, + .version_min = VC_AUDIOSERV_MIN_VER, + .fourcc = VCHIQ_MAKE_FOURCC('A', 'U', 'D', 'S'), .callback = audio_vchi_callback, - .callback_param = instance, + .userdata = instance, }; int status; /* Open the VCHI service connections */ - status = vchi_service_open(vchi_instance, ¶ms, - &instance->vchi_handle); + status = vchiq_open_service(vchiq_instance, ¶ms, + &instance->service_handle); if (status) { dev_err(instance->dev, @@ -145,7 +143,7 @@ vc_vchi_audio_init(struct vchi_instance_handle *vchi_instance, } /* Finished with the service for now */ - vchi_service_release(instance->vchi_handle); + vchiq_release_service(instance->service_handle); return 0; } @@ -155,10 +153,10 @@ static void vc_vchi_audio_deinit(struct bcm2835_audio_instance *instance) int status; mutex_lock(&instance->vchi_mutex); - vchi_service_use(instance->vchi_handle); + vchiq_use_service(instance->service_handle); /* Close all VCHI service connections */ - status = vchi_service_close(instance->vchi_handle); + status = vchiq_close_service(instance->service_handle); if (status) { dev_err(instance->dev, "failed to close VCHI service connection (status=%d)\n", @@ -173,20 +171,20 @@ int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx) int ret; /* Initialize and create a VCHI connection */ - ret = vchi_initialise(&vchi_ctx->vchi_instance); + ret = vchiq_initialise(&vchi_ctx->instance); if (ret) { dev_err(dev, "failed to initialise VCHI instance (ret=%d)\n", ret); return -EIO; } - ret = vchi_connect(vchi_ctx->vchi_instance); + ret = vchiq_connect(vchi_ctx->instance); if (ret) { dev_dbg(dev, "failed to connect VCHI instance (ret=%d)\n", ret); - kfree(vchi_ctx->vchi_instance); - vchi_ctx->vchi_instance = NULL; + kfree(vchi_ctx->instance); + vchi_ctx->instance = NULL; return -EIO; } @@ -196,10 +194,10 @@ int bcm2835_new_vchi_ctx(struct device *dev, struct bcm2835_vchi_ctx *vchi_ctx) void bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx) { - /* Close the VCHI connection - it will also free vchi_instance */ - WARN_ON(vchi_disconnect(vchi_ctx->vchi_instance)); + /* Close the VCHI connection - it will also free vchi_ctx->instance */ + WARN_ON(vchiq_shutdown(vchi_ctx->instance)); - vchi_ctx->vchi_instance = NULL; + vchi_ctx->instance = NULL; } int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream) @@ -217,7 +215,7 @@ int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream) instance->alsa_stream = alsa_stream; alsa_stream->instance = instance; - err = vc_vchi_audio_init(vchi_ctx->vchi_instance, + err = vc_vchi_audio_init(vchi_ctx->instance, instance); if (err < 0) goto free_instance; @@ -228,7 +226,8 @@ int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream) goto deinit; bcm2835_audio_lock(instance); - vchi_get_peer_version(instance->vchi_handle, &instance->peer_version); + vchiq_get_peer_version(instance->service_handle, + &instance->peer_version); bcm2835_audio_unlock(instance); if (instance->peer_version < 2 || force_bulk) instance->max_packet = 0; /* bulk transfer */ @@ -344,16 +343,15 @@ int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream, count = size; if (!instance->max_packet) { /* Send the message to the videocore */ - status = vchi_bulk_queue_transmit(instance->vchi_handle, - src, count, - VCHI_FLAGS_BLOCK_UNTIL_DATA_READ, - NULL); + status = vchiq_bulk_transmit(instance->service_handle, src, + count, NULL, + VCHIQ_BULK_MODE_BLOCKING); } else { while (count > 0) { int bytes = min(instance->max_packet, count); - status = vchi_queue_kernel_message(instance->vchi_handle, - src, bytes); + status = vchiq_queue_kernel_message(instance->service_handle, + src, bytes); src += bytes; count -= bytes; } diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h index d2fe8d36ab7da6cac1b4e90a0920553a81c6ab43..1b36475872d6c0e35a309f17a5e3730e63a67248 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h @@ -6,10 +6,10 @@ #include #include +#include #include #include #include -#include "interface/vchi/vchi.h" #define MAX_SUBSTREAMS (8) #define AVAIL_SUBSTREAMS_MASK (0xff) @@ -44,7 +44,7 @@ enum snd_bcm2835_ctrl { }; struct bcm2835_vchi_ctx { - struct vchi_instance_handle *vchi_instance; + struct vchiq_instance *instance; }; /* definition of the chip-specific record */ diff --git a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h index d6401e914ac9fbbe92ba3c04ff776db71f0cd979..b4fa239c5ebeda4b35de768a0c8ab062cce183c8 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h +++ b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h @@ -8,9 +8,8 @@ #define VC_AUDIOSERV_VER 2 /* FourCC codes used for VCHI communication */ -#define VC_AUDIO_SERVER_NAME MAKE_FOURCC("AUDS") -#define VC_AUDIO_WRITE_COOKIE1 MAKE_FOURCC("BCMA") -#define VC_AUDIO_WRITE_COOKIE2 MAKE_FOURCC("DATA") +#define VC_AUDIO_WRITE_COOKIE1 VCHIQ_MAKE_FOURCC('B', 'C', 'M', 'A') +#define VC_AUDIO_WRITE_COOKIE2 VCHIQ_MAKE_FOURCC('D', 'A', 'T', 'A') /* * List of screens that are currently supported diff --git a/drivers/staging/vc04_services/bcm2835-camera/Kconfig b/drivers/staging/vc04_services/bcm2835-camera/Kconfig index c81baf2c111e8b61fff4e8e0f1b5711adeb4b191..d0653d1ed3c7e6757e6ecefd6dd8e616cab56938 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/Kconfig +++ b/drivers/staging/vc04_services/bcm2835-camera/Kconfig @@ -4,6 +4,7 @@ config VIDEO_BCM2835 depends on MEDIA_SUPPORT depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST) select BCM2835_VCHIQ + select BCM2835_VCHIQ_MMAL select VIDEOBUF2_VMALLOC select BTREE help diff --git a/drivers/staging/vc04_services/bcm2835-camera/Makefile b/drivers/staging/vc04_services/bcm2835-camera/Makefile index 472f21e1f2a1893eb934326430e00425e51eac05..3a76d6ade428f974a5eadcb44238d3d9401a8dba 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/Makefile +++ b/drivers/staging/vc04_services/bcm2835-camera/Makefile @@ -1,11 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 bcm2835-v4l2-$(CONFIG_VIDEO_BCM2835) := \ bcm2835-camera.o \ - controls.o \ - mmal-vchiq.o + controls.o obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-v4l2.o ccflags-y += \ -I $(srctree)/$(src)/.. \ + -I $(srctree)/$(src)/../vchiq-mmal/ \ -D__VCCOREVER__=0x04000000 diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c index 4f1adddb804f8c005958e47c72b02d0367f6721c..df90c1f9d148312502bba9468fcfe3f9557c54f6 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c @@ -75,6 +75,12 @@ static const struct v4l2_fract tpf_max = {.numerator = 1, .denominator = FPS_MIN}, tpf_default = {.numerator = 1000, .denominator = 30000}; +/* Container for MMAL and VB2 buffers*/ +struct vb2_mmal_buffer { + struct vb2_v4l2_buffer vb; + struct mmal_buffer mmal; +}; + /* video formats */ static struct mmal_fmt formats[] = { { @@ -261,14 +267,15 @@ static int buffer_init(struct vb2_buffer *vb) { struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb); - struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb); + struct vb2_mmal_buffer *buf = + container_of(vb2, struct vb2_mmal_buffer, vb); v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n", __func__, dev, vb); - buf->buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); - buf->buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0); + buf->mmal.buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); + buf->mmal.buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0); - return mmal_vchi_buffer_init(dev->instance, buf); + return mmal_vchi_buffer_init(dev->instance, &buf->mmal); } static int buffer_prepare(struct vb2_buffer *vb) @@ -297,11 +304,13 @@ static void buffer_cleanup(struct vb2_buffer *vb) { struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb); - struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb); + struct vb2_mmal_buffer *buf = + container_of(vb2, struct vb2_mmal_buffer, vb); v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n", __func__, dev, vb); - mmal_vchi_buffer_cleanup(buf); + + mmal_vchi_buffer_cleanup(&buf->mmal); } static inline bool is_capturing(struct bm2835_mmal_dev *dev) @@ -313,14 +322,16 @@ static inline bool is_capturing(struct bm2835_mmal_dev *dev) static void buffer_cb(struct vchiq_mmal_instance *instance, struct vchiq_mmal_port *port, int status, - struct mmal_buffer *buf, - unsigned long length, u32 mmal_flags, s64 dts, s64 pts) + struct mmal_buffer *mmal_buf) { struct bm2835_mmal_dev *dev = port->cb_ctx; + struct vb2_mmal_buffer *buf = + container_of(mmal_buf, struct vb2_mmal_buffer, mmal); v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n", - __func__, status, buf, length, mmal_flags, pts); + __func__, status, buf, mmal_buf->length, mmal_buf->mmal_flags, + mmal_buf->pts); if (status) { /* error in transfer */ @@ -331,7 +342,7 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, return; } - if (length == 0) { + if (mmal_buf->length == 0) { /* stream ended */ if (dev->capture.frame_count) { /* empty buffer whilst capturing - expected to be an @@ -347,7 +358,8 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, &dev->capture.frame_count, sizeof(dev->capture.frame_count)); } - if (vchiq_mmal_submit_buffer(instance, port, buf)) + if (vchiq_mmal_submit_buffer(instance, port, + &buf->mmal)) v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "Failed to return EOS buffer"); } else { @@ -367,16 +379,16 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, return; } - if (dev->capture.vc_start_timestamp != -1 && pts) { + if (dev->capture.vc_start_timestamp != -1 && mmal_buf->pts) { ktime_t timestamp; - s64 runtime_us = pts - dev->capture.vc_start_timestamp; - + s64 runtime_us = mmal_buf->pts - + dev->capture.vc_start_timestamp; timestamp = ktime_add_us(dev->capture.kernel_start_ts, runtime_us); v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "Convert start time %llu and %llu with offset %llu to %llu\n", ktime_to_ns(dev->capture.kernel_start_ts), - dev->capture.vc_start_timestamp, pts, + dev->capture.vc_start_timestamp, mmal_buf->pts, ktime_to_ns(timestamp)); buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp); } else { @@ -385,13 +397,13 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, buf->vb.sequence = dev->capture.sequence++; buf->vb.field = V4L2_FIELD_NONE; - vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length); - if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME) + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length); + if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME) buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME; vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); - if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS && + if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS && is_capturing(dev)) { v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "Grab another frame as buffer has EOS"); @@ -472,14 +484,16 @@ static void buffer_queue(struct vb2_buffer *vb) { struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb); - struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb); + struct vb2_mmal_buffer *buf = + container_of(vb2, struct vb2_mmal_buffer, vb); int ret; v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p buf:%p, idx %u\n", __func__, dev, buf, vb2->vb2_buf.index); - ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf); + ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, + &buf->mmal); if (ret < 0) v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n", __func__); @@ -592,7 +606,7 @@ static void stop_streaming(struct vb2_queue *vq) dev->capture.frame_count = 0; /* ensure a format has actually been set */ - if (!dev->capture.port) { + if (!port) { v4l2_err(&dev->v4l2_dev, "no capture port - stream not started?\n"); return; @@ -612,11 +626,11 @@ static void stop_streaming(struct vb2_queue *vq) /* disable the connection from camera to encoder */ ret = vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port); - if (!ret && dev->capture.camera_port != dev->capture.port) { + if (!ret && dev->capture.camera_port != port) { v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "disabling port\n"); - ret = vchiq_mmal_port_disable(dev->instance, dev->capture.port); - } else if (dev->capture.camera_port != dev->capture.port) { + ret = vchiq_mmal_port_disable(dev->instance, port); + } else if (dev->capture.camera_port != port) { v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n", ret); } @@ -1483,7 +1497,7 @@ static int get_num_cameras(struct vchiq_mmal_instance *instance, { int ret; struct vchiq_mmal_component *cam_info_component; - struct mmal_parameter_camera_info_t cam_info = {0}; + struct mmal_parameter_camera_info cam_info = {0}; u32 param_size = sizeof(cam_info); int i; @@ -1916,7 +1930,7 @@ static int bcm2835_mmal_probe(struct platform_device *pdev) q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; q->drv_priv = dev; - q->buf_struct_size = sizeof(struct mmal_buffer); + q->buf_struct_size = sizeof(struct vb2_mmal_buffer); q->ops = &bm2835_mmal_video_qops; q->mem_ops = &vb2_vmalloc_memops; q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h similarity index 56% rename from drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h rename to drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h index b62fd6d6f1ac8e215f430e1f7c9110aca58a357d..18d63df368c480b1a1ef3f1b023e96284ca403bb 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h +++ b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h @@ -1,18 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ -#ifndef VCHIQ_IF_H -#define VCHIQ_IF_H - -#define VCHIQ_SERVICE_HANDLE_INVALID 0 - -#define VCHIQ_SLOT_SIZE 4096 -#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(struct vchiq_header)) -#define VCHIQ_CHANNEL_SIZE VCHIQ_MAX_MSG_SIZE /* For backwards compatibility */ +#ifndef VCHIQ_H +#define VCHIQ_H #define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \ (((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3)) -#define VCHIQ_GET_SERVICE_USERDATA(service) vchiq_get_service_userdata(service) enum vchiq_reason { VCHIQ_SERVICE_OPENED, /* service, -, - */ @@ -60,81 +53,51 @@ struct vchiq_element { unsigned int size; }; -typedef enum vchiq_status (*vchiq_callback)(enum vchiq_reason, - struct vchiq_header *, - unsigned int, void *); - struct vchiq_service_base { int fourcc; - vchiq_callback callback; + enum vchiq_status (*callback)(enum vchiq_reason reason, + struct vchiq_header *header, + unsigned int handle, + void *bulk_userdata); void *userdata; }; struct vchiq_service_params { int fourcc; - vchiq_callback callback; + enum vchiq_status (*callback)(enum vchiq_reason reason, + struct vchiq_header *header, + unsigned int handle, + void *bulk_userdata); void *userdata; short version; /* Increment for non-trivial changes */ short version_min; /* Update for incompatible changes */ }; -struct vchiq_config { - unsigned int max_msg_size; - unsigned int bulk_threshold; /* The message size above which it - is better to use a bulk transfer - (<= max_msg_size) */ - unsigned int max_outstanding_bulks; - unsigned int max_services; - short version; /* The version of VCHIQ */ - short version_min; /* The minimum compatible version of VCHIQ */ -}; - struct vchiq_instance; -typedef void (*vchiq_remote_callback)(void *cb_arg); extern enum vchiq_status vchiq_initialise(struct vchiq_instance **pinstance); extern enum vchiq_status vchiq_shutdown(struct vchiq_instance *instance); extern enum vchiq_status vchiq_connect(struct vchiq_instance *instance); -extern enum vchiq_status vchiq_add_service(struct vchiq_instance *instance, - const struct vchiq_service_params *params, - unsigned int *pservice); extern enum vchiq_status vchiq_open_service(struct vchiq_instance *instance, const struct vchiq_service_params *params, unsigned int *pservice); extern enum vchiq_status vchiq_close_service(unsigned int service); -extern enum vchiq_status vchiq_remove_service(unsigned int service); extern enum vchiq_status vchiq_use_service(unsigned int service); extern enum vchiq_status vchiq_release_service(unsigned int service); -extern enum vchiq_status vchiq_queue_kernel_message(unsigned int handle, - void *context, size_t size); +extern void vchiq_msg_queue_push(unsigned int handle, struct vchiq_header *header); extern void vchiq_release_message(unsigned int service, struct vchiq_header *header); +extern int vchiq_queue_kernel_message(unsigned int handle, void *data, + unsigned int size); extern enum vchiq_status vchiq_bulk_transmit(unsigned int service, const void *data, unsigned int size, void *userdata, enum vchiq_bulk_mode mode); extern enum vchiq_status vchiq_bulk_receive(unsigned int service, void *data, unsigned int size, void *userdata, enum vchiq_bulk_mode mode); -extern enum vchiq_status vchiq_bulk_transmit_handle(unsigned int service, - const void *offset, unsigned int size, - void *userdata, enum vchiq_bulk_mode mode); -extern enum vchiq_status vchiq_bulk_receive_handle(unsigned int service, - void *offset, unsigned int size, void *userdata, - enum vchiq_bulk_mode mode); -extern int vchiq_get_client_id(unsigned int service); extern void *vchiq_get_service_userdata(unsigned int service); -extern void vchiq_get_config(struct vchiq_config *config); -extern enum vchiq_status vchiq_set_service_option(unsigned int service, - enum vchiq_service_option option, int value); - -extern enum vchiq_status vchiq_remote_use(struct vchiq_instance *instance, - vchiq_remote_callback callback, void *cb_arg); -extern enum vchiq_status vchiq_remote_release(struct vchiq_instance *instance); - -extern enum vchiq_status vchiq_dump_phys_mem(unsigned int service, - void *ptr, size_t num_bytes); - extern enum vchiq_status vchiq_get_peer_version(unsigned int handle, short *peer_version); +extern struct vchiq_header *vchiq_msg_hold(unsigned int handle); -#endif /* VCHIQ_IF_H */ +#endif /* VCHIQ_H */ diff --git a/drivers/staging/vc04_services/interface/vchi/TODO b/drivers/staging/vc04_services/interface/TODO similarity index 100% rename from drivers/staging/vc04_services/interface/vchi/TODO rename to drivers/staging/vc04_services/interface/TODO diff --git a/drivers/staging/vc04_services/interface/vchi/vchi.h b/drivers/staging/vc04_services/interface/vchi/vchi.h deleted file mode 100644 index 1a981e98e82b9cd34667d6b09f6736affdad8f08..0000000000000000000000000000000000000000 --- a/drivers/staging/vc04_services/interface/vchi/vchi.h +++ /dev/null @@ -1,159 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#ifndef VCHI_H_ -#define VCHI_H_ - -#include "vchi_cfg.h" -#include "vchi_common.h" - -/****************************************************************************** - * Global defs - *****************************************************************************/ - -#define VCHI_BULK_ROUND_UP(x) ((((unsigned long)(x)) + VCHI_BULK_ALIGN - 1) & ~(VCHI_BULK_ALIGN - 1)) -#define VCHI_BULK_ROUND_DOWN(x) (((unsigned long)(x)) & ~(VCHI_BULK_ALIGN - 1)) -#define VCHI_BULK_ALIGN_NBYTES(x) (VCHI_BULK_ALIGNED(x) ? 0 : (VCHI_BULK_ALIGN - ((unsigned long)(x) & (VCHI_BULK_ALIGN - 1)))) - -#ifdef USE_VCHIQ_ARM -#define VCHI_BULK_ALIGNED(x) 1 -#else -#define VCHI_BULK_ALIGNED(x) (((unsigned long)(x) & (VCHI_BULK_ALIGN - 1)) == 0) -#endif - -struct vchi_version { - uint32_t version; - uint32_t version_min; -}; -#define VCHI_VERSION(v_) { v_, v_ } -#define VCHI_VERSION_EX(v_, m_) { v_, m_ } - -// Macros to manipulate 'FOURCC' values -#define MAKE_FOURCC(x) ((int32_t)((x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3])) - -// Opaque service information -struct opaque_vchi_service_t; - -// Descriptor for a held message. Allocated by client, initialised by vchi_msg_hold, -// vchi_msg_iter_hold or vchi_msg_iter_hold_next. Fields are for internal VCHI use only. -struct vchi_held_msg { - struct opaque_vchi_service_t *service; - void *message; -}; - -// structure used to provide the information needed to open a server or a client -struct service_creation { - struct vchi_version version; - int32_t service_id; - vchi_callback callback; - void *callback_param; -}; - -// Opaque handle for a VCHI instance -struct vchi_instance_handle; - -// Opaque handle for a server or client -struct vchi_service_handle; - -/****************************************************************************** - * Global funcs - implementation is specific to which side you are on - * (local / remote) - *****************************************************************************/ - -// Routine used to initialise the vchi on both local + remote connections -extern int32_t vchi_initialise(struct vchi_instance_handle **instance_handle); - -extern int32_t vchi_connect(struct vchi_instance_handle *instance_handle); - -//When this is called, ensure that all services have no data pending. -//Bulk transfers can remain 'queued' -extern int32_t vchi_disconnect(struct vchi_instance_handle *instance_handle); - -/****************************************************************************** - * Global service API - *****************************************************************************/ -// Routine to open a named service -extern int32_t vchi_service_open(struct vchi_instance_handle *instance_handle, - struct service_creation *setup, - struct vchi_service_handle **handle); - -extern int32_t vchi_get_peer_version(const struct vchi_service_handle *handle, - short *peer_version); - -// Routine to close a named service -extern int32_t vchi_service_close(const struct vchi_service_handle *handle); - -// Routine to increment ref count on a named service -extern int32_t vchi_service_use(const struct vchi_service_handle *handle); - -// Routine to decrement ref count on a named service -extern int32_t vchi_service_release(const struct vchi_service_handle *handle); - -/* Routine to send a message from kernel memory across a service */ -extern int -vchi_queue_kernel_message(struct vchi_service_handle *handle, - void *data, - unsigned int size); - -// Routine to receive a msg from a service -// Dequeue is equivalent to hold, copy into client buffer, release -extern int32_t vchi_msg_dequeue(struct vchi_service_handle *handle, - void *data, - uint32_t max_data_size_to_read, - uint32_t *actual_msg_size, - enum vchi_flags flags); - -// Routine to look at a message in place. -// The message is not dequeued, so a subsequent call to peek or dequeue -// will return the same message. -extern int32_t vchi_msg_peek(struct vchi_service_handle *handle, - void **data, - uint32_t *msg_size, - enum vchi_flags flags); - -// Routine to remove a message after it has been read in place with peek -// The first message on the queue is dequeued. -extern int32_t vchi_msg_remove(struct vchi_service_handle *handle); - -// Routine to look at a message in place. -// The message is dequeued, so the caller is left holding it; the descriptor is -// filled in and must be released when the user has finished with the message. -extern int32_t vchi_msg_hold(struct vchi_service_handle *handle, - void **data, // } may be NULL, as info can be - uint32_t *msg_size, // } obtained from HELD_MSG_T - enum vchi_flags flags, - struct vchi_held_msg *message_descriptor); - -/******************************************************************************* - * Global service support API - operations on held messages - * and message iterators - ******************************************************************************/ - -// Routine to release a held message after it has been processed -extern int32_t vchi_held_msg_release(struct vchi_held_msg *message); - -/****************************************************************************** - * Global bulk API - *****************************************************************************/ - -// Routine to prepare interface for a transfer from the other side -extern int32_t vchi_bulk_queue_receive(struct vchi_service_handle *handle, - void *data_dst, - uint32_t data_size, - enum vchi_flags flags, - void *transfer_handle); - -// Routine to queue up data ready for transfer to the other (once they have signalled they are ready) -extern int32_t vchi_bulk_queue_transmit(struct vchi_service_handle *handle, - const void *data_src, - uint32_t data_size, - enum vchi_flags flags, - void *transfer_handle); - -/****************************************************************************** - * Configuration plumbing - *****************************************************************************/ - -#endif /* VCHI_H_ */ - -/****************************** End of file **********************************/ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h b/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h deleted file mode 100644 index 138c36151a22b312a1aad52fe50bd6ac17c958c9..0000000000000000000000000000000000000000 --- a/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h +++ /dev/null @@ -1,238 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#ifndef VCHI_CFG_H_ -#define VCHI_CFG_H_ - -/******************************************************************************* - * Defines in this first section are part of the VCHI API and may be examined by - * VCHI services. - ******************************************************************************/ - -/* - * Required alignment of base addresses for bulk transfer, if unaligned - * transfers are not enabled - * Really determined by the message driver, and should be available from - * a run-time call. - */ -#ifndef VCHI_BULK_ALIGN -# if __VCCOREVER__ >= 0x04000000 -# define VCHI_BULK_ALIGN 32 // Allows for the need to do cache cleans -# else -# define VCHI_BULK_ALIGN 16 -# endif -#endif - -/* - * Required length multiple for bulk transfers, if unaligned transfers are - * not enabled - * May be less than or greater than VCHI_BULK_ALIGN - * Really determined by the message driver, and should be available from - * a run-time call. - */ -#ifndef VCHI_BULK_GRANULARITY -# if __VCCOREVER__ >= 0x04000000 -# define VCHI_BULK_GRANULARITY 32 // Allows for the need to do cache cleans -# else -# define VCHI_BULK_GRANULARITY 16 -# endif -#endif - -/* The largest possible message to be queued with vchi_msg_queue. */ -#ifndef VCHI_MAX_MSG_SIZE -# if defined VCHI_LOCAL_HOST_PORT -# define VCHI_MAX_MSG_SIZE 16384 // makes file transfers fast, but should they be using bulk? -# else -# define VCHI_MAX_MSG_SIZE 4096 // NOTE: THIS MUST BE LARGER THAN OR EQUAL TO THE SIZE OF THE KHRONOS MERGE BUFFER!! -# endif -#endif - -/****************************************************************************** - * Defines below are system configuration options, and should not be used by - * VCHI services. - ******************************************************************************/ - -/* - * How many connections can we support? A localhost implementation uses - * 2 connections, 1 for host-app, 1 for VMCS, and these are hooked together - * by a loopback MPHI VCFW driver. - */ -#ifndef VCHI_MAX_NUM_CONNECTIONS -# define VCHI_MAX_NUM_CONNECTIONS 3 -#endif - -/* - * How many services can we open per connection? Extending this doesn't cost - * processing time, just a small amount of static memory. - */ -#ifndef VCHI_MAX_SERVICES_PER_CONNECTION -# define VCHI_MAX_SERVICES_PER_CONNECTION 36 -#endif - -/* Adjust if using a message driver that supports more logical TX channels */ -#ifndef VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION -# define VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION 9 // 1 MPHI + 8 CCP2 logical channels -#endif - -/* Adjust if using a message driver that supports more logical RX channels */ -#ifndef VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION -# define VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION 1 // 1 MPHI -#endif - -/* - * How many receive slots do we use. This times VCHI_MAX_MSG_SIZE gives the - * effective receive queue space, less message headers. - */ -#ifndef VCHI_NUM_READ_SLOTS -# if defined(VCHI_LOCAL_HOST_PORT) -# define VCHI_NUM_READ_SLOTS 4 -# else -# define VCHI_NUM_READ_SLOTS 48 -# endif -#endif - -/* - * Do we utilise overrun facility for receive message slots? Can aid peer - * transmit performance. Only define on VideoCore end, talking to host. - */ -//#define VCHI_MSG_RX_OVERRUN - -/* - * How many transmit slots do we use. Generally don't need many, - * as the hardware driver underneath VCHI will usually have its own buffering. - */ -#ifndef VCHI_NUM_WRITE_SLOTS -# define VCHI_NUM_WRITE_SLOTS 4 -#endif - -/* - * If a service has held or queued received messages in VCHI_XOFF_THRESHOLD or - * more slots, then it's taking up too much buffer space, - * and the peer service will be told to stop transmitting with an XOFF message. - * For this to be effective, the VCHI_NUM_READ_SLOTS needs to be considerably - * bigger than VCHI_NUM_WRITE_SLOTS, or the transmit latency is too high. - */ -#ifndef VCHI_XOFF_THRESHOLD -# define VCHI_XOFF_THRESHOLD (VCHI_NUM_READ_SLOTS / 2) -#endif - -/* - * After we've sent an XOFF, the peer will be told to resume transmission - * once the local service has dequeued/released enough messages that it's now - * occupying VCHI_XON_THRESHOLD slots or fewer. - */ -#ifndef VCHI_XON_THRESHOLD -# define VCHI_XON_THRESHOLD (VCHI_NUM_READ_SLOTS / 4) -#endif - -/* - * A size below which a bulk transfer omits the handshake completely and always - * goes via the message channel, if bulk auxiliary is being sent on that - * service. (The user can guarantee this by enabling unaligned transmits). - * Not API. - */ -#ifndef VCHI_MIN_BULK_SIZE -# define VCHI_MIN_BULK_SIZE (VCHI_MAX_MSG_SIZE / 2 < 4096 ? VCHI_MAX_MSG_SIZE / 2 : 4096) -#endif - -/* - * Maximum size of bulk transmission chunks, for each interface type. - * A trade-off between speed and latency; the smaller the chunk size the better - * change of messages and other bulk transmissions getting in when big bulk - * transfers are happening. Set to 0 to not break transmissions into chunks. - */ -#ifndef VCHI_MAX_BULK_CHUNK_SIZE_MPHI -# define VCHI_MAX_BULK_CHUNK_SIZE_MPHI (16 * 1024) -#endif - -/* - * NB Chunked CCP2 transmissions violate the letter of the CCP2 spec - * by using "JPEG8" mode with multiple-line frames. Only use if the receiver - * can cope. - */ -#ifndef VCHI_MAX_BULK_CHUNK_SIZE_CCP2 -# define VCHI_MAX_BULK_CHUNK_SIZE_CCP2 0 -#endif - -/* - * How many TX messages can we have pending in our transmit slots. - * Once exhausted, vchi_msg_queue will be blocked. - */ -#ifndef VCHI_TX_MSG_QUEUE_SIZE -# define VCHI_TX_MSG_QUEUE_SIZE 256 -#endif - -/* - * How many RX messages can we have parsed in the receive slots. Once exhausted, - * parsing will be suspended until older messages are dequeued/released. - */ -#ifndef VCHI_RX_MSG_QUEUE_SIZE -# define VCHI_RX_MSG_QUEUE_SIZE 256 -#endif - -/* - * Really should be able to cope if we run out of received message descriptors, - * by suspending parsing as the comment above says, but we don't. - * This sweeps the issue under the carpet. - */ -#if VCHI_RX_MSG_QUEUE_SIZE < (VCHI_MAX_MSG_SIZE / 16 + 1) * VCHI_NUM_READ_SLOTS -# undef VCHI_RX_MSG_QUEUE_SIZE -# define VCHI_RX_MSG_QUEUE_SIZE ((VCHI_MAX_MSG_SIZE / 16 + 1) * VCHI_NUM_READ_SLOTS) -#endif - -/* - * How many bulk transmits can we have pending. Once exhausted, - * vchi_bulk_queue_transmit will be blocked. - */ -#ifndef VCHI_TX_BULK_QUEUE_SIZE -# define VCHI_TX_BULK_QUEUE_SIZE 64 -#endif - -/* - * How many bulk receives can we have pending. Once exhausted, - *vchi_bulk_queue_receive will be blocked. - */ -#ifndef VCHI_RX_BULK_QUEUE_SIZE -# define VCHI_RX_BULK_QUEUE_SIZE 64 -#endif - -/* - * A limit on how many outstanding bulk requests we expect the peer to give us. - * If the peer asks for more than this, VCHI will fail and assert. - * The number is determined by the peer's hardware - * - it's the number of outstanding requests that can be queued - * on all bulk channels. VC3's MPHI peripheral allows 16. - */ -#ifndef VCHI_MAX_PEER_BULK_REQUESTS -# define VCHI_MAX_PEER_BULK_REQUESTS 32 -#endif - -/* - * Define VCHI_CCP2TX_MANUAL_POWER if the host tells us when to turn the CCP2 - * transmitter on and off. - */ -/*#define VCHI_CCP2TX_MANUAL_POWER*/ - -#ifndef VCHI_CCP2TX_MANUAL_POWER - -/* - * Timeout (in milliseconds) for putting the CCP2TX interface into IDLE state. - * Set negative for no IDLE. - */ -# ifndef VCHI_CCP2TX_IDLE_TIMEOUT -# define VCHI_CCP2TX_IDLE_TIMEOUT 5 -# endif - -/* - * Timeout (in milliseconds) for putting the CCP2TX interface into OFF state. - * Set negative for no OFF. - */ -# ifndef VCHI_CCP2TX_OFF_TIMEOUT -# define VCHI_CCP2TX_OFF_TIMEOUT 1000 -# endif - -#endif /* VCHI_CCP2TX_MANUAL_POWER */ - -#endif /* VCHI_CFG_H_ */ - -/****************************** End of file **********************************/ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_common.h b/drivers/staging/vc04_services/interface/vchi/vchi_common.h deleted file mode 100644 index 7fc04e38936d0b8c5804802ea52f0d096ab337a5..0000000000000000000000000000000000000000 --- a/drivers/staging/vc04_services/interface/vchi/vchi_common.h +++ /dev/null @@ -1,138 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#ifndef VCHI_COMMON_H_ -#define VCHI_COMMON_H_ - -//flags used when sending messages (must be bitmapped) -enum vchi_flags { - VCHI_FLAGS_NONE = 0x0, - VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE = 0x1, // waits for message to be received, or sent (NB. not the same as being seen on other side) - VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2, // run a callback when message sent - VCHI_FLAGS_BLOCK_UNTIL_QUEUED = 0x4, // return once the transfer is in a queue ready to go - VCHI_FLAGS_ALLOW_PARTIAL = 0x8, - VCHI_FLAGS_BLOCK_UNTIL_DATA_READ = 0x10, - VCHI_FLAGS_CALLBACK_WHEN_DATA_READ = 0x20, - - VCHI_FLAGS_ALIGN_SLOT = 0x000080, // internal use only - VCHI_FLAGS_BULK_AUX_QUEUED = 0x010000, // internal use only - VCHI_FLAGS_BULK_AUX_COMPLETE = 0x020000, // internal use only - VCHI_FLAGS_BULK_DATA_QUEUED = 0x040000, // internal use only - VCHI_FLAGS_BULK_DATA_COMPLETE = 0x080000, // internal use only - VCHI_FLAGS_INTERNAL = 0xFF0000 -}; - -// constants for vchi_crc_control() -enum vchi_crc_control { - VCHI_CRC_NOTHING = -1, - VCHI_CRC_PER_SERVICE = 0, - VCHI_CRC_EVERYTHING = 1, -}; - -//callback reasons when an event occurs on a service -enum vchi_callback_reason { - VCHI_CALLBACK_REASON_MIN, - - /* - * This indicates that there is data available handle is the msg id that - * was transmitted with the data - * When a message is received and there was no FULL message available - * previously, send callback - * Tasks get kicked by the callback, reset their event and try and read - * from the fifo until it fails - */ - VCHI_CALLBACK_MSG_AVAILABLE, - VCHI_CALLBACK_MSG_SENT, - VCHI_CALLBACK_MSG_SPACE_AVAILABLE, // XXX not yet implemented - - // This indicates that a transfer from the other side has completed - VCHI_CALLBACK_BULK_RECEIVED, - //This indicates that data queued up to be sent has now gone - //handle is the msg id that was used when sending the data - VCHI_CALLBACK_BULK_SENT, - VCHI_CALLBACK_BULK_RX_SPACE_AVAILABLE, // XXX not yet implemented - VCHI_CALLBACK_BULK_TX_SPACE_AVAILABLE, // XXX not yet implemented - - VCHI_CALLBACK_SERVICE_CLOSED, - - /* - * this side has sent XOFF to peer due to lack of data consumption by - * service (suggests the service may need to take some recovery action - * if it has been deliberately holding off consuming data) - */ - VCHI_CALLBACK_SENT_XOFF, - VCHI_CALLBACK_SENT_XON, - - // indicates that a bulk transfer has finished reading the source buffer - VCHI_CALLBACK_BULK_DATA_READ, - - // power notification events (currently host side only) - VCHI_CALLBACK_PEER_OFF, - VCHI_CALLBACK_PEER_SUSPENDED, - VCHI_CALLBACK_PEER_ON, - VCHI_CALLBACK_PEER_RESUMED, - VCHI_CALLBACK_FORCED_POWER_OFF, - - // some extra notifications provided by vchiq_arm - VCHI_CALLBACK_SERVICE_OPENED, - VCHI_CALLBACK_BULK_RECEIVE_ABORTED, - VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, - - VCHI_CALLBACK_REASON_MAX -}; - -// service control options -enum vchi_service_option { - VCHI_SERVICE_OPTION_MIN, - - VCHI_SERVICE_OPTION_TRACE, - VCHI_SERVICE_OPTION_SYNCHRONOUS, - - VCHI_SERVICE_OPTION_MAX -}; - -//Callback used by all services / bulk transfers -typedef void (*vchi_callback)(void *callback_param, //my service local param - enum vchi_callback_reason reason, - void *handle); //for transmitting msg's only - -/* - * Define vector struct for scatter-gather (vector) operations - * Vectors can be nested - if a vector element has negative length, then - * the data pointer is treated as pointing to another vector array, with - * '-vec_len' elements. Thus to append a header onto an existing vector, - * you can do this: - * - * void foo(const struct vchi_msg_vector *v, int n) - * { - * struct vchi_msg_vector nv[2]; - * nv[0].vec_base = my_header; - * nv[0].vec_len = sizeof my_header; - * nv[1].vec_base = v; - * nv[1].vec_len = -n; - * ... - * - */ -struct vchi_msg_vector { - const void *vec_base; - int32_t vec_len; -}; - -/* - * Iterator structure for reading ahead through received message queue. - * Allocated by client, initialised by vchi_msg_look_ahead. Fields are for - * internal VCHI use only. - * Iterates over messages in queue at the instant of the call to - * vchi_msg_lookahead - will not proceed to messages received since. - * Behaviour is undefined if an iterator is used again after messages for that - * service are removed/dequeued by any means other than vchi_msg_iter_... - * calls on the iterator itself. - */ -struct vchi_msg_iter { - struct opaque_vchi_service_t *service; - void *last; - void *next; - void *remove; -}; - -#endif // VCHI_COMMON_H_ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq.h deleted file mode 100644 index 25af99a0f394bf47c6a408a7ef4ba4375d506293..0000000000000000000000000000000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#ifndef VCHIQ_VCHIQ_H -#define VCHIQ_VCHIQ_H - -#include "vchiq_if.h" -#include "vchiq_util.h" - -/* Do this so that we can test-build the code on non-rpi systems */ -#if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE) - -#else - -#ifndef dsb -#define dsb(a) -#endif - -#endif /* IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE) */ - -#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 38a13e4618a851c83ea1ce48db1e28cbf02b4eb0..5ed36d55701491b16f8c6ed9e309afe3ee91f6ff 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) @@ -287,12 +288,8 @@ cleanup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo) pagelistinfo->num_pages, pagelistinfo->dma_dir); } - if (pagelistinfo->pages_need_release) { - unsigned int i; - - for (i = 0; i < pagelistinfo->num_pages; i++) - put_page(pagelistinfo->pages[i]); - } + if (pagelistinfo->pages_need_release) + unpin_user_pages(pagelistinfo->pages, pagelistinfo->num_pages); dma_free_coherent(g_dev, pagelistinfo->pagelist_buffer_size, pagelistinfo->pagelist, pagelistinfo->dma_addr); @@ -395,7 +392,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type) } /* do not try and release vmalloc pages */ } else { - actual_pages = get_user_pages_fast( + actual_pages = pin_user_pages_fast( (unsigned long)buf & PAGE_MASK, num_pages, type == PAGELIST_READ, @@ -407,10 +404,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type) __func__, actual_pages, num_pages); /* This is probably due to the process being killed */ - while (actual_pages > 0) { - actual_pages--; - put_page(pages[actual_pages]); - } + if (actual_pages > 0) + unpin_user_pages(pages, actual_pages); cleanup_pagelistinfo(pagelistinfo); return NULL; } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 28ea8c3a4cba9dcd0465cfe0447c59da2add7b67..d4d811884861ddda75d71fcc4bda3fa2dfc4db83 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include "vchiq_core.h" @@ -269,7 +271,7 @@ failed: } EXPORT_SYMBOL(vchiq_connect); -enum vchiq_status vchiq_add_service( +static enum vchiq_status vchiq_add_service( struct vchiq_instance *instance, const struct vchiq_service_params *params, unsigned int *phandle) @@ -306,7 +308,6 @@ enum vchiq_status vchiq_add_service( return status; } -EXPORT_SYMBOL(vchiq_add_service); enum vchiq_status vchiq_open_service( struct vchiq_instance *instance, @@ -354,43 +355,67 @@ vchiq_bulk_transmit(unsigned int handle, const void *data, { enum vchiq_status status; - switch (mode) { - case VCHIQ_BULK_MODE_NOCALLBACK: - case VCHIQ_BULK_MODE_CALLBACK: - status = vchiq_bulk_transfer(handle, (void *)data, size, - userdata, mode, - VCHIQ_BULK_TRANSMIT); - break; - case VCHIQ_BULK_MODE_BLOCKING: - status = vchiq_blocking_bulk_transfer(handle, - (void *)data, size, VCHIQ_BULK_TRANSMIT); - break; - default: - return VCHIQ_ERROR; + while (1) { + switch (mode) { + case VCHIQ_BULK_MODE_NOCALLBACK: + case VCHIQ_BULK_MODE_CALLBACK: + status = vchiq_bulk_transfer(handle, (void *)data, size, + userdata, mode, + VCHIQ_BULK_TRANSMIT); + break; + case VCHIQ_BULK_MODE_BLOCKING: + status = vchiq_blocking_bulk_transfer(handle, + (void *)data, size, VCHIQ_BULK_TRANSMIT); + break; + default: + return VCHIQ_ERROR; + } + + /* + * vchiq_*_bulk_transfer() may return VCHIQ_RETRY, so we need + * to implement a retry mechanism since this function is + * supposed to block until queued + */ + if (status != VCHIQ_RETRY) + break; + + msleep(1); } return status; } EXPORT_SYMBOL(vchiq_bulk_transmit); -enum vchiq_status -vchiq_bulk_receive(unsigned int handle, void *data, - unsigned int size, void *userdata, enum vchiq_bulk_mode mode) +enum vchiq_status vchiq_bulk_receive(unsigned int handle, void *data, + unsigned int size, void *userdata, + enum vchiq_bulk_mode mode) { enum vchiq_status status; - switch (mode) { - case VCHIQ_BULK_MODE_NOCALLBACK: - case VCHIQ_BULK_MODE_CALLBACK: - status = vchiq_bulk_transfer(handle, data, size, userdata, - mode, VCHIQ_BULK_RECEIVE); - break; - case VCHIQ_BULK_MODE_BLOCKING: - status = vchiq_blocking_bulk_transfer(handle, - (void *)data, size, VCHIQ_BULK_RECEIVE); - break; - default: - return VCHIQ_ERROR; + while (1) { + switch (mode) { + case VCHIQ_BULK_MODE_NOCALLBACK: + case VCHIQ_BULK_MODE_CALLBACK: + status = vchiq_bulk_transfer(handle, data, size, userdata, + mode, VCHIQ_BULK_RECEIVE); + break; + case VCHIQ_BULK_MODE_BLOCKING: + status = vchiq_blocking_bulk_transfer(handle, + (void *)data, size, VCHIQ_BULK_RECEIVE); + break; + default: + return VCHIQ_ERROR; + } + + /* + * vchiq_*_bulk_transfer() may return VCHIQ_RETRY, so we need + * to implement a retry mechanism since this function is + * supposed to block until queued + */ + if (status != VCHIQ_RETRY) + break; + + msleep(1); } return status; @@ -2547,6 +2572,7 @@ vchiq_use_service(unsigned int handle) } return ret; } +EXPORT_SYMBOL(vchiq_use_service); enum vchiq_status vchiq_release_service(unsigned int handle) @@ -2560,6 +2586,7 @@ vchiq_release_service(unsigned int handle) } return ret; } +EXPORT_SYMBOL(vchiq_release_service); struct service_data_struct { int fourcc; @@ -2805,6 +2832,7 @@ failed_platform_init: static int vchiq_remove(struct platform_device *pdev) { + platform_device_unregister(bcm2835_audio); platform_device_unregister(bcm2835_camera); vchiq_debugfs_deinit(); device_destroy(vchiq_class, vchiq_devid); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index ae9183db44eef05a33f7816395562be962c476c4..5a361e8e7c6ceb050a82941c9724543d98588578 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -1,8 +1,17 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include #include "vchiq_core.h" @@ -39,9 +48,9 @@ struct vchiq_openack_payload { }; enum { - QMFLAGS_IS_BLOCKING = (1 << 0), - QMFLAGS_NO_MUTEX_LOCK = (1 << 1), - QMFLAGS_NO_MUTEX_UNLOCK = (1 << 2) + QMFLAGS_IS_BLOCKING = BIT(0), + QMFLAGS_NO_MUTEX_LOCK = BIT(1), + QMFLAGS_NO_MUTEX_UNLOCK = BIT(2) }; /* we require this for consistency between endpoints */ @@ -323,6 +332,7 @@ vchiq_get_service_userdata(unsigned int handle) rcu_read_unlock(); return userdata; } +EXPORT_SYMBOL(vchiq_get_service_userdata); static void mark_service_closing_internal(struct vchiq_service *service, int sh_thread) @@ -526,14 +536,14 @@ request_poll(struct vchiq_state *state, struct vchiq_service *service, do { value = atomic_read(&service->poll_flags); } while (atomic_cmpxchg(&service->poll_flags, value, - value | (1 << poll_type)) != value); + value | BIT(poll_type)) != value); do { value = atomic_read(&state->poll_services[ service->localport>>5]); } while (atomic_cmpxchg( &state->poll_services[service->localport>>5], - value, value | (1 << (service->localport & 0x1f))) + value, value | BIT(service->localport & 0x1f)) != value); } @@ -1287,19 +1297,19 @@ poll_services(struct vchiq_state *state) flags = atomic_xchg(&state->poll_services[group], 0); for (i = 0; flags; i++) { - if (flags & (1 << i)) { + if (flags & BIT(i)) { struct vchiq_service *service = find_service_by_port(state, (group<<5) + i); u32 service_flags; - flags &= ~(1 << i); + flags &= ~BIT(i); if (!service) continue; service_flags = atomic_xchg(&service->poll_flags, 0); if (service_flags & - (1 << VCHIQ_POLL_REMOVE)) { + BIT(VCHIQ_POLL_REMOVE)) { vchiq_log_info(vchiq_core_log_level, "%d: ps - remove %d<->%d", state->id, service->localport, @@ -1317,7 +1327,7 @@ poll_services(struct vchiq_state *state) request_poll(state, service, VCHIQ_POLL_REMOVE); } else if (service_flags & - (1 << VCHIQ_POLL_TERMINATE)) { + BIT(VCHIQ_POLL_TERMINATE)) { vchiq_log_info(vchiq_core_log_level, "%d: ps - terminate %d<->%d", state->id, service->localport, @@ -1328,11 +1338,11 @@ poll_services(struct vchiq_state *state) request_poll(state, service, VCHIQ_POLL_TERMINATE); } - if (service_flags & (1 << VCHIQ_POLL_TXNOTIFY)) + if (service_flags & BIT(VCHIQ_POLL_TXNOTIFY)) notify_bulks(service, &service->bulk_tx, 1/*retry_poll*/); - if (service_flags & (1 << VCHIQ_POLL_RXNOTIFY)) + if (service_flags & BIT(VCHIQ_POLL_RXNOTIFY)) notify_bulks(service, &service->bulk_rx, 1/*retry_poll*/); @@ -2265,6 +2275,57 @@ fail_free_handler_thread: return VCHIQ_ERROR; } +void vchiq_msg_queue_push(unsigned int handle, struct vchiq_header *header) +{ + struct vchiq_service *service = find_service_by_handle(handle); + int pos; + + while (service->msg_queue_write == service->msg_queue_read + + VCHIQ_MAX_SLOTS) { + if (wait_for_completion_interruptible(&service->msg_queue_pop)) + flush_signals(current); + } + + pos = service->msg_queue_write++ & (VCHIQ_MAX_SLOTS - 1); + service->msg_queue[pos] = header; + + complete(&service->msg_queue_push); +} +EXPORT_SYMBOL(vchiq_msg_queue_push); + +struct vchiq_header *vchiq_msg_hold(unsigned int handle) +{ + struct vchiq_service *service = find_service_by_handle(handle); + struct vchiq_header *header; + int pos; + + if (service->msg_queue_write == service->msg_queue_read) + return NULL; + + while (service->msg_queue_write == service->msg_queue_read) { + if (wait_for_completion_interruptible(&service->msg_queue_push)) + flush_signals(current); + } + + pos = service->msg_queue_read++ & (VCHIQ_MAX_SLOTS - 1); + header = service->msg_queue[pos]; + + complete(&service->msg_queue_pop); + + return header; +} +EXPORT_SYMBOL(vchiq_msg_hold); + +static int vchiq_validate_params(const struct vchiq_service_params *params) +{ + if (!params->callback || !params->fourcc) { + vchiq_loud_error("Can't add service, invalid params\n"); + return -EINVAL; + } + + return 0; +} + /* Called from application thread when a client or server service is created. */ struct vchiq_service * vchiq_add_service_internal(struct vchiq_state *state, @@ -2275,8 +2336,13 @@ vchiq_add_service_internal(struct vchiq_state *state, struct vchiq_service *service; struct vchiq_service __rcu **pservice = NULL; struct vchiq_service_quota *service_quota; + int ret; int i; + ret = vchiq_validate_params(params); + if (ret) + return NULL; + service = kmalloc(sizeof(*service), GFP_KERNEL); if (!service) return service; @@ -2304,12 +2370,17 @@ vchiq_add_service_internal(struct vchiq_state *state, service->state = state; service->instance = instance; service->service_use_count = 0; + service->msg_queue_read = 0; + service->msg_queue_write = 0; init_bulk_queue(&service->bulk_tx); init_bulk_queue(&service->bulk_rx); init_completion(&service->remove_event); init_completion(&service->bulk_remove_event); + init_completion(&service->msg_queue_pop); + init_completion(&service->msg_queue_push); mutex_init(&service->bulk_mutex); memset(&service->stats, 0, sizeof(service->stats)); + memset(&service->msg_queue, 0, sizeof(service->msg_queue)); /* Although it is perfectly possible to use a spinlock ** to protect the creation of services, it is overkill as it @@ -2639,7 +2710,7 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd) case VCHIQ_SRVSTATE_OPENSYNC: mutex_lock(&state->sync_mutex); - /* fall through */ + fallthrough; case VCHIQ_SRVSTATE_OPEN: if (close_recvd) { if (!do_abort_bulks(service)) @@ -2875,6 +2946,7 @@ vchiq_close_service(unsigned int handle) return status; } +EXPORT_SYMBOL(vchiq_close_service); enum vchiq_status vchiq_remove_service(unsigned int handle) @@ -3142,11 +3214,28 @@ error_exit: return status; } -enum vchiq_status vchiq_queue_kernel_message(unsigned int handle, void *context, - size_t size) +int vchiq_queue_kernel_message(unsigned int handle, void *data, unsigned int size) { - return vchiq_queue_message(handle, memcpy_copy_callback, context, size); + enum vchiq_status status; + + while (1) { + status = vchiq_queue_message(handle, memcpy_copy_callback, + data, size); + + /* + * vchiq_queue_message() may return VCHIQ_RETRY, so we need to + * implement a retry mechanism since this function is supposed + * to block until queued + */ + if (status != VCHIQ_RETRY) + break; + + msleep(1); + } + + return status; } +EXPORT_SYMBOL(vchiq_queue_kernel_message); void vchiq_release_message(unsigned int handle, @@ -3180,6 +3269,7 @@ vchiq_release_message(unsigned int handle, unlock_service(service); } +EXPORT_SYMBOL(vchiq_release_message); static void release_message_sync(struct vchiq_state *state, struct vchiq_header *header) @@ -3206,6 +3296,7 @@ exit: unlock_service(service); return status; } +EXPORT_SYMBOL(vchiq_get_peer_version); void vchiq_get_config(struct vchiq_config *config) { diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h index 1fe6cd8b86c02e3ed637de3640d920bb3f4874db..e67692879249cac0dd7f00f6da2547629a1a31e3 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -10,10 +10,26 @@ #include #include #include +#include #include "vchiq_cfg.h" -#include "vchiq.h" + +/* Do this so that we can test-build the code on non-rpi systems */ +#if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE) + +#else + +#ifndef dsb +#define dsb(a) +#endif + +#endif /* IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE) */ + +#define VCHIQ_SERVICE_HANDLE_INVALID 0 + +#define VCHIQ_SLOT_SIZE 4096 +#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(struct vchiq_header)) /* Run time control of log level, based on KERN_XXX level. */ #define VCHIQ_LOG_DEFAULT 4 @@ -297,6 +313,12 @@ struct vchiq_service { uint64_t bulk_tx_bytes; uint64_t bulk_rx_bytes; } stats; + + int msg_queue_read; + int msg_queue_write; + struct completion msg_queue_pop; + struct completion msg_queue_push; + struct vchiq_header *msg_queue[VCHIQ_MAX_SLOTS]; }; /* The quota information is outside struct vchiq_service so that it can @@ -480,6 +502,18 @@ struct bulk_waiter { int actual; }; +struct vchiq_config { + unsigned int max_msg_size; + unsigned int bulk_threshold; /* The message size above which it + is better to use a bulk transfer + (<= max_msg_size) */ + unsigned int max_outstanding_bulks; + unsigned int max_services; + short version; /* The version of VCHIQ */ + short version_min; /* The minimum compatible version of VCHIQ */ +}; + + extern spinlock_t bulk_waiter_spinlock; extern int vchiq_core_log_level; @@ -659,4 +693,14 @@ extern void vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, size_t numBytes); +extern enum vchiq_status vchiq_remove_service(unsigned int service); + +extern int vchiq_get_client_id(unsigned int service); + +extern void vchiq_get_config(struct vchiq_config *config); + +extern enum vchiq_status +vchiq_set_service_option(unsigned int service, enum vchiq_service_option option, + int value); + #endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h index 202889b3774f11bd4d69bb95fb13dd9fcf3b4af4..3653fd99d8a18447265e3dbe26d731292c4f1d5b 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h @@ -5,7 +5,7 @@ #define VCHIQ_IOCTLS_H #include -#include "vchiq_if.h" +#include #define VCHIQ_IOC_MAGIC 0xc4 #define VCHIQ_INVALID_HANDLE (~0) diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c deleted file mode 100644 index 75d87b6992c4b9e1d3ab81ce2ae7afdaf8430ca2..0000000000000000000000000000000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c +++ /dev/null @@ -1,617 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ -#include -#include - -#include "../vchi/vchi.h" -#include "vchiq.h" -#include "vchiq_core.h" - -#include "vchiq_util.h" - -struct shim_service { - unsigned int handle; - - struct vchiu_queue queue; - - vchi_callback callback; - void *callback_param; -}; - -/*********************************************************** - * Name: vchi_msg_peek - * - * Arguments: struct vchi_service_handle *handle, - * void **data, - * uint32_t *msg_size, - - * enum vchi_flags flags - * - * Description: Routine to return a pointer to the current message (to allow in - * place processing). The message can be removed using - * vchi_msg_remove when you're finished - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_msg_peek(struct vchi_service_handle *handle, - void **data, - uint32_t *msg_size, - enum vchi_flags flags) -{ - struct shim_service *service = (struct shim_service *)handle; - struct vchiq_header *header; - - WARN_ON((flags != VCHI_FLAGS_NONE) && - (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); - - if (flags == VCHI_FLAGS_NONE) - if (vchiu_queue_is_empty(&service->queue)) - return -1; - - header = vchiu_queue_peek(&service->queue); - - *data = header->data; - *msg_size = header->size; - - return 0; -} -EXPORT_SYMBOL(vchi_msg_peek); - -/*********************************************************** - * Name: vchi_msg_remove - * - * Arguments: struct vchi_service_handle *handle, - * - * Description: Routine to remove a message (after it has been read with - * vchi_msg_peek) - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_msg_remove(struct vchi_service_handle *handle) -{ - struct shim_service *service = (struct shim_service *)handle; - struct vchiq_header *header; - - header = vchiu_queue_pop(&service->queue); - - vchiq_release_message(service->handle, header); - - return 0; -} -EXPORT_SYMBOL(vchi_msg_remove); - -int vchi_queue_kernel_message(struct vchi_service_handle *handle, void *data, - unsigned int size) -{ - struct shim_service *service = (struct shim_service *)handle; - enum vchiq_status status; - - while (1) { - status = vchiq_queue_kernel_message(service->handle, data, - size); - - /* - * vchiq_queue_message() may return VCHIQ_RETRY, so we need to - * implement a retry mechanism since this function is supposed - * to block until queued - */ - if (status != VCHIQ_RETRY) - break; - - msleep(1); - } - - return status; -} -EXPORT_SYMBOL(vchi_queue_kernel_message); - -/*********************************************************** - * Name: vchi_bulk_queue_receive - * - * Arguments: VCHI_BULK_HANDLE_T handle, - * void *data_dst, - * const uint32_t data_size, - * enum vchi_flags flags - * void *bulk_handle - * - * Description: Routine to setup a rcv buffer - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_bulk_queue_receive(struct vchi_service_handle *handle, void *data_dst, - uint32_t data_size, enum vchi_flags flags, - void *bulk_handle) -{ - struct shim_service *service = (struct shim_service *)handle; - enum vchiq_bulk_mode mode; - enum vchiq_status status; - - switch ((int)flags) { - case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE - | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: - WARN_ON(!service->callback); - mode = VCHIQ_BULK_MODE_CALLBACK; - break; - case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: - mode = VCHIQ_BULK_MODE_BLOCKING; - break; - case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: - case VCHI_FLAGS_NONE: - mode = VCHIQ_BULK_MODE_NOCALLBACK; - break; - default: - WARN(1, "unsupported message\n"); - return VCHIQ_ERROR; - } - - while (1) { - status = vchiq_bulk_receive(service->handle, data_dst, - data_size, bulk_handle, mode); - /* - * vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to - * implement a retry mechanism since this function is supposed - * to block until queued - */ - if (status != VCHIQ_RETRY) - break; - - msleep(1); - } - - return status; -} -EXPORT_SYMBOL(vchi_bulk_queue_receive); - -/*********************************************************** - * Name: vchi_bulk_queue_transmit - * - * Arguments: VCHI_BULK_HANDLE_T handle, - * const void *data_src, - * uint32_t data_size, - * enum vchi_flags flags, - * void *bulk_handle - * - * Description: Routine to transmit some data - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_bulk_queue_transmit(struct vchi_service_handle *handle, - const void *data_src, - uint32_t data_size, - enum vchi_flags flags, - void *bulk_handle) -{ - struct shim_service *service = (struct shim_service *)handle; - enum vchiq_bulk_mode mode; - enum vchiq_status status; - - switch ((int)flags) { - case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE - | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: - WARN_ON(!service->callback); - mode = VCHIQ_BULK_MODE_CALLBACK; - break; - case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ: - case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: - mode = VCHIQ_BULK_MODE_BLOCKING; - break; - case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: - case VCHI_FLAGS_NONE: - mode = VCHIQ_BULK_MODE_NOCALLBACK; - break; - default: - WARN(1, "unsupported message\n"); - return VCHIQ_ERROR; - } - - while (1) { - status = vchiq_bulk_transmit(service->handle, data_src, - data_size, bulk_handle, mode); - - /* - * vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to - * implement a retry mechanism since this function is supposed - * to block until queued - */ - if (status != VCHIQ_RETRY) - break; - - msleep(1); - } - - return status; -} -EXPORT_SYMBOL(vchi_bulk_queue_transmit); - -/*********************************************************** - * Name: vchi_msg_dequeue - * - * Arguments: struct vchi_service_handle *handle, - * void *data, - * uint32_t max_data_size_to_read, - * uint32_t *actual_msg_size - * enum vchi_flags flags - * - * Description: Routine to dequeue a message into the supplied buffer - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_msg_dequeue(struct vchi_service_handle *handle, void *data, - uint32_t max_data_size_to_read, - uint32_t *actual_msg_size, enum vchi_flags flags) -{ - struct shim_service *service = (struct shim_service *)handle; - struct vchiq_header *header; - - WARN_ON((flags != VCHI_FLAGS_NONE) && - (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); - - if (flags == VCHI_FLAGS_NONE) - if (vchiu_queue_is_empty(&service->queue)) - return -1; - - header = vchiu_queue_pop(&service->queue); - - memcpy(data, header->data, header->size < max_data_size_to_read ? - header->size : max_data_size_to_read); - - *actual_msg_size = header->size; - - vchiq_release_message(service->handle, header); - - return 0; -} -EXPORT_SYMBOL(vchi_msg_dequeue); - -/*********************************************************** - * Name: vchi_held_msg_release - * - * Arguments: struct vchi_held_msg *message - * - * Description: Routine to release a held message (after it has been read with - * vchi_msg_hold) - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_held_msg_release(struct vchi_held_msg *message) -{ - /* - * Convert the service field pointer back to an - * unsigned int which is an int. - * This pointer is opaque to everything except - * vchi_msg_hold which simply upcasted the int - * to a pointer. - */ - - vchiq_release_message((unsigned int)(long)message->service, - (struct vchiq_header *)message->message); - - return 0; -} -EXPORT_SYMBOL(vchi_held_msg_release); - -/*********************************************************** - * Name: vchi_msg_hold - * - * Arguments: struct vchi_service_handle *handle, - * void **data, - * uint32_t *msg_size, - * enum vchi_flags flags, - * struct vchi_held_msg *message_handle - * - * Description: Routine to return a pointer to the current message (to allow - * in place processing). The message is dequeued - don't forget - * to release the message using vchi_held_msg_release when you're - * finished. - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ -int32_t vchi_msg_hold(struct vchi_service_handle *handle, void **data, - uint32_t *msg_size, enum vchi_flags flags, - struct vchi_held_msg *message_handle) -{ - struct shim_service *service = (struct shim_service *)handle; - struct vchiq_header *header; - - WARN_ON((flags != VCHI_FLAGS_NONE) && - (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); - - if (flags == VCHI_FLAGS_NONE) - if (vchiu_queue_is_empty(&service->queue)) - return -1; - - header = vchiu_queue_pop(&service->queue); - - *data = header->data; - *msg_size = header->size; - - /* - * upcast the unsigned int which is an int - * to a pointer and stuff it in the held message. - * This pointer is opaque to everything except - * vchi_held_msg_release which simply downcasts it back - * to an int. - */ - - message_handle->service = - (struct opaque_vchi_service_t *)(long)service->handle; - message_handle->message = header; - - return 0; -} -EXPORT_SYMBOL(vchi_msg_hold); - -/*********************************************************** - * Name: vchi_initialise - * - * Arguments: struct vchi_instance_handle **instance_handle - * - * Description: Initialises the hardware but does not transmit anything - * When run as a Host App this will be called twice hence the need - * to malloc the state information - * - * Returns: 0 if successful, failure otherwise - * - ***********************************************************/ - -int32_t vchi_initialise(struct vchi_instance_handle **instance_handle) -{ - struct vchiq_instance *instance; - enum vchiq_status status; - - status = vchiq_initialise(&instance); - - *instance_handle = (struct vchi_instance_handle *)instance; - - return status; -} -EXPORT_SYMBOL(vchi_initialise); - -/*********************************************************** - * Name: vchi_connect - * - * Arguments: struct vchi_instance_handle *instance_handle - * - * Description: Starts the command service on each connection, - * causing INIT messages to be pinged back and forth - * - * Returns: 0 if successful, failure otherwise - * - ***********************************************************/ -int32_t vchi_connect(struct vchi_instance_handle *instance_handle) -{ - struct vchiq_instance *instance = (struct vchiq_instance *)instance_handle; - - return vchiq_connect(instance); -} -EXPORT_SYMBOL(vchi_connect); - -/*********************************************************** - * Name: vchi_disconnect - * - * Arguments: struct vchi_instance_handle *instance_handle - * - * Description: Stops the command service on each connection, - * causing DE-INIT messages to be pinged back and forth - * - * Returns: 0 if successful, failure otherwise - * - ***********************************************************/ -int32_t vchi_disconnect(struct vchi_instance_handle *instance_handle) -{ - struct vchiq_instance *instance = (struct vchiq_instance *)instance_handle; - - return vchiq_shutdown(instance); -} -EXPORT_SYMBOL(vchi_disconnect); - -/*********************************************************** - * Name: vchi_service_open - * Name: vchi_service_create - * - * Arguments: struct vchi_instance_handle *instance_handle - * struct service_creation *setup, - * struct vchi_service_handle **handle - * - * Description: Routine to open a service - * - * Returns: int32_t - success == 0 - * - ***********************************************************/ - -static enum vchiq_status shim_callback(enum vchiq_reason reason, - struct vchiq_header *header, - unsigned int handle, - void *bulk_user) -{ - struct shim_service *service = - (struct shim_service *)VCHIQ_GET_SERVICE_USERDATA(handle); - - if (!service->callback) - goto release; - - switch (reason) { - case VCHIQ_MESSAGE_AVAILABLE: - vchiu_queue_push(&service->queue, header); - - service->callback(service->callback_param, - VCHI_CALLBACK_MSG_AVAILABLE, NULL); - - break; - - case VCHIQ_BULK_TRANSMIT_DONE: - service->callback(service->callback_param, - VCHI_CALLBACK_BULK_SENT, bulk_user); - break; - - case VCHIQ_BULK_RECEIVE_DONE: - service->callback(service->callback_param, - VCHI_CALLBACK_BULK_RECEIVED, bulk_user); - break; - - case VCHIQ_SERVICE_CLOSED: - service->callback(service->callback_param, - VCHI_CALLBACK_SERVICE_CLOSED, NULL); - break; - - case VCHIQ_BULK_TRANSMIT_ABORTED: - service->callback(service->callback_param, - VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, - bulk_user); - break; - - case VCHIQ_BULK_RECEIVE_ABORTED: - service->callback(service->callback_param, - VCHI_CALLBACK_BULK_RECEIVE_ABORTED, - bulk_user); - break; - - default: - WARN(1, "not supported\n"); - break; - } - -release: - return VCHIQ_SUCCESS; -} - -static struct shim_service *service_alloc(struct vchiq_instance *instance, - struct service_creation *setup) -{ - struct shim_service *service = kzalloc(sizeof(struct shim_service), GFP_KERNEL); - - (void)instance; - - if (service) { - if (!vchiu_queue_init(&service->queue, 64)) { - service->callback = setup->callback; - service->callback_param = setup->callback_param; - } else { - kfree(service); - service = NULL; - } - } - - return service; -} - -static void service_free(struct shim_service *service) -{ - if (service) { - vchiu_queue_delete(&service->queue); - kfree(service); - } -} - -int32_t vchi_service_open(struct vchi_instance_handle *instance_handle, - struct service_creation *setup, - struct vchi_service_handle **handle) -{ - struct vchiq_instance *instance = (struct vchiq_instance *)instance_handle; - struct shim_service *service = service_alloc(instance, setup); - - *handle = (struct vchi_service_handle *)service; - - if (service) { - struct vchiq_service_params params; - enum vchiq_status status; - - memset(¶ms, 0, sizeof(params)); - params.fourcc = setup->service_id; - params.callback = shim_callback; - params.userdata = service; - params.version = setup->version.version; - params.version_min = setup->version.version_min; - - status = vchiq_open_service(instance, ¶ms, - &service->handle); - if (status != VCHIQ_SUCCESS) { - service_free(service); - service = NULL; - *handle = NULL; - } - } - - return service ? 0 : -1; -} -EXPORT_SYMBOL(vchi_service_open); - -int32_t vchi_service_close(const struct vchi_service_handle *handle) -{ - int32_t ret = -1; - struct shim_service *service = (struct shim_service *)handle; - - if (service) { - enum vchiq_status status = vchiq_close_service(service->handle); - if (status == VCHIQ_SUCCESS) - service_free(service); - - ret = status; - } - return ret; -} -EXPORT_SYMBOL(vchi_service_close); - -int32_t vchi_get_peer_version(const struct vchi_service_handle *handle, short *peer_version) -{ - int32_t ret = -1; - struct shim_service *service = (struct shim_service *)handle; - - if (service) { - enum vchiq_status status; - - status = vchiq_get_peer_version(service->handle, peer_version); - ret = status; - } - return ret; -} -EXPORT_SYMBOL(vchi_get_peer_version); - -/*********************************************************** - * Name: vchi_service_use - * - * Arguments: const struct vchi_service_handle *handle - * - * Description: Routine to increment refcount on a service - * - * Returns: void - * - ***********************************************************/ -int32_t vchi_service_use(const struct vchi_service_handle *handle) -{ - int32_t ret = -1; - - struct shim_service *service = (struct shim_service *)handle; - if (service) - ret = vchiq_use_service(service->handle); - return ret; -} -EXPORT_SYMBOL(vchi_service_use); - -/*********************************************************** - * Name: vchi_service_release - * - * Arguments: const struct vchi_service_handle *handle - * - * Description: Routine to decrement refcount on a service - * - * Returns: void - * - ***********************************************************/ -int32_t vchi_service_release(const struct vchi_service_handle *handle) -{ - int32_t ret = -1; - - struct shim_service *service = (struct shim_service *)handle; - if (service) - ret = vchiq_release_service(service->handle); - return ret; -} -EXPORT_SYMBOL(vchi_service_release); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c deleted file mode 100644 index 644844d88fedac82ce7e1214bf6c9d7fb3455ed7..0000000000000000000000000000000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#include "vchiq_util.h" - -static inline int is_pow2(int i) -{ - return i && !(i & (i - 1)); -} - -int vchiu_queue_init(struct vchiu_queue *queue, int size) -{ - WARN_ON(!is_pow2(size)); - - queue->size = size; - queue->read = 0; - queue->write = 0; - queue->initialized = 1; - - init_completion(&queue->pop); - init_completion(&queue->push); - - queue->storage = kcalloc(size, sizeof(struct vchiq_header *), - GFP_KERNEL); - if (!queue->storage) { - vchiu_queue_delete(queue); - return -ENOMEM; - } - return 0; -} - -void vchiu_queue_delete(struct vchiu_queue *queue) -{ - kfree(queue->storage); -} - -int vchiu_queue_is_empty(struct vchiu_queue *queue) -{ - return queue->read == queue->write; -} - -void vchiu_queue_push(struct vchiu_queue *queue, struct vchiq_header *header) -{ - if (!queue->initialized) - return; - - while (queue->write == queue->read + queue->size) { - if (wait_for_completion_interruptible(&queue->pop)) - flush_signals(current); - } - - queue->storage[queue->write & (queue->size - 1)] = header; - queue->write++; - - complete(&queue->push); -} - -struct vchiq_header *vchiu_queue_peek(struct vchiu_queue *queue) -{ - while (queue->write == queue->read) { - if (wait_for_completion_interruptible(&queue->push)) - flush_signals(current); - } - - complete(&queue->push); // We haven't removed anything from the queue. - - return queue->storage[queue->read & (queue->size - 1)]; -} - -struct vchiq_header *vchiu_queue_pop(struct vchiu_queue *queue) -{ - struct vchiq_header *header; - - while (queue->write == queue->read) { - if (wait_for_completion_interruptible(&queue->push)) - flush_signals(current); - } - - header = queue->storage[queue->read & (queue->size - 1)]; - queue->read++; - - complete(&queue->pop); - - return header; -} diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h deleted file mode 100644 index f03a4250de0d264baae152ad64ef4553718cccd4..0000000000000000000000000000000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#ifndef VCHIQ_UTIL_H -#define VCHIQ_UTIL_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for time_t */ -#include - -#include "vchiq_if.h" - -struct vchiu_queue { - int size; - int read; - int write; - int initialized; - - struct completion pop; - struct completion push; - - struct vchiq_header **storage; -}; - -extern int vchiu_queue_init(struct vchiu_queue *queue, int size); -extern void vchiu_queue_delete(struct vchiu_queue *queue); - -extern int vchiu_queue_is_empty(struct vchiu_queue *queue); - -extern void vchiu_queue_push(struct vchiu_queue *queue, - struct vchiq_header *header); - -extern struct vchiq_header *vchiu_queue_peek(struct vchiu_queue *queue); -extern struct vchiq_header *vchiu_queue_pop(struct vchiu_queue *queue); - -#endif diff --git a/drivers/staging/vc04_services/vchiq-mmal/Kconfig b/drivers/staging/vc04_services/vchiq-mmal/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..500c0d12e4ff2ff4ab4479744cfd43065f6e9f7b --- /dev/null +++ b/drivers/staging/vc04_services/vchiq-mmal/Kconfig @@ -0,0 +1,7 @@ +config BCM2835_VCHIQ_MMAL + tristate "BCM2835 MMAL VCHIQ service" + depends on (ARCH_BCM2835 || COMPILE_TEST) + help + Enables the MMAL API over VCHIQ interface as used for the + majority of the multimedia services on VideoCore. + Defaults to Y when the Broadcomd BCM2835 camera host is selected. diff --git a/drivers/staging/vc04_services/vchiq-mmal/Makefile b/drivers/staging/vc04_services/vchiq-mmal/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b2a830f48acc63b9575791055b5b172cb4517f74 --- /dev/null +++ b/drivers/staging/vc04_services/vchiq-mmal/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +bcm2835-mmal-vchiq-objs := mmal-vchiq.o + +obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += bcm2835-mmal-vchiq.o + +ccflags-y += \ + -I$(srctree)/$(src)/.. \ + -I$(srctree)/$(src)/../include \ + -D__VCCOREVER__=0x04000000 diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h similarity index 96% rename from drivers/staging/vc04_services/bcm2835-camera/mmal-common.h rename to drivers/staging/vc04_services/vchiq-mmal/mmal-common.h index ce88fac7c24b4b0d5a9da069df28e1cc9e456846..5bd7410a034a450e0f6a237c21cce358523a6506 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h @@ -49,6 +49,11 @@ struct mmal_buffer { unsigned long buffer_size; /* size of allocated buffer */ struct mmal_msg_context *msg_context; + + unsigned long length; + u32 mmal_flags; + s64 dts; + s64 pts; }; /* */ diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h similarity index 100% rename from drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h rename to drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h similarity index 100% rename from drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h rename to drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h similarity index 100% rename from drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h rename to drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h similarity index 100% rename from drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h rename to drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h similarity index 99% rename from drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h rename to drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h index 43cc59316f90a0344f1b4bf2b5074aaf36cf7a37..b636e889c8a1d3928c4b2f80625a0728eb0e9925 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h @@ -28,7 +28,6 @@ #define VC_MMAL_VER 15 #define VC_MMAL_MIN_VER 10 -#define VC_MMAL_SERVER_NAME MAKE_FOURCC("mmal") /* max total message size is 512 bytes */ #define MMAL_MSG_MAX_SIZE 512 @@ -38,6 +37,7 @@ #include "mmal-msg-common.h" #include "mmal-msg-format.h" #include "mmal-msg-port.h" +#include "mmal-vchiq.h" enum mmal_msg_type { MMAL_MSG_TYPE_QUIT = 1, diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h similarity index 96% rename from drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h rename to drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h index f4ac5a6149eacb2a4f8afd7bc6d539263286645c..a1e39b1b1701da124011f843f7b03e5a38d00962 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h @@ -23,21 +23,21 @@ #define MMAL_PARAMETERS_H /** Common parameter ID group, used with many types of component. */ -#define MMAL_PARAMETER_GROUP_COMMON (0 << 16) +#define MMAL_PARAMETER_GROUP_COMMON (0 << 16) /** Camera-specific parameter ID group. */ -#define MMAL_PARAMETER_GROUP_CAMERA (1 << 16) +#define MMAL_PARAMETER_GROUP_CAMERA (1 << 16) /** Video-specific parameter ID group. */ -#define MMAL_PARAMETER_GROUP_VIDEO (2 << 16) +#define MMAL_PARAMETER_GROUP_VIDEO (2 << 16) /** Audio-specific parameter ID group. */ -#define MMAL_PARAMETER_GROUP_AUDIO (3 << 16) +#define MMAL_PARAMETER_GROUP_AUDIO (3 << 16) /** Clock-specific parameter ID group. */ -#define MMAL_PARAMETER_GROUP_CLOCK (4 << 16) +#define MMAL_PARAMETER_GROUP_CLOCK (4 << 16) /** Miracast-specific parameter ID group. */ -#define MMAL_PARAMETER_GROUP_MIRACAST (5 << 16) +#define MMAL_PARAMETER_GROUP_MIRACAST (5 << 16) /* Common parameters */ enum mmal_parameter_common_type { - /**< Never a valid parameter ID */ + /**< Never a valid parameter ID */ MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON, /**< MMAL_PARAMETER_ENCODING_T */ @@ -341,7 +341,7 @@ enum mmal_parameter_imagefx { MMAL_PARAM_IMAGEFX_CARTOON, }; -enum MMAL_PARAM_FLICKERAVOID_T { +enum MMAL_PARAM_FLICKERAVOID { MMAL_PARAM_FLICKERAVOID_OFF, MMAL_PARAM_FLICKERAVOID_AUTO, MMAL_PARAM_FLICKERAVOID_50HZ, @@ -723,7 +723,7 @@ struct mmal_parameter_imagefx_parameters { #define MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES 2 #define MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN 16 -struct mmal_parameter_camera_info_camera_t { +struct mmal_parameter_camera_info_camera { u32 port_id; u32 max_width; u32 max_height; @@ -731,7 +731,7 @@ struct mmal_parameter_camera_info_camera_t { u8 camera_name[MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN]; }; -enum mmal_parameter_camera_info_flash_type_t { +enum mmal_parameter_camera_info_flash_type { /* Make values explicit to ensure they match values in config ini */ MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0, MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED = 1, @@ -739,16 +739,16 @@ enum mmal_parameter_camera_info_flash_type_t { MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_MAX = 0x7FFFFFFF }; -struct mmal_parameter_camera_info_flash_t { - enum mmal_parameter_camera_info_flash_type_t flash_type; +struct mmal_parameter_camera_info_flash { + enum mmal_parameter_camera_info_flash_type flash_type; }; -struct mmal_parameter_camera_info_t { +struct mmal_parameter_camera_info { u32 num_cameras; u32 num_flashes; - struct mmal_parameter_camera_info_camera_t - cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS]; - struct mmal_parameter_camera_info_flash_t + struct mmal_parameter_camera_info_camera + cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS]; + struct mmal_parameter_camera_info_flash flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES]; }; diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c similarity index 88% rename from drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c rename to drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c index de03b90021a80aea988189449eaceccc4080d70e..e798d494f00ffdf8d8ec604553998785577f0cca 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c @@ -17,22 +17,30 @@ #include #include +#include #include #include #include #include #include +#include #include #include "mmal-common.h" #include "mmal-vchiq.h" #include "mmal-msg.h" -#define USE_VCHIQ_ARM -#include "interface/vchi/vchi.h" +/* + * maximum number of components supported. + * This matches the maximum permitted by default on the VPU + */ +#define VCHIQ_MMAL_MAX_COMPONENTS 64 -/* maximum number of components supported */ -#define VCHIQ_MMAL_MAX_COMPONENTS 4 +/* + * Timeout for synchronous msg responses in seconds. + * Helpful to increase this if stopping in the VPU debugger. + */ +#define SYNC_MSG_TIMEOUT 3 /*#define FULL_MSG_DUMP 1*/ @@ -142,7 +150,7 @@ struct mmal_msg_context { struct { /* message handle to release */ - struct vchi_held_msg msg_handle; + struct vchiq_header *msg_handle; /* pointer to received message */ struct mmal_msg *msg; /* received message length */ @@ -155,7 +163,7 @@ struct mmal_msg_context { }; struct vchiq_mmal_instance { - struct vchi_service_handle *handle; + unsigned int service_handle; /* ensure serialised access to service */ struct mutex vchiq_mutex; @@ -167,8 +175,6 @@ struct vchiq_mmal_instance { /* protect accesses to context_map */ struct mutex context_map_lock; - /* component to use next */ - int component_idx; struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS]; /* ordered workqueue to process all bulk operations */ @@ -245,17 +251,25 @@ static void buffer_work_cb(struct work_struct *work) { struct mmal_msg_context *msg_context = container_of(work, struct mmal_msg_context, u.bulk.work); + struct mmal_buffer *buffer = msg_context->u.bulk.buffer; + + if (!buffer) { + pr_err("%s: ctx: %p, No mmal buffer to pass details\n", + __func__, msg_context); + return; + } + + buffer->length = msg_context->u.bulk.buffer_used; + buffer->mmal_flags = msg_context->u.bulk.mmal_flags; + buffer->dts = msg_context->u.bulk.dts; + buffer->pts = msg_context->u.bulk.pts; atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu); msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance, msg_context->u.bulk.port, msg_context->u.bulk.status, - msg_context->u.bulk.buffer, - msg_context->u.bulk.buffer_used, - msg_context->u.bulk.mmal_flags, - msg_context->u.bulk.dts, - msg_context->u.bulk.pts); + msg_context->u.bulk.buffer); } /* workqueue scheduled callback to handle receiving buffers @@ -263,7 +277,7 @@ static void buffer_work_cb(struct work_struct *work) * VCHI will allow up to 4 bulk receives to be scheduled before blocking. * If we block in the service_callback context then we can't process the * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked - * vchi_bulk_queue_receive() call to complete. + * vchiq_bulk_receive() call to complete. */ static void buffer_to_host_work_cb(struct work_struct *work) { @@ -278,21 +292,20 @@ static void buffer_to_host_work_cb(struct work_struct *work) /* Dummy receive to ensure the buffers remain in order */ len = 8; /* queue the bulk submission */ - vchi_service_use(instance->handle); - ret = vchi_bulk_queue_receive(instance->handle, - msg_context->u.bulk.buffer->buffer, - /* Actual receive needs to be a multiple - * of 4 bytes - */ - (len + 3) & ~3, - VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | - VCHI_FLAGS_BLOCK_UNTIL_QUEUED, - msg_context); - - vchi_service_release(instance->handle); + vchiq_use_service(instance->service_handle); + ret = vchiq_bulk_receive(instance->service_handle, + msg_context->u.bulk.buffer->buffer, + /* Actual receive needs to be a multiple + * of 4 bytes + */ + (len + 3) & ~3, + msg_context, + VCHIQ_BULK_MODE_CALLBACK); + + vchiq_release_service(instance->service_handle); if (ret != 0) - pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n", + pr_err("%s: ctx: %p, vchiq_bulk_receive failed %d\n", __func__, msg_context, ret); } @@ -368,7 +381,7 @@ buffer_from_host(struct vchiq_mmal_instance *instance, if (!port->enabled) return -EINVAL; - pr_debug("instance:%p buffer:%p\n", instance->handle, buf); + pr_debug("instance:%u buffer:%p\n", instance->service_handle, buf); /* get context */ if (!buf->msg_context) { @@ -423,14 +436,15 @@ buffer_from_host(struct vchiq_mmal_instance *instance, /* no payload in message */ m.u.buffer_from_host.payload_in_message = 0; - vchi_service_use(instance->handle); + vchiq_use_service(instance->service_handle); - ret = vchi_queue_kernel_message(instance->handle, - &m, - sizeof(struct mmal_msg_header) + - sizeof(m.u.buffer_from_host)); + ret = vchiq_queue_kernel_message(instance->service_handle, &m, + sizeof(struct mmal_msg_header) + + sizeof(m.u.buffer_from_host)); + if (ret) + atomic_dec(&port->buffers_with_vpu); - vchi_service_release(instance->handle); + vchiq_release_service(instance->service_handle); return ret; } @@ -534,55 +548,49 @@ static void bulk_abort_cb(struct vchiq_mmal_instance *instance, } /* incoming event service callback */ -static void service_callback(void *param, - const enum vchi_callback_reason reason, - void *bulk_ctx) +static enum vchiq_status service_callback(enum vchiq_reason reason, + struct vchiq_header *header, + unsigned int handle, void *bulk_ctx) { - struct vchiq_mmal_instance *instance = param; - int status; + struct vchiq_mmal_instance *instance = vchiq_get_service_userdata(handle); u32 msg_len; struct mmal_msg *msg; - struct vchi_held_msg msg_handle; struct mmal_msg_context *msg_context; if (!instance) { pr_err("Message callback passed NULL instance\n"); - return; + return VCHIQ_SUCCESS; } switch (reason) { - case VCHI_CALLBACK_MSG_AVAILABLE: - status = vchi_msg_hold(instance->handle, (void **)&msg, - &msg_len, VCHI_FLAGS_NONE, &msg_handle); - if (status) { - pr_err("Unable to dequeue a message (%d)\n", status); - break; - } + case VCHIQ_MESSAGE_AVAILABLE: + msg = (void *)header->data; + msg_len = header->size; DBG_DUMP_MSG(msg, msg_len, "<<< reply message"); /* handling is different for buffer messages */ switch (msg->h.type) { case MMAL_MSG_TYPE_BUFFER_FROM_HOST: - vchi_held_msg_release(&msg_handle); + vchiq_release_message(handle, header); break; case MMAL_MSG_TYPE_EVENT_TO_HOST: event_to_host_cb(instance, msg, msg_len); - vchi_held_msg_release(&msg_handle); + vchiq_release_message(handle, header); break; case MMAL_MSG_TYPE_BUFFER_TO_HOST: buffer_to_host_cb(instance, msg, msg_len); - vchi_held_msg_release(&msg_handle); + vchiq_release_message(handle, header); break; default: /* messages dependent on header context to complete */ if (!msg->h.context) { pr_err("received message context was null!\n"); - vchi_held_msg_release(&msg_handle); + vchiq_release_message(handle, header); break; } @@ -591,12 +599,12 @@ static void service_callback(void *param, if (!msg_context) { pr_err("received invalid message context %u!\n", msg->h.context); - vchi_held_msg_release(&msg_handle); + vchiq_release_message(handle, header); break; } /* fill in context values */ - msg_context->u.sync.msg_handle = msg_handle; + msg_context->u.sync.msg_handle = header; msg_context->u.sync.msg = msg; msg_context->u.sync.msg_len = msg_len; @@ -616,15 +624,15 @@ static void service_callback(void *param, break; - case VCHI_CALLBACK_BULK_RECEIVED: + case VCHIQ_BULK_RECEIVE_DONE: bulk_receive_cb(instance, bulk_ctx); break; - case VCHI_CALLBACK_BULK_RECEIVE_ABORTED: + case VCHIQ_BULK_RECEIVE_ABORTED: bulk_abort_cb(instance, bulk_ctx); break; - case VCHI_CALLBACK_SERVICE_CLOSED: + case VCHIQ_SERVICE_CLOSED: /* TODO: consider if this requires action if received when * driver is not explicitly closing the service */ @@ -634,13 +642,15 @@ static void service_callback(void *param, pr_err("Received unhandled message reason %d\n", reason); break; } + + return VCHIQ_SUCCESS; } static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance, struct mmal_msg *msg, unsigned int payload_len, struct mmal_msg **msg_out, - struct vchi_held_msg *msg_handle_out) + struct vchiq_header **msg_handle) { struct mmal_msg_context *msg_context; int ret; @@ -668,14 +678,13 @@ static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance, DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len), ">>> sync message"); - vchi_service_use(instance->handle); + vchiq_use_service(instance->service_handle); - ret = vchi_queue_kernel_message(instance->handle, - msg, - sizeof(struct mmal_msg_header) + - payload_len); + ret = vchiq_queue_kernel_message(instance->service_handle, msg, + sizeof(struct mmal_msg_header) + + payload_len); - vchi_service_release(instance->handle); + vchiq_release_service(instance->service_handle); if (ret) { pr_err("error %d queuing message\n", ret); @@ -684,7 +693,7 @@ static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance, } timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt, - 3 * HZ); + SYNC_MSG_TIMEOUT * HZ); if (timeout == 0) { pr_err("timed out waiting for sync completion\n"); ret = -ETIME; @@ -694,7 +703,7 @@ static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance, } *msg_out = msg_context->u.sync.msg; - *msg_handle_out = msg_context->u.sync.msg_handle; + *msg_handle = msg_context->u.sync.msg_handle; release_msg_context(msg_context); return 0; @@ -766,7 +775,7 @@ static int port_info_set(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - struct vchi_held_msg rmsg_handle; + struct vchiq_header *rmsg_handle; pr_debug("setting port info port %p\n", port); if (!port) @@ -815,7 +824,7 @@ static int port_info_set(struct vchiq_mmal_instance *instance, port->component->handle, port->handle); release_msg: - vchi_held_msg_release(&rmsg_handle); + vchiq_release_message(instance->service_handle, rmsg_handle); return ret; } @@ -827,7 +836,7 @@ static int port_info_get(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - struct vchi_held_msg rmsg_handle; + struct vchiq_header *rmsg_handle; /* port info time */ m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET; @@ -910,7 +919,7 @@ release_msg: pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret, port->component->handle, port->handle); - vchi_held_msg_release(&rmsg_handle); + vchiq_release_message(instance->service_handle, rmsg_handle); return ret; } @@ -923,11 +932,11 @@ static int create_component(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - struct vchi_held_msg rmsg_handle; + struct vchiq_header *rmsg_handle; /* build component create message */ m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE; - m.u.component_create.client_component = (u32)(unsigned long)component; + m.u.component_create.client_component = component->client_component; strncpy(m.u.component_create.name, name, sizeof(m.u.component_create.name)); @@ -958,7 +967,7 @@ static int create_component(struct vchiq_mmal_instance *instance, component->inputs, component->outputs, component->clocks); release_msg: - vchi_held_msg_release(&rmsg_handle); + vchiq_release_message(instance->service_handle, rmsg_handle); return ret; } @@ -970,7 +979,7 @@ static int destroy_component(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - struct vchi_held_msg rmsg_handle; + struct vchiq_header *rmsg_handle; m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY; m.u.component_destroy.component_handle = component->handle; @@ -991,7 +1000,7 @@ static int destroy_component(struct vchiq_mmal_instance *instance, release_msg: - vchi_held_msg_release(&rmsg_handle); + vchiq_release_message(instance->service_handle, rmsg_handle); return ret; } @@ -1003,7 +1012,7 @@ static int enable_component(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - struct vchi_held_msg rmsg_handle; + struct vchiq_header *rmsg_handle; m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE; m.u.component_enable.component_handle = component->handle; @@ -1023,7 +1032,7 @@ static int enable_component(struct vchiq_mmal_instance *instance, ret = -rmsg->u.component_enable_reply.status; release_msg: - vchi_held_msg_release(&rmsg_handle); + vchiq_release_message(instance->service_handle, rmsg_handle); return ret; } @@ -1035,7 +1044,7 @@ static int disable_component(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - struct vchi_held_msg rmsg_handle; + struct vchiq_header *rmsg_handle; m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE; m.u.component_disable.component_handle = component->handle; @@ -1056,7 +1065,7 @@ static int disable_component(struct vchiq_mmal_instance *instance, release_msg: - vchi_held_msg_release(&rmsg_handle); + vchiq_release_message(instance->service_handle, rmsg_handle); return ret; } @@ -1068,7 +1077,7 @@ static int get_version(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - struct vchi_held_msg rmsg_handle; + struct vchiq_header *rmsg_handle; m.h.type = MMAL_MSG_TYPE_GET_VERSION; @@ -1088,7 +1097,7 @@ static int get_version(struct vchiq_mmal_instance *instance, *minor_out = rmsg->u.version.minor; release_msg: - vchi_held_msg_release(&rmsg_handle); + vchiq_release_message(instance->service_handle, rmsg_handle); return ret; } @@ -1101,7 +1110,7 @@ static int port_action_port(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - struct vchi_held_msg rmsg_handle; + struct vchiq_header *rmsg_handle; m.h.type = MMAL_MSG_TYPE_PORT_ACTION; m.u.port_action_port.component_handle = port->component->handle; @@ -1130,7 +1139,7 @@ static int port_action_port(struct vchiq_mmal_instance *instance, port_action_type_names[action_type], action_type); release_msg: - vchi_held_msg_release(&rmsg_handle); + vchiq_release_message(instance->service_handle, rmsg_handle); return ret; } @@ -1145,7 +1154,7 @@ static int port_action_handle(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - struct vchi_held_msg rmsg_handle; + struct vchiq_header *rmsg_handle; m.h.type = MMAL_MSG_TYPE_PORT_ACTION; @@ -1178,7 +1187,7 @@ static int port_action_handle(struct vchiq_mmal_instance *instance, action_type, connect_component_handle, connect_port_handle); release_msg: - vchi_held_msg_release(&rmsg_handle); + vchiq_release_message(instance->service_handle, rmsg_handle); return ret; } @@ -1190,7 +1199,7 @@ static int port_parameter_set(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - struct vchi_held_msg rmsg_handle; + struct vchiq_header *rmsg_handle; m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET; @@ -1219,7 +1228,7 @@ static int port_parameter_set(struct vchiq_mmal_instance *instance, ret, port->component->handle, port->handle, parameter_id); release_msg: - vchi_held_msg_release(&rmsg_handle); + vchiq_release_message(instance->service_handle, rmsg_handle); return ret; } @@ -1231,7 +1240,7 @@ static int port_parameter_get(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - struct vchi_held_msg rmsg_handle; + struct vchiq_header *rmsg_handle; m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET; @@ -1254,7 +1263,8 @@ static int port_parameter_get(struct vchiq_mmal_instance *instance, goto release_msg; } - ret = -rmsg->u.port_parameter_get_reply.status; + ret = rmsg->u.port_parameter_get_reply.status; + /* port_parameter_get_reply.size includes the header, * whilst *value_size doesn't. */ @@ -1266,17 +1276,18 @@ static int port_parameter_get(struct vchiq_mmal_instance *instance, */ memcpy(value, &rmsg->u.port_parameter_get_reply.value, *value_size); - *value_size = rmsg->u.port_parameter_get_reply.size; } else { memcpy(value, &rmsg->u.port_parameter_get_reply.value, rmsg->u.port_parameter_get_reply.size); } + /* Always report the size of the returned parameter to the caller */ + *value_size = rmsg->u.port_parameter_get_reply.size; pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__, ret, port->component->handle, port->handle, parameter_id); release_msg: - vchi_held_msg_release(&rmsg_handle); + vchiq_release_message(instance->service_handle, rmsg_handle); return ret; } @@ -1313,11 +1324,14 @@ static int port_disable(struct vchiq_mmal_instance *instance, mmalbuf = list_entry(buf_head, struct mmal_buffer, list); list_del(buf_head); - if (port->buffer_cb) + if (port->buffer_cb) { + mmalbuf->length = 0; + mmalbuf->mmal_flags = 0; + mmalbuf->dts = MMAL_TIME_UNKNOWN; + mmalbuf->pts = MMAL_TIME_UNKNOWN; port->buffer_cb(instance, - port, 0, mmalbuf, 0, 0, - MMAL_TIME_UNKNOWN, - MMAL_TIME_UNKNOWN); + port, 0, mmalbuf); + } } spin_unlock_irqrestore(&port->slock, flags); @@ -1396,6 +1410,7 @@ release_unlock: return ret; } +EXPORT_SYMBOL_GPL(vchiq_mmal_port_set_format); int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance, struct vchiq_mmal_port *port, @@ -1412,6 +1427,7 @@ int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance, return ret; } +EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set); int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance, struct vchiq_mmal_port *port, @@ -1428,6 +1444,7 @@ int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance, return ret; } +EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_get); /* enable a port * @@ -1458,6 +1475,7 @@ unlock: return ret; } +EXPORT_SYMBOL_GPL(vchiq_mmal_port_enable); int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance, struct vchiq_mmal_port *port) @@ -1478,6 +1496,7 @@ int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance, return ret; } +EXPORT_SYMBOL_GPL(vchiq_mmal_port_disable); /* ports will be connected in a tunneled manner so data buffers * are not handled by client. @@ -1565,6 +1584,7 @@ release_unlock: return ret; } +EXPORT_SYMBOL_GPL(vchiq_mmal_port_connect_tunnel); int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance, struct vchiq_mmal_port *port, @@ -1583,6 +1603,7 @@ int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance, return 0; } +EXPORT_SYMBOL_GPL(vchiq_mmal_submit_buffer); int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance, struct mmal_buffer *buf) @@ -1595,6 +1616,7 @@ int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance, buf->msg_context = msg_context; return 0; } +EXPORT_SYMBOL_GPL(mmal_vchi_buffer_init); int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf) { @@ -1606,6 +1628,7 @@ int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf) return 0; } +EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup); /* Initialise a mmal component and its ports * @@ -1616,17 +1639,29 @@ int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance, { int ret; int idx; /* port index */ - struct vchiq_mmal_component *component; + struct vchiq_mmal_component *component = NULL; if (mutex_lock_interruptible(&instance->vchiq_mutex)) return -EINTR; - if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) { + for (idx = 0; idx < VCHIQ_MMAL_MAX_COMPONENTS; idx++) { + if (!instance->component[idx].in_use) { + component = &instance->component[idx]; + component->in_use = 1; + break; + } + } + + if (!component) { ret = -EINVAL; /* todo is this correct error? */ goto unlock; } - component = &instance->component[instance->component_idx]; + /* We need a handle to reference back to our component structure. + * Use the array index in instance->component rather than rolling + * another IDR. + */ + component->client_component = idx; ret = create_component(instance, component, name); if (ret < 0) { @@ -1678,8 +1713,6 @@ int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance, goto release_component; } - instance->component_idx++; - *component_out = component; mutex_unlock(&instance->vchiq_mutex); @@ -1689,10 +1722,13 @@ int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance, release_component: destroy_component(instance, component); unlock: + if (component) + component->in_use = 0; mutex_unlock(&instance->vchiq_mutex); return ret; } +EXPORT_SYMBOL_GPL(vchiq_mmal_component_init); /* * cause a mmal component to be destroyed @@ -1710,10 +1746,13 @@ int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance, ret = destroy_component(instance, component); + component->in_use = 0; + mutex_unlock(&instance->vchiq_mutex); return ret; } +EXPORT_SYMBOL_GPL(vchiq_mmal_component_finalise); /* * cause a mmal component to be enabled @@ -1739,6 +1778,7 @@ int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance, return ret; } +EXPORT_SYMBOL_GPL(vchiq_mmal_component_enable); /* * cause a mmal component to be enabled @@ -1764,6 +1804,7 @@ int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance, return ret; } +EXPORT_SYMBOL_GPL(vchiq_mmal_component_disable); int vchiq_mmal_version(struct vchiq_mmal_instance *instance, u32 *major_out, u32 *minor_out) @@ -1779,6 +1820,7 @@ int vchiq_mmal_version(struct vchiq_mmal_instance *instance, return ret; } +EXPORT_SYMBOL_GPL(vchiq_mmal_version); int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance) { @@ -1790,9 +1832,9 @@ int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance) if (mutex_lock_interruptible(&instance->vchiq_mutex)) return -EINTR; - vchi_service_use(instance->handle); + vchiq_use_service(instance->service_handle); - status = vchi_service_close(instance->handle); + status = vchiq_close_service(instance->service_handle); if (status != 0) pr_err("mmal-vchiq: VCHIQ close failed\n"); @@ -1809,17 +1851,19 @@ int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance) return status; } +EXPORT_SYMBOL_GPL(vchiq_mmal_finalise); int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance) { int status; struct vchiq_mmal_instance *instance; - static struct vchi_instance_handle *vchi_instance; - struct service_creation params = { - .version = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER), - .service_id = VC_MMAL_SERVER_NAME, + static struct vchiq_instance *vchiq_instance; + struct vchiq_service_params params = { + .version = VC_MMAL_VER, + .version_min = VC_MMAL_MIN_VER, + .fourcc = VCHIQ_MAKE_FOURCC('m', 'm', 'a', 'l'), .callback = service_callback, - .callback_param = NULL, + .userdata = NULL, }; /* compile time checks to ensure structure size as they are @@ -1836,14 +1880,14 @@ int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance) BUILD_BUG_ON(sizeof(struct mmal_port) != 64); /* create a vchi instance */ - status = vchi_initialise(&vchi_instance); + status = vchiq_initialise(&vchiq_instance); if (status) { pr_err("Failed to initialise VCHI instance (status=%d)\n", status); return -EIO; } - status = vchi_connect(vchi_instance); + status = vchiq_connect(vchiq_instance); if (status) { pr_err("Failed to connect VCHI instance (status=%d)\n", status); return -EIO; @@ -1861,31 +1905,37 @@ int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance) mutex_init(&instance->context_map_lock); idr_init_base(&instance->context_map, 1); - params.callback_param = instance; + params.userdata = instance; instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq", WQ_MEM_RECLAIM); if (!instance->bulk_wq) goto err_free; - status = vchi_service_open(vchi_instance, ¶ms, &instance->handle); + status = vchiq_open_service(vchiq_instance, ¶ms, + &instance->service_handle); if (status) { pr_err("Failed to open VCHI service connection (status=%d)\n", status); goto err_close_services; } - vchi_service_release(instance->handle); + vchiq_release_service(instance->service_handle); *out_instance = instance; return 0; err_close_services: - vchi_service_close(instance->handle); + vchiq_close_service(instance->service_handle); destroy_workqueue(instance->bulk_wq); err_free: vfree(instance->bulk_scratch); kfree(instance); return -ENODEV; } +EXPORT_SYMBOL_GPL(vchiq_mmal_init); + +MODULE_DESCRIPTION("BCM2835 MMAL VCHIQ interface"); +MODULE_AUTHOR("Dave Stevenson, "); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h similarity index 97% rename from drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h rename to drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h index 47897e81ec586fe99d50a5805de3a4f29ee00e8e..1dc81ecf926825c0a6674d326ee30cd6550ff3ef 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h @@ -16,6 +16,7 @@ #ifndef MMAL_VCHIQ_H #define MMAL_VCHIQ_H +#include "mmal-common.h" #include "mmal-msg-format.h" #define MAX_PORT_COUNT 4 @@ -44,8 +45,7 @@ struct vchiq_mmal_port; typedef void (*vchiq_mmal_buffer_cb)( struct vchiq_mmal_instance *instance, struct vchiq_mmal_port *port, - int status, struct mmal_buffer *buffer, - unsigned long length, u32 mmal_flags, s64 dts, s64 pts); + int status, struct mmal_buffer *buffer); struct vchiq_mmal_port { u32 enabled:1; @@ -82,6 +82,7 @@ struct vchiq_mmal_port { }; struct vchiq_mmal_component { + u32 in_use:1; u32 enabled:1; u32 handle; /* VideoCore handle for component */ u32 inputs; /* Number of input ports */ @@ -91,6 +92,7 @@ struct vchiq_mmal_component { struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */ struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */ struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */ + u32 client_component; /* Used to ref back to client struct */ }; int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance); diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index 62a85c1ca6c4c2d0d5edae577906dca38aaf216b..889fc22f19bd15e38059322786498a0665062cd2 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -133,7 +133,7 @@ void vnt_init_bands(struct vnt_private *priv) priv->hw->wiphy->bands[NL80211_BAND_5GHZ] = &vnt_supported_5ghz_band; - /* fallthrough */ + fallthrough; case RF_RFMD2959: case RF_AIROHA: case RF_AL2230S: diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 41cbec4134b03227422f24f30997312f61c21355..76de1fd568eb0c2442fba331448c9632d82dcb27 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1766,48 +1766,37 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) /*------------------------------------------------------------------*/ -#ifdef CONFIG_PM -static int vt6655_suspend(struct pci_dev *pcid, pm_message_t state) +static int __maybe_unused vt6655_suspend(struct device *dev_d) { - struct vnt_private *priv = pci_get_drvdata(pcid); + struct vnt_private *priv = dev_get_drvdata(dev_d); unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - pci_save_state(pcid); - MACbShutdown(priv); - pci_disable_device(pcid); - spin_unlock_irqrestore(&priv->lock, flags); - pci_set_power_state(pcid, pci_choose_state(pcid, state)); - return 0; } -static int vt6655_resume(struct pci_dev *pcid) +static int __maybe_unused vt6655_resume(struct device *dev_d) { - pci_set_power_state(pcid, PCI_D0); - pci_enable_wake(pcid, PCI_D0, 0); - pci_restore_state(pcid); + device_wakeup_disable(dev_d); return 0; } -#endif MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table); +static SIMPLE_DEV_PM_OPS(vt6655_pm_ops, vt6655_suspend, vt6655_resume); + static struct pci_driver device_driver = { .name = DEVICE_NAME, .id_table = vt6655_pci_id_table, .probe = vt6655_probe, .remove = vt6655_remove, -#ifdef CONFIG_PM - .suspend = vt6655_suspend, - .resume = vt6655_resume, -#endif + .driver.pm = &vt6655_pm_ops, }; module_pci_driver(device_driver); diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index 4d6b48fd119d215803b6256a29c4e35f8e895ca9..94665ddc36a5e18be9db5956e5899b7d40bb738c 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -51,15 +51,15 @@ static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, /* default key last entry */ entry = MAX_KEY_TABLE - 1; key->hw_key_idx = entry; - /* fall through */ + fallthrough; case VNT_KEY_ALLGROUP: key_mode |= VNT_KEY_ALLGROUP; if (onfly_latch) key_mode |= VNT_KEY_ONFLY_ALL; - /* fall through */ + fallthrough; case VNT_KEY_GROUP_ADDRESS: key_mode |= mode; - /* fall through */ + fallthrough; case VNT_KEY_GROUP: key_mode |= (mode << 4); key_mode |= VNT_KEY_GROUP; diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index cfab64d2b3124e0cd7919c9fff35ec7a080a5cc8..4778439e875776c669a937c61c0258600fabd114 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -21,7 +21,7 @@ * s_uGetDataDuration - get tx data required duration * s_uFillDataHead- fulfill tx data duration header * s_uGetRTSCTSDuration- get rtx/cts required duration - * s_uGetRTSCTSRsvTime- get rts/cts reserved time + * get_rtscts_time- get rts/cts reserved time * s_uGetTxRsvTime- get frame reserved time * s_vFillCTSHead- fulfill CTS ctl header * s_vFillFragParameter- Set fragment ctl parameter. @@ -190,45 +190,41 @@ static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type, } /* byFreqType: 0=>5GHZ 1=>2.4GHZ */ -static -__le16 -s_uGetRTSCTSRsvTime( - struct vnt_private *pDevice, - unsigned char byRTSRsvType, - unsigned char byPktType, - unsigned int cbFrameLength, - unsigned short wCurrentRate -) +static __le16 get_rtscts_time(struct vnt_private *priv, + unsigned char rts_rsvtype, + unsigned char pkt_type, + unsigned int frame_length, + unsigned short current_rate) { - unsigned int uRrvTime = 0; - unsigned int uRTSTime = 0; - unsigned int uCTSTime = 0; - unsigned int uAckTime = 0; - unsigned int uDataTime = 0; - - uDataTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, cbFrameLength, wCurrentRate); - if (byRTSRsvType == 0) { /* RTSTxRrvTime_bb */ - uRTSTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate); - uAckTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); - uCTSTime = uAckTime; - } else if (byRTSRsvType == 1) { /* RTSTxRrvTime_ba, only in 2.4GHZ */ - uRTSTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate); - uCTSTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); - uAckTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); - } else if (byRTSRsvType == 2) { /* RTSTxRrvTime_aa */ - uRTSTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 20, pDevice->byTopOFDMBasicRate); - uAckTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); - uCTSTime = uAckTime; - } else if (byRTSRsvType == 3) { /* CTSTxRrvTime_ba, only in 2.4GHZ */ - uCTSTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); - uAckTime = bb_get_frame_time(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); - uRrvTime = uCTSTime + uAckTime + uDataTime + 2 * pDevice->uSIFS; - return cpu_to_le16((u16)uRrvTime); + unsigned int rrv_time = 0; + unsigned int rts_time = 0; + unsigned int cts_time = 0; + unsigned int ack_time = 0; + unsigned int data_time = 0; + + data_time = bb_get_frame_time(priv->byPreambleType, pkt_type, frame_length, current_rate); + if (rts_rsvtype == 0) { /* RTSTxRrvTime_bb */ + rts_time = bb_get_frame_time(priv->byPreambleType, pkt_type, 20, priv->byTopCCKBasicRate); + ack_time = bb_get_frame_time(priv->byPreambleType, pkt_type, 14, priv->byTopCCKBasicRate); + cts_time = ack_time; + } else if (rts_rsvtype == 1) { /* RTSTxRrvTime_ba, only in 2.4GHZ */ + rts_time = bb_get_frame_time(priv->byPreambleType, pkt_type, 20, priv->byTopCCKBasicRate); + cts_time = bb_get_frame_time(priv->byPreambleType, pkt_type, 14, priv->byTopCCKBasicRate); + ack_time = bb_get_frame_time(priv->byPreambleType, pkt_type, 14, priv->byTopOFDMBasicRate); + } else if (rts_rsvtype == 2) { /* RTSTxRrvTime_aa */ + rts_time = bb_get_frame_time(priv->byPreambleType, pkt_type, 20, priv->byTopOFDMBasicRate); + ack_time = bb_get_frame_time(priv->byPreambleType, pkt_type, 14, priv->byTopOFDMBasicRate); + cts_time = ack_time; + } else if (rts_rsvtype == 3) { /* CTSTxRrvTime_ba, only in 2.4GHZ */ + cts_time = bb_get_frame_time(priv->byPreambleType, pkt_type, 14, priv->byTopCCKBasicRate); + ack_time = bb_get_frame_time(priv->byPreambleType, pkt_type, 14, priv->byTopOFDMBasicRate); + rrv_time = cts_time + ack_time + data_time + 2 * priv->uSIFS; + return cpu_to_le16((u16)rrv_time); } /* RTSRrvTime */ - uRrvTime = uRTSTime + uCTSTime + uAckTime + uDataTime + 3 * pDevice->uSIFS; - return cpu_to_le16((u16)uRrvTime); + rrv_time = rts_time + cts_time + ack_time + data_time + 3 * priv->uSIFS; + return cpu_to_le16((u16)rrv_time); } /* byFreqType 0: 5GHz, 1:2.4Ghz */ @@ -921,9 +917,9 @@ s_vGenerateTxParameter( /* Fill RsvTime */ struct vnt_rrv_time_rts *buf = pvRrvTime; - buf->rts_rrv_time_aa = s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate); - buf->rts_rrv_time_ba = s_uGetRTSCTSRsvTime(pDevice, 1, byPktType, cbFrameSize, wCurrentRate); - buf->rts_rrv_time_bb = s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate); + buf->rts_rrv_time_aa = get_rtscts_time(pDevice, 2, byPktType, cbFrameSize, wCurrentRate); + buf->rts_rrv_time_ba = get_rtscts_time(pDevice, 1, byPktType, cbFrameSize, wCurrentRate); + buf->rts_rrv_time_bb = get_rtscts_time(pDevice, 0, byPktType, cbFrameSize, wCurrentRate); buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK); buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK); @@ -933,7 +929,7 @@ s_vGenerateTxParameter( buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK); buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK); - buf->cts_rrv_time_ba = s_uGetRTSCTSRsvTime(pDevice, 3, byPktType, cbFrameSize, wCurrentRate); + buf->cts_rrv_time_ba = get_rtscts_time(pDevice, 3, byPktType, cbFrameSize, wCurrentRate); /* Fill CTS */ s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption); @@ -942,7 +938,7 @@ s_vGenerateTxParameter( if (pvRTS) {/* RTS_need, non PCF mode */ struct vnt_rrv_time_ab *buf = pvRrvTime; - buf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate); + buf->rts_rrv_time = get_rtscts_time(pDevice, 2, byPktType, cbFrameSize, wCurrentRate); buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK); /* Fill RTS */ @@ -956,7 +952,7 @@ s_vGenerateTxParameter( if (pvRTS) {/* RTS_need, non PCF mode */ struct vnt_rrv_time_ab *buf = pvRrvTime; - buf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate); + buf->rts_rrv_time = get_rtscts_time(pDevice, 0, byPktType, cbFrameSize, wCurrentRate); buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK); /* Fill RTS */ diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c index 5d57d34577f5f89779e201817bb7ab0dc078743d..7855689af7cbeaea6a37ae16588ba927ec0b0111 100644 --- a/drivers/staging/vt6656/channel.c +++ b/drivers/staging/vt6656/channel.c @@ -145,7 +145,7 @@ void vnt_init_bands(struct vnt_private *priv) priv->hw->wiphy->bands[NL80211_BAND_5GHZ] = &vnt_supported_5ghz_band; - /* fallthrough */ + fallthrough; case RF_AL2230: case RF_AL2230S: case RF_VT3226: diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c index c66cb53cfc0955e1c909f47a2bf7ef1076c6bf1e..70f75c5760cecad89771dde4d6f29ba6416d0e85 100644 --- a/drivers/staging/vt6656/key.c +++ b/drivers/staging/vt6656/key.c @@ -67,7 +67,7 @@ static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, /* default key last entry */ entry = MAX_KEY_TABLE - 1; key->hw_key_idx = entry; - /* fall through */ + fallthrough; case VNT_KEY_GROUP_ADDRESS: key_mode = mode | (mode << 4); break; diff --git a/drivers/staging/wfx/bh.c b/drivers/staging/wfx/bh.c index 1cbaf8bb4fa3807474ad69845fbac183a5040389..53ae0b5abcdd82917033aa7a6eae02777ff4ad8c 100644 --- a/drivers/staging/wfx/bh.c +++ b/drivers/staging/wfx/bh.c @@ -57,7 +57,6 @@ static int rx_helper(struct wfx_dev *wdev, size_t read_len, int *is_cnf) int release_count; int piggyback = 0; - WARN(read_len < 4, "corrupted read"); WARN(read_len > round_down(0xFFF, 2) * sizeof(u16), "%s: request exceed WFx capability", __func__); @@ -76,20 +75,17 @@ static int rx_helper(struct wfx_dev *wdev, size_t read_len, int *is_cnf) hif = (struct hif_msg *)skb->data; WARN(hif->encrypted & 0x1, "unsupported encryption type"); if (hif->encrypted == 0x2) { - if (wfx_sl_decode(wdev, (void *)hif)) { - dev_kfree_skb(skb); - // If frame was a confirmation, expect trouble in next - // exchange. However, it is harmless to fail to decode - // an indication frame, so try to continue. Anyway, - // piggyback is probably correct. - return piggyback; - } - computed_len = - round_up(le16_to_cpu(hif->len) - sizeof(hif->len), 16) + - sizeof(struct hif_sl_msg) + - sizeof(struct hif_sl_tag); + if (WARN(read_len < sizeof(struct hif_sl_msg), "corrupted read")) + goto err; + computed_len = le16_to_cpu(((struct hif_sl_msg *)hif)->len); + computed_len = round_up(computed_len - sizeof(u16), 16); + computed_len += sizeof(struct hif_sl_msg); + computed_len += sizeof(struct hif_sl_tag); } else { - computed_len = round_up(le16_to_cpu(hif->len), 2); + if (WARN(read_len < sizeof(struct hif_msg), "corrupted read")) + goto err; + computed_len = le16_to_cpu(hif->len); + computed_len = round_up(computed_len, 2); } if (computed_len != read_len) { dev_err(wdev->dev, "inconsistent message length: %zu != %zu\n", @@ -98,6 +94,16 @@ static int rx_helper(struct wfx_dev *wdev, size_t read_len, int *is_cnf) hif, read_len, true); goto err; } + if (hif->encrypted == 0x2) { + if (wfx_sl_decode(wdev, (struct hif_sl_msg *)hif)) { + dev_kfree_skb(skb); + // If frame was a confirmation, expect trouble in next + // exchange. However, it is harmless to fail to decode + // an indication frame, so try to continue. Anyway, + // piggyback is probably correct. + return piggyback; + } + } if (!(hif->id & HIF_ID_IS_INDICATION)) { (*is_cnf)++; diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c index e8da61fb096b2a33cdf68a7030e302c76c3e521e..d19c0478e8be01110f9a05d5560360cac4dbe596 100644 --- a/drivers/staging/wfx/bus_spi.c +++ b/drivers/staging/wfx/bus_spi.c @@ -8,7 +8,6 @@ */ #include #include -#include #include #include #include @@ -21,10 +20,6 @@ #include "main.h" #include "bh.h" -static int gpio_reset = -2; -module_param(gpio_reset, int, 0644); -MODULE_PARM_DESC(gpio_reset, "gpio number for reset. -1 for none."); - #define SET_WRITE 0x7FFF /* usage: and operation */ #define SET_READ 0x8000 /* usage: or operation */ @@ -211,10 +206,15 @@ static int wfx_spi_probe(struct spi_device *func) bus->need_swab = true; spi_set_drvdata(func, bus); - bus->gpio_reset = wfx_get_gpio(&func->dev, gpio_reset, "reset"); + bus->gpio_reset = devm_gpiod_get_optional(&func->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(bus->gpio_reset)) + return PTR_ERR(bus->gpio_reset); if (!bus->gpio_reset) { - dev_warn(&func->dev, "try to load firmware anyway\n"); + dev_warn(&func->dev, + "gpio reset is not defined, trying to load firmware anyway\n"); } else { + gpiod_set_consumer_name(bus->gpio_reset, "wfx reset"); if (spi_get_device_id(func)->driver_data & WFX_RESET_INVERTED) gpiod_toggle_active_low(bus->gpio_reset); gpiod_set_value_cansleep(bus->gpio_reset, 1); diff --git a/drivers/staging/wfx/data_rx.c b/drivers/staging/wfx/data_rx.c index 0e959ebc38b565471069ea688c82efc050badcce..6fb0788807426d232ffa77684cef555d09b15e14 100644 --- a/drivers/staging/wfx/data_rx.c +++ b/drivers/staging/wfx/data_rx.c @@ -13,55 +13,22 @@ #include "bh.h" #include "sta.h" -static int wfx_drop_encrypt_data(struct wfx_dev *wdev, - const struct hif_ind_rx *arg, - struct sk_buff *skb) +static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt) { - struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data; - size_t hdrlen = ieee80211_hdrlen(frame->frame_control); - size_t iv_len, icv_len; + int params, tid; - /* Oops... There is no fast way to ask mac80211 about - * IV/ICV lengths. Even defineas are not exposed. - */ - switch (arg->rx_flags.encryp) { - case HIF_RI_FLAGS_WEP_ENCRYPTED: - iv_len = 4 /* WEP_IV_LEN */; - icv_len = 4 /* WEP_ICV_LEN */; - break; - case HIF_RI_FLAGS_TKIP_ENCRYPTED: - iv_len = 8 /* TKIP_IV_LEN */; - icv_len = 4 /* TKIP_ICV_LEN */ - + 8 /*MICHAEL_MIC_LEN*/; + switch (mgmt->u.action.u.addba_req.action_code) { + case WLAN_ACTION_ADDBA_REQ: + params = le16_to_cpu(mgmt->u.action.u.addba_req.capab); + tid = (params & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; + ieee80211_start_rx_ba_session_offl(wvif->vif, mgmt->sa, tid); break; - case HIF_RI_FLAGS_AES_ENCRYPTED: - iv_len = 8 /* CCMP_HDR_LEN */; - icv_len = 8 /* CCMP_MIC_LEN */; + case WLAN_ACTION_DELBA: + params = le16_to_cpu(mgmt->u.action.u.delba.params); + tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; + ieee80211_stop_rx_ba_session_offl(wvif->vif, mgmt->sa, tid); break; - case HIF_RI_FLAGS_WAPI_ENCRYPTED: - iv_len = 18 /* WAPI_HDR_LEN */; - icv_len = 16 /* WAPI_MIC_LEN */; - break; - default: - dev_err(wdev->dev, "unknown encryption type %d\n", - arg->rx_flags.encryp); - return -EIO; - } - - /* Firmware strips ICV in case of MIC failure. */ - if (arg->status == HIF_STATUS_RX_FAIL_MIC) - icv_len = 0; - - if (skb->len < hdrlen + iv_len + icv_len) { - dev_warn(wdev->dev, "malformed SDU received\n"); - return -EIO; } - - /* Remove IV, ICV and MIC */ - skb_trim(skb, skb->len - icv_len); - memmove(skb->data + iv_len, skb->data, hdrlen); - skb_pull(skb, iv_len); - return 0; } void wfx_rx_cb(struct wfx_vif *wvif, @@ -73,12 +40,6 @@ void wfx_rx_cb(struct wfx_vif *wvif, memset(hdr, 0, sizeof(*hdr)); - // FIXME: Why do we drop these frames? - if (!arg->rcpi_rssi && - (ieee80211_is_probe_resp(frame->frame_control) || - ieee80211_is_beacon(frame->frame_control))) - goto drop; - if (arg->status == HIF_STATUS_RX_FAIL_MIC) hdr->flag |= RX_FLAG_MMIC_ERROR; else if (arg->status) @@ -102,24 +63,26 @@ void wfx_rx_cb(struct wfx_vif *wvif, hdr->rate_idx = arg->rxed_rate; } + if (!arg->rcpi_rssi) { + hdr->flag |= RX_FLAG_NO_SIGNAL_VAL; + dev_info(wvif->wdev->dev, "received frame without RSSI data\n"); + } hdr->signal = arg->rcpi_rssi / 2 - 110; hdr->antenna = 0; - if (arg->rx_flags.encryp) { - if (wfx_drop_encrypt_data(wvif->wdev, arg, skb)) - goto drop; - hdr->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED; - if (arg->rx_flags.encryp == HIF_RI_FLAGS_TKIP_ENCRYPTED) - hdr->flag |= RX_FLAG_MMIC_STRIPPED; - } + if (arg->rx_flags.encryp) + hdr->flag |= RX_FLAG_DECRYPTED; - /* Filter block ACK negotiation: fully controlled by firmware */ + // Block ack negociation is offloaded by the firmware. However, + // re-ordering must be done by the mac80211. if (ieee80211_is_action(frame->frame_control) && - arg->rx_flags.match_uc_addr && - mgmt->u.action.category == WLAN_CATEGORY_BACK) + mgmt->u.action.category == WLAN_CATEGORY_BACK && + skb->len > IEEE80211_MIN_ACTION_SIZE) { + wfx_rx_handle_ba(wvif, mgmt); goto drop; - ieee80211_rx_irqsafe(wvif->wdev->hw, skb); + } + ieee80211_rx_irqsafe(wvif->wdev->hw, skb); return; drop: diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index f042ef36b408e6071b357f110389caee3601d67c..3acf4eb0214dc4e313e4486be0c96a0129bb90a4 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -213,23 +213,6 @@ static bool ieee80211_is_action_back(struct ieee80211_hdr *hdr) return true; } -static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr, - struct wfx_tx_priv *tx_priv, - struct ieee80211_sta *sta) -{ - struct wfx_sta_priv *sta_priv; - int tid = ieee80211_get_tid(hdr); - - if (sta) { - tx_priv->has_sta = true; - sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; - spin_lock_bh(&sta_priv->lock); - sta_priv->buffered[tid]++; - ieee80211_sta_set_buffered(sta, tid, true); - spin_unlock_bh(&sta_priv->lock); - } -} - static u8 wfx_tx_get_link_id(struct wfx_vif *wvif, struct ieee80211_sta *sta, struct ieee80211_hdr *hdr) { @@ -407,8 +390,7 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, req->tx_flags.retry_policy_index = wfx_tx_get_rate_id(wvif, tx_info); // Auxiliary operations - wfx_tx_manage_pm(wvif, hdr, tx_priv, sta); - wfx_tx_queues_put(wvif->wdev, skb); + wfx_tx_queues_put(wvif, skb); if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) schedule_work(&wvif->update_tim_work); wfx_bh_request_tx(wvif->wdev); @@ -436,7 +418,8 @@ void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, wvif = wvif_iterate(wdev, NULL); if (WARN_ON(!wvif)) goto drop; - // FIXME: why? + // Because of TX_AMPDU_SETUP_IN_HW, mac80211 does not try to send any + // BlockAck session management frame. The check below exist just in case. if (ieee80211_is_action_back(hdr)) { dev_info(wdev->dev, "drop BA action\n"); goto drop; @@ -450,37 +433,6 @@ drop: ieee80211_tx_status_irqsafe(wdev->hw, skb); } -static struct ieee80211_hdr *wfx_skb_hdr80211(struct sk_buff *skb) -{ - struct hif_msg *hif = (struct hif_msg *)skb->data; - struct hif_req_tx *req = (struct hif_req_tx *)hif->body; - - return (struct ieee80211_hdr *)(req->frame + req->data_flags.fc_offset); -} - -static void wfx_tx_update_sta(struct wfx_vif *wvif, struct ieee80211_hdr *hdr) -{ - int tid = ieee80211_get_tid(hdr); - struct wfx_sta_priv *sta_priv; - struct ieee80211_sta *sta; - - rcu_read_lock(); // protect sta - sta = ieee80211_find_sta(wvif->vif, hdr->addr1); - if (sta) { - sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; - spin_lock_bh(&sta_priv->lock); - WARN(!sta_priv->buffered[tid], "inconsistent notification"); - sta_priv->buffered[tid]--; - if (!sta_priv->buffered[tid]) - ieee80211_sta_set_buffered(sta, tid, false); - spin_unlock_bh(&sta_priv->lock); - } else { - dev_dbg(wvif->wdev->dev, "%s: sta does not exist anymore\n", - __func__); - } - rcu_read_unlock(); -} - static void wfx_skb_dtor(struct wfx_vif *wvif, struct sk_buff *skb) { struct hif_msg *hif = (struct hif_msg *)skb->data; @@ -533,27 +485,29 @@ static void wfx_tx_fill_rates(struct wfx_dev *wdev, dev_dbg(wdev->dev, "%d more retries than expected\n", tx_count); } -void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg) +void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct hif_cnf_tx *arg) { struct ieee80211_tx_info *tx_info; const struct wfx_tx_priv *tx_priv; + struct wfx_vif *wvif; struct sk_buff *skb; - skb = wfx_pending_get(wvif->wdev, arg->packet_id); + skb = wfx_pending_get(wdev, arg->packet_id); if (!skb) { - dev_warn(wvif->wdev->dev, "received unknown packet_id (%#.8x) from chip\n", + dev_warn(wdev->dev, "received unknown packet_id (%#.8x) from chip\n", arg->packet_id); return; } + wvif = wdev_to_wvif(wdev, ((struct hif_msg *)skb->data)->interface); + WARN_ON(!wvif); + if (!wvif) + return; tx_info = IEEE80211_SKB_CB(skb); tx_priv = wfx_skb_tx_priv(skb); - _trace_tx_stats(arg, skb, - wfx_pending_get_pkt_us_delay(wvif->wdev, skb)); + _trace_tx_stats(arg, skb, wfx_pending_get_pkt_us_delay(wdev, skb)); // You can touch to tx_priv, but don't touch to tx_info->status. - wfx_tx_fill_rates(wvif->wdev, tx_info, arg); - if (tx_priv->has_sta) - wfx_tx_update_sta(wvif, wfx_skb_hdr80211(skb)); + wfx_tx_fill_rates(wdev, tx_info, arg); skb_trim(skb, skb->len - wfx_tx_get_icv_len(tx_priv->hw_key)); // From now, you can touch to tx_info->status, but do not touch to @@ -582,45 +536,58 @@ void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg) wfx_skb_dtor(wvif, skb); } -void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u32 queues, bool drop) +static void wfx_flush_vif(struct wfx_vif *wvif, u32 queues, + struct sk_buff_head *dropped) { - struct wfx_dev *wdev = hw->priv; - struct sk_buff_head dropped; struct wfx_queue *queue; - struct wfx_vif *wvif; - struct hif_msg *hif; - struct sk_buff *skb; - int vif_id = -1; int i; - if (vif) - vif_id = ((struct wfx_vif *)vif->drv_priv)->id; - skb_queue_head_init(&dropped); for (i = 0; i < IEEE80211_NUM_ACS; i++) { if (!(BIT(i) & queues)) continue; - queue = &wdev->tx_queue[i]; - if (drop) - wfx_tx_queue_drop(wdev, queue, vif_id, &dropped); - if (wdev->chip_frozen) + queue = &wvif->tx_queue[i]; + if (dropped) + wfx_tx_queue_drop(wvif, queue, dropped); + } + if (wvif->wdev->chip_frozen) + return; + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + if (!(BIT(i) & queues)) continue; - if (wait_event_timeout(wdev->tx_dequeue, - wfx_tx_queue_empty(wdev, queue, vif_id), + queue = &wvif->tx_queue[i]; + if (wait_event_timeout(wvif->wdev->tx_dequeue, + wfx_tx_queue_empty(wvif, queue), msecs_to_jiffies(1000)) <= 0) - dev_warn(wdev->dev, + dev_warn(wvif->wdev->dev, "frames queued while flushing tx queues?"); } +} + +void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop) +{ + struct wfx_dev *wdev = hw->priv; + struct sk_buff_head dropped; + struct wfx_vif *wvif; + struct hif_msg *hif; + struct sk_buff *skb; + + skb_queue_head_init(&dropped); + if (vif) { + wvif = (struct wfx_vif *)vif->drv_priv; + wfx_flush_vif(wvif, queues, drop ? &dropped : NULL); + } else { + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) + wfx_flush_vif(wvif, queues, drop ? &dropped : NULL); + } wfx_tx_flush(wdev); if (wdev->chip_frozen) wfx_pending_drop(wdev, &dropped); while ((skb = skb_dequeue(&dropped)) != NULL) { hif = (struct hif_msg *)skb->data; wvif = wdev_to_wvif(wdev, hif->interface); - if (wfx_skb_tx_priv(skb)->has_sta) - wfx_tx_update_sta(wvif, wfx_skb_hdr80211(skb)); ieee80211_tx_info_clear_status(IEEE80211_SKB_CB(skb)); wfx_skb_dtor(wvif, skb); } } - diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h index 54fff24508fb995995d777e7b210738f97175487..cff7b9ff99a99489906197182645e79969abaa07 100644 --- a/drivers/staging/wfx/data_tx.h +++ b/drivers/staging/wfx/data_tx.h @@ -36,7 +36,6 @@ struct tx_policy_cache { struct wfx_tx_priv { ktime_t xmit_timestamp; struct ieee80211_key_conf *hw_key; - bool has_sta; } __packed; void wfx_tx_policy_init(struct wfx_vif *wvif); @@ -44,7 +43,7 @@ void wfx_tx_policy_upload_work(struct work_struct *work); void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb); -void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg); +void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct hif_cnf_tx *arg); void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop); diff --git a/drivers/staging/wfx/debug.c b/drivers/staging/wfx/debug.c index 10d649985696a3bf6d702fee11bd35641b46e5e2..3f1712b7c919d8e170f5716807b279647bf8a53f 100644 --- a/drivers/staging/wfx/debug.c +++ b/drivers/staging/wfx/debug.c @@ -334,6 +334,28 @@ static const struct file_operations wfx_send_hif_msg_fops = { .read = wfx_send_hif_msg_read, }; +static int wfx_ps_timeout_set(void *data, u64 val) +{ + struct wfx_dev *wdev = (struct wfx_dev *)data; + struct wfx_vif *wvif; + + wdev->force_ps_timeout = val; + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) + wfx_update_pm(wvif); + return 0; +} + +static int wfx_ps_timeout_get(void *data, u64 *val) +{ + struct wfx_dev *wdev = (struct wfx_dev *)data; + + *val = wdev->force_ps_timeout; + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(wfx_ps_timeout_fops, wfx_ps_timeout_get, wfx_ps_timeout_set, "%lld\n"); + int wfx_debug_init(struct wfx_dev *wdev) { struct dentry *d; @@ -348,6 +370,7 @@ int wfx_debug_init(struct wfx_dev *wdev) &wfx_burn_slk_key_fops); debugfs_create_file("send_hif_msg", 0600, d, wdev, &wfx_send_hif_msg_fops); + debugfs_create_file("ps_timeout", 0600, d, wdev, &wfx_ps_timeout_fops); return 0; } diff --git a/drivers/staging/wfx/fwio.c b/drivers/staging/wfx/fwio.c index 72bb3d2a96138f669a07931a2ffa09e5c47288d5..22d3b684f04ff2c3b243551700e3413f3d9e0519 100644 --- a/drivers/staging/wfx/fwio.c +++ b/drivers/staging/wfx/fwio.c @@ -177,7 +177,7 @@ static int wait_ncp_status(struct wfx_dev *wdev, u32 status) static int upload_firmware(struct wfx_dev *wdev, const u8 *data, size_t len) { int ret; - u32 offs, bytes_done; + u32 offs, bytes_done = 0; ktime_t now, start; if (len % DNLD_BLOCK_SIZE) { @@ -188,15 +188,14 @@ static int upload_firmware(struct wfx_dev *wdev, const u8 *data, size_t len) while (offs < len) { start = ktime_get(); for (;;) { - ret = sram_reg_read(wdev, WFX_DCA_GET, &bytes_done); - if (ret < 0) - return ret; now = ktime_get(); - if (offs + - DNLD_BLOCK_SIZE - bytes_done < DNLD_FIFO_SIZE) + if (offs + DNLD_BLOCK_SIZE - bytes_done < DNLD_FIFO_SIZE) break; if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT))) return -ETIMEDOUT; + ret = sram_reg_read(wdev, WFX_DCA_GET, &bytes_done); + if (ret < 0) + return ret; } if (ktime_compare(now, start)) dev_dbg(wdev->dev, "answer after %lldus\n", @@ -398,10 +397,9 @@ int wfx_init_device(struct wfx_dev *wdev) ret = load_firmware_secure(wdev); if (ret < 0) return ret; - ret = config_reg_write_bits(wdev, - CFG_DIRECT_ACCESS_MODE | - CFG_IRQ_ENABLE_DATA | - CFG_IRQ_ENABLE_WRDY, - CFG_IRQ_ENABLE_DATA); - return ret; + return config_reg_write_bits(wdev, + CFG_DIRECT_ACCESS_MODE | + CFG_IRQ_ENABLE_DATA | + CFG_IRQ_ENABLE_WRDY, + CFG_IRQ_ENABLE_DATA); } diff --git a/drivers/staging/wfx/hif_rx.c b/drivers/staging/wfx/hif_rx.c index bb156033d1e16cd619196663ba746bef45cfd414..cc7c0cf226ba1f1b729a48a8b9b8d0d1a48036e5 100644 --- a/drivers/staging/wfx/hif_rx.c +++ b/drivers/staging/wfx/hif_rx.c @@ -63,13 +63,8 @@ static int hif_tx_confirm(struct wfx_dev *wdev, const struct hif_msg *hif, const void *buf) { const struct hif_cnf_tx *body = buf; - struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - - WARN_ON(!wvif); - if (!wvif) - return -EFAULT; - wfx_tx_confirm_cb(wvif, body); + wfx_tx_confirm_cb(wdev, body); return 0; } @@ -77,16 +72,11 @@ static int hif_multi_tx_confirm(struct wfx_dev *wdev, const struct hif_msg *hif, const void *buf) { const struct hif_cnf_multi_transmit *body = buf; - struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); int i; WARN(body->num_tx_confs <= 0, "corrupted message"); - WARN_ON(!wvif); - if (!wvif) - return -EFAULT; - for (i = 0; i < body->num_tx_confs; i++) - wfx_tx_confirm_cb(wvif, &body->tx_conf_payload[i]); + wfx_tx_confirm_cb(wdev, &body->tx_conf_payload[i]); return 0; } @@ -159,7 +149,6 @@ static int hif_event_indication(struct wfx_dev *wdev, struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); const struct hif_ind_event *body = buf; int type = le32_to_cpu(body->event_id); - int cause; if (!wvif) { dev_warn(wdev->dev, "received event for non-existent vif\n"); @@ -178,13 +167,8 @@ static int hif_event_indication(struct wfx_dev *wdev, dev_dbg(wdev->dev, "ignore BSSREGAINED indication\n"); break; case HIF_EVENT_IND_PS_MODE_ERROR: - cause = le32_to_cpu(body->event_data.ps_mode_error); dev_warn(wdev->dev, "error while processing power save request: %d\n", - cause); - if (cause == HIF_PS_ERROR_AP_NOT_RESP_TO_POLL) { - wvif->bss_not_support_ps_poll = true; - schedule_work(&wvif->update_pm_work); - } + le32_to_cpu(body->event_data.ps_mode_error)); break; default: dev_warn(wdev->dev, "unhandled event indication: %.2x\n", diff --git a/drivers/staging/wfx/hif_tx_mib.c b/drivers/staging/wfx/hif_tx_mib.c index 1689cb42acc0d2b614fd63544533105471b89089..05f1e1e98af9e0598d818242310d3509d90964e1 100644 --- a/drivers/staging/wfx/hif_tx_mib.c +++ b/drivers/staging/wfx/hif_tx_mib.c @@ -113,7 +113,7 @@ int hif_set_beacon_filter_table(struct wfx_vif *wvif, int tbl_len, if (!val) return -ENOMEM; val->num_of_info_elmts = cpu_to_le32(tbl_len); - memcpy(val->ie_table, tbl, tbl_len * sizeof(*tbl)); + memcpy(val->ie_table, tbl, flex_array_size(val, ie_table, tbl_len)); ret = hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_BEACON_FILTER_TABLE, val, buf_len); kfree(val); diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c index 6bd96f476388436f0ef9c1996cfd4ed7c6b3c9df..11dfa088fc86f39de01257ed5f4875dfcdf90870 100644 --- a/drivers/staging/wfx/main.c +++ b/drivers/staging/wfx/main.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -41,10 +40,6 @@ MODULE_DESCRIPTION("Silicon Labs 802.11 Wireless LAN driver for WFx"); MODULE_AUTHOR("Jérôme Pouiller "); MODULE_LICENSE("GPL"); -static int gpio_wakeup = -2; -module_param(gpio_wakeup, int, 0644); -MODULE_PARM_DESC(gpio_wakeup, "gpio number for wakeup. -1 for none."); - #define RATETAB_ENT(_rate, _rateid, _flags) { \ .bitrate = (_rate), \ .hw_value = (_rateid), \ @@ -170,38 +165,6 @@ bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor) return false; } -struct gpio_desc *wfx_get_gpio(struct device *dev, - int override, const char *label) -{ - struct gpio_desc *ret; - char label_buf[256]; - - if (override >= 0) { - snprintf(label_buf, sizeof(label_buf), "wfx_%s", label); - ret = ERR_PTR(devm_gpio_request_one(dev, override, - GPIOF_OUT_INIT_LOW, - label_buf)); - if (!ret) - ret = gpio_to_desc(override); - } else if (override == -1) { - ret = NULL; - } else { - ret = devm_gpiod_get(dev, label, GPIOD_OUT_LOW); - } - if (IS_ERR_OR_NULL(ret)) { - if (!ret || PTR_ERR(ret) == -ENOENT) - dev_warn(dev, "gpio %s is not defined\n", label); - else - dev_warn(dev, "error while requesting gpio %s\n", - label); - ret = NULL; - } else { - dev_dbg(dev, "using gpio %d for %s\n", - desc_to_gpio(ret), label); - } - return ret; -} - /* NOTE: wfx_send_pds() destroy buf */ int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len) { @@ -340,7 +303,12 @@ struct wfx_dev *wfx_init_common(struct device *dev, memcpy(&wdev->pdata, pdata, sizeof(*pdata)); of_property_read_string(dev->of_node, "config-file", &wdev->pdata.file_pds); - wdev->pdata.gpio_wakeup = wfx_get_gpio(dev, gpio_wakeup, "wakeup"); + wdev->pdata.gpio_wakeup = devm_gpiod_get_optional(dev, "wakeup", + GPIOD_OUT_LOW); + if (IS_ERR(wdev->pdata.gpio_wakeup)) + return ERR_CAST(wdev->pdata.gpio_wakeup); + if (wdev->pdata.gpio_wakeup) + gpiod_set_consumer_name(wdev->pdata.gpio_wakeup, "wfx wakeup"); wfx_sl_fill_pdata(dev, &wdev->pdata); mutex_init(&wdev->conf_mutex); @@ -349,8 +317,10 @@ struct wfx_dev *wfx_init_common(struct device *dev, init_completion(&wdev->firmware_ready); INIT_DELAYED_WORK(&wdev->cooling_timeout_work, wfx_cooling_timeout_work); + skb_queue_head_init(&wdev->tx_pending); + init_waitqueue_head(&wdev->tx_dequeue); wfx_init_hif_cmd(&wdev->hif_cmd); - wfx_tx_queues_init(wdev); + wdev->force_ps_timeout = -1; if (devm_add_action_or_reset(dev, wfx_free_common, wdev)) return NULL; @@ -442,8 +412,7 @@ int wfx_probe(struct wfx_dev *wdev) wdev->pdata.gpio_wakeup = gpio_saved; if (wdev->pdata.gpio_wakeup) { dev_dbg(wdev->dev, - "enable 'quiescent' power mode with gpio %d and PDS file %s\n", - desc_to_gpio(wdev->pdata.gpio_wakeup), + "enable 'quiescent' power mode with wakeup GPIO and PDS file %s\n", wdev->pdata.file_pds); gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1); control_reg_write(wdev, 0); diff --git a/drivers/staging/wfx/main.h b/drivers/staging/wfx/main.h index f832ce409fdad0b73c110f18fac37116373f5240..c59d375dd3ad43949b9c7143fcbd2a529656f5ef 100644 --- a/drivers/staging/wfx/main.h +++ b/drivers/staging/wfx/main.h @@ -38,8 +38,6 @@ struct wfx_dev *wfx_init_common(struct device *dev, int wfx_probe(struct wfx_dev *wdev); void wfx_release(struct wfx_dev *wdev); -struct gpio_desc *wfx_get_gpio(struct device *dev, int override, - const char *label); bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor); int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len); diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index 93ea2b72febd0645e4da0b5cad81f2e116a4c1b9..6e315916514324916f33489698b0462999aeffe0 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -12,6 +12,7 @@ #include "wfx.h" #include "sta.h" #include "data_tx.h" +#include "traces.h" void wfx_tx_lock(struct wfx_dev *wdev) { @@ -57,84 +58,57 @@ void wfx_tx_lock_flush(struct wfx_dev *wdev) wfx_tx_flush(wdev); } -void wfx_tx_queues_init(struct wfx_dev *wdev) +void wfx_tx_queues_init(struct wfx_vif *wvif) { int i; - skb_queue_head_init(&wdev->tx_pending); - init_waitqueue_head(&wdev->tx_dequeue); for (i = 0; i < IEEE80211_NUM_ACS; ++i) { - skb_queue_head_init(&wdev->tx_queue[i].normal); - skb_queue_head_init(&wdev->tx_queue[i].cab); + skb_queue_head_init(&wvif->tx_queue[i].normal); + skb_queue_head_init(&wvif->tx_queue[i].cab); } } -void wfx_tx_queues_check_empty(struct wfx_dev *wdev) +void wfx_tx_queues_check_empty(struct wfx_vif *wvif) { int i; - WARN_ON(!skb_queue_empty_lockless(&wdev->tx_pending)); for (i = 0; i < IEEE80211_NUM_ACS; ++i) { - WARN_ON(atomic_read(&wdev->tx_queue[i].pending_frames)); - WARN_ON(!skb_queue_empty_lockless(&wdev->tx_queue[i].normal)); - WARN_ON(!skb_queue_empty_lockless(&wdev->tx_queue[i].cab)); + WARN_ON(atomic_read(&wvif->tx_queue[i].pending_frames)); + WARN_ON(!skb_queue_empty_lockless(&wvif->tx_queue[i].normal)); + WARN_ON(!skb_queue_empty_lockless(&wvif->tx_queue[i].cab)); } } -static bool __wfx_tx_queue_empty(struct wfx_dev *wdev, - struct sk_buff_head *skb_queue, int vif_id) +bool wfx_tx_queue_empty(struct wfx_vif *wvif, struct wfx_queue *queue) { - struct hif_msg *hif_msg; - struct sk_buff *skb; - - spin_lock_bh(&skb_queue->lock); - skb_queue_walk(skb_queue, skb) { - hif_msg = (struct hif_msg *)skb->data; - if (vif_id < 0 || hif_msg->interface == vif_id) { - spin_unlock_bh(&skb_queue->lock); - return false; - } - } - spin_unlock_bh(&skb_queue->lock); - return true; -} - -bool wfx_tx_queue_empty(struct wfx_dev *wdev, - struct wfx_queue *queue, int vif_id) -{ - return __wfx_tx_queue_empty(wdev, &queue->normal, vif_id) && - __wfx_tx_queue_empty(wdev, &queue->cab, vif_id); + return skb_queue_empty(&queue->normal) && skb_queue_empty(&queue->cab); } -static void __wfx_tx_queue_drop(struct wfx_dev *wdev, - struct sk_buff_head *skb_queue, int vif_id, +static void __wfx_tx_queue_drop(struct wfx_vif *wvif, + struct sk_buff_head *skb_queue, struct sk_buff_head *dropped) { struct sk_buff *skb, *tmp; - struct hif_msg *hif_msg; spin_lock_bh(&skb_queue->lock); skb_queue_walk_safe(skb_queue, skb, tmp) { - hif_msg = (struct hif_msg *)skb->data; - if (vif_id < 0 || hif_msg->interface == vif_id) { - __skb_unlink(skb, skb_queue); - skb_queue_head(dropped, skb); - } + __skb_unlink(skb, skb_queue); + skb_queue_head(dropped, skb); } spin_unlock_bh(&skb_queue->lock); } -void wfx_tx_queue_drop(struct wfx_dev *wdev, struct wfx_queue *queue, - int vif_id, struct sk_buff_head *dropped) +void wfx_tx_queue_drop(struct wfx_vif *wvif, struct wfx_queue *queue, + struct sk_buff_head *dropped) { - __wfx_tx_queue_drop(wdev, &queue->cab, vif_id, dropped); - __wfx_tx_queue_drop(wdev, &queue->normal, vif_id, dropped); - wake_up(&wdev->tx_dequeue); + __wfx_tx_queue_drop(wvif, &queue->cab, dropped); + __wfx_tx_queue_drop(wvif, &queue->normal, dropped); + wake_up(&wvif->wdev->tx_dequeue); } -void wfx_tx_queues_put(struct wfx_dev *wdev, struct sk_buff *skb) +void wfx_tx_queues_put(struct wfx_vif *wvif, struct sk_buff *skb) { - struct wfx_queue *queue = &wdev->tx_queue[skb_get_queue_mapping(skb)]; + struct wfx_queue *queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) @@ -146,15 +120,21 @@ void wfx_tx_queues_put(struct wfx_dev *wdev, struct sk_buff *skb) void wfx_pending_drop(struct wfx_dev *wdev, struct sk_buff_head *dropped) { struct wfx_queue *queue; + struct wfx_vif *wvif; + struct hif_msg *hif; struct sk_buff *skb; WARN(!wdev->chip_frozen, "%s should only be used to recover a frozen device", __func__); while ((skb = skb_dequeue(&wdev->tx_pending)) != NULL) { - queue = &wdev->tx_queue[skb_get_queue_mapping(skb)]; - WARN_ON(skb_get_queue_mapping(skb) > 3); - WARN_ON(!atomic_read(&queue->pending_frames)); - atomic_dec(&queue->pending_frames); + hif = (struct hif_msg *)skb->data; + wvif = wdev_to_wvif(wdev, hif->interface); + if (wvif) { + queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; + WARN_ON(skb_get_queue_mapping(skb) > 3); + WARN_ON(!atomic_read(&queue->pending_frames)); + atomic_dec(&queue->pending_frames); + } skb_queue_head(dropped, skb); } } @@ -163,20 +143,26 @@ struct sk_buff *wfx_pending_get(struct wfx_dev *wdev, u32 packet_id) { struct wfx_queue *queue; struct hif_req_tx *req; + struct wfx_vif *wvif; + struct hif_msg *hif; struct sk_buff *skb; spin_lock_bh(&wdev->tx_pending.lock); skb_queue_walk(&wdev->tx_pending, skb) { - req = wfx_skb_txreq(skb); - if (req->packet_id == packet_id) { - spin_unlock_bh(&wdev->tx_pending.lock); - queue = &wdev->tx_queue[skb_get_queue_mapping(skb)]; + hif = (struct hif_msg *)skb->data; + req = (struct hif_req_tx *)hif->body; + if (req->packet_id != packet_id) + continue; + spin_unlock_bh(&wdev->tx_pending.lock); + wvif = wdev_to_wvif(wdev, hif->interface); + if (wvif) { + queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; WARN_ON(skb_get_queue_mapping(skb) > 3); WARN_ON(!atomic_read(&queue->pending_frames)); atomic_dec(&queue->pending_frames); - skb_unlink(skb, &wdev->tx_pending); - return skb; } + skb_unlink(skb, &wdev->tx_pending); + return skb; } spin_unlock_bh(&wdev->tx_pending.lock); WARN(1, "cannot find packet in pending queue"); @@ -221,7 +207,6 @@ unsigned int wfx_pending_get_pkt_us_delay(struct wfx_dev *wdev, bool wfx_tx_queues_has_cab(struct wfx_vif *wvif) { - struct wfx_dev *wdev = wvif->wdev; int i; if (wvif->vif->type != NL80211_IFTYPE_AP) @@ -229,33 +214,39 @@ bool wfx_tx_queues_has_cab(struct wfx_vif *wvif) for (i = 0; i < IEEE80211_NUM_ACS; ++i) // Note: since only AP can have mcast frames in queue and only // one vif can be AP, all queued frames has same interface id - if (!skb_queue_empty_lockless(&wdev->tx_queue[i].cab)) + if (!skb_queue_empty_lockless(&wvif->tx_queue[i].cab)) return true; return false; } static struct sk_buff *wfx_tx_queues_get_skb(struct wfx_dev *wdev) { - struct wfx_queue *sorted_queues[IEEE80211_NUM_ACS]; + struct wfx_queue *queues[IEEE80211_NUM_ACS * ARRAY_SIZE(wdev->vif)]; + int i, j, num_queues = 0; struct wfx_vif *wvif; struct hif_msg *hif; struct sk_buff *skb; - int i, j; - - // bubble sort - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - sorted_queues[i] = &wdev->tx_queue[i]; - for (j = i; j > 0; j--) - if (atomic_read(&sorted_queues[j]->pending_frames) < - atomic_read(&sorted_queues[j - 1]->pending_frames)) - swap(sorted_queues[j - 1], sorted_queues[j]); + + // sort the queues + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + WARN_ON(num_queues >= ARRAY_SIZE(queues)); + queues[num_queues] = &wvif->tx_queue[i]; + for (j = num_queues; j > 0; j--) + if (atomic_read(&queues[j]->pending_frames) < + atomic_read(&queues[j - 1]->pending_frames)) + swap(queues[j - 1], queues[j]); + num_queues++; + } } + wvif = NULL; while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { if (!wvif->after_dtim_tx_allowed) continue; - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - skb = skb_dequeue(&sorted_queues[i]->cab); + for (i = 0; i < num_queues; i++) { + skb = skb_dequeue(&queues[i]->cab); if (!skb) continue; // Note: since only AP can have mcast frames in queue @@ -263,21 +254,22 @@ static struct sk_buff *wfx_tx_queues_get_skb(struct wfx_dev *wdev) // same interface id hif = (struct hif_msg *)skb->data; WARN_ON(hif->interface != wvif->id); - WARN_ON(sorted_queues[i] != - &wdev->tx_queue[skb_get_queue_mapping(skb)]); - atomic_inc(&sorted_queues[i]->pending_frames); + WARN_ON(queues[i] != + &wvif->tx_queue[skb_get_queue_mapping(skb)]); + atomic_inc(&queues[i]->pending_frames); + trace_queues_stats(wdev, queues[i]); return skb; } // No more multicast to sent wvif->after_dtim_tx_allowed = false; schedule_work(&wvif->update_tim_work); } - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - skb = skb_dequeue(&sorted_queues[i]->normal); + + for (i = 0; i < num_queues; i++) { + skb = skb_dequeue(&queues[i]->normal); if (skb) { - WARN_ON(sorted_queues[i] != - &wdev->tx_queue[skb_get_queue_mapping(skb)]); - atomic_inc(&sorted_queues[i]->pending_frames); + atomic_inc(&queues[i]->pending_frames); + trace_queues_stats(wdev, queues[i]); return skb; } } diff --git a/drivers/staging/wfx/queue.h b/drivers/staging/wfx/queue.h index 0c3b7244498e3e84ab113f895dec31e8d0873f2b..22d7c936907f4003a59f232ea506e83be10841a7 100644 --- a/drivers/staging/wfx/queue.h +++ b/drivers/staging/wfx/queue.h @@ -25,16 +25,15 @@ void wfx_tx_unlock(struct wfx_dev *wdev); void wfx_tx_flush(struct wfx_dev *wdev); void wfx_tx_lock_flush(struct wfx_dev *wdev); -void wfx_tx_queues_init(struct wfx_dev *wdev); -void wfx_tx_queues_check_empty(struct wfx_dev *wdev); +void wfx_tx_queues_init(struct wfx_vif *wvif); +void wfx_tx_queues_check_empty(struct wfx_vif *wvif); bool wfx_tx_queues_has_cab(struct wfx_vif *wvif); -void wfx_tx_queues_put(struct wfx_dev *wdev, struct sk_buff *skb); +void wfx_tx_queues_put(struct wfx_vif *wvif, struct sk_buff *skb); struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev); -bool wfx_tx_queue_empty(struct wfx_dev *wdev, struct wfx_queue *queue, - int vif_id); -void wfx_tx_queue_drop(struct wfx_dev *wdev, struct wfx_queue *queue, - int vif_id, struct sk_buff_head *dropped); +bool wfx_tx_queue_empty(struct wfx_vif *wvif, struct wfx_queue *queue); +void wfx_tx_queue_drop(struct wfx_vif *wvif, struct wfx_queue *queue, + struct sk_buff_head *dropped); struct sk_buff *wfx_pending_get(struct wfx_dev *wdev, u32 packet_id); void wfx_pending_drop(struct wfx_dev *wdev, struct sk_buff_head *dropped); diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 12e8a5b638f111aeb636e04a6be71c34877a62a9..4e30ab17a93d488f670d5810edde3f013f4092f2 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -200,7 +200,7 @@ void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, mutex_unlock(&wdev->conf_mutex); } -int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps) +static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps) { struct ieee80211_channel *chan0 = NULL, *chan1 = NULL; struct ieee80211_conf *conf = &wvif->wdev->hw->conf; @@ -217,14 +217,18 @@ int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps) // are differents. if (enable_ps) *enable_ps = true; - if (wvif->bss_not_support_ps_poll) - return 30; - else + if (wvif->wdev->force_ps_timeout > -1) + return wvif->wdev->force_ps_timeout; + else if (wfx_api_older_than(wvif->wdev, 3, 2)) return 0; + else + return 30; } if (enable_ps) *enable_ps = wvif->vif->bss_conf.ps; - if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps) + if (wvif->wdev->force_ps_timeout > -1) + return wvif->wdev->force_ps_timeout; + else if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps) return conf->dynamic_ps_timeout; else return -1; @@ -251,14 +255,6 @@ int wfx_update_pm(struct wfx_vif *wvif) return hif_set_pm(wvif, ps, ps_timeout); } -static void wfx_update_pm_work(struct work_struct *work) -{ - struct wfx_vif *wvif = container_of(work, struct wfx_vif, - update_pm_work); - - wfx_update_pm(wvif); -} - int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params) { @@ -368,7 +364,6 @@ void wfx_reset(struct wfx_vif *wvif) hif_set_block_ack_policy(wvif, 0xFF, 0xFF); wfx_tx_unlock(wdev); wvif->join_in_progress = false; - wvif->bss_not_support_ps_poll = false; cancel_delayed_work_sync(&wvif->beacon_loss_work); wvif = NULL; while ((wvif = wvif_iterate(wdev, wvif)) != NULL) @@ -430,7 +425,6 @@ int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; - spin_lock_init(&sta_priv->lock); sta_priv->vif_id = wvif->id; // In station mode, the firmware interprets new link-id as a TDLS peer. @@ -450,14 +444,7 @@ int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; - int i; - for (i = 0; i < ARRAY_SIZE(sta_priv->buffered); i++) - if (sta_priv->buffered[i]) - // Not an error if paired with trace in - // wfx_tx_update_sta() - dev_dbg(wvif->wdev->dev, "release station while %d pending frame on queue %d", - sta_priv->buffered[i], i); // See note in wfx_sta_add() if (!sta_priv->link_id) return 0; @@ -794,7 +781,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) init_completion(&wvif->set_pm_mode_complete); complete(&wvif->set_pm_mode_complete); - INIT_WORK(&wvif->update_pm_work, wfx_update_pm_work); INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work); mutex_init(&wvif->scan_lock); @@ -805,6 +791,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) hif_set_macaddr(wvif, vif->addr); + wfx_tx_queues_init(wvif); wfx_tx_policy_init(wvif); wvif = NULL; while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { @@ -823,6 +810,7 @@ void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300)); + wfx_tx_queues_check_empty(wvif); mutex_lock(&wdev->conf_mutex); WARN(wvif->link_id_map != 1, "corrupted state"); @@ -855,5 +843,5 @@ void wfx_stop(struct ieee80211_hw *hw) { struct wfx_dev *wdev = hw->priv; - wfx_tx_queues_check_empty(wdev); + WARN_ON(!skb_queue_empty_lockless(&wdev->tx_pending)); } diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h index 8a20ad9ae017ee2932f6ecc5e0e4d268e2ea22ae..6b15a64ac9e28e251cf9a75314cafeca72c81419 100644 --- a/drivers/staging/wfx/sta.h +++ b/drivers/staging/wfx/sta.h @@ -16,9 +16,6 @@ struct wfx_vif; struct wfx_sta_priv { int link_id; int vif_id; - int buffered[IEEE80211_NUM_TIDS]; - // Ensure atomicity of "buffered" and calls to ieee80211_sta_set_buffered() - spinlock_t lock; }; // mac80211 interface @@ -69,6 +66,7 @@ void wfx_cooling_timeout_work(struct work_struct *work); void wfx_suspend_hot_dev(struct wfx_dev *wdev, enum sta_notify_cmd cmd); void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd cmd); void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi); +int wfx_update_pm(struct wfx_vif *wvif); // Other Helpers void wfx_reset(struct wfx_vif *wvif); diff --git a/drivers/staging/wfx/traces.h b/drivers/staging/wfx/traces.h index 0b6fbd51863819461d8bf41743b684924686241a..d376db2f1891ba09e14258e44793554946539113 100644 --- a/drivers/staging/wfx/traces.h +++ b/drivers/staging/wfx/traces.h @@ -439,6 +439,57 @@ TRACE_EVENT(tx_stats, ); #define _trace_tx_stats(tx_cnf, skb, delay) trace_tx_stats(tx_cnf, skb, delay) +TRACE_EVENT(queues_stats, + TP_PROTO(struct wfx_dev *wdev, const struct wfx_queue *elected_queue), + TP_ARGS(wdev, elected_queue), + TP_STRUCT__entry( + __field(int, vif_id) + __field(int, queue_id) + __array(int, hw, IEEE80211_NUM_ACS * 2) + __array(int, drv, IEEE80211_NUM_ACS * 2) + __array(int, cab, IEEE80211_NUM_ACS * 2) + ), + TP_fast_assign( + const struct wfx_queue *queue; + struct wfx_vif *wvif; + int i, j; + + for (j = 0; j < IEEE80211_NUM_ACS * 2; j++) { + __entry->hw[j] = -1; + __entry->drv[j] = -1; + __entry->cab[j] = -1; + } + __entry->vif_id = -1; + __entry->queue_id = -1; + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + j = wvif->id * IEEE80211_NUM_ACS + i; + WARN_ON(j >= IEEE80211_NUM_ACS * 2); + queue = &wvif->tx_queue[i]; + __entry->hw[j] = atomic_read(&queue->pending_frames); + __entry->drv[j] = skb_queue_len(&queue->normal); + __entry->cab[j] = skb_queue_len(&queue->cab); + if (queue == elected_queue) { + __entry->vif_id = wvif->id; + __entry->queue_id = i; + } + } + } + ), + TP_printk("got skb from %d/%d, pend. hw/norm/cab: [ %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d ] [ %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d ]", + __entry->vif_id, __entry->queue_id, + __entry->hw[0], __entry->drv[0], __entry->cab[0], + __entry->hw[1], __entry->drv[1], __entry->cab[1], + __entry->hw[2], __entry->drv[2], __entry->cab[2], + __entry->hw[3], __entry->drv[3], __entry->cab[3], + __entry->hw[4], __entry->drv[4], __entry->cab[4], + __entry->hw[5], __entry->drv[5], __entry->cab[5], + __entry->hw[6], __entry->drv[6], __entry->cab[6], + __entry->hw[7], __entry->drv[7], __entry->cab[7] + ) +); + #endif /* This part must be outside protection */ diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 73e216733ce4fc41f54c1ac26b749f72f31a566d..38e24d7f72f24d36905c0b258a4cfb4d7a404f77 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -48,7 +48,6 @@ struct wfx_dev { struct mutex conf_mutex; struct wfx_hif_cmd hif_cmd; - struct wfx_queue tx_queue[4]; struct sk_buff_head tx_pending; wait_queue_head_t tx_dequeue; atomic_t tx_lock; @@ -60,6 +59,7 @@ struct wfx_dev { struct mutex rx_stats_lock; struct hif_tx_power_loop_info tx_power_loop_info; struct mutex tx_power_loop_info_lock; + int force_ps_timeout; }; struct wfx_vif { @@ -75,6 +75,7 @@ struct wfx_vif { struct delayed_work beacon_loss_work; + struct wfx_queue tx_queue[4]; struct tx_policy_cache tx_policy_cache; struct work_struct tx_policy_upload_work; @@ -92,8 +93,6 @@ struct wfx_vif { bool scan_abort; struct ieee80211_scan_request *scan_req; - bool bss_not_support_ps_poll; - struct work_struct update_pm_work; struct completion set_pm_mode_complete; }; diff --git a/drivers/staging/wilc1000/TODO b/drivers/staging/wilc1000/TODO deleted file mode 100644 index 862e9eac9d6090c85950104d08ff70d74506836c..0000000000000000000000000000000000000000 --- a/drivers/staging/wilc1000/TODO +++ /dev/null @@ -1,3 +0,0 @@ -TODO: -- support soft-ap and p2p mode -- support resume/suspend function diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index fac38c842ac50bce8f53441369f61fd8cd20a0bd..759e475e303c06c440cb85fb6e640441eb20f19f 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -359,16 +359,15 @@ static int prism2_scan(struct wiphy *wiphy, freq = ieee80211_channel_to_frequency(msg2.dschannel.data, NL80211_BAND_2GHZ); bss = cfg80211_inform_bss(wiphy, - ieee80211_get_channel(wiphy, freq), - CFG80211_BSS_FTYPE_UNKNOWN, - (const u8 *)&msg2.bssid.data.data, - msg2.timestamp.data, msg2.capinfo.data, - msg2.beaconperiod.data, - ie_buf, - ie_len, - (msg2.signal.data - 65536) * 100, /* Conversion to signed type */ - GFP_KERNEL - ); + ieee80211_get_channel(wiphy, freq), + CFG80211_BSS_FTYPE_UNKNOWN, + (const u8 *)&msg2.bssid.data.data, + msg2.timestamp.data, msg2.capinfo.data, + msg2.beaconperiod.data, + ie_buf, + ie_len, + (msg2.signal.data - 65536) * 100, /* Conversion to signed type */ + GFP_KERNEL); if (!bss) { err = -ENOMEM; diff --git a/drivers/target/iscsi/cxgbit/cxgbit.h b/drivers/target/iscsi/cxgbit/cxgbit.h index c04cd0832decd024b20e3d14b567e3f22ba415c6..406903398dfdc722a8e36b69027c20251af2ab1e 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit.h +++ b/drivers/target/iscsi/cxgbit/cxgbit.h @@ -207,7 +207,6 @@ struct cxgbit_sock { /* socket lock */ spinlock_t lock; wait_queue_head_t waitq; - wait_queue_head_t ack_waitq; bool lock_owner; struct kref kref; u32 max_iso_npdu; diff --git a/drivers/target/iscsi/cxgbit/cxgbit_cm.c b/drivers/target/iscsi/cxgbit/cxgbit_cm.c index a2b5c796bbc4a5dfee4513bd93a6449e57d4dbc4..518ded214e74e31c6ccb6796d7af4e34cc2b7640 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_cm.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_cm.c @@ -1360,7 +1360,6 @@ cxgbit_pass_accept_req(struct cxgbit_device *cdev, struct sk_buff *skb) cxgbit_sock_reset_wr_list(csk); spin_lock_init(&csk->lock); init_waitqueue_head(&csk->waitq); - init_waitqueue_head(&csk->ack_waitq); csk->lock_owner = false; if (cxgbit_alloc_csk_skb(csk)) { @@ -1485,6 +1484,26 @@ u32 cxgbit_send_tx_flowc_wr(struct cxgbit_sock *csk) return flowclen16; } +static int +cxgbit_send_tcb_skb(struct cxgbit_sock *csk, struct sk_buff *skb) +{ + spin_lock_bh(&csk->lock); + if (unlikely(csk->com.state != CSK_STATE_ESTABLISHED)) { + spin_unlock_bh(&csk->lock); + pr_err("%s: csk 0x%p, tid %u, state %u\n", + __func__, csk, csk->tid, csk->com.state); + __kfree_skb(skb); + return -1; + } + + cxgbit_get_csk(csk); + cxgbit_init_wr_wait(&csk->com.wr_wait); + cxgbit_ofld_send(csk->com.cdev, skb); + spin_unlock_bh(&csk->lock); + + return 0; +} + int cxgbit_setup_conn_digest(struct cxgbit_sock *csk) { struct sk_buff *skb; @@ -1510,10 +1529,8 @@ int cxgbit_setup_conn_digest(struct cxgbit_sock *csk) (dcrc ? ULP_CRC_DATA : 0)) << 4); set_wr_txq(skb, CPL_PRIORITY_CONTROL, csk->ctrlq_idx); - cxgbit_get_csk(csk); - cxgbit_init_wr_wait(&csk->com.wr_wait); - - cxgbit_ofld_send(csk->com.cdev, skb); + if (cxgbit_send_tcb_skb(csk, skb)) + return -1; ret = cxgbit_wait_for_reply(csk->com.cdev, &csk->com.wr_wait, @@ -1545,10 +1562,8 @@ int cxgbit_setup_conn_pgidx(struct cxgbit_sock *csk, u32 pg_idx) req->val = cpu_to_be64(pg_idx << 8); set_wr_txq(skb, CPL_PRIORITY_CONTROL, csk->ctrlq_idx); - cxgbit_get_csk(csk); - cxgbit_init_wr_wait(&csk->com.wr_wait); - - cxgbit_ofld_send(csk->com.cdev, skb); + if (cxgbit_send_tcb_skb(csk, skb)) + return -1; ret = cxgbit_wait_for_reply(csk->com.cdev, &csk->com.wr_wait, @@ -1871,7 +1886,6 @@ static void cxgbit_fw4_ack(struct cxgbit_sock *csk, struct sk_buff *skb) if (csk->snd_una != snd_una) { csk->snd_una = snd_una; dst_confirm(csk->dst); - wake_up(&csk->ack_waitq); } } diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index fcdc4211e3c27f2896d0782a9b2693dbeaf9f5d6..9b3eb2e8c92ad9e4a5233f8b88caab5ef757b9d3 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -284,18 +284,6 @@ void cxgbit_push_tx_frames(struct cxgbit_sock *csk) } } -static bool cxgbit_lock_sock(struct cxgbit_sock *csk) -{ - spin_lock_bh(&csk->lock); - - if (before(csk->write_seq, csk->snd_una + csk->snd_win)) - csk->lock_owner = true; - - spin_unlock_bh(&csk->lock); - - return csk->lock_owner; -} - static void cxgbit_unlock_sock(struct cxgbit_sock *csk) { struct sk_buff_head backlogq; @@ -325,20 +313,16 @@ static int cxgbit_queue_skb(struct cxgbit_sock *csk, struct sk_buff *skb) { int ret = 0; - wait_event_interruptible(csk->ack_waitq, cxgbit_lock_sock(csk)); + spin_lock_bh(&csk->lock); + csk->lock_owner = true; + spin_unlock_bh(&csk->lock); if (unlikely((csk->com.state != CSK_STATE_ESTABLISHED) || signal_pending(current))) { __kfree_skb(skb); __skb_queue_purge(&csk->ppodq); ret = -1; - spin_lock_bh(&csk->lock); - if (csk->lock_owner) { - spin_unlock_bh(&csk->lock); - goto unlock; - } - spin_unlock_bh(&csk->lock); - return ret; + goto unlock; } csk->write_seq += skb->len + diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 685d771b51d410cacfa4bfc444426f6b6c268cfc..f88a52fec88952c74515f4ad4beaedbec2252cd6 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -481,7 +481,7 @@ static bool __iscsi_target_sk_check_close(struct sock *sk) { if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) { pr_debug("__iscsi_target_sk_check_close: TCP_CLOSE_WAIT|TCP_CLOSE," - "returning FALSE\n"); + "returning TRUE\n"); return true; } return false; @@ -625,13 +625,37 @@ static void iscsi_target_do_login_rx(struct work_struct *work) pr_debug("iscsi_target_do_login_rx after rx_login_io, %p, %s:%d\n", conn, current->comm, current->pid); + /* + * LOGIN_FLAGS_READ_ACTIVE is cleared so that sk_data_ready + * could be triggered again after this. + * + * LOGIN_FLAGS_WRITE_ACTIVE is cleared after we successfully + * process a login PDU, so that sk_state_chage can do login + * cleanup as needed if the socket is closed. If a delayed work is + * ongoing (LOGIN_FLAGS_WRITE_ACTIVE or LOGIN_FLAGS_READ_ACTIVE), + * sk_state_change will leave the cleanup to the delayed work or + * it will schedule a delayed work to do cleanup. + */ + if (conn->sock) { + struct sock *sk = conn->sock->sk; + + write_lock_bh(&sk->sk_callback_lock); + if (!test_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags)) { + clear_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags); + set_bit(LOGIN_FLAGS_WRITE_ACTIVE, &conn->login_flags); + } + write_unlock_bh(&sk->sk_callback_lock); + } + rc = iscsi_target_do_login(conn, login); if (rc < 0) { goto err; } else if (!rc) { - if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_READ_ACTIVE)) + if (iscsi_target_sk_check_and_clear(conn, + LOGIN_FLAGS_WRITE_ACTIVE)) goto err; } else if (rc == 1) { + cancel_delayed_work(&conn->login_work); iscsi_target_nego_release(conn); iscsi_post_login_handler(np, conn, zero_tsih); iscsit_deaccess_np(np, tpg, tpg_np); @@ -640,6 +664,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work) err: iscsi_target_restore_sock_callbacks(conn); + cancel_delayed_work(&conn->login_work); iscsi_target_login_drop(conn, login); iscsit_deaccess_np(np, tpg, tpg_np); } @@ -670,9 +695,10 @@ static void iscsi_target_sk_state_change(struct sock *sk) state = __iscsi_target_sk_check_close(sk); pr_debug("__iscsi_target_sk_close_change: state: %d\n", state); - if (test_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) { - pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1 sk_state_change" - " conn: %p\n", conn); + if (test_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags) || + test_bit(LOGIN_FLAGS_WRITE_ACTIVE, &conn->login_flags)) { + pr_debug("Got LOGIN_FLAGS_{READ|WRITE}_ACTIVE=1" + " sk_state_change conn: %p\n", conn); if (state) set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags); write_unlock_bh(&sk->sk_callback_lock); diff --git a/drivers/target/target_core_fabric_lib.c b/drivers/target/target_core_fabric_lib.c index 1e031d81e59e871dc96025e9963f3abe9723199d..6600ae44f29d9e969e4c3c15f4add85564a15616 100644 --- a/drivers/target/target_core_fabric_lib.c +++ b/drivers/target/target_core_fabric_lib.c @@ -132,33 +132,27 @@ static int iscsi_get_pr_transport_id( unsigned char *buf) { u32 off = 4, padding = 0; + int isid_len; u16 len = 0; spin_lock_irq(&se_nacl->nacl_sess_lock); /* - * From spc4r17 Section 7.5.4.6: TransportID for initiator - * ports using SCSI over iSCSI. + * Only null terminate the last field. * - * The null-terminated, null-padded (see 4.4.2) ISCSI NAME field - * shall contain the iSCSI name of an iSCSI initiator node (see - * RFC 3720). The first ISCSI NAME field byte containing an ASCII - * null character terminates the ISCSI NAME field without regard for - * the specified length of the iSCSI TransportID or the contents of - * the ADDITIONAL LENGTH field. - */ - len = sprintf(&buf[off], "%s", se_nacl->initiatorname); - /* - * Add Extra byte for NULL terminator - */ - len++; - /* - * If there is ISID present with the registration and *format code == 1 - * 1, use iSCSI Initiator port TransportID format. + * From spc4r37 section 7.6.4.6: TransportID for initiator ports using + * SCSI over iSCSI. + * + * Table 507 TPID=0 Initiator device TransportID * - * Otherwise use iSCSI Initiator device TransportID format that - * does not contain the ASCII encoded iSCSI Initiator iSID value - * provied by the iSCSi Initiator during the iSCSI login process. + * The null-terminated, null-padded (see 4.3.2) ISCSI NAME field shall + * contain the iSCSI name of an iSCSI initiator node (see RFC 7143). + * The first ISCSI NAME field byte containing an ASCII null character + * terminates the ISCSI NAME field without regard for the specified + * length of the iSCSI TransportID or the contents of the ADDITIONAL + * LENGTH field. */ + len = sprintf(&buf[off], "%s", se_nacl->initiatorname); + off += len; if ((*format_code == 1) && (pr_reg->isid_present_at_reg)) { /* * Set FORMAT CODE 01b for iSCSI Initiator port TransportID @@ -166,8 +160,12 @@ static int iscsi_get_pr_transport_id( */ buf[0] |= 0x40; /* - * From spc4r17 Section 7.5.4.6: TransportID for initiator - * ports using SCSI over iSCSI. Table 390 + * From spc4r37 Section 7.6.4.6 + * + * Table 508 TPID=1 Initiator port TransportID. + * + * The ISCSI NAME field shall not be null-terminated + * (see 4.3.2) and shall not be padded. * * The SEPARATOR field shall contain the five ASCII * characters ",i,0x". @@ -177,23 +175,24 @@ static int iscsi_get_pr_transport_id( * (see RFC 3720) in the form of ASCII characters that are the * hexadecimal digits converted from the binary iSCSI initiator * session identifier value. The first ISCSI INITIATOR SESSION - * ID field byte containing an ASCII null character + * ID field byte containing an ASCII null character terminates + * the ISCSI INITIATOR SESSION ID field without regard for the + * specified length of the iSCSI TransportID or the contents + * of the ADDITIONAL LENGTH field. */ - buf[off+len] = 0x2c; off++; /* ASCII Character: "," */ - buf[off+len] = 0x69; off++; /* ASCII Character: "i" */ - buf[off+len] = 0x2c; off++; /* ASCII Character: "," */ - buf[off+len] = 0x30; off++; /* ASCII Character: "0" */ - buf[off+len] = 0x78; off++; /* ASCII Character: "x" */ + buf[off++] = 0x2c; /* ASCII Character: "," */ + buf[off++] = 0x69; /* ASCII Character: "i" */ + buf[off++] = 0x2c; /* ASCII Character: "," */ + buf[off++] = 0x30; /* ASCII Character: "0" */ + buf[off++] = 0x78; /* ASCII Character: "x" */ len += 5; - buf[off+len] = pr_reg->pr_reg_isid[0]; off++; - buf[off+len] = pr_reg->pr_reg_isid[1]; off++; - buf[off+len] = pr_reg->pr_reg_isid[2]; off++; - buf[off+len] = pr_reg->pr_reg_isid[3]; off++; - buf[off+len] = pr_reg->pr_reg_isid[4]; off++; - buf[off+len] = pr_reg->pr_reg_isid[5]; off++; - buf[off+len] = '\0'; off++; - len += 7; + + isid_len = sprintf(buf + off, "%s", pr_reg->pr_reg_isid); + off += isid_len; + len += isid_len; } + buf[off] = '\0'; + len += 1; spin_unlock_irq(&se_nacl->nacl_sess_lock); /* * The ADDITIONAL LENGTH field specifies the number of bytes that follow @@ -236,7 +235,7 @@ static int iscsi_get_pr_transport_id_len( */ if (pr_reg->isid_present_at_reg) { len += 5; /* For ",i,0x" ASCII separator */ - len += 7; /* For iSCSI Initiator Session ID + Null terminator */ + len += strlen(pr_reg->pr_reg_isid); *format_code = 1; } else *format_code = 0; @@ -265,9 +264,7 @@ static char *iscsi_parse_pr_out_transport_id( char **port_nexus_ptr) { char *p; - u32 tid_len, padding; int i; - u16 add_len; u8 format_code = (buf[0] & 0xc0); /* * Check for FORMAT CODE 00b or 01b from spc4r17, section 7.5.4.6: @@ -293,23 +290,11 @@ static char *iscsi_parse_pr_out_transport_id( */ if (out_tid_len) { /* The shift works thanks to integer promotion rules */ - add_len = get_unaligned_be16(&buf[2]); - - tid_len = strlen(&buf[4]); - tid_len += 4; /* Add four bytes for iSCSI Transport ID header */ - tid_len += 1; /* Add one byte for NULL terminator */ - padding = ((-tid_len) & 3); - if (padding != 0) - tid_len += padding; - - if ((add_len + 4) != tid_len) { - pr_debug("LIO-Target Extracted add_len: %hu " - "does not match calculated tid_len: %u," - " using tid_len instead\n", add_len+4, tid_len); - *out_tid_len = tid_len; - } else - *out_tid_len = (add_len + 4); + *out_tid_len = get_unaligned_be16(&buf[2]); + /* Add four bytes for iSCSI Transport ID header */ + *out_tid_len += 4; } + /* * Check for ',i,0x' separator between iSCSI Name and iSCSI Initiator * Session ID as defined in Table 390 - iSCSI initiator port TransportID @@ -334,6 +319,16 @@ static char *iscsi_parse_pr_out_transport_id( * iscsi_target.c:lio_sess_get_initiator_sid() */ for (i = 0; i < 12; i++) { + /* + * The first ISCSI INITIATOR SESSION ID field byte + * containing an ASCII null character terminates the + * ISCSI INITIATOR SESSION ID field without regard for + * the specified length of the iSCSI TransportID or the + * contents of the ADDITIONAL LENGTH field. + */ + if (*p == '\0') + break; + if (isdigit(*p)) { p++; continue; diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 853344415963579ccfa116d961c5a8a2fcd63a56..e7b3c6e5d5744ca75cff1d17ac000f2e2125213d 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -138,6 +138,7 @@ int init_se_kmem_caches(void); void release_se_kmem_caches(void); u32 scsi_get_new_index(scsi_index_t); void transport_subsystem_check_init(void); +void transport_uninit_session(struct se_session *); unsigned char *transport_dump_cmd_direction(struct se_cmd *); void transport_dump_dev_state(struct se_device *, char *, int *); void transport_dump_dev_info(struct se_device *, struct se_lun *, diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 91e41cc55704d07e23fbcf67bc4f5e5bcfedaca6..8fc88654bff63c0f90341b5f6e0578d358d5a3f6 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1159,7 +1159,6 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg( { struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_pr_registration *pr_reg, *pr_reg_tmp; - struct se_portal_group *tpg; spin_lock(&pr_tmpl->registration_lock); list_for_each_entry_safe(pr_reg, pr_reg_tmp, @@ -1170,21 +1169,11 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg( if (pr_reg->pr_reg_nacl != nacl) continue; - tpg = pr_reg->pr_reg_nacl->se_tpg; /* * If this registration does NOT contain a fabric provided * ISID, then we have found a match. */ if (!pr_reg->isid_present_at_reg) { - /* - * Determine if this SCSI device server requires that - * SCSI Intiatior TransportID w/ ISIDs is enforced - * for fabric modules (iSCSI) requiring them. - */ - if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL) { - if (dev->dev_attrib.enforce_pr_isids) - continue; - } atomic_inc_mb(&pr_reg->pr_res_holders); spin_unlock(&pr_tmpl->registration_lock); return pr_reg; @@ -1530,13 +1519,16 @@ core_scsi3_decode_spec_i_port( kfree(tidh_new); return TCM_INSUFFICIENT_REGISTRATION_RESOURCES; } + + if (core_scsi3_lunacl_depend_item(local_pr_reg->pr_reg_deve)) { + kfree(tidh_new); + kref_put(&local_pr_reg->pr_reg_deve->pr_kref, + target_pr_kref_release); + kmem_cache_free(t10_pr_reg_cache, local_pr_reg); + return TCM_INSUFFICIENT_REGISTRATION_RESOURCES; + } + tidh_new->dest_pr_reg = local_pr_reg; - /* - * The local I_T nexus does not hold any configfs dependances, - * so we set tidh_new->dest_se_deve to NULL to prevent the - * configfs_undepend_item() calls in the tid_dest_list loops below. - */ - tidh_new->dest_se_deve = NULL; list_add_tail(&tidh_new->dest_list, &tid_dest_list); if (cmd->data_length < 28) { @@ -1591,10 +1583,25 @@ core_scsi3_decode_spec_i_port( continue; dest_rtpi = tmp_lun->lun_rtpi; + iport_ptr = NULL; i_str = target_parse_pr_out_transport_id(tmp_tpg, ptr, &tid_len, &iport_ptr); if (!i_str) continue; + /* + * Determine if this SCSI device server requires that + * SCSI Intiatior TransportID w/ ISIDs is enforced + * for fabric modules (iSCSI) requiring them. + */ + if (tpg->se_tpg_tfo->sess_get_initiator_sid && + dev->dev_attrib.enforce_pr_isids && + !iport_ptr) { + pr_warn("SPC-PR: enforce_pr_isids is set but a isid has not been sent in the SPEC_I_PT data for %s.", + i_str); + ret = TCM_INVALID_PARAMETER_LIST; + spin_unlock(&dev->se_port_lock); + goto out_unmap; + } atomic_inc_mb(&tmp_tpg->tpg_pr_ref_count); spin_unlock(&dev->se_port_lock); @@ -1810,12 +1817,9 @@ core_scsi3_decode_spec_i_port( dest_node_acl->initiatorname, i_buf, (dest_se_deve) ? dest_se_deve->mapped_lun : 0); - if (!dest_se_deve) { - kref_put(&local_pr_reg->pr_reg_deve->pr_kref, - target_pr_kref_release); + if (dest_pr_reg == local_pr_reg) continue; - } - core_scsi3_lunacl_undepend_item(dest_se_deve); + core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); } @@ -1829,11 +1833,16 @@ out: * including *dest_pr_reg and the configfs dependances.. */ list_for_each_entry_safe(tidh, tidh_tmp, &tid_dest_list, dest_list) { + bool is_local = false; + dest_tpg = tidh->dest_tpg; dest_node_acl = tidh->dest_node_acl; dest_se_deve = tidh->dest_se_deve; dest_pr_reg = tidh->dest_pr_reg; + if (dest_pr_reg == local_pr_reg) + is_local = true; + list_del(&tidh->dest_list); kfree(tidh); /* @@ -1849,13 +1858,11 @@ out: } kmem_cache_free(t10_pr_reg_cache, dest_pr_reg); + core_scsi3_lunacl_undepend_item(dest_se_deve); - if (!dest_se_deve) { - kref_put(&local_pr_reg->pr_reg_deve->pr_kref, - target_pr_kref_release); + if (is_local) continue; - } - core_scsi3_lunacl_undepend_item(dest_se_deve); + core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); } diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 89c84d472cd7e429b37d09e640c3b8913a7a47c1..e4513ef091593f8560c9815ac55be306a0f84118 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -116,14 +116,16 @@ void core_tmr_abort_task( struct se_tmr_req *tmr, struct se_session *se_sess) { - struct se_cmd *se_cmd; + LIST_HEAD(aborted_list); + struct se_cmd *se_cmd, *next; unsigned long flags; + bool rc; u64 ref_tag; - spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); - list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { + spin_lock_irqsave(&dev->execute_task_lock, flags); + list_for_each_entry_safe(se_cmd, next, &dev->state_list, state_list) { - if (dev != se_cmd->se_dev) + if (se_sess != se_cmd->se_sess) continue; /* skip task management functions, including tmr->task_cmd */ @@ -137,11 +139,16 @@ void core_tmr_abort_task( printk("ABORT_TASK: Found referenced %s task_tag: %llu\n", se_cmd->se_tfo->fabric_name, ref_tag); - if (!__target_check_io_state(se_cmd, se_sess, - dev->dev_attrib.emulate_tas)) + spin_lock(&se_sess->sess_cmd_lock); + rc = __target_check_io_state(se_cmd, se_sess, 0); + spin_unlock(&se_sess->sess_cmd_lock); + if (!rc) continue; - spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + list_move_tail(&se_cmd->state_list, &aborted_list); + se_cmd->state_active = false; + + spin_unlock_irqrestore(&dev->execute_task_lock, flags); /* * Ensure that this ABORT request is visible to the LU RESET @@ -151,6 +158,11 @@ void core_tmr_abort_task( WARN_ON_ONCE(transport_lookup_tmr_lun(tmr->task_cmd) < 0); + if (dev->transport->tmr_notify) + dev->transport->tmr_notify(dev, TMR_ABORT_TASK, + &aborted_list); + + list_del_init(&se_cmd->state_list); target_put_cmd_and_wait(se_cmd); printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for" @@ -159,7 +171,10 @@ void core_tmr_abort_task( atomic_long_inc(&dev->aborts_complete); return; } - spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + spin_unlock_irqrestore(&dev->execute_task_lock, flags); + + if (dev->transport->tmr_notify) + dev->transport->tmr_notify(dev, TMR_ABORT_TASK, &aborted_list); printk("ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: %lld\n", tmr->ref_task_tag); @@ -312,6 +327,11 @@ static void core_tmr_drain_state_list( } spin_unlock_irqrestore(&dev->execute_task_lock, flags); + if (dev->transport->tmr_notify) + dev->transport->tmr_notify(dev, preempt_and_abort_list ? + TMR_LUN_RESET_PRO : TMR_LUN_RESET, + &drain_task_list); + while (!list_empty(&drain_task_list)) { cmd = list_entry(drain_task_list.next, struct se_cmd, state_list); list_del_init(&cmd->state_list); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 90ecdd706a0170e7aa4cadda309b381494898e83..9fb0be0aa620438babaaf1e1664cc4ad7aa05b1d 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -236,6 +236,11 @@ int transport_init_session(struct se_session *se_sess) } EXPORT_SYMBOL(transport_init_session); +void transport_uninit_session(struct se_session *se_sess) +{ + percpu_ref_exit(&se_sess->cmd_count); +} + /** * transport_alloc_session - allocate a session object and initialize it * @sup_prot_ops: bitmask that defines which T10-PI modes are supported. @@ -579,7 +584,7 @@ void transport_free_session(struct se_session *se_sess) sbitmap_queue_free(&se_sess->sess_tag_pool); kvfree(se_sess->sess_cmd_map); } - percpu_ref_exit(&se_sess->cmd_count); + transport_uninit_session(se_sess); kmem_cache_free(se_sess_cache, se_sess); } EXPORT_SYMBOL(transport_free_session); @@ -2941,6 +2946,7 @@ static const char *target_tmf_name(enum tcm_tmreq_table tmf) case TMR_LUN_RESET: return "LUN_RESET"; case TMR_TARGET_WARM_RESET: return "TARGET_WARM_RESET"; case TMR_TARGET_COLD_RESET: return "TARGET_COLD_RESET"; + case TMR_LUN_RESET_PRO: return "LUN_RESET_PRO"; case TMR_UNKNOWN: break; } return "(?)"; diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 560bfec933bc30a4e557682a60936a1df5aaae1f..9b75923505020534a878aa32fc3eafc034ac7776 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -118,6 +118,7 @@ struct tcmu_dev { #define TCMU_DEV_BIT_OPEN 0 #define TCMU_DEV_BIT_BROKEN 1 #define TCMU_DEV_BIT_BLOCKED 2 +#define TCMU_DEV_BIT_TMR_NOTIFY 3 unsigned long flags; struct uio_info uio_info; @@ -137,6 +138,7 @@ struct tcmu_dev { struct mutex cmdr_lock; struct list_head qfull_queue; + struct list_head tmr_queue; uint32_t dbi_max; uint32_t dbi_thresh; @@ -181,9 +183,17 @@ struct tcmu_cmd { unsigned long deadline; #define TCMU_CMD_BIT_EXPIRED 0 -#define TCMU_CMD_BIT_INFLIGHT 1 unsigned long flags; }; + +struct tcmu_tmr { + struct list_head queue_entry; + + uint8_t tmr_type; + uint32_t tmr_cmd_cnt; + int16_t tmr_cmd_ids[0]; +}; + /* * To avoid dead lock the mutex lock order should always be: * @@ -542,6 +552,8 @@ tcmu_get_block_page(struct tcmu_dev *udev, uint32_t dbi) static inline void tcmu_free_cmd(struct tcmu_cmd *tcmu_cmd) { + if (tcmu_cmd->se_cmd) + tcmu_cmd->se_cmd->priv = NULL; kfree(tcmu_cmd->dbi); kmem_cache_free(tcmu_cmd_cache, tcmu_cmd); } @@ -601,7 +613,7 @@ static inline void tcmu_flush_dcache_range(void *vaddr, size_t size) size = round_up(size+offset, PAGE_SIZE); while (size) { - flush_dcache_page(virt_to_page(start)); + flush_dcache_page(vmalloc_to_page(start)); start += PAGE_SIZE; size -= PAGE_SIZE; } @@ -676,8 +688,10 @@ static void scatter_data_area(struct tcmu_dev *udev, from = kmap_atomic(sg_page(sg)) + sg->offset; while (sg_remaining > 0) { if (block_remaining == 0) { - if (to) + if (to) { + flush_dcache_page(page); kunmap_atomic(to); + } block_remaining = DATA_BLOCK_SIZE; dbi = tcmu_cmd_get_dbi(tcmu_cmd); @@ -722,7 +736,6 @@ static void scatter_data_area(struct tcmu_dev *udev, memcpy(to + offset, from + sg->length - sg_remaining, copy_bytes); - tcmu_flush_dcache_range(to, copy_bytes); } sg_remaining -= copy_bytes; @@ -731,8 +744,10 @@ static void scatter_data_area(struct tcmu_dev *udev, kunmap_atomic(from - sg->offset); } - if (to) + if (to) { + flush_dcache_page(page); kunmap_atomic(to); + } } static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd, @@ -778,13 +793,13 @@ static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd, dbi = tcmu_cmd_get_dbi(cmd); page = tcmu_get_block_page(udev, dbi); from = kmap_atomic(page); + flush_dcache_page(page); } copy_bytes = min_t(size_t, sg_remaining, block_remaining); if (read_len < copy_bytes) copy_bytes = read_len; offset = DATA_BLOCK_SIZE - block_remaining; - tcmu_flush_dcache_range(from, copy_bytes); memcpy(to + sg->length - sg_remaining, from + offset, copy_bytes); @@ -840,6 +855,9 @@ static bool is_ring_space_avail(struct tcmu_dev *udev, struct tcmu_cmd *cmd, return false; } + if (!data_needed) + return true; + /* try to check and get the data blocks as needed */ space = spc_bitmap_free(udev->data_bitmap, udev->dbi_thresh); if ((space * DATA_BLOCK_SIZE) < data_needed) { @@ -922,6 +940,34 @@ static int add_to_qfull_queue(struct tcmu_cmd *tcmu_cmd) return 0; } +static uint32_t ring_insert_padding(struct tcmu_dev *udev, size_t cmd_size) +{ + struct tcmu_cmd_entry_hdr *hdr; + struct tcmu_mailbox *mb = udev->mb_addr; + uint32_t cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */ + + /* Insert a PAD if end-of-ring space is too small */ + if (head_to_end(cmd_head, udev->cmdr_size) < cmd_size) { + size_t pad_size = head_to_end(cmd_head, udev->cmdr_size); + + hdr = (void *) mb + CMDR_OFF + cmd_head; + tcmu_hdr_set_op(&hdr->len_op, TCMU_OP_PAD); + tcmu_hdr_set_len(&hdr->len_op, pad_size); + hdr->cmd_id = 0; /* not used for PAD */ + hdr->kflags = 0; + hdr->uflags = 0; + tcmu_flush_dcache_range(hdr, sizeof(*hdr)); + + UPDATE_HEAD(mb->cmd_head, pad_size, udev->cmdr_size); + tcmu_flush_dcache_range(mb, sizeof(*mb)); + + cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */ + WARN_ON(cmd_head != 0); + } + + return cmd_head; +} + /** * queue_cmd_ring - queue cmd to ring or internally * @tcmu_cmd: cmd to queue @@ -937,7 +983,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err) struct tcmu_dev *udev = tcmu_cmd->tcmu_dev; struct se_cmd *se_cmd = tcmu_cmd->se_cmd; size_t base_command_size, command_size; - struct tcmu_mailbox *mb; + struct tcmu_mailbox *mb = udev->mb_addr; struct tcmu_cmd_entry *entry; struct iovec *iov; int iov_cnt, cmd_id; @@ -976,8 +1022,6 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err) if (!list_empty(&udev->qfull_queue)) goto queue; - mb = udev->mb_addr; - cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */ if ((command_size > (udev->cmdr_size / 2)) || data_length > udev->data_size) { pr_warn("TCMU: Request of size %zu/%zu is too big for %u/%zu " @@ -997,24 +1041,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err) goto queue; } - /* Insert a PAD if end-of-ring space is too small */ - if (head_to_end(cmd_head, udev->cmdr_size) < command_size) { - size_t pad_size = head_to_end(cmd_head, udev->cmdr_size); - - entry = (void *) mb + CMDR_OFF + cmd_head; - tcmu_hdr_set_op(&entry->hdr.len_op, TCMU_OP_PAD); - tcmu_hdr_set_len(&entry->hdr.len_op, pad_size); - entry->hdr.cmd_id = 0; /* not used for PAD */ - entry->hdr.kflags = 0; - entry->hdr.uflags = 0; - tcmu_flush_dcache_range(entry, sizeof(entry->hdr)); - - UPDATE_HEAD(mb->cmd_head, pad_size, udev->cmdr_size); - tcmu_flush_dcache_range(mb, sizeof(*mb)); - - cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */ - WARN_ON(cmd_head != 0); - } + cmd_head = ring_insert_padding(udev, command_size); entry = (void *) mb + CMDR_OFF + cmd_head; memset(entry, 0, command_size); @@ -1078,7 +1105,6 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err) tcmu_flush_dcache_range(mb, sizeof(*mb)); list_add_tail(&tcmu_cmd->queue_entry, &udev->inflight_queue); - set_bit(TCMU_CMD_BIT_INFLIGHT, &tcmu_cmd->flags); /* TODO: only if FLUSH and FUA? */ uio_event_notify(&udev->uio_info); @@ -1094,27 +1120,177 @@ queue: return 1; } +/** + * queue_tmr_ring - queue tmr info to ring or internally + * @udev: related tcmu_dev + * @tmr: tcmu_tmr containing tmr info to queue + * + * Returns: + * 0 success + * 1 internally queued to wait for ring memory to free. + */ +static int +queue_tmr_ring(struct tcmu_dev *udev, struct tcmu_tmr *tmr) +{ + struct tcmu_tmr_entry *entry; + int cmd_size; + int id_list_sz; + struct tcmu_mailbox *mb = udev->mb_addr; + uint32_t cmd_head; + + if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) + goto out_free; + + id_list_sz = sizeof(tmr->tmr_cmd_ids[0]) * tmr->tmr_cmd_cnt; + cmd_size = round_up(sizeof(*entry) + id_list_sz, TCMU_OP_ALIGN_SIZE); + + if (!list_empty(&udev->tmr_queue) || + !is_ring_space_avail(udev, NULL, cmd_size, 0)) { + list_add_tail(&tmr->queue_entry, &udev->tmr_queue); + pr_debug("adding tmr %p on dev %s to TMR ring space wait queue\n", + tmr, udev->name); + return 1; + } + + cmd_head = ring_insert_padding(udev, cmd_size); + + entry = (void *)mb + CMDR_OFF + cmd_head; + memset(entry, 0, cmd_size); + tcmu_hdr_set_op(&entry->hdr.len_op, TCMU_OP_TMR); + tcmu_hdr_set_len(&entry->hdr.len_op, cmd_size); + entry->tmr_type = tmr->tmr_type; + entry->cmd_cnt = tmr->tmr_cmd_cnt; + memcpy(&entry->cmd_ids[0], &tmr->tmr_cmd_ids[0], id_list_sz); + tcmu_flush_dcache_range(entry, cmd_size); + + UPDATE_HEAD(mb->cmd_head, cmd_size, udev->cmdr_size); + tcmu_flush_dcache_range(mb, sizeof(*mb)); + + uio_event_notify(&udev->uio_info); + +out_free: + kfree(tmr); + + return 0; +} + static sense_reason_t tcmu_queue_cmd(struct se_cmd *se_cmd) { struct se_device *se_dev = se_cmd->se_dev; struct tcmu_dev *udev = TCMU_DEV(se_dev); struct tcmu_cmd *tcmu_cmd; - sense_reason_t scsi_ret; - int ret; + sense_reason_t scsi_ret = TCM_CHECK_CONDITION_ABORT_CMD; + int ret = -1; tcmu_cmd = tcmu_alloc_cmd(se_cmd); if (!tcmu_cmd) return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; mutex_lock(&udev->cmdr_lock); - ret = queue_cmd_ring(tcmu_cmd, &scsi_ret); - mutex_unlock(&udev->cmdr_lock); + se_cmd->priv = tcmu_cmd; + if (!(se_cmd->transport_state & CMD_T_ABORTED)) + ret = queue_cmd_ring(tcmu_cmd, &scsi_ret); if (ret < 0) tcmu_free_cmd(tcmu_cmd); + mutex_unlock(&udev->cmdr_lock); return scsi_ret; } +static void tcmu_set_next_deadline(struct list_head *queue, + struct timer_list *timer) +{ + struct tcmu_cmd *cmd; + + if (!list_empty(queue)) { + cmd = list_first_entry(queue, struct tcmu_cmd, queue_entry); + mod_timer(timer, cmd->deadline); + } else + del_timer(timer); +} + +static int +tcmu_tmr_type(enum tcm_tmreq_table tmf) +{ + switch (tmf) { + case TMR_ABORT_TASK: return TCMU_TMR_ABORT_TASK; + case TMR_ABORT_TASK_SET: return TCMU_TMR_ABORT_TASK_SET; + case TMR_CLEAR_ACA: return TCMU_TMR_CLEAR_ACA; + case TMR_CLEAR_TASK_SET: return TCMU_TMR_CLEAR_TASK_SET; + case TMR_LUN_RESET: return TCMU_TMR_LUN_RESET; + case TMR_TARGET_WARM_RESET: return TCMU_TMR_TARGET_WARM_RESET; + case TMR_TARGET_COLD_RESET: return TCMU_TMR_TARGET_COLD_RESET; + case TMR_LUN_RESET_PRO: return TCMU_TMR_LUN_RESET_PRO; + default: return TCMU_TMR_UNKNOWN; + } +} + +static void +tcmu_tmr_notify(struct se_device *se_dev, enum tcm_tmreq_table tmf, + struct list_head *cmd_list) +{ + int i = 0, cmd_cnt = 0; + bool unqueued = false; + uint16_t *cmd_ids = NULL; + struct tcmu_cmd *cmd; + struct se_cmd *se_cmd; + struct tcmu_tmr *tmr; + struct tcmu_dev *udev = TCMU_DEV(se_dev); + + mutex_lock(&udev->cmdr_lock); + + /* First we check for aborted commands in qfull_queue */ + list_for_each_entry(se_cmd, cmd_list, state_list) { + i++; + if (!se_cmd->priv) + continue; + cmd = se_cmd->priv; + /* Commands on qfull queue have no id yet */ + if (cmd->cmd_id) { + cmd_cnt++; + continue; + } + pr_debug("Removing aborted command %p from queue on dev %s.\n", + cmd, udev->name); + + list_del_init(&cmd->queue_entry); + tcmu_free_cmd(cmd); + target_complete_cmd(se_cmd, SAM_STAT_TASK_ABORTED); + unqueued = true; + } + if (unqueued) + tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer); + + if (!test_bit(TCMU_DEV_BIT_TMR_NOTIFY, &udev->flags)) + goto unlock; + + pr_debug("TMR event %d on dev %s, aborted cmds %d, afflicted cmd_ids %d\n", + tcmu_tmr_type(tmf), udev->name, i, cmd_cnt); + + tmr = kmalloc(sizeof(*tmr) + cmd_cnt * sizeof(*cmd_ids), GFP_KERNEL); + if (!tmr) + goto unlock; + + tmr->tmr_type = tcmu_tmr_type(tmf); + tmr->tmr_cmd_cnt = cmd_cnt; + + if (cmd_cnt != 0) { + cmd_cnt = 0; + list_for_each_entry(se_cmd, cmd_list, state_list) { + if (!se_cmd->priv) + continue; + cmd = se_cmd->priv; + if (cmd->cmd_id) + tmr->tmr_cmd_ids[cmd_cnt++] = cmd->cmd_id; + } + } + + queue_tmr_ring(udev, tmr); + +unlock: + mutex_unlock(&udev->cmdr_lock); +} + static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *entry) { struct se_cmd *se_cmd = cmd->se_cmd; @@ -1178,35 +1354,47 @@ done: target_complete_cmd(cmd->se_cmd, entry->rsp.scsi_status); out: - cmd->se_cmd = NULL; tcmu_cmd_free_data(cmd, cmd->dbi_cnt); tcmu_free_cmd(cmd); } -static void tcmu_set_next_deadline(struct list_head *queue, - struct timer_list *timer) +static int tcmu_run_tmr_queue(struct tcmu_dev *udev) { - struct tcmu_cmd *tcmu_cmd, *tmp_cmd; - unsigned long deadline = 0; + struct tcmu_tmr *tmr, *tmp; + LIST_HEAD(tmrs); - list_for_each_entry_safe(tcmu_cmd, tmp_cmd, queue, queue_entry) { - if (!time_after(jiffies, tcmu_cmd->deadline)) { - deadline = tcmu_cmd->deadline; - break; + if (list_empty(&udev->tmr_queue)) + return 1; + + pr_debug("running %s's tmr queue\n", udev->name); + + list_splice_init(&udev->tmr_queue, &tmrs); + + list_for_each_entry_safe(tmr, tmp, &tmrs, queue_entry) { + list_del_init(&tmr->queue_entry); + + pr_debug("removing tmr %p on dev %s from queue\n", + tmr, udev->name); + + if (queue_tmr_ring(udev, tmr)) { + pr_debug("ran out of space during tmr queue run\n"); + /* + * tmr was requeued, so just put all tmrs back in + * the queue + */ + list_splice_tail(&tmrs, &udev->tmr_queue); + return 0; } } - if (deadline) - mod_timer(timer, deadline); - else - del_timer(timer); + return 1; } static unsigned int tcmu_handle_completions(struct tcmu_dev *udev) { struct tcmu_mailbox *mb; struct tcmu_cmd *cmd; - int handled = 0; + bool free_space = false; if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) { pr_err("ring broken, not handling completions\n"); @@ -1220,9 +1408,19 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev) struct tcmu_cmd_entry *entry = (void *) mb + CMDR_OFF + udev->cmdr_last_cleaned; - tcmu_flush_dcache_range(entry, sizeof(*entry)); + /* + * Flush max. up to end of cmd ring since current entry might + * be a padding that is shorter than sizeof(*entry) + */ + size_t ring_left = head_to_end(udev->cmdr_last_cleaned, + udev->cmdr_size); + tcmu_flush_dcache_range(entry, ring_left < sizeof(*entry) ? + ring_left : sizeof(*entry)); - if (tcmu_hdr_get_op(entry->hdr.len_op) == TCMU_OP_PAD) { + free_space = true; + + if (tcmu_hdr_get_op(entry->hdr.len_op) == TCMU_OP_PAD || + tcmu_hdr_get_op(entry->hdr.len_op) == TCMU_OP_TMR) { UPDATE_HEAD(udev->cmdr_last_cleaned, tcmu_hdr_get_len(entry->hdr.len_op), udev->cmdr_size); @@ -1243,40 +1441,35 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev) UPDATE_HEAD(udev->cmdr_last_cleaned, tcmu_hdr_get_len(entry->hdr.len_op), udev->cmdr_size); - - handled++; } + if (free_space) + free_space = tcmu_run_tmr_queue(udev); - if (mb->cmd_tail == mb->cmd_head) { - /* no more pending commands */ - del_timer(&udev->cmd_timer); - - if (list_empty(&udev->qfull_queue)) { - /* - * no more pending or waiting commands so try to - * reclaim blocks if needed. - */ - if (atomic_read(&global_db_count) > - tcmu_global_max_blocks) - schedule_delayed_work(&tcmu_unmap_work, 0); - } - } else if (udev->cmd_time_out) { - tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer); + if (atomic_read(&global_db_count) > tcmu_global_max_blocks && + idr_is_empty(&udev->commands) && list_empty(&udev->qfull_queue)) { + /* + * Allocated blocks exceeded global block limit, currently no + * more pending or waiting commands so try to reclaim blocks. + */ + schedule_delayed_work(&tcmu_unmap_work, 0); } + if (udev->cmd_time_out) + tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer); - return handled; + return free_space; } static void tcmu_check_expired_ring_cmd(struct tcmu_cmd *cmd) { struct se_cmd *se_cmd; - if (!time_after(jiffies, cmd->deadline)) + if (!time_after_eq(jiffies, cmd->deadline)) return; set_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags); list_del_init(&cmd->queue_entry); se_cmd = cmd->se_cmd; + se_cmd->priv = NULL; cmd->se_cmd = NULL; pr_debug("Timing out inflight cmd %u on dev %s.\n", @@ -1289,7 +1482,7 @@ static void tcmu_check_expired_queue_cmd(struct tcmu_cmd *cmd) { struct se_cmd *se_cmd; - if (!time_after(jiffies, cmd->deadline)) + if (!time_after_eq(jiffies, cmd->deadline)) return; pr_debug("Timing out queued cmd %p on dev %s.\n", @@ -1373,6 +1566,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name) INIT_LIST_HEAD(&udev->node); INIT_LIST_HEAD(&udev->timedout_entry); INIT_LIST_HEAD(&udev->qfull_queue); + INIT_LIST_HEAD(&udev->tmr_queue); INIT_LIST_HEAD(&udev->inflight_queue); idr_init(&udev->commands); @@ -1447,8 +1641,8 @@ static int tcmu_irqcontrol(struct uio_info *info, s32 irq_on) struct tcmu_dev *udev = container_of(info, struct tcmu_dev, uio_info); mutex_lock(&udev->cmdr_lock); - tcmu_handle_completions(udev); - run_qfull_queue(udev, false); + if (tcmu_handle_completions(udev)) + run_qfull_queue(udev, false); mutex_unlock(&udev->cmdr_lock); return 0; @@ -1601,6 +1795,16 @@ static void tcmu_blocks_release(struct radix_tree_root *blocks, } } +static void tcmu_remove_all_queued_tmr(struct tcmu_dev *udev) +{ + struct tcmu_tmr *tmr, *tmp; + + list_for_each_entry_safe(tmr, tmp, &udev->tmr_queue, queue_entry) { + list_del_init(&tmr->queue_entry); + kfree(tmr); + } +} + static void tcmu_dev_kref_release(struct kref *kref) { struct tcmu_dev *udev = container_of(kref, struct tcmu_dev, kref); @@ -1623,6 +1827,8 @@ static void tcmu_dev_kref_release(struct kref *kref) if (tcmu_check_and_free_pending_cmd(cmd) != 0) all_expired = false; } + /* There can be left over TMR cmds. Remove them. */ + tcmu_remove_all_queued_tmr(udev); if (!list_empty(&udev->qfull_queue)) all_expired = false; idr_destroy(&udev->commands); @@ -1877,7 +2083,9 @@ static int tcmu_configure_device(struct se_device *dev) /* Initialise the mailbox of the ring buffer */ mb = udev->mb_addr; mb->version = TCMU_MAILBOX_VERSION; - mb->flags = TCMU_MAILBOX_FLAG_CAP_OOOC | TCMU_MAILBOX_FLAG_CAP_READ_LEN; + mb->flags = TCMU_MAILBOX_FLAG_CAP_OOOC | + TCMU_MAILBOX_FLAG_CAP_READ_LEN | + TCMU_MAILBOX_FLAG_CAP_TMR; mb->cmdr_off = CMDR_OFF; mb->cmdr_size = udev->cmdr_size; @@ -2047,6 +2255,15 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level) del_timer(&udev->cmd_timer); + /* + * ring is empty and qfull queue never contains aborted commands. + * So TMRs in tmr queue do not contain relevant cmd_ids. + * After a ring reset userspace should do a fresh start, so + * even LUN RESET message is no longer relevant. + * Therefore remove all TMRs from qfull queue + */ + tcmu_remove_all_queued_tmr(udev); + run_qfull_queue(udev, false); mutex_unlock(&udev->cmdr_lock); @@ -2493,6 +2710,39 @@ static ssize_t tcmu_emulate_write_cache_store(struct config_item *item, } CONFIGFS_ATTR(tcmu_, emulate_write_cache); +static ssize_t tcmu_tmr_notification_show(struct config_item *item, char *page) +{ + struct se_dev_attrib *da = container_of(to_config_group(item), + struct se_dev_attrib, da_group); + struct tcmu_dev *udev = TCMU_DEV(da->da_dev); + + return snprintf(page, PAGE_SIZE, "%i\n", + test_bit(TCMU_DEV_BIT_TMR_NOTIFY, &udev->flags)); +} + +static ssize_t tcmu_tmr_notification_store(struct config_item *item, + const char *page, size_t count) +{ + struct se_dev_attrib *da = container_of(to_config_group(item), + struct se_dev_attrib, da_group); + struct tcmu_dev *udev = TCMU_DEV(da->da_dev); + u8 val; + int ret; + + ret = kstrtou8(page, 0, &val); + if (ret < 0) + return ret; + if (val > 1) + return -EINVAL; + + if (val) + set_bit(TCMU_DEV_BIT_TMR_NOTIFY, &udev->flags); + else + clear_bit(TCMU_DEV_BIT_TMR_NOTIFY, &udev->flags); + return count; +} +CONFIGFS_ATTR(tcmu_, tmr_notification); + static ssize_t tcmu_block_dev_show(struct config_item *item, char *page) { struct se_device *se_dev = container_of(to_config_group(item), @@ -2574,6 +2824,7 @@ static struct configfs_attribute *tcmu_attrib_attrs[] = { &tcmu_attr_dev_config, &tcmu_attr_dev_size, &tcmu_attr_emulate_write_cache, + &tcmu_attr_tmr_notification, &tcmu_attr_nl_reply_supported, NULL, }; @@ -2599,6 +2850,7 @@ static struct target_backend_ops tcmu_ops = { .destroy_device = tcmu_destroy_device, .free_device = tcmu_free_device, .parse_cdb = tcmu_parse_cdb, + .tmr_notify = tcmu_tmr_notify, .set_configfs_dev_params = tcmu_set_configfs_dev_params, .show_configfs_dev_params = tcmu_show_configfs_dev_params, .get_device_type = sbc_get_device_type, @@ -2625,7 +2877,8 @@ static void find_free_blocks(void) } /* Try to complete the finished commands first */ - tcmu_handle_completions(udev); + if (tcmu_handle_completions(udev)) + run_qfull_queue(udev, false); /* Skip the udevs in idle */ if (!udev->dbi_thresh) { diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c index 0d00ccbeb0503c25b2addee7f41b1b5b6494bd15..44e15d7fb2f09ea4f90a4fb94bf68ae9e5bf8a89 100644 --- a/drivers/target/target_core_xcopy.c +++ b/drivers/target/target_core_xcopy.c @@ -474,7 +474,7 @@ int target_xcopy_setup_pt(void) memset(&xcopy_pt_sess, 0, sizeof(struct se_session)); ret = transport_init_session(&xcopy_pt_sess); if (ret < 0) - return ret; + goto destroy_wq; xcopy_pt_nacl.se_tpg = &xcopy_pt_tpg; xcopy_pt_nacl.nacl_sess = &xcopy_pt_sess; @@ -483,12 +483,19 @@ int target_xcopy_setup_pt(void) xcopy_pt_sess.se_node_acl = &xcopy_pt_nacl; return 0; + +destroy_wq: + destroy_workqueue(xcopy_wq); + xcopy_wq = NULL; + return ret; } void target_xcopy_release_pt(void) { - if (xcopy_wq) + if (xcopy_wq) { destroy_workqueue(xcopy_wq); + transport_uninit_session(&xcopy_pt_sess); + } } /* diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 3eb2348e52427495bb36a0fc1b6bb34453a319a7..13991d68c844384e2bb4c6ce316a0d2bfd72a7d8 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -17,6 +17,16 @@ menuconfig THERMAL if THERMAL +config THERMAL_NETLINK + bool "Thermal netlink management" + depends on NET + default y + help + The thermal framework has a netlink interface to do thermal + zones discovery, temperature readings and events such as + trip point crossed, cooling device update or governor + change. It is recommended to enable the feature. + config THERMAL_STATISTICS bool "Thermal state transition statistics" help @@ -180,16 +190,6 @@ config CPU_IDLE_THERMAL idle cycle. endif -config CLOCK_THERMAL - bool "Generic clock cooling support" - depends on COMMON_CLK - depends on PM_OPP - help - This entry implements the generic clock cooling mechanism through - frequency clipping. Typically used to cool off co-processors. The - device that is configured to use this cooling mechanism will be - controlled to reduce clock frequency whenever temperature is high. - config DEVFREQ_THERMAL bool "Generic device cooling support" depends on PM_DEVFREQ diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 0c8b84a09b9aa7555b811ebe0da5a9b898ced8de..b8d96d26f9ec3f6c74c5a4f40fb81fcdc91cc091 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -7,6 +7,9 @@ obj-$(CONFIG_THERMAL) += thermal_sys.o thermal_sys-y += thermal_core.o thermal_sysfs.o \ thermal_helpers.o +# netlink interface to manage the thermal framework +thermal_sys-$(CONFIG_THERMAL_NETLINK) += thermal_netlink.o + # interface to/from other layers providing sensors thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o thermal_sys-$(CONFIG_THERMAL_OF) += thermal_of.o @@ -22,9 +25,6 @@ thermal_sys-$(CONFIG_THERMAL_GOV_POWER_ALLOCATOR) += gov_power_allocator.o thermal_sys-$(CONFIG_CPU_FREQ_THERMAL) += cpufreq_cooling.o thermal_sys-$(CONFIG_CPU_IDLE_THERMAL) += cpuidle_cooling.o -# clock cooling -thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o - # devfreq cooling thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 7c447cd149e7fab3c25939041c4e6bf98e783167..c2ebfb5be4b3dc715c49b1bfec275df6836a34ba 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -874,6 +874,12 @@ static int armada_thermal_probe(struct platform_device *pdev) return PTR_ERR(tz); } + ret = thermal_zone_device_enable(tz); + if (ret) { + thermal_zone_device_unregister(tz); + return ret; + } + drvdata->type = LEGACY; drvdata->data.tz = tz; platform_set_drvdata(pdev, drvdata); diff --git a/drivers/thermal/clock_cooling.c b/drivers/thermal/clock_cooling.c deleted file mode 100644 index 56cb1f46a428ebc87acf4144808fa10051bc727a..0000000000000000000000000000000000000000 --- a/drivers/thermal/clock_cooling.c +++ /dev/null @@ -1,445 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * drivers/thermal/clock_cooling.c - * - * Copyright (C) 2014 Eduardo Valentin - * - * Copyright (C) 2013 Texas Instruments Inc. - * Contact: Eduardo Valentin - * - * Highly based on cpufreq_cooling.c. - * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) - * Copyright (C) 2012 Amit Daniel - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * struct clock_cooling_device - data for cooling device with clock - * @id: unique integer value corresponding to each clock_cooling_device - * registered. - * @dev: struct device pointer to the device being used to cool off using - * clock frequencies. - * @cdev: thermal_cooling_device pointer to keep track of the - * registered cooling device. - * @clk_rate_change_nb: reference to notifier block used to receive clock - * rate changes. - * @freq_table: frequency table used to keep track of available frequencies. - * @clock_state: integer value representing the current state of clock - * cooling devices. - * @clock_val: integer value representing the absolute value of the clipped - * frequency. - * @clk: struct clk reference used to enforce clock limits. - * @lock: mutex lock to protect this struct. - * - * This structure is required for keeping information of each - * clock_cooling_device registered. In order to prevent corruption of this a - * mutex @lock is used. - */ -struct clock_cooling_device { - int id; - struct device *dev; - struct thermal_cooling_device *cdev; - struct notifier_block clk_rate_change_nb; - struct cpufreq_frequency_table *freq_table; - unsigned long clock_state; - unsigned long clock_val; - struct clk *clk; - struct mutex lock; /* lock to protect the content of this struct */ -}; -#define to_clock_cooling_device(x) \ - container_of(x, struct clock_cooling_device, clk_rate_change_nb) -static DEFINE_IDA(clock_ida); - -/* Below code defines functions to be used for clock as cooling device */ - -enum clock_cooling_property { - GET_LEVEL, - GET_FREQ, - GET_MAXL, -}; - -/** - * clock_cooling_get_property - fetch a property of interest for a give cpu. - * @ccdev: clock cooling device reference - * @input: query parameter - * @output: query return - * @property: type of query (frequency, level, max level) - * - * This is the common function to - * 1. get maximum clock cooling states - * 2. translate frequency to cooling state - * 3. translate cooling state to frequency - * Note that the code may be not in good shape - * but it is written in this way in order to: - * a) reduce duplicate code as most of the code can be shared. - * b) make sure the logic is consistent when translating between - * cooling states and frequencies. - * - * Return: 0 on success, -EINVAL when invalid parameters are passed. - */ -static int clock_cooling_get_property(struct clock_cooling_device *ccdev, - unsigned long input, - unsigned long *output, - enum clock_cooling_property property) -{ - int i; - unsigned long max_level = 0, level = 0; - unsigned int freq = CPUFREQ_ENTRY_INVALID; - int descend = -1; - struct cpufreq_frequency_table *pos, *table = ccdev->freq_table; - - if (!output) - return -EINVAL; - - if (!table) - return -EINVAL; - - cpufreq_for_each_valid_entry(pos, table) { - /* ignore duplicate entry */ - if (freq == pos->frequency) - continue; - - /* get the frequency order */ - if (freq != CPUFREQ_ENTRY_INVALID && descend == -1) - descend = freq > pos->frequency; - - freq = pos->frequency; - max_level++; - } - - /* No valid cpu frequency entry */ - if (max_level == 0) - return -EINVAL; - - /* max_level is an index, not a counter */ - max_level--; - - /* get max level */ - if (property == GET_MAXL) { - *output = max_level; - return 0; - } - - if (property == GET_FREQ) - level = descend ? input : (max_level - input); - - i = 0; - cpufreq_for_each_valid_entry(pos, table) { - /* ignore duplicate entry */ - if (freq == pos->frequency) - continue; - - /* now we have a valid frequency entry */ - freq = pos->frequency; - - if (property == GET_LEVEL && (unsigned int)input == freq) { - /* get level by frequency */ - *output = descend ? i : (max_level - i); - return 0; - } - if (property == GET_FREQ && level == i) { - /* get frequency by level */ - *output = freq; - return 0; - } - i++; - } - - return -EINVAL; -} - -/** - * clock_cooling_get_level - return the cooling level of given clock cooling. - * @cdev: reference of a thermal cooling device of used as clock cooling device - * @freq: the frequency of interest - * - * This function will match the cooling level corresponding to the - * requested @freq and return it. - * - * Return: The matched cooling level on success or THERMAL_CSTATE_INVALID - * otherwise. - */ -unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev, - unsigned long freq) -{ - struct clock_cooling_device *ccdev = cdev->devdata; - unsigned long val; - - if (clock_cooling_get_property(ccdev, (unsigned long)freq, &val, - GET_LEVEL)) - return THERMAL_CSTATE_INVALID; - - return val; -} -EXPORT_SYMBOL_GPL(clock_cooling_get_level); - -/** - * clock_cooling_get_frequency - get the absolute value of frequency from level. - * @ccdev: clock cooling device reference - * @level: cooling level - * - * This function matches cooling level with frequency. Based on a cooling level - * of frequency, equals cooling state of cpu cooling device, it will return - * the corresponding frequency. - * e.g level=0 --> 1st MAX FREQ, level=1 ---> 2nd MAX FREQ, .... etc - * - * Return: 0 on error, the corresponding frequency otherwise. - */ -static unsigned long -clock_cooling_get_frequency(struct clock_cooling_device *ccdev, - unsigned long level) -{ - int ret = 0; - unsigned long freq; - - ret = clock_cooling_get_property(ccdev, level, &freq, GET_FREQ); - if (ret) - return 0; - - return freq; -} - -/** - * clock_cooling_apply - function to apply frequency clipping. - * @ccdev: clock_cooling_device pointer containing frequency clipping data. - * @cooling_state: value of the cooling state. - * - * Function used to make sure the clock layer is aware of current thermal - * limits. The limits are applied by updating the clock rate in case it is - * higher than the corresponding frequency based on the requested cooling_state. - * - * Return: 0 on success, an error code otherwise (-EINVAL in case wrong - * cooling state). - */ -static int clock_cooling_apply(struct clock_cooling_device *ccdev, - unsigned long cooling_state) -{ - unsigned long clip_freq, cur_freq; - int ret = 0; - - /* Here we write the clipping */ - /* Check if the old cooling action is same as new cooling action */ - if (ccdev->clock_state == cooling_state) - return 0; - - clip_freq = clock_cooling_get_frequency(ccdev, cooling_state); - if (!clip_freq) - return -EINVAL; - - cur_freq = clk_get_rate(ccdev->clk); - - mutex_lock(&ccdev->lock); - ccdev->clock_state = cooling_state; - ccdev->clock_val = clip_freq; - /* enforce clock level */ - if (cur_freq > clip_freq) - ret = clk_set_rate(ccdev->clk, clip_freq); - mutex_unlock(&ccdev->lock); - - return ret; -} - -/** - * clock_cooling_clock_notifier - notifier callback on clock rate changes. - * @nb: struct notifier_block * with callback info. - * @event: value showing clock event for which this function invoked. - * @data: callback-specific data - * - * Callback to hijack the notification on clock transition. - * Every time there is a clock change, we intercept all pre change events - * and block the transition in case the new rate infringes thermal limits. - * - * Return: NOTIFY_DONE (success) or NOTIFY_BAD (new_rate > thermal limit). - */ -static int clock_cooling_clock_notifier(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct clk_notifier_data *ndata = data; - struct clock_cooling_device *ccdev = to_clock_cooling_device(nb); - - switch (event) { - case PRE_RATE_CHANGE: - /* - * checks on current state - * TODO: current method is not best we can find as it - * allows possibly voltage transitions, in case DVFS - * layer is also hijacking clock pre notifications. - */ - if (ndata->new_rate > ccdev->clock_val) - return NOTIFY_BAD; - /* fall through */ - case POST_RATE_CHANGE: - case ABORT_RATE_CHANGE: - default: - return NOTIFY_DONE; - } -} - -/* clock cooling device thermal callback functions are defined below */ - -/** - * clock_cooling_get_max_state - callback function to get the max cooling state. - * @cdev: thermal cooling device pointer. - * @state: fill this variable with the max cooling state. - * - * Callback for the thermal cooling device to return the clock - * max cooling state. - * - * Return: 0 on success, an error code otherwise. - */ -static int clock_cooling_get_max_state(struct thermal_cooling_device *cdev, - unsigned long *state) -{ - struct clock_cooling_device *ccdev = cdev->devdata; - unsigned long count = 0; - int ret; - - ret = clock_cooling_get_property(ccdev, 0, &count, GET_MAXL); - if (!ret) - *state = count; - - return ret; -} - -/** - * clock_cooling_get_cur_state - function to get the current cooling state. - * @cdev: thermal cooling device pointer. - * @state: fill this variable with the current cooling state. - * - * Callback for the thermal cooling device to return the clock - * current cooling state. - * - * Return: 0 (success) - */ -static int clock_cooling_get_cur_state(struct thermal_cooling_device *cdev, - unsigned long *state) -{ - struct clock_cooling_device *ccdev = cdev->devdata; - - *state = ccdev->clock_state; - - return 0; -} - -/** - * clock_cooling_set_cur_state - function to set the current cooling state. - * @cdev: thermal cooling device pointer. - * @state: set this variable to the current cooling state. - * - * Callback for the thermal cooling device to change the clock cooling - * current cooling state. - * - * Return: 0 on success, an error code otherwise. - */ -static int clock_cooling_set_cur_state(struct thermal_cooling_device *cdev, - unsigned long state) -{ - struct clock_cooling_device *clock_device = cdev->devdata; - - return clock_cooling_apply(clock_device, state); -} - -/* Bind clock callbacks to thermal cooling device ops */ -static struct thermal_cooling_device_ops const clock_cooling_ops = { - .get_max_state = clock_cooling_get_max_state, - .get_cur_state = clock_cooling_get_cur_state, - .set_cur_state = clock_cooling_set_cur_state, -}; - -/** - * clock_cooling_register - function to create clock cooling device. - * @dev: struct device pointer to the device used as clock cooling device. - * @clock_name: string containing the clock used as cooling mechanism. - * - * This interface function registers the clock cooling device with the name - * "thermal-clock-%x". The cooling device is based on clock frequencies. - * The struct device is assumed to be capable of DVFS transitions. - * The OPP layer is used to fetch and fill the available frequencies for - * the referred device. The ordered frequency table is used to control - * the clock cooling device cooling states and to limit clock transitions - * based on the cooling state requested by the thermal framework. - * - * Return: a valid struct thermal_cooling_device pointer on success, - * on failure, it returns a corresponding ERR_PTR(). - */ -struct thermal_cooling_device * -clock_cooling_register(struct device *dev, const char *clock_name) -{ - struct thermal_cooling_device *cdev; - struct clock_cooling_device *ccdev = NULL; - char dev_name[THERMAL_NAME_LENGTH]; - int ret = 0; - - ccdev = devm_kzalloc(dev, sizeof(*ccdev), GFP_KERNEL); - if (!ccdev) - return ERR_PTR(-ENOMEM); - - mutex_init(&ccdev->lock); - ccdev->dev = dev; - ccdev->clk = devm_clk_get(dev, clock_name); - if (IS_ERR(ccdev->clk)) - return ERR_CAST(ccdev->clk); - - ret = ida_simple_get(&clock_ida, 0, 0, GFP_KERNEL); - if (ret < 0) - return ERR_PTR(ret); - ccdev->id = ret; - - snprintf(dev_name, sizeof(dev_name), "thermal-clock-%d", ccdev->id); - - cdev = thermal_cooling_device_register(dev_name, ccdev, - &clock_cooling_ops); - if (IS_ERR(cdev)) { - ida_simple_remove(&clock_ida, ccdev->id); - return ERR_PTR(-EINVAL); - } - ccdev->cdev = cdev; - ccdev->clk_rate_change_nb.notifier_call = clock_cooling_clock_notifier; - - /* Assuming someone has already filled the opp table for this device */ - ret = dev_pm_opp_init_cpufreq_table(dev, &ccdev->freq_table); - if (ret) { - ida_simple_remove(&clock_ida, ccdev->id); - return ERR_PTR(ret); - } - ccdev->clock_state = 0; - ccdev->clock_val = clock_cooling_get_frequency(ccdev, 0); - - clk_notifier_register(ccdev->clk, &ccdev->clk_rate_change_nb); - - return cdev; -} -EXPORT_SYMBOL_GPL(clock_cooling_register); - -/** - * clock_cooling_unregister - function to remove clock cooling device. - * @cdev: thermal cooling device pointer. - * - * This interface function unregisters the "thermal-clock-%x" cooling device. - */ -void clock_cooling_unregister(struct thermal_cooling_device *cdev) -{ - struct clock_cooling_device *ccdev; - - if (!cdev) - return; - - ccdev = cdev->devdata; - - clk_notifier_unregister(ccdev->clk, &ccdev->clk_rate_change_nb); - dev_pm_opp_free_cpufreq_table(ccdev->dev, &ccdev->freq_table); - - thermal_cooling_device_unregister(ccdev->cdev); - ida_simple_remove(&clock_ida, ccdev->id); -} -EXPORT_SYMBOL_GPL(clock_cooling_unregister); diff --git a/drivers/thermal/da9062-thermal.c b/drivers/thermal/da9062-thermal.c index c32709badeda7bbf36e85cedd470bddad2c01532..4d74994f160aebfa6c37cbc62a06eb88576f3601 100644 --- a/drivers/thermal/da9062-thermal.c +++ b/drivers/thermal/da9062-thermal.c @@ -49,7 +49,6 @@ struct da9062_thermal { struct da9062 *hw; struct delayed_work work; struct thermal_zone_device *zone; - enum thermal_device_mode mode; struct mutex lock; /* protection for da9062_thermal temperature */ int temperature; int irq; @@ -121,14 +120,6 @@ static irqreturn_t da9062_thermal_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static int da9062_thermal_get_mode(struct thermal_zone_device *z, - enum thermal_device_mode *mode) -{ - struct da9062_thermal *thermal = z->devdata; - *mode = thermal->mode; - return 0; -} - static int da9062_thermal_get_trip_type(struct thermal_zone_device *z, int trip, enum thermal_trip_type *type) @@ -181,7 +172,6 @@ static int da9062_thermal_get_temp(struct thermal_zone_device *z, static struct thermal_zone_device_ops da9062_thermal_ops = { .get_temp = da9062_thermal_get_temp, - .get_mode = da9062_thermal_get_mode, .get_trip_type = da9062_thermal_get_trip_type, .get_trip_temp = da9062_thermal_get_trip_temp, }; @@ -233,7 +223,6 @@ static int da9062_thermal_probe(struct platform_device *pdev) thermal->config = match->data; thermal->hw = chip; - thermal->mode = THERMAL_DEVICE_ENABLED; thermal->dev = &pdev->dev; INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on); @@ -248,6 +237,11 @@ static int da9062_thermal_probe(struct platform_device *pdev) ret = PTR_ERR(thermal->zone); goto err; } + ret = thermal_zone_device_enable(thermal->zone); + if (ret) { + dev_err(&pdev->dev, "Cannot enable thermal zone device\n"); + goto err_zone; + } dev_dbg(&pdev->dev, "TJUNC temperature polling period set at %d ms\n", diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c index f7f32e98331b1e1ba41d7b6b7b15a437d7306f42..a12d2909622956d9ab2373abe7f4e663372a35a4 100644 --- a/drivers/thermal/devfreq_cooling.c +++ b/drivers/thermal/devfreq_cooling.c @@ -1,18 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * devfreq_cooling: Thermal cooling device implementation for devices using * devfreq * * Copyright (C) 2014-2015 ARM Limited * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * * TODO: * - If OPPs are added or removed after devfreq cooling has * registered, the devfreq cooling won't react to it. diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c index 75901ced4a622f10484de23d1e36338a3dcdbe76..73182eb94bc08b6ccea494eb06c833010f0bd307 100644 --- a/drivers/thermal/dove_thermal.c +++ b/drivers/thermal/dove_thermal.c @@ -153,6 +153,12 @@ static int dove_thermal_probe(struct platform_device *pdev) return PTR_ERR(thermal); } + ret = thermal_zone_device_enable(thermal); + if (ret) { + thermal_zone_device_unregister(thermal); + return ret; + } + platform_set_drvdata(pdev, thermal); return 0; diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c index 44636475b2a348e115a9027a29d77a45f35fc91b..5cb518d8f1562573425ab498ee1f7cd164c7815f 100644 --- a/drivers/thermal/gov_power_allocator.c +++ b/drivers/thermal/gov_power_allocator.c @@ -1,16 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * A power allocator to manage temperature * * Copyright (C) 2014 ARM Ltd. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #define pr_fmt(fmt) "Power allocator: " fmt diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 2d26ae80e20228e96bcb2e4b4a2958f2dd57bbee..ee05950afd2f97df7d954eb0830a2f688b52270c 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -549,8 +549,10 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, { struct thermal_zone_device *tzd = sensor->tzd; - tzd->ops->set_mode(tzd, - on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); + if (on) + thermal_zone_device_enable(tzd); + else + thermal_zone_device_disable(tzd); } static int hisi_thermal_probe(struct platform_device *pdev) diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c index e6061e26d4ac001734b905efe5231bd1acc3085b..f5124f14cf81386126c540841410c7c2d5b74679 100644 --- a/drivers/thermal/imx8mm_thermal.c +++ b/drivers/thermal/imx8mm_thermal.c @@ -220,6 +220,7 @@ static const struct of_device_id imx8mm_tmu_table[] = { { .compatible = "fsl,imx8mp-tmu", .data = &imx8mp_tmu_data, }, { }, }; +MODULE_DEVICE_TABLE(of, imx8mm_tmu_table); static struct platform_driver imx8mm_tmu = { .driver = { diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 1b84ea674edb740d140ae547f3da685266e64b68..3f74ab4c1ab9f184a3e0c449a0f91951a7bd46a4 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -197,7 +197,6 @@ struct imx_thermal_data { struct cpufreq_policy *policy; struct thermal_zone_device *tz; struct thermal_cooling_device *cdev; - enum thermal_device_mode mode; struct regmap *tempmon; u32 c1, c2; /* See formula in imx_init_calib() */ int temp_passive; @@ -253,10 +252,11 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) const struct thermal_soc_data *soc_data = data->socdata; struct regmap *map = data->tempmon; unsigned int n_meas; - bool wait; + bool wait, run_measurement; u32 val; - if (data->mode == THERMAL_DEVICE_ENABLED) { + run_measurement = !data->irq_enabled; + if (!run_measurement) { /* Check if a measurement is currently in progress */ regmap_read(map, soc_data->temp_data, &val); wait = !(val & soc_data->temp_valid_mask); @@ -283,7 +283,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) regmap_read(map, soc_data->temp_data, &val); - if (data->mode != THERMAL_DEVICE_ENABLED) { + if (run_measurement) { regmap_write(map, soc_data->sensor_ctrl + REG_CLR, soc_data->measure_temp_mask); regmap_write(map, soc_data->sensor_ctrl + REG_SET, @@ -331,27 +331,14 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) return 0; } -static int imx_get_mode(struct thermal_zone_device *tz, - enum thermal_device_mode *mode) -{ - struct imx_thermal_data *data = tz->devdata; - - *mode = data->mode; - - return 0; -} - -static int imx_set_mode(struct thermal_zone_device *tz, - enum thermal_device_mode mode) +static int imx_change_mode(struct thermal_zone_device *tz, + enum thermal_device_mode mode) { struct imx_thermal_data *data = tz->devdata; struct regmap *map = data->tempmon; const struct thermal_soc_data *soc_data = data->socdata; if (mode == THERMAL_DEVICE_ENABLED) { - tz->polling_delay = IMX_POLLING_DELAY; - tz->passive_delay = IMX_PASSIVE_DELAY; - regmap_write(map, soc_data->sensor_ctrl + REG_CLR, soc_data->power_down_mask); regmap_write(map, soc_data->sensor_ctrl + REG_SET, @@ -367,18 +354,12 @@ static int imx_set_mode(struct thermal_zone_device *tz, regmap_write(map, soc_data->sensor_ctrl + REG_SET, soc_data->power_down_mask); - tz->polling_delay = 0; - tz->passive_delay = 0; - if (data->irq_enabled) { disable_irq(data->irq); data->irq_enabled = false; } } - data->mode = mode; - thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); - return 0; } @@ -467,8 +448,7 @@ static struct thermal_zone_device_ops imx_tz_ops = { .bind = imx_bind, .unbind = imx_unbind, .get_temp = imx_get_temp, - .get_mode = imx_get_mode, - .set_mode = imx_set_mode, + .change_mode = imx_change_mode, .get_trip_type = imx_get_trip_type, .get_trip_temp = imx_get_trip_temp, .get_crit_temp = imx_get_crit_temp, @@ -832,7 +812,9 @@ static int imx_thermal_probe(struct platform_device *pdev) data->socdata->measure_temp_mask); data->irq_enabled = true; - data->mode = THERMAL_DEVICE_ENABLED; + ret = thermal_zone_device_enable(data->tz); + if (ret) + goto thermal_zone_unregister; ret = devm_request_threaded_irq(&pdev->dev, data->irq, imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread, @@ -874,19 +856,18 @@ static int imx_thermal_remove(struct platform_device *pdev) static int __maybe_unused imx_thermal_suspend(struct device *dev) { struct imx_thermal_data *data = dev_get_drvdata(dev); - struct regmap *map = data->tempmon; + int ret; /* * Need to disable thermal sensor, otherwise, when thermal core * try to get temperature before thermal sensor resume, a wrong * temperature will be read as the thermal sensor is powered - * down. + * down. This is done in change_mode() operation called from + * thermal_zone_device_disable() */ - regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, - data->socdata->measure_temp_mask); - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, - data->socdata->power_down_mask); - data->mode = THERMAL_DEVICE_DISABLED; + ret = thermal_zone_device_disable(data->tz); + if (ret) + return ret; clk_disable_unprepare(data->thermal_clk); return 0; @@ -895,18 +876,15 @@ static int __maybe_unused imx_thermal_suspend(struct device *dev) static int __maybe_unused imx_thermal_resume(struct device *dev) { struct imx_thermal_data *data = dev_get_drvdata(dev); - struct regmap *map = data->tempmon; int ret; ret = clk_prepare_enable(data->thermal_clk); if (ret) return ret; /* Enabled thermal sensor after resume */ - regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, - data->socdata->power_down_mask); - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, - data->socdata->measure_temp_mask); - data->mode = THERMAL_DEVICE_ENABLED; + ret = thermal_zone_device_enable(data->tz); + if (ret) + return ret; return 0; } diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index 12448ccd27f16806f715dcd211ba0b426b47396d..4f5859d4c780f9a25f2f424540be07ec61269e47 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -48,7 +48,6 @@ struct int3400_thermal_priv { struct acpi_device *adev; struct platform_device *pdev; struct thermal_zone_device *thermal; - int mode; int art_count; struct art *arts; int trt_count; @@ -383,42 +382,20 @@ static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, return 0; } -static int int3400_thermal_get_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode *mode) +static int int3400_thermal_change_mode(struct thermal_zone_device *thermal, + enum thermal_device_mode mode) { struct int3400_thermal_priv *priv = thermal->devdata; - - if (!priv) - return -EINVAL; - - *mode = priv->mode; - - return 0; -} - -static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode mode) -{ - struct int3400_thermal_priv *priv = thermal->devdata; - bool enable; int result = 0; if (!priv) return -EINVAL; - if (mode == THERMAL_DEVICE_ENABLED) - enable = true; - else if (mode == THERMAL_DEVICE_DISABLED) - enable = false; - else - return -EINVAL; - - if (enable != priv->mode) { - priv->mode = enable; + if (mode != thermal->mode) result = int3400_thermal_run_osc(priv->adev->handle, - priv->current_uuid_index, - enable); - } + priv->current_uuid_index, + mode == THERMAL_DEVICE_ENABLED); + evaluate_odvp(priv); @@ -427,8 +404,7 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, static struct thermal_zone_device_ops int3400_thermal_ops = { .get_temp = int3400_thermal_get_temp, - .get_mode = int3400_thermal_get_mode, - .set_mode = int3400_thermal_set_mode, + .change_mode = int3400_thermal_change_mode, }; static struct thermal_zone_params int3400_thermal_params = { diff --git a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c index 432213272f1e7d88e1f3b494cd3b0792de4f38d5..6e479deff76b040d98870c415210896008a3027e 100644 --- a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c +++ b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c @@ -259,9 +259,14 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev, ret = PTR_ERR(int34x_thermal_zone->zone); goto err_thermal_zone; } + ret = thermal_zone_device_enable(int34x_thermal_zone->zone); + if (ret) + goto err_enable; return int34x_thermal_zone; +err_enable: + thermal_zone_device_unregister(int34x_thermal_zone->zone); err_thermal_zone: acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table); kfree(int34x_thermal_zone->aux_trips); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c index 297db1d2d960c6ab3d11a4ce724f9c11c585ed55..81e8b15ef405d581121a0ad873ef399ad99bac6c 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c @@ -43,7 +43,7 @@ #define PCI_DEVICE_ID_PROC_ICL_THERMAL 0x8a03 /* JasperLake thermal reporting device */ -#define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4503 +#define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4E03 /* TigerLake thermal reporting device */ #define PCI_DEVICE_ID_PROC_TGL_THERMAL 0x9A03 diff --git a/drivers/thermal/intel/intel_pch_thermal.c b/drivers/thermal/intel/intel_pch_thermal.c index 56401fd4708d9904585bd9c4a37df798b91cafd9..3b813ebb6ca1db1f9a0b8447a02de9ec46d7f6cf 100644 --- a/drivers/thermal/intel/intel_pch_thermal.c +++ b/drivers/thermal/intel/intel_pch_thermal.c @@ -24,6 +24,7 @@ #define PCH_THERMAL_DID_SKL_H 0xA131 /* Skylake PCH 100 series */ #define PCH_THERMAL_DID_CNL 0x9Df9 /* CNL PCH */ #define PCH_THERMAL_DID_CNL_H 0xA379 /* CNL-H PCH */ +#define PCH_THERMAL_DID_CNL_LP 0x02F9 /* CNL-LP PCH */ #define PCH_THERMAL_DID_CML_H 0X06F9 /* CML-H PCH */ /* Wildcat Point-LP PCH Thermal registers */ @@ -352,9 +353,14 @@ static int intel_pch_thermal_probe(struct pci_dev *pdev, err = PTR_ERR(ptd->tzd); goto error_cleanup; } + err = thermal_zone_device_enable(ptd->tzd); + if (err) + goto err_unregister; return 0; +err_unregister: + thermal_zone_device_unregister(ptd->tzd); error_cleanup: iounmap(ptd->hw_base); error_release: @@ -405,6 +411,8 @@ static const struct pci_device_id intel_pch_thermal_id[] = { .driver_data = board_cnl, }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_H), .driver_data = board_cnl, }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_LP), + .driver_data = board_cnl, }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CML_H), .driver_data = board_cml, }, { 0, }, diff --git a/drivers/thermal/intel/intel_quark_dts_thermal.c b/drivers/thermal/intel/intel_quark_dts_thermal.c index d704fc104cfd6ef7300d37ad704c2627cb91aef8..3eafc6b0e6c307a951148f4dd5543aaef133b550 100644 --- a/drivers/thermal/intel/intel_quark_dts_thermal.c +++ b/drivers/thermal/intel/intel_quark_dts_thermal.c @@ -103,7 +103,6 @@ struct soc_sensor_entry { bool locked; u32 store_ptps; u32 store_dts_enable; - enum thermal_device_mode mode; struct thermal_zone_device *tzone; }; @@ -127,10 +126,8 @@ static int soc_dts_enable(struct thermal_zone_device *tzd) if (ret) return ret; - if (out & QRK_DTS_ENABLE_BIT) { - aux_entry->mode = THERMAL_DEVICE_ENABLED; + if (out & QRK_DTS_ENABLE_BIT) return 0; - } if (!aux_entry->locked) { out |= QRK_DTS_ENABLE_BIT; @@ -138,10 +135,7 @@ static int soc_dts_enable(struct thermal_zone_device *tzd) QRK_DTS_REG_OFFSET_ENABLE, out); if (ret) return ret; - - aux_entry->mode = THERMAL_DEVICE_ENABLED; } else { - aux_entry->mode = THERMAL_DEVICE_DISABLED; pr_info("DTS is locked. Cannot enable DTS\n"); ret = -EPERM; } @@ -160,10 +154,8 @@ static int soc_dts_disable(struct thermal_zone_device *tzd) if (ret) return ret; - if (!(out & QRK_DTS_ENABLE_BIT)) { - aux_entry->mode = THERMAL_DEVICE_DISABLED; + if (!(out & QRK_DTS_ENABLE_BIT)) return 0; - } if (!aux_entry->locked) { out &= ~QRK_DTS_ENABLE_BIT; @@ -172,10 +164,7 @@ static int soc_dts_disable(struct thermal_zone_device *tzd) if (ret) return ret; - - aux_entry->mode = THERMAL_DEVICE_DISABLED; } else { - aux_entry->mode = THERMAL_DEVICE_ENABLED; pr_info("DTS is locked. Cannot disable DTS\n"); ret = -EPERM; } @@ -309,16 +298,8 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, return 0; } -static int sys_get_mode(struct thermal_zone_device *tzd, - enum thermal_device_mode *mode) -{ - struct soc_sensor_entry *aux_entry = tzd->devdata; - *mode = aux_entry->mode; - return 0; -} - -static int sys_set_mode(struct thermal_zone_device *tzd, - enum thermal_device_mode mode) +static int sys_change_mode(struct thermal_zone_device *tzd, + enum thermal_device_mode mode) { int ret; @@ -338,8 +319,7 @@ static struct thermal_zone_device_ops tzone_ops = { .get_trip_type = sys_get_trip_type, .set_trip_temp = sys_set_trip_temp, .get_crit_temp = sys_get_crit_temp, - .get_mode = sys_get_mode, - .set_mode = sys_set_mode, + .change_mode = sys_change_mode, }; static void free_soc_dts(struct soc_sensor_entry *aux_entry) @@ -414,9 +394,7 @@ static struct soc_sensor_entry *alloc_soc_dts(void) goto err_ret; } - mutex_lock(&dts_update_mutex); - err = soc_dts_enable(aux_entry->tzone); - mutex_unlock(&dts_update_mutex); + err = thermal_zone_device_enable(aux_entry->tzone); if (err) goto err_aux_status; diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.c b/drivers/thermal/intel/intel_soc_dts_iosf.c index f75271b669c654b2690382075366e9015f6cd1f2..4f1a2f7c016cc14edc25a1af043a9d30e3a0e650 100644 --- a/drivers/thermal/intel/intel_soc_dts_iosf.c +++ b/drivers/thermal/intel/intel_soc_dts_iosf.c @@ -329,6 +329,9 @@ static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts, ret = PTR_ERR(dts->tzone); goto err_ret; } + ret = thermal_zone_device_enable(dts->tzone); + if (ret) + goto err_enable; ret = soc_dts_enable(id); if (ret) diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c index a006b9fd1d72b04bf4381b0905d1728cded7c1eb..b81c33202f41a02e7a1f3fb8d3754fcf589a3504 100644 --- a/drivers/thermal/intel/x86_pkg_temp_thermal.c +++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c @@ -363,6 +363,12 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) kfree(zonedev); return err; } + err = thermal_zone_device_enable(zonedev->tzone); + if (err) { + thermal_zone_device_unregister(zonedev->tzone); + kfree(zonedev); + return err; + } /* Store MSR value for package thermal interrupt, to restore at exit */ rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low, zonedev->msr_pkg_therm_high); diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c index 189b675cf14d9233cbd688c0e46108b1ac06a53e..7fb6e476c82a4be1982bfce70a35e0f7ea9bc35c 100644 --- a/drivers/thermal/kirkwood_thermal.c +++ b/drivers/thermal/kirkwood_thermal.c @@ -65,6 +65,7 @@ static int kirkwood_thermal_probe(struct platform_device *pdev) struct thermal_zone_device *thermal = NULL; struct kirkwood_thermal_priv *priv; struct resource *res; + int ret; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -82,6 +83,12 @@ static int kirkwood_thermal_probe(struct platform_device *pdev) "Failed to register thermal zone device\n"); return PTR_ERR(thermal); } + ret = thermal_zone_device_enable(thermal); + if (ret) { + thermal_zone_device_unregister(thermal); + dev_err(&pdev->dev, "Failed to enable thermal zone device\n"); + return ret; + } platform_set_drvdata(pdev, thermal); diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index 42c9cd0e5f7754c5c7087224c9cc6227d967e3fe..0bd7aa564bc25cc6d9d9303c59a6d9f0f8b5986b 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -38,6 +38,7 @@ #define TEMP_MONIDET0 0x014 #define TEMP_MONIDET1 0x018 #define TEMP_MSRCTL0 0x038 +#define TEMP_MSRCTL1 0x03c #define TEMP_AHBPOLL 0x040 #define TEMP_AHBTO 0x044 #define TEMP_ADCPNP0 0x048 @@ -120,18 +121,32 @@ * MT2701 has 3 sensors and needs 3 VTS calibration data. * MT2712 has 4 sensors and needs 4 VTS calibration data. */ -#define CALIB_BUF0_VALID BIT(0) -#define CALIB_BUF1_ADC_GE(x) (((x) >> 22) & 0x3ff) -#define CALIB_BUF0_VTS_TS1(x) (((x) >> 17) & 0x1ff) -#define CALIB_BUF0_VTS_TS2(x) (((x) >> 8) & 0x1ff) -#define CALIB_BUF1_VTS_TS3(x) (((x) >> 0) & 0x1ff) -#define CALIB_BUF2_VTS_TS4(x) (((x) >> 23) & 0x1ff) -#define CALIB_BUF2_VTS_TS5(x) (((x) >> 5) & 0x1ff) -#define CALIB_BUF2_VTS_TSABB(x) (((x) >> 14) & 0x1ff) -#define CALIB_BUF0_DEGC_CALI(x) (((x) >> 1) & 0x3f) -#define CALIB_BUF0_O_SLOPE(x) (((x) >> 26) & 0x3f) -#define CALIB_BUF0_O_SLOPE_SIGN(x) (((x) >> 7) & 0x1) -#define CALIB_BUF1_ID(x) (((x) >> 9) & 0x1) +#define CALIB_BUF0_VALID_V1 BIT(0) +#define CALIB_BUF1_ADC_GE_V1(x) (((x) >> 22) & 0x3ff) +#define CALIB_BUF0_VTS_TS1_V1(x) (((x) >> 17) & 0x1ff) +#define CALIB_BUF0_VTS_TS2_V1(x) (((x) >> 8) & 0x1ff) +#define CALIB_BUF1_VTS_TS3_V1(x) (((x) >> 0) & 0x1ff) +#define CALIB_BUF2_VTS_TS4_V1(x) (((x) >> 23) & 0x1ff) +#define CALIB_BUF2_VTS_TS5_V1(x) (((x) >> 5) & 0x1ff) +#define CALIB_BUF2_VTS_TSABB_V1(x) (((x) >> 14) & 0x1ff) +#define CALIB_BUF0_DEGC_CALI_V1(x) (((x) >> 1) & 0x3f) +#define CALIB_BUF0_O_SLOPE_V1(x) (((x) >> 26) & 0x3f) +#define CALIB_BUF0_O_SLOPE_SIGN_V1(x) (((x) >> 7) & 0x1) +#define CALIB_BUF1_ID_V1(x) (((x) >> 9) & 0x1) + +/* + * Layout of the fuses providing the calibration data + * These macros could be used for MT7622. + */ +#define CALIB_BUF0_ADC_OE_V2(x) (((x) >> 22) & 0x3ff) +#define CALIB_BUF0_ADC_GE_V2(x) (((x) >> 12) & 0x3ff) +#define CALIB_BUF0_DEGC_CALI_V2(x) (((x) >> 6) & 0x3f) +#define CALIB_BUF0_O_SLOPE_V2(x) (((x) >> 0) & 0x3f) +#define CALIB_BUF1_VTS_TS1_V2(x) (((x) >> 23) & 0x1ff) +#define CALIB_BUF1_VTS_TS2_V2(x) (((x) >> 14) & 0x1ff) +#define CALIB_BUF1_VTS_TSABB_V2(x) (((x) >> 5) & 0x1ff) +#define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) +#define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) enum { VTS1, @@ -143,6 +158,11 @@ enum { MAX_NUM_VTS, }; +enum mtk_thermal_version { + MTK_THERMAL_V1 = 1, + MTK_THERMAL_V2, +}; + /* MT2701 thermal sensors */ #define MT2701_TS1 0 #define MT2701_TS2 1 @@ -248,6 +268,7 @@ struct mtk_thermal_data { const int *controller_offset; bool need_switch_bank; struct thermal_bank_cfg bank_data[MAX_NUM_ZONES]; + enum mtk_thermal_version version; }; struct mtk_thermal { @@ -261,8 +282,10 @@ struct mtk_thermal { /* Calibration values */ s32 adc_ge; + s32 adc_oe; s32 degc_cali; s32 o_slope; + s32 o_slope_sign; s32 vts[MAX_NUM_VTS]; const struct mtk_thermal_data *conf; @@ -401,6 +424,7 @@ static const struct mtk_thermal_data mt8173_thermal_data = { .msr = mt8173_msr, .adcpnp = mt8173_adcpnp, .sensor_mux_values = mt8173_mux_values, + .version = MTK_THERMAL_V1, }; /* @@ -431,6 +455,7 @@ static const struct mtk_thermal_data mt2701_thermal_data = { .msr = mt2701_msr, .adcpnp = mt2701_adcpnp, .sensor_mux_values = mt2701_mux_values, + .version = MTK_THERMAL_V1, }; /* @@ -461,6 +486,7 @@ static const struct mtk_thermal_data mt2712_thermal_data = { .msr = mt2712_msr, .adcpnp = mt2712_adcpnp, .sensor_mux_values = mt2712_mux_values, + .version = MTK_THERMAL_V1, }; /* @@ -485,6 +511,7 @@ static const struct mtk_thermal_data mt7622_thermal_data = { .msr = mt7622_msr, .adcpnp = mt7622_adcpnp, .sensor_mux_values = mt7622_mux_values, + .version = MTK_THERMAL_V2, }; /* @@ -517,6 +544,7 @@ static const struct mtk_thermal_data mt8183_thermal_data = { .msr = mt8183_msr, .adcpnp = mt8183_adcpnp, .sensor_mux_values = mt8183_mux_values, + .version = MTK_THERMAL_V1, }; /** @@ -528,7 +556,7 @@ static const struct mtk_thermal_data mt8183_thermal_data = { * This converts the raw ADC value to mcelsius using the SoC specific * calibration constants */ -static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw) +static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw) { s32 tmp; @@ -543,6 +571,36 @@ static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw) return mt->degc_cali * 500 - tmp; } +static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw) +{ + s32 format_1 = 0; + s32 format_2 = 0; + s32 g_oe = 1; + s32 g_gain = 1; + s32 g_x_roomt = 0; + s32 tmp = 0; + + if (raw == 0) + return 0; + + raw &= 0xfff; + g_gain = 10000 + (((mt->adc_ge - 512) * 10000) >> 12); + g_oe = mt->adc_oe - 512; + format_1 = mt->vts[VTS2] + 3105 - g_oe; + format_2 = (mt->degc_cali * 10) >> 1; + g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain; + + tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt; + tmp = tmp * 10 * 100 / 11; + + if (mt->o_slope_sign == 0) + tmp = tmp / (165 - mt->o_slope); + else + tmp = tmp / (165 + mt->o_slope); + + return (format_2 - tmp) * 100; +} + /** * mtk_thermal_get_bank - get bank * @bank: The bank @@ -596,9 +654,13 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank) for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { raw = readl(mt->thermal_base + conf->msr[i]); - temp = raw_to_mcelsius(mt, - conf->bank_data[bank->id].sensors[i], - raw); + if (mt->conf->version == MTK_THERMAL_V1) { + temp = raw_to_mcelsius_v1( + mt, conf->bank_data[bank->id].sensors[i], raw); + } else { + temp = raw_to_mcelsius_v2( + mt, conf->bank_data[bank->id].sensors[i], raw); + } /* * The first read of a sensor often contains very high bogus @@ -700,9 +762,11 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num, writel(auxadc_phys_base + AUXADC_CON1_CLR_V, controller_base + TEMP_ADCMUXADDR); - /* AHB address for pnp sensor mux selection */ - writel(apmixed_phys_base + APMIXED_SYS_TS_CON1, - controller_base + TEMP_PNPMUXADDR); + if (mt->conf->version == MTK_THERMAL_V1) { + /* AHB address for pnp sensor mux selection */ + writel(apmixed_phys_base + APMIXED_SYS_TS_CON1, + controller_base + TEMP_PNPMUXADDR); + } /* AHB value for auxadc enable */ writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN); @@ -759,6 +823,68 @@ static u64 of_get_phys_base(struct device_node *np) return of_translate_address(np, regaddr_p); } +static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf) +{ + int i; + + if (!(buf[0] & CALIB_BUF0_VALID_V1)) + return -EINVAL; + + mt->adc_ge = CALIB_BUF1_ADC_GE_V1(buf[1]); + + for (i = 0; i < mt->conf->num_sensors; i++) { + switch (mt->conf->vts_index[i]) { + case VTS1: + mt->vts[VTS1] = CALIB_BUF0_VTS_TS1_V1(buf[0]); + break; + case VTS2: + mt->vts[VTS2] = CALIB_BUF0_VTS_TS2_V1(buf[0]); + break; + case VTS3: + mt->vts[VTS3] = CALIB_BUF1_VTS_TS3_V1(buf[1]); + break; + case VTS4: + mt->vts[VTS4] = CALIB_BUF2_VTS_TS4_V1(buf[2]); + break; + case VTS5: + mt->vts[VTS5] = CALIB_BUF2_VTS_TS5_V1(buf[2]); + break; + case VTSABB: + mt->vts[VTSABB] = + CALIB_BUF2_VTS_TSABB_V1(buf[2]); + break; + default: + break; + } + } + + mt->degc_cali = CALIB_BUF0_DEGC_CALI_V1(buf[0]); + if (CALIB_BUF1_ID_V1(buf[1]) & + CALIB_BUF0_O_SLOPE_SIGN_V1(buf[0])) + mt->o_slope = -CALIB_BUF0_O_SLOPE_V1(buf[0]); + else + mt->o_slope = CALIB_BUF0_O_SLOPE_V1(buf[0]); + + return 0; +} + +static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf) +{ + if (!CALIB_BUF1_VALID_V2(buf[1])) + return -EINVAL; + + mt->adc_oe = CALIB_BUF0_ADC_OE_V2(buf[0]); + mt->adc_ge = CALIB_BUF0_ADC_GE_V2(buf[0]); + mt->degc_cali = CALIB_BUF0_DEGC_CALI_V2(buf[0]); + mt->o_slope = CALIB_BUF0_O_SLOPE_V2(buf[0]); + mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V2(buf[1]); + mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V2(buf[1]); + mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V2(buf[1]); + mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V2(buf[1]); + + return 0; +} + static int mtk_thermal_get_calibration_data(struct device *dev, struct mtk_thermal *mt) { @@ -794,42 +920,14 @@ static int mtk_thermal_get_calibration_data(struct device *dev, goto out; } - if (buf[0] & CALIB_BUF0_VALID) { - mt->adc_ge = CALIB_BUF1_ADC_GE(buf[1]); - - for (i = 0; i < mt->conf->num_sensors; i++) { - switch (mt->conf->vts_index[i]) { - case VTS1: - mt->vts[VTS1] = CALIB_BUF0_VTS_TS1(buf[0]); - break; - case VTS2: - mt->vts[VTS2] = CALIB_BUF0_VTS_TS2(buf[0]); - break; - case VTS3: - mt->vts[VTS3] = CALIB_BUF1_VTS_TS3(buf[1]); - break; - case VTS4: - mt->vts[VTS4] = CALIB_BUF2_VTS_TS4(buf[2]); - break; - case VTS5: - mt->vts[VTS5] = CALIB_BUF2_VTS_TS5(buf[2]); - break; - case VTSABB: - mt->vts[VTSABB] = CALIB_BUF2_VTS_TSABB(buf[2]); - break; - default: - break; - } - } + if (mt->conf->version == MTK_THERMAL_V1) + ret = mtk_thermal_extract_efuse_v1(mt, buf); + else + ret = mtk_thermal_extract_efuse_v2(mt, buf); - mt->degc_cali = CALIB_BUF0_DEGC_CALI(buf[0]); - if (CALIB_BUF1_ID(buf[1]) & - CALIB_BUF0_O_SLOPE_SIGN(buf[0])) - mt->o_slope = -CALIB_BUF0_O_SLOPE(buf[0]); - else - mt->o_slope = CALIB_BUF0_O_SLOPE(buf[0]); - } else { + if (ret) { dev_info(dev, "Device not calibrated, using default calibration values\n"); + ret = 0; } out: @@ -863,6 +961,28 @@ static const struct of_device_id mtk_thermal_of_match[] = { }; MODULE_DEVICE_TABLE(of, mtk_thermal_of_match); +static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base) +{ + int tmp; + + tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1); + tmp &= ~(0x37); + tmp |= 0x1; + writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1); + udelay(200); +} + +static void mtk_thermal_release_periodic_ts(struct mtk_thermal *mt, + void __iomem *auxadc_base) +{ + int tmp; + + writel(0x800, auxadc_base + AUXADC_CON1_SET_V); + writel(0x1, mt->thermal_base + TEMP_MONCTL0); + tmp = readl(mt->thermal_base + TEMP_MSRCTL1); + writel((tmp & (~0x10e)), mt->thermal_base + TEMP_MSRCTL1); +} + static int mtk_thermal_probe(struct platform_device *pdev) { int ret, i, ctrl_id; @@ -871,6 +991,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) struct resource *res; u64 auxadc_phys_base, apmixed_phys_base; struct thermal_zone_device *tzdev; + void __iomem *apmixed_base, *auxadc_base; mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL); if (!mt) @@ -905,6 +1026,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) return -ENODEV; } + auxadc_base = of_iomap(auxadc, 0); auxadc_phys_base = of_get_phys_base(auxadc); of_node_put(auxadc); @@ -920,6 +1042,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) return -ENODEV; } + apmixed_base = of_iomap(apmixedsys, 0); apmixed_phys_base = of_get_phys_base(apmixedsys); of_node_put(apmixedsys); @@ -945,6 +1068,11 @@ static int mtk_thermal_probe(struct platform_device *pdev) goto err_disable_clk_auxadc; } + if (mt->conf->version == MTK_THERMAL_V2) { + mtk_thermal_turn_on_buffer(apmixed_base); + mtk_thermal_release_periodic_ts(mt, auxadc_base); + } + for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) for (i = 0; i < mt->conf->num_banks; i++) mtk_thermal_init_bank(mt, i, apmixed_phys_base, diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c index 959a9371d205c9d96b6da0791a4d7718dc157204..e64db5f80d909a8ad980c177986b5f069168b45b 100644 --- a/drivers/thermal/qcom/tsens-v0_1.c +++ b/drivers/thermal/qcom/tsens-v0_1.c @@ -48,6 +48,63 @@ #define MSM8916_CAL_SEL_MASK 0xe0000000 #define MSM8916_CAL_SEL_SHIFT 29 +/* eeprom layout data for 8939 */ +#define MSM8939_BASE0_MASK 0x000000ff +#define MSM8939_BASE1_MASK 0xff000000 +#define MSM8939_BASE0_SHIFT 0 +#define MSM8939_BASE1_SHIFT 24 + +#define MSM8939_S0_P1_MASK 0x000001f8 +#define MSM8939_S1_P1_MASK 0x001f8000 +#define MSM8939_S2_P1_MASK_0_4 0xf8000000 +#define MSM8939_S2_P1_MASK_5 0x00000001 +#define MSM8939_S3_P1_MASK 0x00001f80 +#define MSM8939_S4_P1_MASK 0x01f80000 +#define MSM8939_S5_P1_MASK 0x00003f00 +#define MSM8939_S6_P1_MASK 0x03f00000 +#define MSM8939_S7_P1_MASK 0x0000003f +#define MSM8939_S8_P1_MASK 0x0003f000 +#define MSM8939_S9_P1_MASK 0x07e00000 + +#define MSM8939_S0_P2_MASK 0x00007e00 +#define MSM8939_S1_P2_MASK 0x07e00000 +#define MSM8939_S2_P2_MASK 0x0000007e +#define MSM8939_S3_P2_MASK 0x0007e000 +#define MSM8939_S4_P2_MASK 0x7e000000 +#define MSM8939_S5_P2_MASK 0x000fc000 +#define MSM8939_S6_P2_MASK 0xfc000000 +#define MSM8939_S7_P2_MASK 0x00000fc0 +#define MSM8939_S8_P2_MASK 0x00fc0000 +#define MSM8939_S9_P2_MASK_0_4 0xf8000000 +#define MSM8939_S9_P2_MASK_5 0x00002000 + +#define MSM8939_S0_P1_SHIFT 3 +#define MSM8939_S1_P1_SHIFT 15 +#define MSM8939_S2_P1_SHIFT_0_4 27 +#define MSM8939_S2_P1_SHIFT_5 0 +#define MSM8939_S3_P1_SHIFT 7 +#define MSM8939_S4_P1_SHIFT 19 +#define MSM8939_S5_P1_SHIFT 8 +#define MSM8939_S6_P1_SHIFT 20 +#define MSM8939_S7_P1_SHIFT 0 +#define MSM8939_S8_P1_SHIFT 12 +#define MSM8939_S9_P1_SHIFT 21 + +#define MSM8939_S0_P2_SHIFT 9 +#define MSM8939_S1_P2_SHIFT 21 +#define MSM8939_S2_P2_SHIFT 1 +#define MSM8939_S3_P2_SHIFT 13 +#define MSM8939_S4_P2_SHIFT 25 +#define MSM8939_S5_P2_SHIFT 14 +#define MSM8939_S6_P2_SHIFT 26 +#define MSM8939_S7_P2_SHIFT 6 +#define MSM8939_S8_P2_SHIFT 18 +#define MSM8939_S9_P2_SHIFT_0_4 27 +#define MSM8939_S9_P2_SHIFT_5 13 + +#define MSM8939_CAL_SEL_MASK 0x7 +#define MSM8939_CAL_SEL_SHIFT 0 + /* eeprom layout data for 8974 */ #define BASE1_MASK 0xff #define S0_P1_MASK 0x3f00 @@ -189,6 +246,76 @@ static int calibrate_8916(struct tsens_priv *priv) return 0; } +static int calibrate_8939(struct tsens_priv *priv) +{ + int base0 = 0, base1 = 0, i; + u32 p1[10], p2[10]; + int mode = 0; + u32 *qfprom_cdata; + u32 cdata[6]; + + qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); + if (IS_ERR(qfprom_cdata)) + return PTR_ERR(qfprom_cdata); + + /* Mapping between qfprom nvmem and calibration data */ + cdata[0] = qfprom_cdata[12]; + cdata[1] = qfprom_cdata[13]; + cdata[2] = qfprom_cdata[0]; + cdata[3] = qfprom_cdata[1]; + cdata[4] = qfprom_cdata[22]; + cdata[5] = qfprom_cdata[21]; + + mode = (cdata[0] & MSM8939_CAL_SEL_MASK) >> MSM8939_CAL_SEL_SHIFT; + dev_dbg(priv->dev, "calibration mode is %d\n", mode); + + switch (mode) { + case TWO_PT_CALIB: + base1 = (cdata[3] & MSM8939_BASE1_MASK) >> MSM8939_BASE1_SHIFT; + p2[0] = (cdata[0] & MSM8939_S0_P2_MASK) >> MSM8939_S0_P2_SHIFT; + p2[1] = (cdata[0] & MSM8939_S1_P2_MASK) >> MSM8939_S1_P2_SHIFT; + p2[2] = (cdata[1] & MSM8939_S2_P2_MASK) >> MSM8939_S2_P2_SHIFT; + p2[3] = (cdata[1] & MSM8939_S3_P2_MASK) >> MSM8939_S3_P2_SHIFT; + p2[4] = (cdata[1] & MSM8939_S4_P2_MASK) >> MSM8939_S4_P2_SHIFT; + p2[5] = (cdata[2] & MSM8939_S5_P2_MASK) >> MSM8939_S5_P2_SHIFT; + p2[6] = (cdata[2] & MSM8939_S6_P2_MASK) >> MSM8939_S6_P2_SHIFT; + p2[7] = (cdata[3] & MSM8939_S7_P2_MASK) >> MSM8939_S7_P2_SHIFT; + p2[8] = (cdata[3] & MSM8939_S8_P2_MASK) >> MSM8939_S8_P2_SHIFT; + p2[9] = (cdata[4] & MSM8939_S9_P2_MASK_0_4) >> MSM8939_S9_P2_SHIFT_0_4; + p2[9] |= ((cdata[5] & MSM8939_S9_P2_MASK_5) >> MSM8939_S9_P2_SHIFT_5) << 5; + for (i = 0; i < priv->num_sensors; i++) + p2[i] = (base1 + p2[i]) << 2; + fallthrough; + case ONE_PT_CALIB2: + base0 = (cdata[2] & MSM8939_BASE0_MASK) >> MSM8939_BASE0_SHIFT; + p1[0] = (cdata[0] & MSM8939_S0_P1_MASK) >> MSM8939_S0_P1_SHIFT; + p1[1] = (cdata[0] & MSM8939_S1_P1_MASK) >> MSM8939_S1_P1_SHIFT; + p1[2] = (cdata[0] & MSM8939_S2_P1_MASK_0_4) >> MSM8939_S2_P1_SHIFT_0_4; + p1[2] |= ((cdata[1] & MSM8939_S2_P1_MASK_5) >> MSM8939_S2_P1_SHIFT_5) << 5; + p1[3] = (cdata[1] & MSM8939_S3_P1_MASK) >> MSM8939_S3_P1_SHIFT; + p1[4] = (cdata[1] & MSM8939_S4_P1_MASK) >> MSM8939_S4_P1_SHIFT; + p1[5] = (cdata[2] & MSM8939_S5_P1_MASK) >> MSM8939_S5_P1_SHIFT; + p1[6] = (cdata[2] & MSM8939_S6_P1_MASK) >> MSM8939_S6_P1_SHIFT; + p1[7] = (cdata[3] & MSM8939_S7_P1_MASK) >> MSM8939_S7_P1_SHIFT; + p1[8] = (cdata[3] & MSM8939_S8_P1_MASK) >> MSM8939_S8_P1_SHIFT; + p1[9] = (cdata[4] & MSM8939_S9_P1_MASK) >> MSM8939_S9_P1_SHIFT; + for (i = 0; i < priv->num_sensors; i++) + p1[i] = ((base0) + p1[i]) << 2; + break; + default: + for (i = 0; i < priv->num_sensors; i++) { + p1[i] = 500; + p2[i] = 780; + } + break; + } + + compute_intercept_slope(priv, p1, p2, mode); + kfree(qfprom_cdata); + + return 0; +} + static int calibrate_8974(struct tsens_priv *priv) { int base1 = 0, base2 = 0, i; @@ -325,7 +452,7 @@ static int calibrate_8974(struct tsens_priv *priv) return 0; } -/* v0.1: 8916, 8974 */ +/* v0.1: 8916, 8939, 8974 */ static struct tsens_features tsens_v0_1_feat = { .ver_major = VER_0_1, @@ -386,6 +513,21 @@ struct tsens_plat_data data_8916 = { .fields = tsens_v0_1_regfields, }; +static const struct tsens_ops ops_8939 = { + .init = init_common, + .calibrate = calibrate_8939, + .get_temp = get_temp_common, +}; + +struct tsens_plat_data data_8939 = { + .num_sensors = 10, + .ops = &ops_8939, + .hw_ids = (unsigned int []){ 0, 1, 2, 4, 5, 6, 7, 8, 9, 10 }, + + .feat = &tsens_v0_1_feat, + .fields = tsens_v0_1_regfields, +}; + static const struct tsens_ops ops_8974 = { .init = init_common, .calibrate = calibrate_8974, diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 39c4462e38f622031e729059263f58b857558503..d8ce3a687b80d470ae911026074b4e27810091a5 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -897,6 +897,9 @@ static const struct of_device_id tsens_table[] = { { .compatible = "qcom,msm8916-tsens", .data = &data_8916, + }, { + .compatible = "qcom,msm8939-tsens", + .data = &data_8939, }, { .compatible = "qcom,msm8974-tsens", .data = &data_8974, diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index 59d01162c66afbe1109fb07ea583792792577ba0..f40b625f897e8c096b9884c90c0ee0bedc59a012 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -585,7 +585,7 @@ int get_temp_common(const struct tsens_sensor *s, int *temp); extern struct tsens_plat_data data_8960; /* TSENS v0.1 targets */ -extern struct tsens_plat_data data_8916, data_8974; +extern struct tsens_plat_data data_8916, data_8939, data_8974; /* TSENS v1 targets */ extern struct tsens_plat_data data_tsens_v1, data_8976; diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index c48c5e9b8f203dd106839e69e7d0f1db948a64bf..0dd47dca3e7712563ed007c63cacee78dd3bdc5d 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -63,7 +63,7 @@ #define TSC_MAX_NUM 3 /* default THCODE values if FUSEs are missing */ -static const int thcode[TSC_MAX_NUM][3] = { +static const int thcodes[TSC_MAX_NUM][3] = { { 3397, 2800, 2221 }, { 3393, 2795, 2216 }, { 3389, 2805, 2237 }, @@ -172,7 +172,7 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp) /* Read register and convert to mili Celsius */ reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK; - if (reg <= thcode[tsc->id][1]) + if (reg <= thcodes[tsc->id][1]) val = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1, tsc->coef.a1); else @@ -314,6 +314,10 @@ static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { .compatible = "renesas,r8a774b1-thermal", .data = &rcar_gen3_ths_tj_1, }, + { + .compatible = "renesas,r8a774e1-thermal", + .data = &rcar_gen3_ths_tj_1, + }, { .compatible = "renesas,r8a7795-thermal", .data = &rcar_gen3_ths_tj_1, @@ -430,7 +434,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) priv->tscs[i] = tsc; priv->thermal_init(tsc); - rcar_gen3_thermal_calc_coefs(tsc, ptat, thcode[i], + rcar_gen3_thermal_calc_coefs(tsc, ptat, thcodes[i], *rcar_gen3_ths_tj_1); zone = devm_thermal_zone_of_sensor_register(dev, i, tsc, diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 46aeb28b4e901133ce06d07d4b78252e4f60ec8f..787710bb88fee890cc6afc419e5521e7d9092bfa 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -550,12 +550,19 @@ static int rcar_thermal_probe(struct platform_device *pdev) priv->zone = devm_thermal_zone_of_sensor_register( dev, i, priv, &rcar_thermal_zone_of_ops); - else + else { priv->zone = thermal_zone_device_register( "rcar_thermal", 1, 0, priv, &rcar_thermal_zone_ops, NULL, 0, idle); + + ret = thermal_zone_device_enable(priv->zone); + if (ret) { + thermal_zone_device_unregister(priv->zone); + priv->zone = ERR_PTR(ret); + } + } if (IS_ERR(priv->zone)) { dev_err(dev, "can't register thermal zone\n"); ret = PTR_ERR(priv->zone); diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 15a71ecc916c1a619c5997f3a693b97a2798484e..aa9e0e31ef9849cb1d849a6f74392f970a541d2a 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -1068,8 +1068,10 @@ rockchip_thermal_toggle_sensor(struct rockchip_thermal_sensor *sensor, bool on) { struct thermal_zone_device *tzd = sensor->tzd; - tzd->ops->set_mode(tzd, - on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); + if (on) + thermal_zone_device_enable(tzd); + else + thermal_zone_device_disable(tzd); } static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev) diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index f68f581fd669202f600696221b0e2f79d140f580..ee33ed692e4f7ee13983e7fffee97d346a7a5e55 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -131,6 +131,11 @@ static int spear_thermal_probe(struct platform_device *pdev) ret = PTR_ERR(spear_thermal); goto disable_clk; } + ret = thermal_zone_device_enable(spear_thermal); + if (ret) { + dev_err(&pdev->dev, "Cannot enable thermal zone\n"); + goto unregister_tzd; + } platform_set_drvdata(pdev, spear_thermal); @@ -139,6 +144,8 @@ static int spear_thermal_probe(struct platform_device *pdev) return 0; +unregister_tzd: + thermal_zone_device_unregister(spear_thermal); disable_clk: clk_disable(stdev->clk); diff --git a/drivers/thermal/sprd_thermal.c b/drivers/thermal/sprd_thermal.c index 4cde70dcf655659f6a36135ddf8a2e502d2b6f90..3682edb2f46692d0892abfe34524f75328bcfe93 100644 --- a/drivers/thermal/sprd_thermal.c +++ b/drivers/thermal/sprd_thermal.c @@ -322,8 +322,10 @@ static void sprd_thm_toggle_sensor(struct sprd_thermal_sensor *sen, bool on) { struct thermal_zone_device *tzd = sen->tzd; - tzd->ops->set_mode(tzd, - on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); + if (on) + thermal_zone_device_enable(tzd); + else + thermal_zone_device_disable(tzd); } static int sprd_thm_probe(struct platform_device *pdev) diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c index b928ca6a289b73a94af830ff8062bd62548c87a1..1276b95604fed7dc7b8a038ca95871ba0a136ff7 100644 --- a/drivers/thermal/st/st_thermal.c +++ b/drivers/thermal/st/st_thermal.c @@ -246,11 +246,16 @@ int st_thermal_register(struct platform_device *pdev, ret = PTR_ERR(sensor->thermal_dev); goto sensor_off; } + ret = thermal_zone_device_enable(sensor->thermal_dev); + if (ret) + goto tzd_unregister; platform_set_drvdata(pdev, sensor); return 0; +tzd_unregister: + thermal_zone_device_unregister(sensor->thermal_dev); sensor_off: st_thermal_sensor_off(sensor); diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index b71196eaf90e8247a551556483370150dedd7e72..72bf159bceccd83c187bb114ad9eacb175dfa6a0 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -215,6 +215,8 @@ exit: mutex_unlock(&tz->lock); mutex_unlock(&thermal_governor_lock); + thermal_notify_tz_gov_change(tz->id, policy); + return ret; } @@ -301,13 +303,22 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, cancel_delayed_work(&tz->poll_queue); } +static inline bool should_stop_polling(struct thermal_zone_device *tz) +{ + return !thermal_zone_device_is_enabled(tz); +} + static void monitor_thermal_zone(struct thermal_zone_device *tz) { + bool stop; + + stop = should_stop_polling(tz); + mutex_lock(&tz->lock); - if (tz->passive) + if (!stop && tz->passive) thermal_zone_device_set_polling(tz, tz->passive_delay); - else if (tz->polling_delay) + else if (!stop && tz->polling_delay) thermal_zone_device_set_polling(tz, tz->polling_delay); else thermal_zone_device_set_polling(tz, 0); @@ -406,12 +417,25 @@ static void handle_critical_trips(struct thermal_zone_device *tz, static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) { enum thermal_trip_type type; + int trip_temp, hyst = 0; /* Ignore disabled trip points */ if (test_bit(trip, &tz->trips_disabled)) return; + tz->ops->get_trip_temp(tz, trip, &trip_temp); tz->ops->get_trip_type(tz, trip, &type); + if (tz->ops->get_trip_hyst) + tz->ops->get_trip_hyst(tz, trip, &hyst); + + if (tz->last_temperature != THERMAL_TEMP_INVALID) { + if (tz->last_temperature < trip_temp && + tz->temperature >= trip_temp) + thermal_notify_tz_trip_up(tz->id, trip); + if (tz->last_temperature >= trip_temp && + tz->temperature < (trip_temp - hyst)) + thermal_notify_tz_trip_down(tz->id, trip); + } if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT) handle_critical_trips(tz, trip, type); @@ -443,6 +467,8 @@ static void update_temperature(struct thermal_zone_device *tz) mutex_unlock(&tz->lock); trace_thermal_temperature(tz); + + thermal_genl_sampling_temp(tz->id, temp); } static void thermal_zone_device_init(struct thermal_zone_device *tz) @@ -459,11 +485,71 @@ static void thermal_zone_device_reset(struct thermal_zone_device *tz) thermal_zone_device_init(tz); } +static int thermal_zone_device_set_mode(struct thermal_zone_device *tz, + enum thermal_device_mode mode) +{ + int ret = 0; + + mutex_lock(&tz->lock); + + /* do nothing if mode isn't changing */ + if (mode == tz->mode) { + mutex_unlock(&tz->lock); + + return ret; + } + + if (tz->ops->change_mode) + ret = tz->ops->change_mode(tz, mode); + + if (!ret) + tz->mode = mode; + + mutex_unlock(&tz->lock); + + thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + + if (mode == THERMAL_DEVICE_ENABLED) + thermal_notify_tz_enable(tz->id); + else + thermal_notify_tz_disable(tz->id); + + return ret; +} + +int thermal_zone_device_enable(struct thermal_zone_device *tz) +{ + return thermal_zone_device_set_mode(tz, THERMAL_DEVICE_ENABLED); +} +EXPORT_SYMBOL_GPL(thermal_zone_device_enable); + +int thermal_zone_device_disable(struct thermal_zone_device *tz) +{ + return thermal_zone_device_set_mode(tz, THERMAL_DEVICE_DISABLED); +} +EXPORT_SYMBOL_GPL(thermal_zone_device_disable); + +int thermal_zone_device_is_enabled(struct thermal_zone_device *tz) +{ + enum thermal_device_mode mode; + + mutex_lock(&tz->lock); + + mode = tz->mode; + + mutex_unlock(&tz->lock); + + return mode == THERMAL_DEVICE_ENABLED; +} + void thermal_zone_device_update(struct thermal_zone_device *tz, enum thermal_notify_event event) { int count; + if (should_stop_polling(tz)) + return; + if (atomic_read(&in_suspend)) return; @@ -617,6 +703,73 @@ void thermal_zone_device_rebind_exception(struct thermal_zone_device *tz, mutex_unlock(&thermal_list_lock); } +int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), + void *data) +{ + struct thermal_governor *gov; + int ret = 0; + + mutex_lock(&thermal_governor_lock); + list_for_each_entry(gov, &thermal_governor_list, governor_list) { + ret = cb(gov, data); + if (ret) + break; + } + mutex_unlock(&thermal_governor_lock); + + return ret; +} + +int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *, + void *), void *data) +{ + struct thermal_cooling_device *cdev; + int ret = 0; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(cdev, &thermal_cdev_list, node) { + ret = cb(cdev, data); + if (ret) + break; + } + mutex_unlock(&thermal_list_lock); + + return ret; +} + +int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *), + void *data) +{ + struct thermal_zone_device *tz; + int ret = 0; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(tz, &thermal_tz_list, node) { + ret = cb(tz, data); + if (ret) + break; + } + mutex_unlock(&thermal_list_lock); + + return ret; +} + +struct thermal_zone_device *thermal_zone_get_by_id(int id) +{ + struct thermal_zone_device *tz, *match = NULL; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(tz, &thermal_tz_list, node) { + if (tz->id == id) { + match = tz; + break; + } + } + mutex_unlock(&thermal_list_lock); + + return match; +} + void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz, const char *cdev_type, size_t size) { @@ -1340,6 +1493,8 @@ thermal_zone_device_register(const char *type, int trips, int mask, if (atomic_cmpxchg(&tz->need_update, 1, 0)) thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + thermal_notify_tz_create(tz->id, tz->type); + return tz; unregister: @@ -1411,6 +1566,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) ida_destroy(&tz->ida); mutex_destroy(&tz->lock); device_unregister(&tz->device); + + thermal_notify_tz_delete(tz->id); } EXPORT_SYMBOL_GPL(thermal_zone_device_unregister); @@ -1456,7 +1613,6 @@ static int thermal_pm_notify(struct notifier_block *nb, unsigned long mode, void *_unused) { struct thermal_zone_device *tz; - enum thermal_device_mode tz_mode; switch (mode) { case PM_HIBERNATION_PREPARE: @@ -1469,11 +1625,7 @@ static int thermal_pm_notify(struct notifier_block *nb, case PM_POST_SUSPEND: atomic_set(&in_suspend, 0); list_for_each_entry(tz, &thermal_tz_list, node) { - tz_mode = THERMAL_DEVICE_ENABLED; - if (tz->ops->get_mode) - tz->ops->get_mode(tz, &tz_mode); - - if (tz_mode == THERMAL_DEVICE_DISABLED) + if (!thermal_zone_device_is_enabled(tz)) continue; thermal_zone_device_init(tz); @@ -1495,6 +1647,10 @@ static int __init thermal_init(void) { int result; + result = thermal_netlink_init(); + if (result) + goto error; + mutex_init(&poweroff_lock); result = thermal_register_governors(); if (result) @@ -1527,4 +1683,4 @@ error: mutex_destroy(&poweroff_lock); return result; } -core_initcall(thermal_init); +postcore_initcall(thermal_init); diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index c95689586e19ac77df86ae84b734db25922c50e6..e00fc5585ea805680c56e0dd1a029fae41f965dd 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -12,6 +12,8 @@ #include #include +#include "thermal_netlink.h" + /* Default Thermal Governor */ #if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE) #define DEFAULT_THERMAL_GOVERNOR "step_wise" @@ -41,6 +43,17 @@ extern struct thermal_governor *__governor_thermal_table_end[]; __governor < __governor_thermal_table_end; \ __governor++) +int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *), + void *); + +int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *, + void *), void *); + +int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), + void *thermal_governor); + +struct thermal_zone_device *thermal_zone_get_by_id(int id); + struct thermal_attr { struct device_attribute attr; char name[THERMAL_NAME_LENGTH]; @@ -166,4 +179,6 @@ of_thermal_get_trip_points(struct thermal_zone_device *tz) } #endif +int thermal_zone_device_is_enabled(struct thermal_zone_device *tz); + #endif /* __THERMAL_CORE_H__ */ diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c index 87b1256fa2f206a03b6eb19f07d9203ae0677cfa..c94bc824e5d36ab34594cc35e0bcf2444efc85d9 100644 --- a/drivers/thermal/thermal_helpers.c +++ b/drivers/thermal/thermal_helpers.c @@ -175,6 +175,16 @@ exit: mutex_unlock(&tz->lock); } +static void thermal_cdev_set_cur_state(struct thermal_cooling_device *cdev, + int target) +{ + if (cdev->ops->set_cur_state(cdev, target)) + return; + + thermal_notify_cdev_state_update(cdev->id, target); + thermal_cooling_device_stats_update(cdev, target); +} + void thermal_cdev_update(struct thermal_cooling_device *cdev) { struct thermal_instance *instance; @@ -197,8 +207,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) target = instance->target; } - if (!cdev->ops->set_cur_state(cdev, target)) - thermal_cooling_device_stats_update(cdev, target); + thermal_cdev_set_cur_state(cdev, target); cdev->updated = true; mutex_unlock(&cdev->lock); diff --git a/drivers/thermal/thermal_netlink.c b/drivers/thermal/thermal_netlink.c new file mode 100644 index 0000000000000000000000000000000000000000..af7b2383e8f6b1fc2e3863ec419bdb77ff307e10 --- /dev/null +++ b/drivers/thermal/thermal_netlink.c @@ -0,0 +1,647 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2020 Linaro Limited + * + * Author: Daniel Lezcano + * + * Generic netlink for thermal management framework + */ +#include +#include +#include +#include + +#include "thermal_core.h" + +static const struct genl_multicast_group thermal_genl_mcgrps[] = { + { .name = THERMAL_GENL_SAMPLING_GROUP_NAME, }, + { .name = THERMAL_GENL_EVENT_GROUP_NAME, }, +}; + +static const struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = { + /* Thermal zone */ + [THERMAL_GENL_ATTR_TZ] = { .type = NLA_NESTED }, + [THERMAL_GENL_ATTR_TZ_ID] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_TEMP] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_TRIP] = { .type = NLA_NESTED }, + [THERMAL_GENL_ATTR_TZ_TRIP_ID] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_TRIP_TEMP] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_TRIP_TYPE] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_TRIP_HYST] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_MODE] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_NAME] = { .type = NLA_STRING, + .len = THERMAL_NAME_LENGTH }, + /* Governor(s) */ + [THERMAL_GENL_ATTR_TZ_GOV] = { .type = NLA_NESTED }, + [THERMAL_GENL_ATTR_TZ_GOV_NAME] = { .type = NLA_STRING, + .len = THERMAL_NAME_LENGTH }, + /* Cooling devices */ + [THERMAL_GENL_ATTR_CDEV] = { .type = NLA_NESTED }, + [THERMAL_GENL_ATTR_CDEV_ID] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_CDEV_CUR_STATE] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_CDEV_MAX_STATE] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_CDEV_NAME] = { .type = NLA_STRING, + .len = THERMAL_NAME_LENGTH }, +}; + +struct param { + struct nlattr **attrs; + struct sk_buff *msg; + const char *name; + int tz_id; + int cdev_id; + int trip_id; + int trip_temp; + int trip_type; + int trip_hyst; + int temp; + int cdev_state; + int cdev_max_state; +}; + +typedef int (*cb_t)(struct param *); + +static struct genl_family thermal_gnl_family; + +/************************** Sampling encoding *******************************/ + +int thermal_genl_sampling_temp(int id, int temp) +{ + struct sk_buff *skb; + void *hdr; + + skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0, + THERMAL_GENL_SAMPLING_TEMP); + if (!hdr) + return -EMSGSIZE; + + if (nla_put_u32(skb, THERMAL_GENL_ATTR_TZ_ID, id)) + goto out_cancel; + + if (nla_put_u32(skb, THERMAL_GENL_ATTR_TZ_TEMP, temp)) + goto out_cancel; + + genlmsg_end(skb, hdr); + + genlmsg_multicast(&thermal_gnl_family, skb, 0, 0, GFP_KERNEL); + + return 0; +out_cancel: + genlmsg_cancel(skb, hdr); + nlmsg_free(skb); + + return -EMSGSIZE; +} + +/**************************** Event encoding *********************************/ + +static int thermal_genl_event_tz_create(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_string(p->msg, THERMAL_GENL_ATTR_TZ_NAME, p->name)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_tz(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_tz_trip_up(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_tz_trip_add(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, p->trip_type) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, p->trip_temp) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, p->trip_hyst)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_tz_trip_delete(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_cdev_add(struct param *p) +{ + if (nla_put_string(p->msg, THERMAL_GENL_ATTR_CDEV_NAME, + p->name) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID, + p->cdev_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_MAX_STATE, + p->cdev_max_state)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_cdev_delete(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID, p->cdev_id)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_cdev_state_update(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID, + p->cdev_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_CUR_STATE, + p->cdev_state)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_gov_change(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_string(p->msg, THERMAL_GENL_ATTR_GOV_NAME, p->name)) + return -EMSGSIZE; + + return 0; +} + +int thermal_genl_event_tz_delete(struct param *p) + __attribute__((alias("thermal_genl_event_tz"))); + +int thermal_genl_event_tz_enable(struct param *p) + __attribute__((alias("thermal_genl_event_tz"))); + +int thermal_genl_event_tz_disable(struct param *p) + __attribute__((alias("thermal_genl_event_tz"))); + +int thermal_genl_event_tz_trip_down(struct param *p) + __attribute__((alias("thermal_genl_event_tz_trip_up"))); + +int thermal_genl_event_tz_trip_change(struct param *p) + __attribute__((alias("thermal_genl_event_tz_trip_add"))); + +static cb_t event_cb[] = { + [THERMAL_GENL_EVENT_TZ_CREATE] = thermal_genl_event_tz_create, + [THERMAL_GENL_EVENT_TZ_DELETE] = thermal_genl_event_tz_delete, + [THERMAL_GENL_EVENT_TZ_ENABLE] = thermal_genl_event_tz_enable, + [THERMAL_GENL_EVENT_TZ_DISABLE] = thermal_genl_event_tz_disable, + [THERMAL_GENL_EVENT_TZ_TRIP_UP] = thermal_genl_event_tz_trip_up, + [THERMAL_GENL_EVENT_TZ_TRIP_DOWN] = thermal_genl_event_tz_trip_down, + [THERMAL_GENL_EVENT_TZ_TRIP_CHANGE] = thermal_genl_event_tz_trip_change, + [THERMAL_GENL_EVENT_TZ_TRIP_ADD] = thermal_genl_event_tz_trip_add, + [THERMAL_GENL_EVENT_TZ_TRIP_DELETE] = thermal_genl_event_tz_trip_delete, + [THERMAL_GENL_EVENT_CDEV_ADD] = thermal_genl_event_cdev_add, + [THERMAL_GENL_EVENT_CDEV_DELETE] = thermal_genl_event_cdev_delete, + [THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = thermal_genl_event_cdev_state_update, + [THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = thermal_genl_event_gov_change, +}; + +/* + * Generic netlink event encoding + */ +static int thermal_genl_send_event(enum thermal_genl_event event, + struct param *p) +{ + struct sk_buff *msg; + int ret = -EMSGSIZE; + void *hdr; + + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + p->msg = msg; + + hdr = genlmsg_put(msg, 0, 0, &thermal_gnl_family, 0, event); + if (!hdr) + goto out_free_msg; + + ret = event_cb[event](p); + if (ret) + goto out_cancel_msg; + + genlmsg_end(msg, hdr); + + genlmsg_multicast(&thermal_gnl_family, msg, 0, 1, GFP_KERNEL); + + return 0; + +out_cancel_msg: + genlmsg_cancel(msg, hdr); +out_free_msg: + nlmsg_free(msg); + + return ret; +} + +int thermal_notify_tz_create(int tz_id, const char *name) +{ + struct param p = { .tz_id = tz_id, .name = name }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_CREATE, &p); +} + +int thermal_notify_tz_delete(int tz_id) +{ + struct param p = { .tz_id = tz_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_DELETE, &p); +} + +int thermal_notify_tz_enable(int tz_id) +{ + struct param p = { .tz_id = tz_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_ENABLE, &p); +} + +int thermal_notify_tz_disable(int tz_id) +{ + struct param p = { .tz_id = tz_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_DISABLE, &p); +} + +int thermal_notify_tz_trip_down(int tz_id, int trip_id) +{ + struct param p = { .tz_id = tz_id, .trip_id = trip_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_DOWN, &p); +} + +int thermal_notify_tz_trip_up(int tz_id, int trip_id) +{ + struct param p = { .tz_id = tz_id, .trip_id = trip_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_UP, &p); +} + +int thermal_notify_tz_trip_add(int tz_id, int trip_id, int trip_type, + int trip_temp, int trip_hyst) +{ + struct param p = { .tz_id = tz_id, .trip_id = trip_id, + .trip_type = trip_type, .trip_temp = trip_temp, + .trip_hyst = trip_hyst }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_ADD, &p); +} + +int thermal_notify_tz_trip_delete(int tz_id, int trip_id) +{ + struct param p = { .tz_id = tz_id, .trip_id = trip_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_DELETE, &p); +} + +int thermal_notify_tz_trip_change(int tz_id, int trip_id, int trip_type, + int trip_temp, int trip_hyst) +{ + struct param p = { .tz_id = tz_id, .trip_id = trip_id, + .trip_type = trip_type, .trip_temp = trip_temp, + .trip_hyst = trip_hyst }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_CHANGE, &p); +} + +int thermal_notify_cdev_state_update(int cdev_id, int cdev_state) +{ + struct param p = { .cdev_id = cdev_id, .cdev_state = cdev_state }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_STATE_UPDATE, &p); +} + +int thermal_notify_cdev_add(int cdev_id, const char *name, int cdev_max_state) +{ + struct param p = { .cdev_id = cdev_id, .name = name, + .cdev_max_state = cdev_max_state }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_ADD, &p); +} + +int thermal_notify_cdev_delete(int cdev_id) +{ + struct param p = { .cdev_id = cdev_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_DELETE, &p); +} + +int thermal_notify_tz_gov_change(int tz_id, const char *name) +{ + struct param p = { .tz_id = tz_id, .name = name }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_GOV_CHANGE, &p); +} + +/*************************** Command encoding ********************************/ + +static int __thermal_genl_cmd_tz_get_id(struct thermal_zone_device *tz, + void *data) +{ + struct sk_buff *msg = data; + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, tz->id) || + nla_put_string(msg, THERMAL_GENL_ATTR_TZ_NAME, tz->type)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_cmd_tz_get_id(struct param *p) +{ + struct sk_buff *msg = p->msg; + struct nlattr *start_tz; + int ret; + + start_tz = nla_nest_start(msg, THERMAL_GENL_ATTR_TZ); + if (!start_tz) + return -EMSGSIZE; + + ret = for_each_thermal_zone(__thermal_genl_cmd_tz_get_id, msg); + if (ret) + goto out_cancel_nest; + + nla_nest_end(msg, start_tz); + + return 0; + +out_cancel_nest: + nla_nest_cancel(msg, start_tz); + + return ret; +} + +static int thermal_genl_cmd_tz_get_trip(struct param *p) +{ + struct sk_buff *msg = p->msg; + struct thermal_zone_device *tz; + struct nlattr *start_trip; + int i, id; + + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) + return -EINVAL; + + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); + + tz = thermal_zone_get_by_id(id); + if (!tz) + return -EINVAL; + + start_trip = nla_nest_start(msg, THERMAL_GENL_ATTR_TZ_TRIP); + if (!start_trip) + return -EMSGSIZE; + + mutex_lock(&tz->lock); + + for (i = 0; i < tz->trips; i++) { + + enum thermal_trip_type type; + int temp, hyst; + + tz->ops->get_trip_type(tz, i, &type); + tz->ops->get_trip_temp(tz, i, &temp); + tz->ops->get_trip_hyst(tz, i, &hyst); + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, i) || + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, type) || + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, temp) || + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, hyst)) + goto out_cancel_nest; + } + + mutex_unlock(&tz->lock); + + nla_nest_end(msg, start_trip); + + return 0; + +out_cancel_nest: + mutex_unlock(&tz->lock); + + return -EMSGSIZE; +} + +static int thermal_genl_cmd_tz_get_temp(struct param *p) +{ + struct sk_buff *msg = p->msg; + struct thermal_zone_device *tz; + int temp, ret, id; + + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) + return -EINVAL; + + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); + + tz = thermal_zone_get_by_id(id); + if (!tz) + return -EINVAL; + + ret = thermal_zone_get_temp(tz, &temp); + if (ret) + return ret; + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id) || + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TEMP, temp)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_cmd_tz_get_gov(struct param *p) +{ + struct sk_buff *msg = p->msg; + struct thermal_zone_device *tz; + int id, ret = 0; + + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) + return -EINVAL; + + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); + + tz = thermal_zone_get_by_id(id); + if (!tz) + return -EINVAL; + + mutex_lock(&tz->lock); + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id) || + nla_put_string(msg, THERMAL_GENL_ATTR_TZ_GOV_NAME, + tz->governor->name)) + ret = -EMSGSIZE; + + mutex_unlock(&tz->lock); + + return ret; +} + +static int __thermal_genl_cmd_cdev_get(struct thermal_cooling_device *cdev, + void *data) +{ + struct sk_buff *msg = data; + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_CDEV_ID, cdev->id)) + return -EMSGSIZE; + + if (nla_put_string(msg, THERMAL_GENL_ATTR_CDEV_NAME, cdev->type)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_cmd_cdev_get(struct param *p) +{ + struct sk_buff *msg = p->msg; + struct nlattr *start_cdev; + int ret; + + start_cdev = nla_nest_start(msg, THERMAL_GENL_ATTR_CDEV); + if (!start_cdev) + return -EMSGSIZE; + + ret = for_each_thermal_cooling_device(__thermal_genl_cmd_cdev_get, msg); + if (ret) + goto out_cancel_nest; + + nla_nest_end(msg, start_cdev); + + return 0; +out_cancel_nest: + nla_nest_cancel(msg, start_cdev); + + return ret; +} + +static cb_t cmd_cb[] = { + [THERMAL_GENL_CMD_TZ_GET_ID] = thermal_genl_cmd_tz_get_id, + [THERMAL_GENL_CMD_TZ_GET_TRIP] = thermal_genl_cmd_tz_get_trip, + [THERMAL_GENL_CMD_TZ_GET_TEMP] = thermal_genl_cmd_tz_get_temp, + [THERMAL_GENL_CMD_TZ_GET_GOV] = thermal_genl_cmd_tz_get_gov, + [THERMAL_GENL_CMD_CDEV_GET] = thermal_genl_cmd_cdev_get, +}; + +static int thermal_genl_cmd_dumpit(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct param p = { .msg = skb }; + const struct genl_dumpit_info *info = genl_dumpit_info(cb); + int cmd = info->ops->cmd; + int ret; + void *hdr; + + hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0, cmd); + if (!hdr) + return -EMSGSIZE; + + ret = cmd_cb[cmd](&p); + if (ret) + goto out_cancel_msg; + + genlmsg_end(skb, hdr); + + return 0; + +out_cancel_msg: + genlmsg_cancel(skb, hdr); + + return ret; +} + +static int thermal_genl_cmd_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct param p = { .attrs = info->attrs }; + struct sk_buff *msg; + void *hdr; + int cmd = info->genlhdr->cmd; + int ret = -EMSGSIZE; + + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + p.msg = msg; + + hdr = genlmsg_put_reply(msg, info, &thermal_gnl_family, 0, cmd); + if (!hdr) + goto out_free_msg; + + ret = cmd_cb[cmd](&p); + if (ret) + goto out_cancel_msg; + + genlmsg_end(msg, hdr); + + return genlmsg_reply(msg, info); + +out_cancel_msg: + genlmsg_cancel(msg, hdr); +out_free_msg: + nlmsg_free(msg); + + return ret; +} + +static const struct genl_ops thermal_genl_ops[] = { + { + .cmd = THERMAL_GENL_CMD_TZ_GET_ID, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .dumpit = thermal_genl_cmd_dumpit, + }, + { + .cmd = THERMAL_GENL_CMD_TZ_GET_TRIP, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = thermal_genl_cmd_doit, + }, + { + .cmd = THERMAL_GENL_CMD_TZ_GET_TEMP, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = thermal_genl_cmd_doit, + }, + { + .cmd = THERMAL_GENL_CMD_TZ_GET_GOV, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = thermal_genl_cmd_doit, + }, + { + .cmd = THERMAL_GENL_CMD_CDEV_GET, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .dumpit = thermal_genl_cmd_dumpit, + }, +}; + +static struct genl_family thermal_gnl_family __ro_after_init = { + .hdrsize = 0, + .name = THERMAL_GENL_FAMILY_NAME, + .version = THERMAL_GENL_VERSION, + .maxattr = THERMAL_GENL_ATTR_MAX, + .policy = thermal_genl_policy, + .ops = thermal_genl_ops, + .n_ops = ARRAY_SIZE(thermal_genl_ops), + .mcgrps = thermal_genl_mcgrps, + .n_mcgrps = ARRAY_SIZE(thermal_genl_mcgrps), +}; + +int __init thermal_netlink_init(void) +{ + return genl_register_family(&thermal_gnl_family); +} diff --git a/drivers/thermal/thermal_netlink.h b/drivers/thermal/thermal_netlink.h new file mode 100644 index 0000000000000000000000000000000000000000..828d1dddfa98b5677628748542bea40c7d7e71bd --- /dev/null +++ b/drivers/thermal/thermal_netlink.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Linaro Ltd 2020 + * Author: Daniel Lezcano + */ + +/* Netlink notification function */ +#ifdef CONFIG_THERMAL_NETLINK +int __init thermal_netlink_init(void); +int thermal_notify_tz_create(int tz_id, const char *name); +int thermal_notify_tz_delete(int tz_id); +int thermal_notify_tz_enable(int tz_id); +int thermal_notify_tz_disable(int tz_id); +int thermal_notify_tz_trip_down(int tz_id, int id); +int thermal_notify_tz_trip_up(int tz_id, int id); +int thermal_notify_tz_trip_delete(int tz_id, int id); +int thermal_notify_tz_trip_add(int tz_id, int id, int type, + int temp, int hyst); +int thermal_notify_tz_trip_change(int tz_id, int id, int type, + int temp, int hyst); +int thermal_notify_cdev_state_update(int cdev_id, int state); +int thermal_notify_cdev_add(int cdev_id, const char *name, int max_state); +int thermal_notify_cdev_delete(int cdev_id); +int thermal_notify_tz_gov_change(int tz_id, const char *name); +int thermal_genl_sampling_temp(int id, int temp); +#else +static inline int thermal_netlink_init(void) +{ + return 0; +} + +static inline int thermal_notify_tz_create(int tz_id, const char *name) +{ + return 0; +} + +static inline int thermal_notify_tz_delete(int tz_id) +{ + return 0; +} + +static inline int thermal_notify_tz_enable(int tz_id) +{ + return 0; +} + +static inline int thermal_notify_tz_disable(int tz_id) +{ + return 0; +} + +static inline int thermal_notify_tz_trip_down(int tz_id, int id) +{ + return 0; +} + +static inline int thermal_notify_tz_trip_up(int tz_id, int id) +{ + return 0; +} + +static inline int thermal_notify_tz_trip_delete(int tz_id, int id) +{ + return 0; +} + +static inline int thermal_notify_tz_trip_add(int tz_id, int id, int type, + int temp, int hyst) +{ + return 0; +} + +static inline int thermal_notify_tz_trip_change(int tz_id, int id, int type, + int temp, int hyst) +{ + return 0; +} + +static inline int thermal_notify_cdev_state_update(int cdev_id, int state) +{ + return 0; +} + +static inline int thermal_notify_cdev_add(int cdev_id, const char *name, + int max_state) +{ + return 0; +} + +static inline int thermal_notify_cdev_delete(int cdev_id) +{ + return 0; +} + +static inline int thermal_notify_tz_gov_change(int tz_id, const char *name) +{ + return 0; +} + +static inline int thermal_genl_sampling_temp(int id, int temp) +{ + return 0; +} +#endif /* CONFIG_THERMAL_NETLINK */ diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index ddf88dbe7ba2934721c240811b22e3a6930210c3..69ef12f852b7d56c6251dc0834e3873c7df6b6a2 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -51,7 +51,6 @@ struct __thermal_bind_params { /** * struct __thermal_zone - internal representation of a thermal zone - * @mode: current thermal zone device mode (enabled/disabled) * @passive_delay: polling interval while passive cooling is activated * @polling_delay: zone polling interval * @slope: slope of the temperature adjustment curve @@ -65,7 +64,6 @@ struct __thermal_bind_params { */ struct __thermal_zone { - enum thermal_device_mode mode; int passive_delay; int polling_delay; int slope; @@ -269,39 +267,6 @@ static int of_thermal_unbind(struct thermal_zone_device *thermal, return 0; } -static int of_thermal_get_mode(struct thermal_zone_device *tz, - enum thermal_device_mode *mode) -{ - struct __thermal_zone *data = tz->devdata; - - *mode = data->mode; - - return 0; -} - -static int of_thermal_set_mode(struct thermal_zone_device *tz, - enum thermal_device_mode mode) -{ - struct __thermal_zone *data = tz->devdata; - - mutex_lock(&tz->lock); - - if (mode == THERMAL_DEVICE_ENABLED) { - tz->polling_delay = data->polling_delay; - tz->passive_delay = data->passive_delay; - } else { - tz->polling_delay = 0; - tz->passive_delay = 0; - } - - mutex_unlock(&tz->lock); - - data->mode = mode; - thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); - - return 0; -} - static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip, enum thermal_trip_type *type) { @@ -393,9 +358,6 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz, } static struct thermal_zone_device_ops of_thermal_ops = { - .get_mode = of_thermal_get_mode, - .set_mode = of_thermal_set_mode, - .get_trip_type = of_thermal_get_trip_type, .get_trip_temp = of_thermal_get_trip_temp, .set_trip_temp = of_thermal_set_trip_temp, @@ -554,7 +516,7 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data, tzd = thermal_zone_of_add_sensor(child, sensor_np, data, ops); if (!IS_ERR(tzd)) - tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED); + thermal_zone_device_enable(tzd); of_node_put(child); goto exit; @@ -979,7 +941,6 @@ __init *thermal_of_build_thermal_zone(struct device_node *np) finish: of_node_put(child); - tz->mode = THERMAL_DEVICE_DISABLED; return tz; diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index aa99edb4dff7dca35439ed9536dee82f1e1c5b8c..8c231219e15dd088699ce6fb2c1a113db1351f9a 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -49,18 +49,9 @@ static ssize_t mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct thermal_zone_device *tz = to_thermal_zone(dev); - enum thermal_device_mode mode; - int result; - - if (!tz->ops->get_mode) - return -EPERM; + int enabled = thermal_zone_device_is_enabled(tz); - result = tz->ops->get_mode(tz, &mode); - if (result) - return result; - - return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled" - : "disabled"); + return sprintf(buf, "%s\n", enabled ? "enabled" : "disabled"); } static ssize_t @@ -70,13 +61,10 @@ mode_store(struct device *dev, struct device_attribute *attr, struct thermal_zone_device *tz = to_thermal_zone(dev); int result; - if (!tz->ops->set_mode) - return -EPERM; - if (!strncmp(buf, "enabled", sizeof("enabled") - 1)) - result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED); + result = thermal_zone_device_enable(tz); else if (!strncmp(buf, "disabled", sizeof("disabled") - 1)) - result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED); + result = thermal_zone_device_disable(tz); else result = -EINVAL; @@ -124,7 +112,8 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, { struct thermal_zone_device *tz = to_thermal_zone(dev); int trip, ret; - int temperature; + int temperature, hyst = 0; + enum thermal_trip_type type; if (!tz->ops->set_trip_temp) return -EPERM; @@ -139,6 +128,18 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, if (ret) return ret; + if (tz->ops->get_trip_hyst) { + ret = tz->ops->get_trip_hyst(tz, trip, &hyst); + if (ret) + return ret; + } + + ret = tz->ops->get_trip_type(tz, trip, &type); + if (ret) + return ret; + + thermal_notify_tz_trip_change(tz->id, trip, type, temperature, hyst); + thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); return count; @@ -428,30 +429,13 @@ static struct attribute_group thermal_zone_attribute_group = { .attrs = thermal_zone_dev_attrs, }; -/* We expose mode only if .get_mode is present */ static struct attribute *thermal_zone_mode_attrs[] = { &dev_attr_mode.attr, NULL, }; -static umode_t thermal_zone_mode_is_visible(struct kobject *kobj, - struct attribute *attr, - int attrno) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct thermal_zone_device *tz; - - tz = container_of(dev, struct thermal_zone_device, device); - - if (tz->ops->get_mode) - return attr->mode; - - return 0; -} - static struct attribute_group thermal_zone_mode_attribute_group = { .attrs = thermal_zone_mode_attrs, - .is_visible = thermal_zone_mode_is_visible, }; /* We expose passive only if passive trips are present */ diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index 85776db4bf3461d112926cd47487dd3269a54fe7..2ce4b19f312ac66724788dc9f1f628ffb3ea6f01 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -169,7 +169,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, data = ti_bandgap_get_sensor_data(bgp, id); - if (!IS_ERR_OR_NULL(data)) + if (IS_ERR_OR_NULL(data)) data = ti_thermal_build_data(bgp, id); if (!data) diff --git a/drivers/tty/moxa.h b/drivers/tty/moxa.h index 563d2dce80b3cd98e7b18a9179c413ca9ac9b70d..f0a4381b6861456ca812e599b0450518c2b10fa8 100644 --- a/drivers/tty/moxa.h +++ b/drivers/tty/moxa.h @@ -138,7 +138,7 @@ #define IntrQuit 0x40 /* received QUIT code */ #define IntrEOF 0x80 /* received EOF code */ -#define IntrRxTrigger 0x100 /* rx data count reach tigger value */ +#define IntrRxTrigger 0x100 /* rx data count reach trigger value */ #define IntrTxTrigger 0x200 /* tx data count below trigger value */ #define Magic_no (Config_base + 0) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index aab3cccc6789dac9dd2f7ca3a5545a3be2ef3734..87f450b7c1779ae9da2cc8ad71aa1ab5a6792c46 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -43,6 +45,8 @@ struct dw8250_data { int msr_mask_off; struct clk *clk; struct clk *pclk; + struct notifier_block clk_notifier; + struct work_struct clk_work; struct reset_control *rst; unsigned int skip_autocfg:1; @@ -54,6 +58,16 @@ static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data) return container_of(data, struct dw8250_data, data); } +static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb) +{ + return container_of(nb, struct dw8250_data, clk_notifier); +} + +static inline struct dw8250_data *work_to_dw8250_data(struct work_struct *work) +{ + return container_of(work, struct dw8250_data, clk_work); +} + static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) { struct dw8250_data *d = to_dw8250_data(p->private_data); @@ -260,6 +274,46 @@ static int dw8250_handle_irq(struct uart_port *p) return 0; } +static void dw8250_clk_work_cb(struct work_struct *work) +{ + struct dw8250_data *d = work_to_dw8250_data(work); + struct uart_8250_port *up; + unsigned long rate; + + rate = clk_get_rate(d->clk); + if (rate <= 0) + return; + + up = serial8250_get_port(d->data.line); + + serial8250_update_uartclk(&up->port, rate); +} + +static int dw8250_clk_notifier_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct dw8250_data *d = clk_to_dw8250_data(nb); + + /* + * We have no choice but to defer the uartclk update due to two + * deadlocks. First one is caused by a recursive mutex lock which + * happens when clk_set_rate() is called from dw8250_set_termios(). + * Second deadlock is more tricky and is caused by an inverted order of + * the clk and tty-port mutexes lock. It happens if clock rate change + * is requested asynchronously while set_termios() is executed between + * tty-port mutex lock and clk_set_rate() function invocation and + * vise-versa. Anyway if we didn't have the reference clock alteration + * in the dw8250_set_termios() method we wouldn't have needed this + * deferred event handling complication. + */ + if (event == POST_RATE_CHANGE) { + queue_work(system_unbound_wq, &d->clk_work); + return NOTIFY_OK; + } + + return NOTIFY_DONE; +} + static void dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) { @@ -275,27 +329,27 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old) { - unsigned int baud = tty_termios_baud_rate(termios); + unsigned long newrate = tty_termios_baud_rate(termios) * 16; struct dw8250_data *d = to_dw8250_data(p->private_data); long rate; int ret; clk_disable_unprepare(d->clk); - rate = clk_round_rate(d->clk, baud * 16); - if (rate < 0) - ret = rate; - else if (rate == 0) - ret = -ENOENT; - else - ret = clk_set_rate(d->clk, rate); + rate = clk_round_rate(d->clk, newrate); + if (rate > 0) { + /* + * Premilinary set the uartclk to the new clock rate so the + * clock update event handler caused by the clk_set_rate() + * calling wouldn't actually update the UART divisor since + * we about to do this anyway. + */ + swap(p->uartclk, rate); + ret = clk_set_rate(d->clk, newrate); + if (ret) + swap(p->uartclk, rate); + } clk_prepare_enable(d->clk); - if (ret) - goto out; - - p->uartclk = rate; - -out: p->status &= ~UPSTAT_AUTOCTS; if (termios->c_cflag & CRTSCTS) p->status |= UPSTAT_AUTOCTS; @@ -319,6 +373,39 @@ static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios) serial8250_do_set_ldisc(p, termios); } +static int dw8250_startup(struct uart_port *p) +{ + struct dw8250_data *d = to_dw8250_data(p->private_data); + int ret; + + /* + * Some platforms may provide a reference clock shared between several + * devices. In this case before using the serial port first we have to + * make sure that any clock state change is known to the UART port at + * least post factum. + */ + if (d->clk) { + ret = clk_notifier_register(d->clk, &d->clk_notifier); + if (ret) + dev_warn(p->dev, "Failed to set the clock notifier\n"); + } + + return serial8250_do_startup(p); +} + +static void dw8250_shutdown(struct uart_port *p) +{ + struct dw8250_data *d = to_dw8250_data(p->private_data); + + serial8250_do_shutdown(p); + + if (d->clk) { + clk_notifier_unregister(d->clk, &d->clk_notifier); + + flush_work(&d->clk_work); + } +} + /* * dw8250_fallback_dma_filter will prevent the UART from getting just any free * channel on platforms that have DMA engines, but don't have any channels @@ -414,6 +501,8 @@ static int dw8250_probe(struct platform_device *pdev) p->serial_out = dw8250_serial_out; p->set_ldisc = dw8250_set_ldisc; p->set_termios = dw8250_set_termios; + p->startup = dw8250_startup; + p->shutdown = dw8250_shutdown; p->membase = devm_ioremap(dev, regs->start, resource_size(regs)); if (!p->membase) @@ -475,6 +564,9 @@ static int dw8250_probe(struct platform_device *pdev) if (IS_ERR(data->clk)) return PTR_ERR(data->clk); + INIT_WORK(&data->clk_work, dw8250_clk_work_cb); + data->clk_notifier.notifier_call = dw8250_clk_notifier_cb; + err = clk_prepare_enable(data->clk); if (err) dev_warn(dev, "could not enable optional baudclk: %d\n", err); diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c index 2a76e22d2ec046158d5ad4d1d689b5b7098c3de6..db88dee3a3999a34fcdff1ccc193e315e1dc219c 100644 --- a/drivers/tty/serial/8250/8250_em.c +++ b/drivers/tty/serial/8250/8250_em.c @@ -78,14 +78,18 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value) static int serial8250_em_probe(struct platform_device *pdev) { - struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct serial8250_em_priv *priv; struct uart_8250_port up; - int ret; + struct resource *regs; + int irq, ret; - if (!regs || !irq) { - dev_err(&pdev->dev, "missing registers or irq\n"); + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "missing registers\n"); return -EINVAL; } @@ -101,7 +105,7 @@ static int serial8250_em_probe(struct platform_device *pdev) memset(&up, 0, sizeof(up)); up.port.mapbase = regs->start; - up.port.irq = irq->start; + up.port.irq = irq; up.port.type = PORT_UNKNOWN; up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP; up.port.dev = &pdev->dev; diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index 424c07c5f6299beb2d06009d86278be15fcaabe7..dde766fa465ffaab3b9acf6242d48d93465ac84a 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -207,12 +207,11 @@ static unsigned int ingenic_uart_serial_in(struct uart_port *p, int offset) static int ingenic_uart_probe(struct platform_device *pdev) { struct uart_8250_port uart = {}; - struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct ingenic_uart_data *data; const struct ingenic_uart_config *cdata; const struct of_device_id *match; - int err, line; + struct resource *regs; + int irq, err, line; match = of_match_device(of_match, &pdev->dev); if (!match) { @@ -221,8 +220,13 @@ static int ingenic_uart_probe(struct platform_device *pdev) } cdata = match->data; - if (!regs || !irq) { - dev_err(&pdev->dev, "no registers/irq defined\n"); + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "no registers defined\n"); return -EINVAL; } @@ -238,7 +242,7 @@ static int ingenic_uart_probe(struct platform_device *pdev) uart.port.regshift = 2; uart.port.serial_out = ingenic_uart_serial_out; uart.port.serial_in = ingenic_uart_serial_in; - uart.port.irq = irq->start; + uart.port.irq = irq; uart.port.dev = &pdev->dev; uart.port.fifosize = cdata->fifosize; uart.tx_loadsz = cdata->tx_loadsz; diff --git a/drivers/tty/serial/8250/8250_men_mcb.c b/drivers/tty/serial/8250/8250_men_mcb.c index e985f344b2dd3197b5dac0d05ef027651ff14fe5..737c4c31e8a05c82d72ce110bf88d7c59a72f090 100644 --- a/drivers/tty/serial/8250/8250_men_mcb.c +++ b/drivers/tty/serial/8250/8250_men_mcb.c @@ -51,7 +51,7 @@ static u32 men_lookup_uartclk(struct mcb_device *mdev) return clkval; } -static unsigned int get_num_ports(struct mcb_device *mdev, +static int get_num_ports(struct mcb_device *mdev, void __iomem *membase) { switch (mdev->id) { @@ -140,7 +140,7 @@ static void serial_8250_men_mcb_remove(struct mcb_device *mdev) return; num_ports = get_num_ports(mdev, data[0].uart.port.membase); - if (num_ports < 0 || num_ports > 4) { + if (num_ports <= 0 || num_ports > 4) { dev_err(&mdev->dev, "error retrieving number of ports!\n"); return; } diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index 98b8a3e30733bde03c94eace68e3fcf31a94e2e8..7b0dec14c8b80cf3e612ca533d6a738608979507 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -512,13 +512,17 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p, static int mtk8250_probe(struct platform_device *pdev) { struct uart_8250_port uart = {}; - struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct mtk8250_data *data; - int err; + struct resource *regs; + int irq, err; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; - if (!regs || !irq) { - dev_err(&pdev->dev, "no registers/irq defined\n"); + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "no registers defined\n"); return -EINVAL; } @@ -542,7 +546,7 @@ static int mtk8250_probe(struct platform_device *pdev) spin_lock_init(&uart.port.lock); uart.port.mapbase = regs->start; - uart.port.irq = irq->start; + uart.port.irq = irq; uart.port.pm = mtk8250_do_pm; uart.port.type = PORT_16550; uart.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT; diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 16cfb887c5a3eba11ea3e0b0fd433c3f8e10ce6e..562087df7d334bb376d15f647c2bd35f87cd0afc 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -1209,17 +1209,21 @@ MODULE_DEVICE_TABLE(of, omap8250_dt_ids); static int omap8250_probe(struct platform_device *pdev) { - struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct device_node *np = pdev->dev.of_node; struct omap8250_priv *priv; const struct omap8250_platdata *pdata; struct uart_8250_port up; - int ret; + struct resource *regs; void __iomem *membase; + int irq, ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; - if (!regs || !irq) { - dev_err(&pdev->dev, "missing registers or irq\n"); + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "missing registers\n"); return -EINVAL; } @@ -1236,7 +1240,7 @@ static int omap8250_probe(struct platform_device *pdev) up.port.dev = &pdev->dev; up.port.mapbase = regs->start; up.port.membase = membase; - up.port.irq = irq->start; + up.port.irq = irq; /* * It claims to be 16C750 compatible however it is a little different. * It has EFR and has no FCR7_64byte bit. The AFE (which it claims to diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 1632f7d25acca98f94a6466117cfbbc643815250..09475695effd472dd027922b5642d189a23921ec 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -2631,6 +2632,46 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, (port->uartclk + tolerance) / 16); } +/* + * Note in order to avoid the tty port mutex deadlock don't use the next method + * within the uart port callbacks. Primarily it's supposed to be utilized to + * handle a sudden reference clock rate change. + */ +void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned int baud, quot, frac = 0; + struct ktermios *termios; + unsigned long flags; + + mutex_lock(&port->state->port.mutex); + + if (port->uartclk == uartclk) + goto out_lock; + + port->uartclk = uartclk; + termios = &port->state->port.tty->termios; + + baud = serial8250_get_baud_rate(port, termios, NULL); + quot = serial8250_get_divisor(port, baud, &frac); + + serial8250_rpm_get(up); + spin_lock_irqsave(&port->lock, flags); + + uart_update_timeout(port, termios->c_cflag, baud); + + serial8250_set_divisor(port, baud, quot, frac); + serial_port_out(port, UART_LCR, up->lcr); + serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS); + + spin_unlock_irqrestore(&port->lock, flags); + serial8250_rpm_put(up); + +out_lock: + mutex_unlock(&port->state->port.mutex); +} +EXPORT_SYMBOL_GPL(serial8250_update_uartclk); + void serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c index 11612d174716f4ebf0f464a990e89b422c8991dc..33ca98bfa5b37c1bfccc0e441729f4f33fce892e 100644 --- a/drivers/tty/serial/8250/8250_pxa.c +++ b/drivers/tty/serial/8250/8250_pxa.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -93,12 +92,15 @@ static int serial_pxa_probe(struct platform_device *pdev) { struct uart_8250_port uart = {}; struct pxa8250_data *data; - struct resource *mmres, *irqres; - int ret; + struct resource *mmres; + int irq, ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!mmres || !irqres) + if (!mmres) return -ENODEV; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); @@ -121,7 +123,7 @@ static int serial_pxa_probe(struct platform_device *pdev) uart.port.iotype = UPIO_MEM32; uart.port.mapbase = mmres->start; uart.port.regshift = 2; - uart.port.irq = irqres->start; + uart.port.irq = irq; uart.port.fifosize = 64; uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE; uart.port.dev = &pdev->dev; diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index d2ae033aea40315968daffe83864b6f46f673f3c..603137da47363bda89a2778badeb38b84be81374 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -222,7 +222,7 @@ config SERIAL_8250_MANY_PORTS Say Y here if you have dumb serial boards other than the four standard COM 1/2/3/4 ports. This may happen if you have an AST FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available - from ), or other custom + from ), or other custom serial port hardware which acts similar to standard serial port hardware. If you only use the standard COM 1/2/3/4 ports, you can say N here to save some memory. You can also say Y if you have an @@ -266,7 +266,7 @@ config SERIAL_8250_BOCA depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS help Say Y here if you have a Boca serial board. Please read the Boca - mini-HOWTO, available from + mini-HOWTO, available from To compile this driver as a module, choose M here: the module will be called 8250_boca. diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 780908d435577e7de79a2f5b4df3a32b1699d729..8a0352eb337c84ea5c9dd318edd7726b3946f583 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -502,20 +502,27 @@ config SERIAL_IMX can enable its onboard serial port by enabling this option. config SERIAL_IMX_CONSOLE - bool "Console on IMX serial port" - depends on SERIAL_IMX=y + tristate "Console on IMX serial port" + depends on SERIAL_IMX select SERIAL_CORE_CONSOLE - select SERIAL_EARLYCON if OF help If you have enabled the serial port on the Freescale IMX - CPU you can make it the console by answering Y to this option. + CPU you can make it the console by answering Y/M to this option. - Even if you say Y here, the currently visible virtual console + Even if you say Y/M here, the currently visible virtual console (/dev/tty0) will still be used as the system console by default, but you can alter that using a kernel command line option such as "console=ttymxc0". (Try "man bootparam" or see the documentation of your bootloader about how to pass options to the kernel at boot time.) +config SERIAL_IMX_EARLYCON + bool "Earlycon on IMX serial port" + depends on OF + select SERIAL_EARLYCON + help + If you have enabled the earlycon on the Freescale IMX + CPU you can make it the earlycon by answering Y to this option. + config SERIAL_UARTLITE tristate "Xilinx uartlite serial port support" depends on HAS_IOMEM diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c index c90e503d6b57e658b2b76d470296c5fcf20106da..d0ca9cf29b62ff24566c43e6e04eb6f5d1d0ab75 100644 --- a/drivers/tty/serial/altera_jtaguart.c +++ b/drivers/tty/serial/altera_jtaguart.c @@ -27,7 +27,7 @@ /* * Altera JTAG UART register definitions according to the Altera JTAG UART - * datasheet: http://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf + * datasheet: https://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf */ #define ALTERA_JTAGUART_SIZE 8 diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 8efd7c2a34fe8d27728c62e8139e7724a4460f86..c010f639298dd17a451e5606c69b525417e08529 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2607,7 +2607,6 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE); uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.line = index; - spin_lock_init(&uap->port.lock); amba_ports[index] = uap; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 90298c4030421bea9440b2a786cb2669a3de81b7..7ca64224922410715cf13921d7393f49b67eb62f 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1925,6 +1925,9 @@ static void __lpuart32_serial_setbrg(struct uart_port *port, tmp_sbr++; } + if (tmp_sbr > UARTBAUD_SBR_MASK) + continue; + if (tmp_diff <= baud_diff) { baud_diff = tmp_diff; osr = tmp_osr; diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 1265e8d86d8abbf4d1f5441aa2e8c123aabb1894..ce8c472cf385baf6c73bb4d761c04f19d541d92d 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -188,6 +189,13 @@ struct imx_uart_data { enum imx_uart_type devtype; }; +enum imx_tx_state { + OFF, + WAIT_AFTER_RTS, + SEND, + WAIT_AFTER_SEND, +}; + struct imx_port { struct uart_port port; struct timer_list timer; @@ -224,6 +232,10 @@ struct imx_port { unsigned int dma_tx_nents; unsigned int saved_reg[10]; bool context_saved; + + enum imx_tx_state tx_state; + struct hrtimer trigger_start_tx; + struct hrtimer trigger_stop_tx; }; struct imx_port_ucrs { @@ -361,7 +373,7 @@ static inline int imx_uart_is_imx6q(struct imx_port *sport) /* * Save and restore functions for UCR1, UCR2 and UCR3 registers */ -#if defined(CONFIG_SERIAL_IMX_CONSOLE) +#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE) static void imx_uart_ucrs_save(struct imx_port *sport, struct imx_port_ucrs *ucr) { @@ -400,6 +412,15 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2) mctrl_gpio_set(sport->gpios, sport->port.mctrl); } +static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec) +{ + long sec = msec / MSEC_PER_SEC; + long nsec = (msec % MSEC_PER_SEC) * 1000000; + ktime_t t = ktime_set(sec, nsec); + + hrtimer_start(hrt, t, HRTIMER_MODE_REL); +} + /* called with port.lock taken and irqs off */ static void imx_uart_start_rx(struct uart_port *port) { @@ -427,7 +448,10 @@ static void imx_uart_start_rx(struct uart_port *port) static void imx_uart_stop_tx(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; - u32 ucr1; + u32 ucr1, ucr4, usr2; + + if (sport->tx_state == OFF) + return; /* * We are maybe in the SMP context, so if the DMA TX thread is running @@ -439,21 +463,44 @@ static void imx_uart_stop_tx(struct uart_port *port) ucr1 = imx_uart_readl(sport, UCR1); imx_uart_writel(sport, ucr1 & ~UCR1_TRDYEN, UCR1); - /* in rs485 mode disable transmitter if shifter is empty */ - if (port->rs485.flags & SER_RS485_ENABLED && - imx_uart_readl(sport, USR2) & USR2_TXDC) { - u32 ucr2 = imx_uart_readl(sport, UCR2), ucr4; - if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) - imx_uart_rts_active(sport, &ucr2); - else - imx_uart_rts_inactive(sport, &ucr2); - imx_uart_writel(sport, ucr2, UCR2); + usr2 = imx_uart_readl(sport, USR2); + if (!(usr2 & USR2_TXDC)) { + /* The shifter is still busy, so retry once TC triggers */ + return; + } - imx_uart_start_rx(port); + ucr4 = imx_uart_readl(sport, UCR4); + ucr4 &= ~UCR4_TCEN; + imx_uart_writel(sport, ucr4, UCR4); - ucr4 = imx_uart_readl(sport, UCR4); - ucr4 &= ~UCR4_TCEN; - imx_uart_writel(sport, ucr4, UCR4); + /* in rs485 mode disable transmitter */ + if (port->rs485.flags & SER_RS485_ENABLED) { + if (sport->tx_state == SEND) { + sport->tx_state = WAIT_AFTER_SEND; + start_hrtimer_ms(&sport->trigger_stop_tx, + port->rs485.delay_rts_after_send); + return; + } + + if (sport->tx_state == WAIT_AFTER_RTS || + sport->tx_state == WAIT_AFTER_SEND) { + u32 ucr2; + + hrtimer_try_to_cancel(&sport->trigger_start_tx); + + ucr2 = imx_uart_readl(sport, UCR2); + if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) + imx_uart_rts_active(sport, &ucr2); + else + imx_uart_rts_inactive(sport, &ucr2); + imx_uart_writel(sport, ucr2, UCR2); + + imx_uart_start_rx(port); + + sport->tx_state = OFF; + } + } else { + sport->tx_state = OFF; } } @@ -651,28 +698,50 @@ static void imx_uart_start_tx(struct uart_port *port) if (!sport->port.x_char && uart_circ_empty(&port->state->xmit)) return; + /* + * We cannot simply do nothing here if sport->tx_state == SEND already + * because UCR1_TXMPTYEN might already have been cleared in + * imx_uart_stop_tx(), but tx_state is still SEND. + */ + if (port->rs485.flags & SER_RS485_ENABLED) { - u32 ucr2; + if (sport->tx_state == OFF) { + u32 ucr2 = imx_uart_readl(sport, UCR2); + if (port->rs485.flags & SER_RS485_RTS_ON_SEND) + imx_uart_rts_active(sport, &ucr2); + else + imx_uart_rts_inactive(sport, &ucr2); + imx_uart_writel(sport, ucr2, UCR2); - ucr2 = imx_uart_readl(sport, UCR2); - if (port->rs485.flags & SER_RS485_RTS_ON_SEND) - imx_uart_rts_active(sport, &ucr2); - else - imx_uart_rts_inactive(sport, &ucr2); - imx_uart_writel(sport, ucr2, UCR2); + if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) + imx_uart_stop_rx(port); + + sport->tx_state = WAIT_AFTER_RTS; + start_hrtimer_ms(&sport->trigger_start_tx, + port->rs485.delay_rts_before_send); + return; + } - if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) - imx_uart_stop_rx(port); + if (sport->tx_state == WAIT_AFTER_SEND + || sport->tx_state == WAIT_AFTER_RTS) { - /* - * Enable transmitter and shifter empty irq only if DMA is off. - * In the DMA case this is done in the tx-callback. - */ - if (!sport->dma_is_enabled) { - u32 ucr4 = imx_uart_readl(sport, UCR4); - ucr4 |= UCR4_TCEN; - imx_uart_writel(sport, ucr4, UCR4); + hrtimer_try_to_cancel(&sport->trigger_stop_tx); + + /* + * Enable transmitter and shifter empty irq only if DMA + * is off. In the DMA case this is done in the + * tx-callback. + */ + if (!sport->dma_is_enabled) { + u32 ucr4 = imx_uart_readl(sport, UCR4); + ucr4 |= UCR4_TCEN; + imx_uart_writel(sport, ucr4, UCR4); + } + + sport->tx_state = SEND; } + } else { + sport->tx_state = SEND; } if (!sport->dma_is_enabled) { @@ -1630,7 +1699,6 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_cflag & CRTSCTS) ucr2 &= ~UCR2_IRTS; - if (termios->c_cflag & CSTOPB) ucr2 |= UCR2_STPB; if (termios->c_cflag & PARENB) { @@ -1857,10 +1925,6 @@ static int imx_uart_rs485_config(struct uart_port *port, struct imx_port *sport = (struct imx_port *)port; u32 ucr2; - /* unimplemented */ - rs485conf->delay_rts_before_send = 0; - rs485conf->delay_rts_after_send = 0; - /* RTS is required to control the transmitter */ if (!sport->have_rtscts && !sport->have_rtsgpio) rs485conf->flags &= ~SER_RS485_ENABLED; @@ -1915,7 +1979,7 @@ static const struct uart_ops imx_uart_pops = { static struct imx_port *imx_uart_ports[UART_NR]; -#ifdef CONFIG_SERIAL_IMX_CONSOLE +#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE) static void imx_uart_console_putchar(struct uart_port *port, int ch) { struct imx_port *sport = (struct imx_port *)port; @@ -2112,39 +2176,6 @@ static struct console imx_uart_console = { #define IMX_CONSOLE &imx_uart_console -#ifdef CONFIG_OF -static void imx_uart_console_early_putchar(struct uart_port *port, int ch) -{ - struct imx_port *sport = (struct imx_port *)port; - - while (imx_uart_readl(sport, IMX21_UTS) & UTS_TXFULL) - cpu_relax(); - - imx_uart_writel(sport, ch, URTX0); -} - -static void imx_uart_console_early_write(struct console *con, const char *s, - unsigned count) -{ - struct earlycon_device *dev = con->data; - - uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar); -} - -static int __init -imx_console_early_setup(struct earlycon_device *dev, const char *opt) -{ - if (!dev->port.membase) - return -ENODEV; - - dev->con->write = imx_uart_console_early_write; - - return 0; -} -OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup); -OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup); -#endif - #else #define IMX_CONSOLE NULL #endif @@ -2223,6 +2254,32 @@ static void imx_uart_probe_pdata(struct imx_port *sport, sport->have_rtscts = 1; } +static enum hrtimer_restart imx_trigger_start_tx(struct hrtimer *t) +{ + struct imx_port *sport = container_of(t, struct imx_port, trigger_start_tx); + unsigned long flags; + + spin_lock_irqsave(&sport->port.lock, flags); + if (sport->tx_state == WAIT_AFTER_RTS) + imx_uart_start_tx(&sport->port); + spin_unlock_irqrestore(&sport->port.lock, flags); + + return HRTIMER_NORESTART; +} + +static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t) +{ + struct imx_port *sport = container_of(t, struct imx_port, trigger_stop_tx); + unsigned long flags; + + spin_lock_irqsave(&sport->port.lock, flags); + if (sport->tx_state == WAIT_AFTER_SEND) + imx_uart_stop_tx(&sport->port); + spin_unlock_irqrestore(&sport->port.lock, flags); + + return HRTIMER_NORESTART; +} + static int imx_uart_probe(struct platform_device *pdev) { struct imx_port *sport; @@ -2369,6 +2426,11 @@ static int imx_uart_probe(struct platform_device *pdev) clk_disable_unprepare(sport->clk_ipg); + hrtimer_init(&sport->trigger_start_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&sport->trigger_stop_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + sport->trigger_start_tx.function = imx_trigger_start_tx; + sport->trigger_stop_tx.function = imx_trigger_stop_tx; + /* * Allocate the IRQ(s) i.MX1 has three interrupts whereas later * chips only have one interrupt. @@ -2406,9 +2468,6 @@ static int imx_uart_probe(struct platform_device *pdev) } } - /* We need to initialize lock even for non-registered console */ - spin_lock_init(&sport->port.lock); - imx_uart_ports[sport->port.line] = sport; platform_set_drvdata(pdev, sport); diff --git a/drivers/tty/serial/imx_earlycon.c b/drivers/tty/serial/imx_earlycon.c new file mode 100644 index 0000000000000000000000000000000000000000..795606e1a22f963b954bf300147fbe04ea2af9b3 --- /dev/null +++ b/drivers/tty/serial/imx_earlycon.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define URTX0 0x40 /* Transmitter Register */ +#define UTS_TXFULL (1<<4) /* TxFIFO full */ +#define IMX21_UTS 0xb4 /* UART Test Register on all other i.mx*/ + +static void imx_uart_console_early_putchar(struct uart_port *port, int ch) +{ + while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL) + cpu_relax(); + + writel_relaxed(ch, port->membase + URTX0); +} + +static void imx_uart_console_early_write(struct console *con, const char *s, + unsigned count) +{ + struct earlycon_device *dev = con->data; + + uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar); +} + +static int __init +imx_console_early_setup(struct earlycon_device *dev, const char *opt) +{ + if (!dev->port.membase) + return -ENODEV; + + dev->con->write = imx_uart_console_early_write; + + return 0; +} +OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup); +OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup); + +MODULE_AUTHOR("NXP"); +MODULE_DESCRIPTION("IMX earlycon driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c index 592e51d8944ee8f24ce4587794045fa86e56b396..cd30da0ef08344a2bb0342f6c705c4e3f6438c3f 100644 --- a/drivers/tty/serial/jsm/jsm_driver.c +++ b/drivers/tty/serial/jsm/jsm_driver.c @@ -16,7 +16,7 @@ #include "jsm.h" -MODULE_AUTHOR("Digi International, http://www.digi.com"); +MODULE_AUTHOR("Digi International, https://www.digi.com"); MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("jsm"); diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index 84ffede27f230b0ae6c7d23261d8feadcc76490f..49d0c7f2b29b8f927915327025a84a555a73a7bd 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -538,7 +538,8 @@ static int __init kgdboc_earlycon_init(char *opt) if (!con) { /* - * Both earlycon and kgdboc_earlycon are initialized during * early parameter parsing. We cannot guarantee earlycon gets + * Both earlycon and kgdboc_earlycon are initialized during + * early parameter parsing. We cannot guarantee earlycon gets * in first and, in any case, on ACPI systems earlycon may * defer its own initialization (usually to somewhere within * setup_arch() ). To cope with either of these situations diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 60a9c53fa7cbf9c03e9277bb5e580596170ea9e6..87f005e5d2affddec960654ebc39efb93c601bcc 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -696,6 +696,7 @@ static void msm_enable_ms(struct uart_port *port) } static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) + __must_hold(&port->lock) { struct tty_port *tport = &port->state->port; unsigned int sr; @@ -771,6 +772,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) } static void msm_handle_rx(struct uart_port *port) + __must_hold(&port->lock) { struct tty_port *tport = &port->state->port; unsigned int sr; diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 40fa7a27722dfe2700de76ca0f136c40ef0187c9..67aca8cb9cd413ecbdc33355a00f4e60e3278854 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1857,41 +1857,24 @@ static void pch_uart_pci_remove(struct pci_dev *pdev) kfree(priv); return; } -#ifdef CONFIG_PM -static int pch_uart_pci_suspend(struct pci_dev *pdev, pm_message_t state) + +static int __maybe_unused pch_uart_pci_suspend(struct device *dev) { - struct eg20t_port *priv = pci_get_drvdata(pdev); + struct eg20t_port *priv = dev_get_drvdata(dev); uart_suspend_port(&pch_uart_driver, &priv->port); - pci_save_state(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } -static int pch_uart_pci_resume(struct pci_dev *pdev) +static int __maybe_unused pch_uart_pci_resume(struct device *dev) { - struct eg20t_port *priv = pci_get_drvdata(pdev); - int ret; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, - "%s-pci_enable_device failed(ret=%d) ", __func__, ret); - return ret; - } + struct eg20t_port *priv = dev_get_drvdata(dev); uart_resume_port(&pch_uart_driver, &priv->port); return 0; } -#else -#define pch_uart_pci_suspend NULL -#define pch_uart_pci_resume NULL -#endif static const struct pci_device_id pch_uart_pci_id[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811), @@ -1945,13 +1928,16 @@ probe_error: return ret; } +static SIMPLE_DEV_PM_OPS(pch_uart_pci_pm_ops, + pch_uart_pci_suspend, + pch_uart_pci_resume); + static struct pci_driver pch_uart_pci_driver = { .name = "pch_uart", .id_table = pch_uart_pci_id, .probe = pch_uart_pci_probe, .remove = pch_uart_pci_remove, - .suspend = pch_uart_pci_suspend, - .resume = pch_uart_pci_resume, + .driver.pm = &pch_uart_pci_pm_ops, }; static int __init pch_uart_module_init(void) diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index ba65a3bbd72a09873bbf83aca1fe5dd92874f31d..96e7aa479961c16c3733f42997d27309fc3b7d49 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -213,6 +213,7 @@ static void pmz_interrupt_control(struct uart_pmac_port *uap, int enable) } static bool pmz_receive_chars(struct uart_pmac_port *uap) + __must_hold(&uap->port.lock) { struct tty_port *port; unsigned char ch, r1, drop, flag; diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 07b7b6b05b8b2dcfc511729475b5c1ea0b35f61b..3aa29d201f54d38e1d24f63b883679d4a50ffa9a 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -768,7 +768,7 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, u8 buf[sizeof(u32)]; int c; - memset(buf, 0, ARRAY_SIZE(buf)); + memset(buf, 0, sizeof(buf)); tx_bytes = min_t(size_t, remaining, BYTES_PER_FIFO_WORD); for (c = 0; c < tx_bytes ; c++) { diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index d913d9b2762a645ba98031a90b9401729b7ea773..8ed3482d2e1ebd44616e7e3dc060c6fd3734b7bc 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -6,7 +6,7 @@ * http://armlinux.simtec.co.uk/ */ -/* Hote on 2410 error handling +/* Note on 2410 error handling * * The s3c2410 manual has a love/hate affair with the contents of the * UERSTAT register in the UART blocks, and keeps marking some of the @@ -327,7 +327,6 @@ static void s3c24xx_serial_tx_dma_complete(void *args) unsigned long flags; int count; - dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); count = dma->tx_bytes_requested - state.residue; async_tx_ack(dma->tx_desc); @@ -409,7 +408,6 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, struct circ_buf *xmit = &port->state->xmit; struct s3c24xx_uart_dma *dma = ourport->dma; - if (ourport->tx_mode != S3C24XX_TX_DMA) enable_tx_dma(ourport); @@ -816,7 +814,6 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id) return IRQ_HANDLED; } - static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id) { struct s3c24xx_uart_port *ourport = dev_id; @@ -842,8 +839,8 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) count >= ourport->min_dma_size) { int align = dma_get_cache_alignment() - (xmit->tail & (dma_get_cache_alignment() - 1)); - if (count-align >= ourport->min_dma_size) { - dma_count = count-align; + if (count - align >= ourport->min_dma_size) { + dma_count = count - align; count = align; } } @@ -1589,7 +1586,6 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser) return 0; } - #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE static struct console s3c24xx_serial_console; @@ -1672,7 +1668,6 @@ s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = { } }, #if CONFIG_SERIAL_SAMSUNG_UARTS > 2 - [2] = { .port = { .lock = __PORT_LOCK_UNLOCKED(2), @@ -1728,7 +1723,6 @@ static void s3c24xx_serial_resetport(struct uart_port *port, udelay(1); } - #ifdef CONFIG_ARM_S3C24XX_CPUFREQ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb, @@ -1903,9 +1897,9 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, port->mapbase = res->start; ret = platform_get_irq(platdev, 0); - if (ret < 0) + if (ret < 0) { port->irq = 0; - else { + } else { port->irq = ret; ourport->rx_irq = ret; ourport->tx_irq = ret + 1; @@ -1977,8 +1971,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[]; static int probe_index; -static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data( - struct platform_device *pdev) +static inline struct s3c24xx_serial_drv_data * +s3c24xx_get_driver_data(struct platform_device *pdev) { #ifdef CONFIG_OF if (pdev->dev.of_node) { @@ -2329,7 +2323,6 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, *baud = rate / (16 * (ubrdiv + 1)); dev_dbg(port->dev, "calculated baud %d\n", *baud); } - } static int __init @@ -2696,6 +2689,7 @@ static int __init s3c2410_early_console_setup(struct earlycon_device *device, device->port.private_data = &s3c2410_early_console_data; return samsung_early_console_setup(device, opt); } + OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart", s3c2410_early_console_setup); @@ -2710,6 +2704,7 @@ static int __init s3c2440_early_console_setup(struct earlycon_device *device, device->port.private_data = &s3c2440_early_console_data; return samsung_early_console_setup(device, opt); } + OF_EARLYCON_DECLARE(s3c2412, "samsung,s3c2412-uart", s3c2440_early_console_setup); OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart", @@ -2728,6 +2723,7 @@ static int __init s5pv210_early_console_setup(struct earlycon_device *device, device->port.private_data = &s5pv210_early_console_data; return samsung_early_console_setup(device, opt); } + OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart", s5pv210_early_console_setup); OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart", diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index 04d1b0807e664c71248ed2f82b574dbbd0b88a33..b87914ae6da8f27de4f430affd7225e3776b6126 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -439,16 +439,16 @@ static char tegra_uart_decode_rx_error(struct tegra_uart_port *tup, /* Overrrun error */ flag = TTY_OVERRUN; tup->uport.icount.overrun++; - dev_err(tup->uport.dev, "Got overrun errors\n"); + dev_dbg(tup->uport.dev, "Got overrun errors\n"); } else if (lsr & UART_LSR_PE) { /* Parity error */ flag = TTY_PARITY; tup->uport.icount.parity++; - dev_err(tup->uport.dev, "Got Parity errors\n"); + dev_dbg(tup->uport.dev, "Got Parity errors\n"); } else if (lsr & UART_LSR_FE) { flag = TTY_FRAME; tup->uport.icount.frame++; - dev_err(tup->uport.dev, "Got frame errors\n"); + dev_dbg(tup->uport.dev, "Got frame errors\n"); } else if (lsr & UART_LSR_BI) { /* * Break error diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 5f3daabdc916e3eba27bb982b14dde7a4e7fb243..3403dd79051737b50a6f5849eddb36bdee63241d 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1120,7 +1121,7 @@ out: return ret; } -static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state) +static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state) { struct tty_port *port = &state->port; struct uart_port *uport; @@ -1523,6 +1524,7 @@ static void uart_set_termios(struct tty_struct *tty, /* Handle transition away from B0 status */ else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { unsigned int mask = TIOCM_DTR; + if (!(cflag & CRTSCTS) || !tty_throttled(tty)) mask |= TIOCM_RTS; uart_set_mctrl(uport, mask); @@ -2279,6 +2281,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) if (console_suspend_enabled || !uart_console(uport)) { /* Protected by port mutex for now */ struct tty_struct *tty = port->tty; + ret = ops->startup(uport); if (ret == 0) { if (tty) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 204bb68ce3ca91a1d9338658154bd5465109e4d3..e1179e74a2b89d892f4c8e0edceb3378c6755e5a 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -3301,9 +3301,6 @@ static int sci_probe_single(struct platform_device *dev, sciport->port.flags |= UPF_HARD_FLOW; } - if (sci_uart_driver.cons->index == sciport->port.line) - spin_lock_init(&sciport->port.lock); - ret = uart_add_one_port(&sci_uart_driver, &sciport->port); if (ret) { sci_cleanup_single(sciport); diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c index 0b5110dad051085639bc5550f63a6ce52e720d32..13eadcb8aec4e1554cca30ad399577cf1dace2ae 100644 --- a/drivers/tty/serial/sifive.c +++ b/drivers/tty/serial/sifive.c @@ -883,7 +883,6 @@ console_initcall(sifive_console_init); static void __ssp_add_console_port(struct sifive_serial_port *ssp) { - spin_lock_init(&ssp->port.lock); sifive_serial_console_ports[ssp->port.line] = ssp; } diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 8602ff3573218a4cdf97706602fd150fb73038e2..143300a8009098f946740357a2a51c9851eba054 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -129,9 +129,13 @@ static int stm32_config_rs485(struct uart_port *port, if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { cr3 &= ~USART_CR3_DEP; rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; + mctrl_gpio_set(stm32_port->gpios, + stm32_port->port.mctrl & ~TIOCM_RTS); } else { cr3 |= USART_CR3_DEP; rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; + mctrl_gpio_set(stm32_port->gpios, + stm32_port->port.mctrl | TIOCM_RTS); } writel_relaxed(cr3, port->membase + ofs->cr3); @@ -847,9 +851,13 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { cr3 &= ~USART_CR3_DEP; rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; + mctrl_gpio_set(stm32_port->gpios, + stm32_port->port.mctrl & ~TIOCM_RTS); } else { cr3 |= USART_CR3_DEP; rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; + mctrl_gpio_set(stm32_port->gpios, + stm32_port->port.mctrl | TIOCM_RTS); } } else { @@ -1033,8 +1041,9 @@ static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev) if (WARN_ON(id >= STM32_MAX_PORTS)) return NULL; - stm32_ports[id].hw_flow_control = of_property_read_bool(np, - "st,hw-flow-ctrl"); + stm32_ports[id].hw_flow_control = + of_property_read_bool (np, "st,hw-flow-ctrl") /*deprecated*/ || + of_property_read_bool (np, "uart-has-rtscts"); stm32_ports[id].port.line = id; stm32_ports[id].cr1_irq = USART_CR1_RXNEIE; stm32_ports[id].cr3_irq = 0; diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index e35073e93a5b4710a56039a3e36ed15a00dc9b90..eafada8fb6fad8755104ffa4fdc7cb40c8cc1d6e 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c @@ -567,9 +567,6 @@ static int hv_probe(struct platform_device *op) sunserial_console_match(&sunhv_console, op->dev.of_node, &sunhv_reg, port->line, false); - /* We need to initialize lock even for non-registered console */ - spin_lock_init(&port->lock); - err = uart_add_one_port(&sunhv_reg, port); if (err) goto out_unregister_driver; diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index 7dbd0c471d921a86be197ff5eb19f0f17a15e5f5..09379db613d8b7f69cab5ffa66d0a90c868cdec2 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -32,7 +32,7 @@ * Register definitions * * For register details see datasheet: - * http://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf + * https://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf */ #define ULITE_RX 0x00 diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 08d2976593d5d62aa14ce86aa5eb4227e43f2cb2..0dba40eace46fc2e08b040ee134d05144b79639c 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -252,7 +252,6 @@ struct mgsl_struct { char device_name[25]; /* device instance name */ - unsigned int bus_type; /* expansion bus type (ISA,EISA,PCI) */ unsigned char bus; /* expansion bus number (zero based) */ unsigned char function; /* PCI device number */ @@ -3432,15 +3431,9 @@ static inline void line_info(struct seq_file *m, struct mgsl_struct *info) char stat_buf[30]; unsigned long flags; - if (info->bus_type == MGSL_BUS_TYPE_PCI) { - seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", - info->device_name, info->io_base, info->irq_level, - info->phys_memory_base, info->phys_lcr_base); - } else { - seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d", - info->device_name, info->io_base, - info->irq_level, info->dma_level); - } + seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", + info->device_name, info->io_base, info->irq_level, + info->phys_memory_base, info->phys_lcr_base); /* output current serial signal states */ spin_lock_irqsave(&info->irq_spinlock,flags); @@ -3556,54 +3549,27 @@ static int mgsl_allocate_dma_buffers(struct mgsl_struct *info) if ( info->max_frame_size % DMABUFFERSIZE ) BuffersPerFrame++; - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* - * The PCI adapter has 256KBytes of shared memory to use. - * This is 64 PAGE_SIZE buffers. - * - * The first page is used for padding at this time so the - * buffer list does not begin at offset 0 of the PCI - * adapter's shared memory. - * - * The 2nd page is used for the buffer list. A 4K buffer - * list can hold 128 DMA_BUFFER structures at 32 bytes - * each. - * - * This leaves 62 4K pages. - * - * The next N pages are used for transmit frame(s). We - * reserve enough 4K page blocks to hold the required - * number of transmit dma buffers (num_tx_dma_buffers), - * each of MaxFrameSize size. - * - * Of the remaining pages (62-N), determine how many can - * be used to receive full MaxFrameSize inbound frames - */ - info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame; - info->rx_buffer_count = 62 - info->tx_buffer_count; - } else { - /* Calculate the number of PAGE_SIZE buffers needed for */ - /* receive and transmit DMA buffers. */ - - - /* Calculate the number of DMA buffers necessary to */ - /* hold 7 max size receive frames and one max size transmit frame. */ - /* The receive buffer count is bumped by one so we avoid an */ - /* End of List condition if all receive buffers are used when */ - /* using linked list DMA buffers. */ - - info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame; - info->rx_buffer_count = (BuffersPerFrame * MAXRXFRAMES) + 6; - - /* - * limit total TxBuffers & RxBuffers to 62 4K total - * (ala PCI Allocation) - */ - - if ( (info->tx_buffer_count + info->rx_buffer_count) > 62 ) - info->rx_buffer_count = 62 - info->tx_buffer_count; - - } + /* + * The PCI adapter has 256KBytes of shared memory to use. This is 64 + * PAGE_SIZE buffers. + * + * The first page is used for padding at this time so the buffer list + * does not begin at offset 0 of the PCI adapter's shared memory. + * + * The 2nd page is used for the buffer list. A 4K buffer list can hold + * 128 DMA_BUFFER structures at 32 bytes each. + * + * This leaves 62 4K pages. + * + * The next N pages are used for transmit frame(s). We reserve enough + * 4K page blocks to hold the required number of transmit dma buffers + * (num_tx_dma_buffers), each of MaxFrameSize size. + * + * Of the remaining pages (62-N), determine how many can be used to + * receive full MaxFrameSize inbound frames + */ + info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame; + info->rx_buffer_count = 62 - info->tx_buffer_count; if ( debug_level >= DEBUG_LEVEL_INFO ) printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n", @@ -3652,23 +3618,10 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) { unsigned int i; - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* PCI adapter uses shared memory. */ - info->buffer_list = info->memory_base + info->last_mem_alloc; - info->buffer_list_phys = info->last_mem_alloc; - info->last_mem_alloc += BUFFERLISTSIZE; - } else { - /* ISA adapter uses system memory. */ - /* The buffer lists are allocated as a common buffer that both */ - /* the processor and adapter can access. This allows the driver to */ - /* inspect portions of the buffer while other portions are being */ - /* updated by the adapter using Bus Master DMA. */ - - info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL); - if (info->buffer_list == NULL) - return -ENOMEM; - info->buffer_list_phys = (u32)(info->buffer_list_dma_addr); - } + /* PCI adapter uses shared memory. */ + info->buffer_list = info->memory_base + info->last_mem_alloc; + info->buffer_list_phys = info->last_mem_alloc; + info->last_mem_alloc += BUFFERLISTSIZE; /* We got the memory for the buffer entry lists. */ /* Initialize the memory block to all zeros. */ @@ -3734,9 +3687,6 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) */ static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) { - if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI) - dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr); - info->buffer_list = NULL; info->rx_buffer_list = NULL; info->tx_buffer_list = NULL; @@ -3762,24 +3712,13 @@ static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) { int i; - u32 phys_addr; /* Allocate page sized buffers for the receive buffer list */ for ( i = 0; i < Buffercount; i++ ) { - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* PCI adapter uses shared memory buffers. */ - BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc; - phys_addr = info->last_mem_alloc; - info->last_mem_alloc += DMABUFFERSIZE; - } else { - /* ISA adapter uses system memory. */ - BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL); - if (BufferList[i].virt_addr == NULL) - return -ENOMEM; - phys_addr = (u32)(BufferList[i].dma_addr); - } - BufferList[i].phys_addr = phys_addr; + BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc; + BufferList[i].phys_addr = info->last_mem_alloc; + info->last_mem_alloc += DMABUFFERSIZE; } return 0; @@ -3807,8 +3746,6 @@ static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *Buf if ( BufferList ) { for ( i = 0 ; i < Buffercount ; i++ ) { if ( BufferList[i].virt_addr ) { - if ( info->bus_type != MGSL_BUS_TYPE_PCI ) - dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr); BufferList[i].virt_addr = NULL; } } @@ -4040,58 +3977,40 @@ static int mgsl_claim_resources(struct mgsl_struct *info) } info->irq_requested = true; - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) { - printk( "%s(%d):mem addr conflict device %s Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base); - goto errout; - } - info->shared_mem_requested = true; - if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) { - printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset); - goto errout; - } - info->lcr_mem_requested = true; - - info->memory_base = ioremap(info->phys_memory_base, - 0x40000); - if (!info->memory_base) { - printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - goto errout; - } - - if ( !mgsl_memory_test(info) ) { - printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - goto errout; - } - - info->lcr_base = ioremap(info->phys_lcr_base, - PAGE_SIZE); - if (!info->lcr_base) { - printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); - goto errout; - } - info->lcr_base += info->lcr_offset; + if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) { + printk( "%s(%d):mem addr conflict device %s Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base); + goto errout; + } + info->shared_mem_requested = true; + if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) { + printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset); + goto errout; + } + info->lcr_mem_requested = true; + + info->memory_base = ioremap(info->phys_memory_base, 0x40000); + if (!info->memory_base) { + printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + goto errout; + } - } else { - /* claim DMA channel */ + if ( !mgsl_memory_test(info) ) { + printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + goto errout; + } - if (request_dma(info->dma_level,info->device_name) < 0){ - printk( "%s(%d):Can't request DMA channel on device %s DMA=%d\n", - __FILE__,__LINE__,info->device_name, info->dma_level ); - goto errout; - } - info->dma_requested = true; - - /* ISA adapter uses bus master DMA */ - set_dma_mode(info->dma_level,DMA_MODE_CASCADE); - enable_dma(info->dma_level); + info->lcr_base = ioremap(info->phys_lcr_base, PAGE_SIZE); + if (!info->lcr_base) { + printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); + goto errout; } - + info->lcr_base += info->lcr_offset; + if ( mgsl_allocate_dma_buffers(info) < 0 ) { printk( "%s(%d):Can't allocate DMA buffers on device %s DMA=%d\n", __FILE__,__LINE__,info->device_name, info->dma_level ); @@ -4200,16 +4119,10 @@ static void mgsl_add_device( struct mgsl_struct *info ) else if ( info->max_frame_size > 65535 ) info->max_frame_size = 65535; - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n", - info->hw_version + 1, info->device_name, info->io_base, info->irq_level, - info->phys_memory_base, info->phys_lcr_base, - info->max_frame_size ); - } else { - printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n", - info->device_name, info->io_base, info->irq_level, info->dma_level, - info->max_frame_size ); - } + printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n", + info->hw_version + 1, info->device_name, info->io_base, info->irq_level, + info->phys_memory_base, info->phys_lcr_base, + info->max_frame_size ); #if SYNCLINK_GENERIC_HDLC hdlcdev_init(info); @@ -4420,8 +4333,7 @@ static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ) outw( Cmd + info->loopback_bits, info->io_base + CCAR ); /* Read to flush write to CCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base + CCAR ); + inw( info->io_base + CCAR ); } /* end of usc_RTCmd() */ @@ -4445,8 +4357,7 @@ static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ) outw( Cmd + info->mbre_bit, info->io_base ); /* Read to flush write to DCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base ); + inw( info->io_base ); } /* end of usc_DmaCmd() */ @@ -4475,8 +4386,7 @@ static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) outw( RegValue, info->io_base ); /* Read to flush write to DCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base ); + inw( info->io_base ); } /* end of usc_OutDmaReg() */ @@ -4528,8 +4438,7 @@ static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) outw( RegValue, info->io_base + CCAR ); /* Read to flush write to CCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base + CCAR ); + inw( info->io_base + CCAR ); } /* end of usc_OutReg() */ @@ -4728,10 +4637,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) RegValue = usc_InReg( info, RICR ) & 0xc0; - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - usc_OutReg( info, RICR, (u16)(0x030a | RegValue) ); - else - usc_OutReg( info, RICR, (u16)(0x140a | RegValue) ); + usc_OutReg( info, RICR, (u16)(0x030a | RegValue) ); /* Unlatch all Rx status bits and clear Rx status IRQ Pending */ @@ -4792,10 +4698,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) * 0000 0000 0011 0110 = 0x0036 */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - usc_OutReg( info, TICR, 0x0736 ); - else - usc_OutReg( info, TICR, 0x1436 ); + usc_OutReg( info, TICR, 0x0736 ); usc_UnlatchTxstatusBits( info, TXSTATUS_ALL ); usc_ClearIrqPendingBits( info, TRANSMIT_STATUS ); @@ -4885,10 +4788,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) /* DPLL is enabled. Use BRG1 to provide continuous reference clock */ /* for DPLL. DPLL mode in HCR is dependent on the encoding used. */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - XtalSpeed = 11059200; - else - XtalSpeed = 14745600; + XtalSpeed = 11059200; if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) { DpllDivisor = 16; @@ -5011,13 +4911,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) * 0110 0000 0000 1011 = 0x600b */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* PCI adapter does not need DMA wait state */ - usc_OutDmaReg( info, DCR, 0xa00b ); - } - else - usc_OutDmaReg( info, DCR, 0x800b ); - + /* PCI adapter does not need DMA wait state */ + usc_OutDmaReg( info, DCR, 0xa00b ); /* Receive DMA mode Register (RDMR) * @@ -5109,12 +5004,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) * <7..0> 0x00 Maximum number of clock cycles per bus grant */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* don't limit bus occupancy on PCI adapter */ - usc_OutDmaReg( info, BDCR, 0x0000 ); - } - else - usc_OutDmaReg( info, BDCR, 0x2000 ); + /* don't limit bus occupancy on PCI adapter */ + usc_OutDmaReg( info, BDCR, 0x0000 ); usc_stop_transmitter(info); usc_stop_receiver(info); @@ -5155,10 +5046,7 @@ static void usc_enable_loopback(struct mgsl_struct *info, int enable) /* Write 16-bit Time Constant for BRG0 */ /* use clock speed if available, otherwise use 8 for diagnostics */ if (info->params.clock_speed) { - if (info->bus_type == MGSL_BUS_TYPE_PCI) - usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1)); - else - usc_OutReg(info, TC0R, (u16)((14745600/info->params.clock_speed)-1)); + usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1)); } else usc_OutReg(info, TC0R, (u16)8); @@ -5201,10 +5089,7 @@ static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate ) u16 Tc; if ( data_rate ) { - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - XtalSpeed = 11059200; - else - XtalSpeed = 14745600; + XtalSpeed = 11059200; /* Tc = (Xtal/Speed) - 1 */ @@ -5682,44 +5567,38 @@ static void usc_load_txfifo( struct mgsl_struct *info ) */ static void usc_reset( struct mgsl_struct *info ) { - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - int i; - u32 readval; + int i; + u32 readval; - /* Set BIT30 of Misc Control Register */ - /* (Local Control Register 0x50) to force reset of USC. */ + /* Set BIT30 of Misc Control Register */ + /* (Local Control Register 0x50) to force reset of USC. */ - volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50); - u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28); + volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50); + u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28); - info->misc_ctrl_value |= BIT30; - *MiscCtrl = info->misc_ctrl_value; + info->misc_ctrl_value |= BIT30; + *MiscCtrl = info->misc_ctrl_value; - /* - * Force at least 170ns delay before clearing - * reset bit. Each read from LCR takes at least - * 30ns so 10 times for 300ns to be safe. - */ - for(i=0;i<10;i++) - readval = *MiscCtrl; - - info->misc_ctrl_value &= ~BIT30; - *MiscCtrl = info->misc_ctrl_value; - - *LCR0BRDR = BUS_DESCRIPTOR( - 1, // Write Strobe Hold (0-3) - 2, // Write Strobe Delay (0-3) - 2, // Read Strobe Delay (0-3) - 0, // NWDD (Write data-data) (0-3) - 4, // NWAD (Write Addr-data) (0-31) - 0, // NXDA (Read/Write Data-Addr) (0-3) - 0, // NRDD (Read Data-Data) (0-3) - 5 // NRAD (Read Addr-Data) (0-31) - ); - } else { - /* do HW reset */ - outb( 0,info->io_base + 8 ); - } + /* + * Force at least 170ns delay before clearing reset bit. Each read from + * LCR takes at least 30ns so 10 times for 300ns to be safe. + */ + for(i=0;i<10;i++) + readval = *MiscCtrl; + + info->misc_ctrl_value &= ~BIT30; + *MiscCtrl = info->misc_ctrl_value; + + *LCR0BRDR = BUS_DESCRIPTOR( + 1, // Write Strobe Hold (0-3) + 2, // Write Strobe Delay (0-3) + 2, // Read Strobe Delay (0-3) + 0, // NWDD (Write data-data) (0-3) + 4, // NWAD (Write Addr-data) (0-31) + 0, // NXDA (Read/Write Data-Addr) (0-3) + 0, // NRDD (Read Data-Data) (0-3) + 5 // NRAD (Read Addr-Data) (0-31) + ); info->mbre_bit = 0; info->loopback_bits = 0; @@ -6228,11 +6107,7 @@ static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate ) * ClkSpeed = 921600 (ISA), 691200 (PCI) */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) ); - else - usc_OutReg( info, TC0R, (u16)((921600/data_rate) - 1) ); - + usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) ); /* * Hardware Configuration Register (HCR) @@ -6837,10 +6712,7 @@ static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, /* Actually copy data from source buffer to DMA buffer. */ /* Also set the data count for this individual DMA buffer. */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount); - else - memcpy(pBufEntry->virt_addr, Buffer, Copycount); + mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount); pBufEntry->count = Copycount; @@ -7315,9 +7187,6 @@ static bool mgsl_memory_test( struct mgsl_struct *info ) unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long); unsigned long * TestAddr; - if ( info->bus_type != MGSL_BUS_TYPE_PCI ) - return true; - TestAddr = (unsigned long *)info->memory_base; /* Test data lines with test pattern at one location. */ @@ -8003,7 +7872,6 @@ static int synclink_init_one (struct pci_dev *dev, info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1); info->phys_lcr_base &= ~(PAGE_SIZE-1); - info->bus_type = MGSL_BUS_TYPE_PCI; info->io_addr_size = 8; info->irq_flags = IRQF_SHARED; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 5a6f36b391d95d8662d82984f8842f3948545bca..ceed72c9a88f78505200248ca83b970218ccff71 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1405,7 +1405,7 @@ void tty_save_termios(struct tty_struct *tty) /* Stash the termios data */ tp = tty->driver->termios[idx]; if (tp == NULL) { - tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); + tp = kmalloc(sizeof(*tp), GFP_KERNEL); if (tp == NULL) return; tty->driver->termios[idx] = tp; @@ -2489,7 +2489,7 @@ static int tty_tiocsserial(struct tty_struct *tty, struct serial_struct __user * struct serial_struct v; int flags; - if (copy_from_user(&v, ss, sizeof(struct serial_struct))) + if (copy_from_user(&v, ss, sizeof(*ss))) return -EFAULT; flags = v.flags & ASYNC_DEPRECATED; @@ -2507,11 +2507,11 @@ static int tty_tiocgserial(struct tty_struct *tty, struct serial_struct __user * struct serial_struct v; int err; - memset(&v, 0, sizeof(struct serial_struct)); + memset(&v, 0, sizeof(v)); if (!tty->ops->get_serial) return -ENOTTY; err = tty->ops->get_serial(tty, &v); - if (!err && copy_to_user(ss, &v, sizeof(struct serial_struct))) + if (!err && copy_to_user(ss, &v, sizeof(v))) err = -EFAULT; return err; } @@ -2673,25 +2673,25 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #ifdef CONFIG_COMPAT struct serial_struct32 { - compat_int_t type; - compat_int_t line; - compat_uint_t port; - compat_int_t irq; - compat_int_t flags; - compat_int_t xmit_fifo_size; - compat_int_t custom_divisor; - compat_int_t baud_base; - unsigned short close_delay; - char io_type; - char reserved_char[1]; - compat_int_t hub6; - unsigned short closing_wait; /* time to wait before closing */ - unsigned short closing_wait2; /* no longer used... */ - compat_uint_t iomem_base; - unsigned short iomem_reg_shift; - unsigned int port_high; - /* compat_ulong_t iomap_base FIXME */ - compat_int_t reserved[1]; + compat_int_t type; + compat_int_t line; + compat_uint_t port; + compat_int_t irq; + compat_int_t flags; + compat_int_t xmit_fifo_size; + compat_int_t custom_divisor; + compat_int_t baud_base; + unsigned short close_delay; + char io_type; + char reserved_char; + compat_int_t hub6; + unsigned short closing_wait; /* time to wait before closing */ + unsigned short closing_wait2; /* no longer used... */ + compat_uint_t iomem_base; + unsigned short iomem_reg_shift; + unsigned int port_high; + /* compat_ulong_t iomap_base FIXME */ + compat_int_t reserved; }; static int compat_tty_tiocsserial(struct tty_struct *tty, @@ -2705,7 +2705,7 @@ static int compat_tty_tiocsserial(struct tty_struct *tty, struct serial_struct v; int flags; - if (copy_from_user(&v32, ss, sizeof(struct serial_struct32))) + if (copy_from_user(&v32, ss, sizeof(*ss))) return -EFAULT; memcpy(&v, &v32, offsetof(struct serial_struct32, iomem_base)); @@ -2743,7 +2743,7 @@ static int compat_tty_tiocgserial(struct tty_struct *tty, 0xfffffff : ptr_to_compat(v.iomem_base); v32.iomem_reg_shift = v.iomem_reg_shift; v32.port_high = v.port_high; - if (copy_to_user(ss, &v32, sizeof(struct serial_struct32))) + if (copy_to_user(ss, &v32, sizeof(v32))) err = -EFAULT; } return err; @@ -3215,7 +3215,7 @@ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner, if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1)) return ERR_PTR(-EINVAL); - driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); + driver = kzalloc(sizeof(*driver), GFP_KERNEL); if (!driver) return ERR_PTR(-ENOMEM); diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c index c1be96bb3ecfb829ec4802e7f1116bb94837a84d..5947b54d92bec3295ee9dd1b3991783e565e68cf 100644 --- a/drivers/tty/vt/consolemap.c +++ b/drivers/tty/vt/consolemap.c @@ -542,7 +542,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) if (!ct) return 0; - unilist = vmemdup_user(list, ct * sizeof(struct unipair)); + unilist = vmemdup_user(list, array_size(sizeof(struct unipair), ct)); if (IS_ERR(unilist)) return PTR_ERR(unilist); diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index f80199984ee0f666d42a2200a67caf0288fe6f37..0db53b5b3acf6b7d33338b659c81b586e841804f 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -2019,7 +2020,7 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) goto reterr; } kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0'; - i = kbs->kb_func; + i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC); switch (cmd) { case KDGKBSENT: diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 31bb3647a99c380a4511f4865c6f5d8e95424098..8e74654c1b271678a52e322caef07b40eec12ee9 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -193,7 +193,7 @@ static int vc_selection_store_chars(struct vc_data *vc, bool unicode) /* Allocate a new buffer before freeing the old one ... */ /* chars can take up to 4 bytes with unicode */ bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1, - GFP_KERNEL); + GFP_KERNEL | __GFP_NOWARN); if (!bp) { printk(KERN_WARNING "selection: kmalloc() failed\n"); clear_selection(); diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 42d8c67a481f03c654850c56557419079bc71e79..ccb533fd00a29aad764a2634ce4ba8fc2f005efd 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -127,14 +127,6 @@ struct con_driver { static struct con_driver registered_con_driver[MAX_NR_CON_DRIVER]; const struct consw *conswitchp; -/* A bitmap for codes <32. A bit of 1 indicates that the code - * corresponding to that bit number invokes some special action - * (such as cursor movement) and should not be displayed as a - * glyph unless the disp_ctrl mode is explicitly enabled. - */ -#define CTRL_ACTION 0x0d00ff81 -#define CTRL_ALWAYS 0x0800f501 /* Cannot be overridden by disp_ctrl */ - /* * Here is the default bell parameters: 750HZ, 1/8th of a second */ @@ -171,7 +163,7 @@ module_param(default_utf8, int, S_IRUGO | S_IWUSR); int global_cursor_default = -1; module_param(global_cursor_default, int, S_IRUGO | S_IWUSR); -static int cur_default = CUR_DEFAULT; +static int cur_default = CUR_UNDERLINE; module_param(cur_default, int, S_IRUGO | S_IWUSR); /* @@ -381,7 +373,7 @@ static void vc_uniscr_putc(struct vc_data *vc, char32_t uc) struct uni_screen *uniscr = get_vc_uniscr(vc); if (uniscr) - uniscr->lines[vc->vc_y][vc->vc_x] = uc; + uniscr->lines[vc->state.y][vc->state.x] = uc; } static void vc_uniscr_insert(struct vc_data *vc, unsigned int nr) @@ -389,8 +381,8 @@ static void vc_uniscr_insert(struct vc_data *vc, unsigned int nr) struct uni_screen *uniscr = get_vc_uniscr(vc); if (uniscr) { - char32_t *ln = uniscr->lines[vc->vc_y]; - unsigned int x = vc->vc_x, cols = vc->vc_cols; + char32_t *ln = uniscr->lines[vc->state.y]; + unsigned int x = vc->state.x, cols = vc->vc_cols; memmove(&ln[x + nr], &ln[x], (cols - x - nr) * sizeof(*ln)); memset32(&ln[x], ' ', nr); @@ -402,8 +394,8 @@ static void vc_uniscr_delete(struct vc_data *vc, unsigned int nr) struct uni_screen *uniscr = get_vc_uniscr(vc); if (uniscr) { - char32_t *ln = uniscr->lines[vc->vc_y]; - unsigned int x = vc->vc_x, cols = vc->vc_cols; + char32_t *ln = uniscr->lines[vc->state.y]; + unsigned int x = vc->state.x, cols = vc->vc_cols; memcpy(&ln[x], &ln[x + nr], (cols - x - nr) * sizeof(*ln)); memset32(&ln[cols - nr], ' ', nr); @@ -416,7 +408,7 @@ static void vc_uniscr_clear_line(struct vc_data *vc, unsigned int x, struct uni_screen *uniscr = get_vc_uniscr(vc); if (uniscr) { - char32_t *ln = uniscr->lines[vc->vc_y]; + char32_t *ln = uniscr->lines[vc->state.y]; memset32(&ln[x], ' ', nr); } @@ -705,8 +697,9 @@ void update_region(struct vc_data *vc, unsigned long start, int count) /* Structure of attributes is hardware-dependent */ -static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, - u8 _underline, u8 _reverse, u8 _italic) +static u8 build_attr(struct vc_data *vc, u8 _color, + enum vc_intensity _intensity, bool _blink, bool _underline, + bool _reverse, bool _italic) { if (vc->vc_sw->con_build_attr) return vc->vc_sw->con_build_attr(vc, _color, _intensity, @@ -726,21 +719,21 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 a = _color; if (!vc->vc_can_do_color) return _intensity | - (_italic ? 2 : 0) | - (_underline ? 4 : 0) | - (_reverse ? 8 : 0) | - (_blink ? 0x80 : 0); + (_italic << 1) | + (_underline << 2) | + (_reverse << 3) | + (_blink << 7); if (_italic) a = (a & 0xF0) | vc->vc_itcolor; else if (_underline) a = (a & 0xf0) | vc->vc_ulcolor; - else if (_intensity == 0) + else if (_intensity == VCI_HALF_BRIGHT) a = (a & 0xf0) | vc->vc_halfcolor; if (_reverse) - a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77); + a = (a & 0x88) | (((a >> 4) | (a << 4)) & 0x77); if (_blink) a ^= 0x80; - if (_intensity == 2) + if (_intensity == VCI_BOLD) a ^= 0x08; if (vc->vc_hi_font_mask == 0x100) a <<= 1; @@ -750,10 +743,12 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, static void update_attr(struct vc_data *vc) { - vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity, - vc->vc_blink, vc->vc_underline, - vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic); - vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' '; + vc->vc_attr = build_attr(vc, vc->state.color, vc->state.intensity, + vc->state.blink, vc->state.underline, + vc->state.reverse ^ vc->vc_decscnm, vc->state.italic); + vc->vc_video_erase_char = ' ' | (build_attr(vc, vc->state.color, + VCI_NORMAL, vc->state.blink, false, + vc->vc_decscnm, false) << 8); } /* Note: inverting the screen twice should revert to the original state */ @@ -782,14 +777,18 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed) } else if (vc->vc_hi_font_mask == 0x100) { while (cnt--) { a = scr_readw(q); - a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4); + a = (a & 0x11ff) | + ((a & 0xe000) >> 4) | + ((a & 0x0e00) << 4); scr_writew(a, q); q++; } } else { while (cnt--) { a = scr_readw(q); - a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4); + a = (a & 0x88ff) | + ((a & 0x7000) >> 4) | + ((a & 0x0700) << 4); scr_writew(a, q); q++; } @@ -842,12 +841,12 @@ static void insert_char(struct vc_data *vc, unsigned int nr) unsigned short *p = (unsigned short *) vc->vc_pos; vc_uniscr_insert(vc, nr); - scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2); + scr_memmovew(p + nr, p, (vc->vc_cols - vc->state.x - nr) * 2); scr_memsetw(p, vc->vc_video_erase_char, nr * 2); vc->vc_need_wrap = 0; if (con_should_update(vc)) do_update_region(vc, (unsigned long) p, - vc->vc_cols - vc->vc_x); + vc->vc_cols - vc->state.x); } static void delete_char(struct vc_data *vc, unsigned int nr) @@ -855,13 +854,13 @@ static void delete_char(struct vc_data *vc, unsigned int nr) unsigned short *p = (unsigned short *) vc->vc_pos; vc_uniscr_delete(vc, nr); - scr_memcpyw(p, p + nr, (vc->vc_cols - vc->vc_x - nr) * 2); - scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char, + scr_memcpyw(p, p + nr, (vc->vc_cols - vc->state.x - nr) * 2); + scr_memsetw(p + vc->vc_cols - vc->state.x - nr, vc->vc_video_erase_char, nr * 2); vc->vc_need_wrap = 0; if (con_should_update(vc)) do_update_region(vc, (unsigned long) p, - vc->vc_cols - vc->vc_x); + vc->vc_cols - vc->state.x); } static int softcursor_original = -1; @@ -871,16 +870,21 @@ static void add_softcursor(struct vc_data *vc) int i = scr_readw((u16 *) vc->vc_pos); u32 type = vc->vc_cursor_type; - if (! (type & 0x10)) return; - if (softcursor_original != -1) return; + if (!(type & CUR_SW)) + return; + if (softcursor_original != -1) + return; softcursor_original = i; - i |= ((type >> 8) & 0xff00 ); - i ^= ((type) & 0xff00 ); - if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000; - if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700; - scr_writew(i, (u16 *) vc->vc_pos); + i |= CUR_SET(type); + i ^= CUR_CHANGE(type); + if ((type & CUR_ALWAYS_BG) && + (softcursor_original & CUR_BG) == (i & CUR_BG)) + i ^= CUR_BG; + if ((type & CUR_INVERT_FG_BG) && (i & CUR_FG) == ((i & CUR_BG) >> 4)) + i ^= CUR_FG; + scr_writew(i, (u16 *)vc->vc_pos); if (con_should_update(vc)) - vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x); + vc->vc_sw->con_putc(vc, i, vc->state.y, vc->state.x); } static void hide_softcursor(struct vc_data *vc) @@ -889,7 +893,7 @@ static void hide_softcursor(struct vc_data *vc) scr_writew(softcursor_original, (u16 *)vc->vc_pos); if (con_should_update(vc)) vc->vc_sw->con_putc(vc, softcursor_original, - vc->vc_y, vc->vc_x); + vc->state.y, vc->state.x); softcursor_original = -1; } } @@ -911,7 +915,7 @@ static void set_cursor(struct vc_data *vc) if (vc_is_sel(vc)) clear_selection(); add_softcursor(vc); - if ((vc->vc_cursor_type & 0x0f) != 1) + if (CUR_SIZE(vc->vc_cursor_type) != CUR_NONE) vc->vc_sw->con_cursor(vc, CM_DRAW); } else hide_cursor(vc); @@ -927,7 +931,8 @@ static void set_origin(struct vc_data *vc) vc->vc_origin = (unsigned long)vc->vc_screenbuf; vc->vc_visible_origin = vc->vc_origin; vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size; - vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x; + vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->state.y + + 2 * vc->state.x; } static void save_screen(struct vc_data *vc) @@ -1256,8 +1261,8 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, new_origin = (long) newscreen; new_scr_end = new_origin + new_screen_size; - if (vc->vc_y > new_rows) { - if (old_rows - vc->vc_y < new_rows) { + if (vc->state.y > new_rows) { + if (old_rows - vc->state.y < new_rows) { /* * Cursor near the bottom, copy contents from the * bottom of buffer @@ -1268,7 +1273,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, * Cursor is in no man's land, copy 1/2 screenful * from the top and bottom of cursor position */ - first_copied_row = (vc->vc_y - new_rows/2); + first_copied_row = (vc->state.y - new_rows/2); } old_origin += first_copied_row * old_row_size; } else @@ -1302,7 +1307,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, /* do part of a reset_terminal() */ vc->vc_top = 0; vc->vc_bottom = vc->vc_rows; - gotoxy(vc, vc->vc_x, vc->vc_y); + gotoxy(vc, vc->state.x, vc->state.y); save_cur(vc); if (tty) { @@ -1399,12 +1404,6 @@ enum { EPecma = 0, EPdec, EPeq, EPgt, EPlt}; #define kbdapplic VC_APPLIC #define lnm VC_CRLF -/* - * this is what the terminal answers to a ESC-Z or csi0c query. - */ -#define VT100ID "\033[?1;2c" -#define VT102ID "\033[?6c" - const unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7, 8,12,10,14, 9,13,11,15 }; @@ -1437,12 +1436,12 @@ static void gotoxy(struct vc_data *vc, int new_x, int new_y) int min_y, max_y; if (new_x < 0) - vc->vc_x = 0; + vc->state.x = 0; else { if (new_x >= vc->vc_cols) - vc->vc_x = vc->vc_cols - 1; + vc->state.x = vc->vc_cols - 1; else - vc->vc_x = new_x; + vc->state.x = new_x; } if (vc->vc_decom) { @@ -1453,12 +1452,13 @@ static void gotoxy(struct vc_data *vc, int new_x, int new_y) max_y = vc->vc_rows; } if (new_y < min_y) - vc->vc_y = min_y; + vc->state.y = min_y; else if (new_y >= max_y) - vc->vc_y = max_y - 1; + vc->state.y = max_y - 1; else - vc->vc_y = new_y; - vc->vc_pos = vc->vc_origin + vc->vc_y * vc->vc_size_row + (vc->vc_x<<1); + vc->state.y = new_y; + vc->vc_pos = vc->vc_origin + vc->state.y * vc->vc_size_row + + (vc->state.x << 1); vc->vc_need_wrap = 0; } @@ -1485,10 +1485,10 @@ static void lf(struct vc_data *vc) /* don't scroll if above bottom of scrolling region, or * if below scrolling region */ - if (vc->vc_y + 1 == vc->vc_bottom) + if (vc->state.y + 1 == vc->vc_bottom) con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_UP, 1); - else if (vc->vc_y < vc->vc_rows - 1) { - vc->vc_y++; + else if (vc->state.y < vc->vc_rows - 1) { + vc->state.y++; vc->vc_pos += vc->vc_size_row; } vc->vc_need_wrap = 0; @@ -1500,10 +1500,10 @@ static void ri(struct vc_data *vc) /* don't scroll if below top of scrolling region, or * if above scrolling region */ - if (vc->vc_y == vc->vc_top) + if (vc->state.y == vc->vc_top) con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_DOWN, 1); - else if (vc->vc_y > 0) { - vc->vc_y--; + else if (vc->state.y > 0) { + vc->state.y--; vc->vc_pos -= vc->vc_size_row; } vc->vc_need_wrap = 0; @@ -1511,16 +1511,16 @@ static void ri(struct vc_data *vc) static inline void cr(struct vc_data *vc) { - vc->vc_pos -= vc->vc_x << 1; - vc->vc_need_wrap = vc->vc_x = 0; + vc->vc_pos -= vc->state.x << 1; + vc->vc_need_wrap = vc->state.x = 0; notify_write(vc, '\r'); } static inline void bs(struct vc_data *vc) { - if (vc->vc_x) { + if (vc->state.x) { vc->vc_pos -= 2; - vc->vc_x--; + vc->state.x--; vc->vc_need_wrap = 0; notify_write(vc, '\b'); } @@ -1538,16 +1538,16 @@ static void csi_J(struct vc_data *vc, int vpar) switch (vpar) { case 0: /* erase from cursor to end of display */ - vc_uniscr_clear_line(vc, vc->vc_x, - vc->vc_cols - vc->vc_x); - vc_uniscr_clear_lines(vc, vc->vc_y + 1, - vc->vc_rows - vc->vc_y - 1); + vc_uniscr_clear_line(vc, vc->state.x, + vc->vc_cols - vc->state.x); + vc_uniscr_clear_lines(vc, vc->state.y + 1, + vc->vc_rows - vc->state.y - 1); count = (vc->vc_scr_end - vc->vc_pos) >> 1; start = (unsigned short *)vc->vc_pos; break; case 1: /* erase from start to cursor */ - vc_uniscr_clear_line(vc, 0, vc->vc_x + 1); - vc_uniscr_clear_lines(vc, 0, vc->vc_y); + vc_uniscr_clear_line(vc, 0, vc->state.x + 1); + vc_uniscr_clear_lines(vc, 0, vc->state.y); count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1; start = (unsigned short *)vc->vc_origin; break; @@ -1577,49 +1577,51 @@ static void csi_K(struct vc_data *vc, int vpar) switch (vpar) { case 0: /* erase from cursor to end of line */ offset = 0; - count = vc->vc_cols - vc->vc_x; + count = vc->vc_cols - vc->state.x; break; case 1: /* erase from start of line to cursor */ - offset = -vc->vc_x; - count = vc->vc_x + 1; + offset = -vc->state.x; + count = vc->state.x + 1; break; case 2: /* erase whole line */ - offset = -vc->vc_x; + offset = -vc->state.x; count = vc->vc_cols; break; default: return; } - vc_uniscr_clear_line(vc, vc->vc_x + offset, count); + vc_uniscr_clear_line(vc, vc->state.x + offset, count); scr_memsetw(start + offset, vc->vc_video_erase_char, 2 * count); vc->vc_need_wrap = 0; if (con_should_update(vc)) do_update_region(vc, (unsigned long)(start + offset), count); } -static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */ +/* erase the following vpar positions */ +static void csi_X(struct vc_data *vc, unsigned int vpar) { /* not vt100? */ - int count; + unsigned int count; if (!vpar) vpar++; - count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar; - vc_uniscr_clear_line(vc, vc->vc_x, count); + count = min(vpar, vc->vc_cols - vc->state.x); + + vc_uniscr_clear_line(vc, vc->state.x, count); scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count); if (con_should_update(vc)) - vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count); + vc->vc_sw->con_clear(vc, vc->state.y, vc->state.x, 1, count); vc->vc_need_wrap = 0; } static void default_attr(struct vc_data *vc) { - vc->vc_intensity = 1; - vc->vc_italic = 0; - vc->vc_underline = 0; - vc->vc_reverse = 0; - vc->vc_blink = 0; - vc->vc_color = vc->vc_def_color; + vc->state.intensity = VCI_NORMAL; + vc->state.italic = false; + vc->state.underline = false; + vc->state.reverse = false; + vc->state.blink = false; + vc->state.color = vc->vc_def_color; } struct rgb { u8 r; u8 g; u8 b; }; @@ -1655,19 +1657,19 @@ static void rgb_foreground(struct vc_data *vc, const struct rgb *c) if (hue == 7 && max <= 0x55) { hue = 0; - vc->vc_intensity = 2; + vc->state.intensity = VCI_BOLD; } else if (max > 0xaa) - vc->vc_intensity = 2; + vc->state.intensity = VCI_BOLD; else - vc->vc_intensity = 1; + vc->state.intensity = VCI_NORMAL; - vc->vc_color = (vc->vc_color & 0xf0) | hue; + vc->state.color = (vc->state.color & 0xf0) | hue; } static void rgb_background(struct vc_data *vc, const struct rgb *c) { /* For backgrounds, err on the dark side. */ - vc->vc_color = (vc->vc_color & 0x0f) + vc->state.color = (vc->state.color & 0x0f) | (c->r&0x80) >> 1 | (c->g&0x80) >> 2 | (c->b&0x80) >> 3; } @@ -1718,13 +1720,13 @@ static void csi_m(struct vc_data *vc) default_attr(vc); break; case 1: - vc->vc_intensity = 2; + vc->state.intensity = VCI_BOLD; break; case 2: - vc->vc_intensity = 0; + vc->state.intensity = VCI_HALF_BRIGHT; break; case 3: - vc->vc_italic = 1; + vc->state.italic = true; break; case 21: /* @@ -1732,21 +1734,19 @@ static void csi_m(struct vc_data *vc) * convert it to a single underline. */ case 4: - vc->vc_underline = 1; + vc->state.underline = true; break; case 5: - vc->vc_blink = 1; + vc->state.blink = true; break; case 7: - vc->vc_reverse = 1; + vc->state.reverse = true; break; case 10: /* ANSI X3.64-1979 (SCO-ish?) * Select primary font, don't display control chars if * defined, don't set bit 8 on output. */ - vc->vc_translate = set_translate(vc->vc_charset == 0 - ? vc->vc_G0_charset - : vc->vc_G1_charset, vc); + vc->vc_translate = set_translate(vc->state.Gx_charset[vc->state.charset], vc); vc->vc_disp_ctrl = 0; vc->vc_toggle_meta = 0; break; @@ -1767,19 +1767,19 @@ static void csi_m(struct vc_data *vc) vc->vc_toggle_meta = 1; break; case 22: - vc->vc_intensity = 1; + vc->state.intensity = VCI_NORMAL; break; case 23: - vc->vc_italic = 0; + vc->state.italic = false; break; case 24: - vc->vc_underline = 0; + vc->state.underline = false; break; case 25: - vc->vc_blink = 0; + vc->state.blink = false; break; case 27: - vc->vc_reverse = 0; + vc->state.reverse = false; break; case 38: i = vc_t416_color(vc, i, rgb_foreground); @@ -1788,64 +1788,70 @@ static void csi_m(struct vc_data *vc) i = vc_t416_color(vc, i, rgb_background); break; case 39: - vc->vc_color = (vc->vc_def_color & 0x0f) | - (vc->vc_color & 0xf0); + vc->state.color = (vc->vc_def_color & 0x0f) | + (vc->state.color & 0xf0); break; case 49: - vc->vc_color = (vc->vc_def_color & 0xf0) | - (vc->vc_color & 0x0f); + vc->state.color = (vc->vc_def_color & 0xf0) | + (vc->state.color & 0x0f); break; default: if (vc->vc_par[i] >= 90 && vc->vc_par[i] <= 107) { if (vc->vc_par[i] < 100) - vc->vc_intensity = 2; + vc->state.intensity = VCI_BOLD; vc->vc_par[i] -= 60; } if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37) - vc->vc_color = color_table[vc->vc_par[i] - 30] - | (vc->vc_color & 0xf0); + vc->state.color = color_table[vc->vc_par[i] - 30] + | (vc->state.color & 0xf0); else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47) - vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4) - | (vc->vc_color & 0x0f); + vc->state.color = (color_table[vc->vc_par[i] - 40] << 4) + | (vc->state.color & 0x0f); break; } update_attr(vc); } -static void respond_string(const char *p, struct tty_port *port) +static void respond_string(const char *p, size_t len, struct tty_port *port) { - while (*p) { - tty_insert_flip_char(port, *p, 0); - p++; - } + tty_insert_flip_string(port, p, len); tty_schedule_flip(port); } static void cursor_report(struct vc_data *vc, struct tty_struct *tty) { char buf[40]; + int len; - sprintf(buf, "\033[%d;%dR", vc->vc_y + (vc->vc_decom ? vc->vc_top + 1 : 1), vc->vc_x + 1); - respond_string(buf, tty->port); + len = sprintf(buf, "\033[%d;%dR", vc->state.y + + (vc->vc_decom ? vc->vc_top + 1 : 1), + vc->state.x + 1); + respond_string(buf, len, tty->port); } static inline void status_report(struct tty_struct *tty) { - respond_string("\033[0n", tty->port); /* Terminal ok */ + static const char teminal_ok[] = "\033[0n"; + + respond_string(teminal_ok, strlen(teminal_ok), tty->port); } static inline void respond_ID(struct tty_struct *tty) { - respond_string(VT102ID, tty->port); + /* terminal answer to an ESC-Z or csi0c query. */ + static const char vt102_id[] = "\033[?6c"; + + respond_string(vt102_id, strlen(vt102_id), tty->port); } void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry) { char buf[8]; + int len; - sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx), - (char)('!' + mry)); - respond_string(buf, tty->port); + len = sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), + (char)('!' + mrx), (char)('!' + mry)); + respond_string(buf, len, tty->port); } /* invoked via ioctl(TIOCLINUX) and through set_selection_user */ @@ -1930,14 +1936,14 @@ static void setterm_command(struct vc_data *vc) case 1: /* set color for underline mode */ if (vc->vc_can_do_color && vc->vc_par[1] < 16) { vc->vc_ulcolor = color_table[vc->vc_par[1]]; - if (vc->vc_underline) + if (vc->state.underline) update_attr(vc); } break; case 2: /* set color for half intensity mode */ if (vc->vc_can_do_color && vc->vc_par[1] < 16) { vc->vc_halfcolor = color_table[vc->vc_par[1]]; - if (vc->vc_intensity == 0) + if (vc->state.intensity == VCI_HALF_BRIGHT) update_attr(vc); } break; @@ -1991,8 +1997,8 @@ static void setterm_command(struct vc_data *vc) /* console_lock is held */ static void csi_at(struct vc_data *vc, unsigned int nr) { - if (nr > vc->vc_cols - vc->vc_x) - nr = vc->vc_cols - vc->vc_x; + if (nr > vc->vc_cols - vc->state.x) + nr = vc->vc_cols - vc->state.x; else if (!nr) nr = 1; insert_char(vc, nr); @@ -2001,19 +2007,19 @@ static void csi_at(struct vc_data *vc, unsigned int nr) /* console_lock is held */ static void csi_L(struct vc_data *vc, unsigned int nr) { - if (nr > vc->vc_rows - vc->vc_y) - nr = vc->vc_rows - vc->vc_y; + if (nr > vc->vc_rows - vc->state.y) + nr = vc->vc_rows - vc->state.y; else if (!nr) nr = 1; - con_scroll(vc, vc->vc_y, vc->vc_bottom, SM_DOWN, nr); + con_scroll(vc, vc->state.y, vc->vc_bottom, SM_DOWN, nr); vc->vc_need_wrap = 0; } /* console_lock is held */ static void csi_P(struct vc_data *vc, unsigned int nr) { - if (nr > vc->vc_cols - vc->vc_x) - nr = vc->vc_cols - vc->vc_x; + if (nr > vc->vc_cols - vc->state.x) + nr = vc->vc_cols - vc->state.x; else if (!nr) nr = 1; delete_char(vc, nr); @@ -2022,44 +2028,28 @@ static void csi_P(struct vc_data *vc, unsigned int nr) /* console_lock is held */ static void csi_M(struct vc_data *vc, unsigned int nr) { - if (nr > vc->vc_rows - vc->vc_y) - nr = vc->vc_rows - vc->vc_y; + if (nr > vc->vc_rows - vc->state.y) + nr = vc->vc_rows - vc->state.y; else if (!nr) nr=1; - con_scroll(vc, vc->vc_y, vc->vc_bottom, SM_UP, nr); + con_scroll(vc, vc->state.y, vc->vc_bottom, SM_UP, nr); vc->vc_need_wrap = 0; } /* console_lock is held (except via vc_init->reset_terminal */ static void save_cur(struct vc_data *vc) { - vc->vc_saved_x = vc->vc_x; - vc->vc_saved_y = vc->vc_y; - vc->vc_s_intensity = vc->vc_intensity; - vc->vc_s_italic = vc->vc_italic; - vc->vc_s_underline = vc->vc_underline; - vc->vc_s_blink = vc->vc_blink; - vc->vc_s_reverse = vc->vc_reverse; - vc->vc_s_charset = vc->vc_charset; - vc->vc_s_color = vc->vc_color; - vc->vc_saved_G0 = vc->vc_G0_charset; - vc->vc_saved_G1 = vc->vc_G1_charset; + memcpy(&vc->saved_state, &vc->state, sizeof(vc->state)); } /* console_lock is held */ static void restore_cur(struct vc_data *vc) { - gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y); - vc->vc_intensity = vc->vc_s_intensity; - vc->vc_italic = vc->vc_s_italic; - vc->vc_underline = vc->vc_s_underline; - vc->vc_blink = vc->vc_s_blink; - vc->vc_reverse = vc->vc_s_reverse; - vc->vc_charset = vc->vc_s_charset; - vc->vc_color = vc->vc_s_color; - vc->vc_G0_charset = vc->vc_saved_G0; - vc->vc_G1_charset = vc->vc_saved_G1; - vc->vc_translate = set_translate(vc->vc_charset ? vc->vc_G1_charset : vc->vc_G0_charset, vc); + memcpy(&vc->state, &vc->saved_state, sizeof(vc->state)); + + gotoxy(vc, vc->state.x, vc->state.y); + vc->vc_translate = set_translate(vc->state.Gx_charset[vc->state.charset], + vc); update_attr(vc); vc->vc_need_wrap = 0; } @@ -2071,14 +2061,16 @@ enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey, /* console_lock is held (except via vc_init()) */ static void reset_terminal(struct vc_data *vc, int do_clear) { + unsigned int i; + vc->vc_top = 0; vc->vc_bottom = vc->vc_rows; vc->vc_state = ESnormal; vc->vc_priv = EPecma; vc->vc_translate = set_translate(LAT1_MAP, vc); - vc->vc_G0_charset = LAT1_MAP; - vc->vc_G1_charset = GRAF_MAP; - vc->vc_charset = 0; + vc->state.Gx_charset[0] = LAT1_MAP; + vc->state.Gx_charset[1] = GRAF_MAP; + vc->state.charset = 0; vc->vc_need_wrap = 0; vc->vc_report_mouse = 0; vc->vc_utf = default_utf8; @@ -2101,14 +2093,9 @@ static void reset_terminal(struct vc_data *vc, int do_clear) default_attr(vc); update_attr(vc); - vc->vc_tab_stop[0] = - vc->vc_tab_stop[1] = - vc->vc_tab_stop[2] = - vc->vc_tab_stop[3] = - vc->vc_tab_stop[4] = - vc->vc_tab_stop[5] = - vc->vc_tab_stop[6] = - vc->vc_tab_stop[7] = 0x01010101; + bitmap_zero(vc->vc_tab_stop, VC_TABSTOPS_COUNT); + for (i = 0; i < VC_TABSTOPS_COUNT; i += 8) + set_bit(i, vc->vc_tab_stop); vc->vc_bell_pitch = DEFAULT_BELL_PITCH; vc->vc_bell_duration = DEFAULT_BELL_DURATION; @@ -2120,6 +2107,29 @@ static void reset_terminal(struct vc_data *vc, int do_clear) csi_J(vc, 2); } +static void vc_setGx(struct vc_data *vc, unsigned int which, int c) +{ + unsigned char *charset = &vc->state.Gx_charset[which]; + + switch (c) { + case '0': + *charset = GRAF_MAP; + break; + case 'B': + *charset = LAT1_MAP; + break; + case 'U': + *charset = IBMPC_MAP; + break; + case 'K': + *charset = USER_MAP; + break; + } + + if (vc->state.charset == which) + vc->vc_translate = set_translate(*charset, vc); +} + /* console_lock is held */ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) { @@ -2142,13 +2152,15 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) bs(vc); return; case 9: - vc->vc_pos -= (vc->vc_x << 1); - while (vc->vc_x < vc->vc_cols - 1) { - vc->vc_x++; - if (vc->vc_tab_stop[7 & (vc->vc_x >> 5)] & (1 << (vc->vc_x & 31))) - break; - } - vc->vc_pos += (vc->vc_x << 1); + vc->vc_pos -= (vc->state.x << 1); + + vc->state.x = find_next_bit(vc->vc_tab_stop, + min(vc->vc_cols - 1, VC_TABSTOPS_COUNT), + vc->state.x + 1); + if (vc->state.x >= VC_TABSTOPS_COUNT) + vc->state.x = vc->vc_cols - 1; + + vc->vc_pos += (vc->state.x << 1); notify_write(vc, '\t'); return; case 10: case 11: case 12: @@ -2160,13 +2172,13 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) cr(vc); return; case 14: - vc->vc_charset = 1; - vc->vc_translate = set_translate(vc->vc_G1_charset, vc); + vc->state.charset = 1; + vc->vc_translate = set_translate(vc->state.Gx_charset[1], vc); vc->vc_disp_ctrl = 1; return; case 15: - vc->vc_charset = 0; - vc->vc_translate = set_translate(vc->vc_G0_charset, vc); + vc->state.charset = 0; + vc->vc_translate = set_translate(vc->state.Gx_charset[0], vc); vc->vc_disp_ctrl = 0; return; case 24: case 26: @@ -2206,7 +2218,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) lf(vc); return; case 'H': - vc->vc_tab_stop[7 & (vc->vc_x >> 5)] |= (1 << (vc->vc_x & 31)); + if (vc->state.x < VC_TABSTOPS_COUNT) + set_bit(vc->state.x, vc->vc_tab_stop); return; case 'Z': respond_ID(tty); @@ -2320,7 +2333,10 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) case 'c': if (vc->vc_priv == EPdec) { if (vc->vc_par[0]) - vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16); + vc->vc_cursor_type = + CUR_MAKE(vc->vc_par[0], + vc->vc_par[1], + vc->vc_par[2]); else vc->vc_cursor_type = cur_default; return; @@ -2353,42 +2369,42 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) case 'G': case '`': if (vc->vc_par[0]) vc->vc_par[0]--; - gotoxy(vc, vc->vc_par[0], vc->vc_y); + gotoxy(vc, vc->vc_par[0], vc->state.y); return; case 'A': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, vc->vc_x, vc->vc_y - vc->vc_par[0]); + gotoxy(vc, vc->state.x, vc->state.y - vc->vc_par[0]); return; case 'B': case 'e': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, vc->vc_x, vc->vc_y + vc->vc_par[0]); + gotoxy(vc, vc->state.x, vc->state.y + vc->vc_par[0]); return; case 'C': case 'a': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, vc->vc_x + vc->vc_par[0], vc->vc_y); + gotoxy(vc, vc->state.x + vc->vc_par[0], vc->state.y); return; case 'D': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, vc->vc_x - vc->vc_par[0], vc->vc_y); + gotoxy(vc, vc->state.x - vc->vc_par[0], vc->state.y); return; case 'E': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, 0, vc->vc_y + vc->vc_par[0]); + gotoxy(vc, 0, vc->state.y + vc->vc_par[0]); return; case 'F': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, 0, vc->vc_y - vc->vc_par[0]); + gotoxy(vc, 0, vc->state.y - vc->vc_par[0]); return; case 'd': if (vc->vc_par[0]) vc->vc_par[0]--; - gotoxay(vc, vc->vc_x ,vc->vc_par[0]); + gotoxay(vc, vc->state.x ,vc->vc_par[0]); return; case 'H': case 'f': if (vc->vc_par[0]) @@ -2417,18 +2433,10 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) respond_ID(tty); return; case 'g': - if (!vc->vc_par[0]) - vc->vc_tab_stop[7 & (vc->vc_x >> 5)] &= ~(1 << (vc->vc_x & 31)); - else if (vc->vc_par[0] == 3) { - vc->vc_tab_stop[0] = - vc->vc_tab_stop[1] = - vc->vc_tab_stop[2] = - vc->vc_tab_stop[3] = - vc->vc_tab_stop[4] = - vc->vc_tab_stop[5] = - vc->vc_tab_stop[6] = - vc->vc_tab_stop[7] = 0; - } + if (!vc->vc_par[0] && vc->state.x < VC_TABSTOPS_COUNT) + set_bit(vc->state.x, vc->vc_tab_stop); + else if (vc->vc_par[0] == 3) + bitmap_zero(vc->vc_tab_stop, VC_TABSTOPS_COUNT); return; case 'm': csi_m(vc); @@ -2502,29 +2510,11 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) } return; case ESsetG0: - if (c == '0') - vc->vc_G0_charset = GRAF_MAP; - else if (c == 'B') - vc->vc_G0_charset = LAT1_MAP; - else if (c == 'U') - vc->vc_G0_charset = IBMPC_MAP; - else if (c == 'K') - vc->vc_G0_charset = USER_MAP; - if (vc->vc_charset == 0) - vc->vc_translate = set_translate(vc->vc_G0_charset, vc); + vc_setGx(vc, 0, c); vc->vc_state = ESnormal; return; case ESsetG1: - if (c == '0') - vc->vc_G1_charset = GRAF_MAP; - else if (c == 'B') - vc->vc_G1_charset = LAT1_MAP; - else if (c == 'U') - vc->vc_G1_charset = IBMPC_MAP; - else if (c == 'K') - vc->vc_G1_charset = USER_MAP; - if (vc->vc_charset == 1) - vc->vc_translate = set_translate(vc->vc_G1_charset, vc); + vc_setGx(vc, 1, c); vc->vc_state = ESnormal; return; case ESosc: @@ -2536,7 +2526,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) /* is_double_width() is based on the wcwidth() implementation by * Markus Kuhn -- 2007-05-26 (Unicode 5.0) - * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c + * Latest version: https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c */ struct interval { uint32_t first; @@ -2571,30 +2561,300 @@ static int is_double_width(uint32_t ucs) sizeof(struct interval), ucs_cmp) != NULL; } -static void con_flush(struct vc_data *vc, unsigned long draw_from, - unsigned long draw_to, int *draw_x) +struct vc_draw_region { + unsigned long from, to; + int x; +}; + +static void con_flush(struct vc_data *vc, struct vc_draw_region *draw) { - if (*draw_x < 0) + if (draw->x < 0) return; - vc->vc_sw->con_putcs(vc, (u16 *)draw_from, - (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, *draw_x); - *draw_x = -1; + vc->vc_sw->con_putcs(vc, (u16 *)draw->from, + (u16 *)draw->to - (u16 *)draw->from, vc->state.y, + draw->x); + draw->x = -1; +} + +static inline int vc_translate_ascii(const struct vc_data *vc, int c) +{ + if (IS_ENABLED(CONFIG_CONSOLE_TRANSLATIONS)) { + if (vc->vc_toggle_meta) + c |= 0x80; + + return vc->vc_translate[c]; + } + + return c; +} + + +/** + * vc_sanitize_unicode -- Replace invalid Unicode code points with U+FFFD + * @c: the received character, or U+FFFD for invalid sequences. + */ +static inline int vc_sanitize_unicode(const int c) +{ + if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) + return 0xfffd; + + return c; +} + +/** + * vc_translate_unicode -- Combine UTF-8 into Unicode in @vc_utf_char + * + * @vc_utf_char is the being-constructed unicode character. + * @vc_utf_count is the number of continuation bytes still expected to arrive. + * @vc_npar is the number of continuation bytes arrived so far. + */ +static int vc_translate_unicode(struct vc_data *vc, int c, bool *rescan) +{ + static const u32 utf8_length_changes[] = { + 0x0000007f, 0x000007ff, 0x0000ffff, + 0x001fffff, 0x03ffffff, 0x7fffffff + }; + + /* Continuation byte received */ + if ((c & 0xc0) == 0x80) { + /* Unexpected continuation byte? */ + if (!vc->vc_utf_count) + return 0xfffd; + + vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); + vc->vc_npar++; + if (--vc->vc_utf_count) + goto need_more_bytes; + + /* Got a whole character */ + c = vc->vc_utf_char; + /* Reject overlong sequences */ + if (c <= utf8_length_changes[vc->vc_npar - 1] || + c > utf8_length_changes[vc->vc_npar]) + return 0xfffd; + + return vc_sanitize_unicode(c); + } + + /* Single ASCII byte or first byte of a sequence received */ + if (vc->vc_utf_count) { + /* Continuation byte expected */ + *rescan = true; + vc->vc_utf_count = 0; + return 0xfffd; + } + + /* Nothing to do if an ASCII byte was received */ + if (c <= 0x7f) + return c; + + /* First byte of a multibyte sequence received */ + vc->vc_npar = 0; + if ((c & 0xe0) == 0xc0) { + vc->vc_utf_count = 1; + vc->vc_utf_char = (c & 0x1f); + } else if ((c & 0xf0) == 0xe0) { + vc->vc_utf_count = 2; + vc->vc_utf_char = (c & 0x0f); + } else if ((c & 0xf8) == 0xf0) { + vc->vc_utf_count = 3; + vc->vc_utf_char = (c & 0x07); + } else if ((c & 0xfc) == 0xf8) { + vc->vc_utf_count = 4; + vc->vc_utf_char = (c & 0x03); + } else if ((c & 0xfe) == 0xfc) { + vc->vc_utf_count = 5; + vc->vc_utf_char = (c & 0x01); + } else { + /* 254 and 255 are invalid */ + return 0xfffd; + } + +need_more_bytes: + return -1; +} + +static int vc_translate(struct vc_data *vc, int *c, bool *rescan) +{ + /* Do no translation at all in control states */ + if (vc->vc_state != ESnormal) + return *c; + + if (vc->vc_utf && !vc->vc_disp_ctrl) + return *c = vc_translate_unicode(vc, *c, rescan); + + /* no utf or alternate charset mode */ + return vc_translate_ascii(vc, *c); +} + +static inline unsigned char vc_invert_attr(const struct vc_data *vc) +{ + if (!vc->vc_can_do_color) + return vc->vc_attr ^ 0x08; + + if (vc->vc_hi_font_mask == 0x100) + return (vc->vc_attr & 0x11) | + ((vc->vc_attr & 0xe0) >> 4) | + ((vc->vc_attr & 0x0e) << 4); + + return (vc->vc_attr & 0x88) | + ((vc->vc_attr & 0x70) >> 4) | + ((vc->vc_attr & 0x07) << 4); +} + +static bool vc_is_control(struct vc_data *vc, int tc, int c) +{ + /* + * A bitmap for codes <32. A bit of 1 indicates that the code + * corresponding to that bit number invokes some special action (such + * as cursor movement) and should not be displayed as a glyph unless + * the disp_ctrl mode is explicitly enabled. + */ + static const u32 CTRL_ACTION = 0x0d00ff81; + /* Cannot be overridden by disp_ctrl */ + static const u32 CTRL_ALWAYS = 0x0800f501; + + if (vc->vc_state != ESnormal) + return true; + + if (!tc) + return true; + + /* + * If the original code was a control character we only allow a glyph + * to be displayed if the code is not normally used (such as for cursor + * movement) or if the disp_ctrl mode has been explicitly enabled. + * Certain characters (as given by the CTRL_ALWAYS bitmap) are always + * displayed as control characters, as the console would be pretty + * useless without them; to display an arbitrary font position use the + * direct-to-font zone in UTF-8 mode. + */ + if (c < 32) { + if (vc->vc_disp_ctrl) + return CTRL_ALWAYS & BIT(c); + else + return vc->vc_utf || (CTRL_ACTION & BIT(c)); + } + + if (c == 127 && !vc->vc_disp_ctrl) + return true; + + if (c == 128 + 27) + return true; + + return false; +} + +static int vc_con_write_normal(struct vc_data *vc, int tc, int c, + struct vc_draw_region *draw) +{ + int next_c; + unsigned char vc_attr = vc->vc_attr; + u16 himask = vc->vc_hi_font_mask, charmask = himask ? 0x1ff : 0xff; + u8 width = 1; + bool inverse = false; + + if (vc->vc_utf && !vc->vc_disp_ctrl) { + if (is_double_width(c)) + width = 2; + } + + /* Now try to find out how to display it */ + tc = conv_uni_to_pc(vc, tc); + if (tc & ~charmask) { + if (tc == -1 || tc == -2) + return -1; /* nothing to display */ + + /* Glyph not found */ + if ((!vc->vc_utf || vc->vc_disp_ctrl || c < 128) && + !(c & ~charmask)) { + /* + * In legacy mode use the glyph we get by a 1:1 + * mapping. + * This would make absolutely no sense with Unicode in + * mind, but do this for ASCII characters since a font + * may lack Unicode mapping info and we don't want to + * end up with having question marks only. + */ + tc = c; + } else { + /* + * Display U+FFFD. If it's not found, display an inverse + * question mark. + */ + tc = conv_uni_to_pc(vc, 0xfffd); + if (tc < 0) { + inverse = true; + tc = conv_uni_to_pc(vc, '?'); + if (tc < 0) + tc = '?'; + + vc_attr = vc_invert_attr(vc); + con_flush(vc, draw); + } + } + } + + next_c = c; + while (1) { + if (vc->vc_need_wrap || vc->vc_decim) + con_flush(vc, draw); + if (vc->vc_need_wrap) { + cr(vc); + lf(vc); + } + if (vc->vc_decim) + insert_char(vc, 1); + vc_uniscr_putc(vc, next_c); + + if (himask) + tc = ((tc & 0x100) ? himask : 0) | + (tc & 0xff); + tc |= (vc_attr << 8) & ~himask; + + scr_writew(tc, (u16 *)vc->vc_pos); + + if (con_should_update(vc) && draw->x < 0) { + draw->x = vc->state.x; + draw->from = vc->vc_pos; + } + if (vc->state.x == vc->vc_cols - 1) { + vc->vc_need_wrap = vc->vc_decawm; + draw->to = vc->vc_pos + 2; + } else { + vc->state.x++; + draw->to = (vc->vc_pos += 2); + } + + if (!--width) + break; + + /* A space is printed in the second column */ + tc = conv_uni_to_pc(vc, ' '); + if (tc < 0) + tc = ' '; + next_c = ' '; + } + notify_write(vc, c); + + if (inverse) + con_flush(vc, draw); + + return 0; } /* acquires console_lock */ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) { - int c, next_c, tc, ok, n = 0, draw_x = -1; + struct vc_draw_region draw = { + .x = -1, + }; + int c, tc, n = 0; unsigned int currcons; - unsigned long draw_from = 0, draw_to = 0; struct vc_data *vc; - unsigned char vc_attr; struct vt_notifier_param param; - uint8_t rescan; - uint8_t inverse; - uint8_t width; - u16 himask, charmask; + bool rescan; if (in_interrupt()) return count; @@ -2615,8 +2875,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co return 0; } - himask = vc->vc_hi_font_mask; - charmask = himask ? 0x1ff : 0xff; /* undraw cursor first */ if (con_is_fg(vc)) @@ -2626,209 +2884,35 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co while (!tty->stopped && count) { int orig = *buf; - c = orig; buf++; n++; count--; - rescan = 0; - inverse = 0; - width = 1; - - /* Do no translation at all in control states */ - if (vc->vc_state != ESnormal) { - tc = c; - } else if (vc->vc_utf && !vc->vc_disp_ctrl) { - /* Combine UTF-8 into Unicode in vc_utf_char. - * vc_utf_count is the number of continuation bytes still - * expected to arrive. - * vc_npar is the number of continuation bytes arrived so - * far - */ rescan_last_byte: - if ((c & 0xc0) == 0x80) { - /* Continuation byte received */ - static const uint32_t utf8_length_changes[] = { 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff }; - if (vc->vc_utf_count) { - vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); - vc->vc_npar++; - if (--vc->vc_utf_count) { - /* Still need some bytes */ - continue; - } - /* Got a whole character */ - c = vc->vc_utf_char; - /* Reject overlong sequences */ - if (c <= utf8_length_changes[vc->vc_npar - 1] || - c > utf8_length_changes[vc->vc_npar]) - c = 0xfffd; - } else { - /* Unexpected continuation byte */ - vc->vc_utf_count = 0; - c = 0xfffd; - } - } else { - /* Single ASCII byte or first byte of a sequence received */ - if (vc->vc_utf_count) { - /* Continuation byte expected */ - rescan = 1; - vc->vc_utf_count = 0; - c = 0xfffd; - } else if (c > 0x7f) { - /* First byte of a multibyte sequence received */ - vc->vc_npar = 0; - if ((c & 0xe0) == 0xc0) { - vc->vc_utf_count = 1; - vc->vc_utf_char = (c & 0x1f); - } else if ((c & 0xf0) == 0xe0) { - vc->vc_utf_count = 2; - vc->vc_utf_char = (c & 0x0f); - } else if ((c & 0xf8) == 0xf0) { - vc->vc_utf_count = 3; - vc->vc_utf_char = (c & 0x07); - } else if ((c & 0xfc) == 0xf8) { - vc->vc_utf_count = 4; - vc->vc_utf_char = (c & 0x03); - } else if ((c & 0xfe) == 0xfc) { - vc->vc_utf_count = 5; - vc->vc_utf_char = (c & 0x01); - } else { - /* 254 and 255 are invalid */ - c = 0xfffd; - } - if (vc->vc_utf_count) { - /* Still need some bytes */ - continue; - } - } - /* Nothing to do if an ASCII byte was received */ - } - /* End of UTF-8 decoding. */ - /* c is the received character, or U+FFFD for invalid sequences. */ - /* Replace invalid Unicode code points with U+FFFD too */ - if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) - c = 0xfffd; - tc = c; - } else { /* no utf or alternate charset mode */ - tc = vc_translate(vc, c); - } + c = orig; + rescan = false; + + tc = vc_translate(vc, &c, &rescan); + if (tc == -1) + continue; param.c = tc; if (atomic_notifier_call_chain(&vt_notifier_list, VT_PREWRITE, ¶m) == NOTIFY_STOP) continue; - /* If the original code was a control character we - * only allow a glyph to be displayed if the code is - * not normally used (such as for cursor movement) or - * if the disp_ctrl mode has been explicitly enabled. - * Certain characters (as given by the CTRL_ALWAYS - * bitmap) are always displayed as control characters, - * as the console would be pretty useless without - * them; to display an arbitrary font position use the - * direct-to-font zone in UTF-8 mode. - */ - ok = tc && (c >= 32 || - !(vc->vc_disp_ctrl ? (CTRL_ALWAYS >> c) & 1 : - vc->vc_utf || ((CTRL_ACTION >> c) & 1))) - && (c != 127 || vc->vc_disp_ctrl) - && (c != 128+27); - - if (vc->vc_state == ESnormal && ok) { - if (vc->vc_utf && !vc->vc_disp_ctrl) { - if (is_double_width(c)) - width = 2; - } - /* Now try to find out how to display it */ - tc = conv_uni_to_pc(vc, tc); - if (tc & ~charmask) { - if (tc == -1 || tc == -2) { - continue; /* nothing to display */ - } - /* Glyph not found */ - if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) { - /* In legacy mode use the glyph we get by a 1:1 mapping. - This would make absolutely no sense with Unicode in mind, - but do this for ASCII characters since a font may lack - Unicode mapping info and we don't want to end up with - having question marks only. */ - tc = c; - } else { - /* Display U+FFFD. If it's not found, display an inverse question mark. */ - tc = conv_uni_to_pc(vc, 0xfffd); - if (tc < 0) { - inverse = 1; - tc = conv_uni_to_pc(vc, '?'); - if (tc < 0) tc = '?'; - } - } - } - - if (!inverse) { - vc_attr = vc->vc_attr; - } else { - /* invert vc_attr */ - if (!vc->vc_can_do_color) { - vc_attr = (vc->vc_attr) ^ 0x08; - } else if (vc->vc_hi_font_mask == 0x100) { - vc_attr = ((vc->vc_attr) & 0x11) | (((vc->vc_attr) & 0xe0) >> 4) | (((vc->vc_attr) & 0x0e) << 4); - } else { - vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4); - } - con_flush(vc, draw_from, draw_to, &draw_x); - } - - next_c = c; - while (1) { - if (vc->vc_need_wrap || vc->vc_decim) - con_flush(vc, draw_from, draw_to, - &draw_x); - if (vc->vc_need_wrap) { - cr(vc); - lf(vc); - } - if (vc->vc_decim) - insert_char(vc, 1); - vc_uniscr_putc(vc, next_c); - scr_writew(himask ? - ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : - (vc_attr << 8) + tc, - (u16 *) vc->vc_pos); - if (con_should_update(vc) && draw_x < 0) { - draw_x = vc->vc_x; - draw_from = vc->vc_pos; - } - if (vc->vc_x == vc->vc_cols - 1) { - vc->vc_need_wrap = vc->vc_decawm; - draw_to = vc->vc_pos + 2; - } else { - vc->vc_x++; - draw_to = (vc->vc_pos += 2); - } - - if (!--width) break; - - tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */ - if (tc < 0) tc = ' '; - next_c = ' '; - } - notify_write(vc, c); - - if (inverse) - con_flush(vc, draw_from, draw_to, &draw_x); - - if (rescan) { - rescan = 0; - inverse = 0; - width = 1; - c = orig; - goto rescan_last_byte; - } + if (vc_is_control(vc, tc, c)) { + con_flush(vc, &draw); + do_con_trol(tty, vc, orig); continue; } - con_flush(vc, draw_from, draw_to, &draw_x); - do_con_trol(tty, vc, orig); + + if (vc_con_write_normal(vc, tc, c, &draw) < 0) + continue; + + if (rescan) + goto rescan_last_byte; } - con_flush(vc, draw_from, draw_to, &draw_x); + con_flush(vc, &draw); vc_uniscr_debug_check(vc); console_conditional_schedule(); notify_update(vc); @@ -2978,25 +3062,25 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) hide_cursor(vc); start = (ushort *)vc->vc_pos; - start_x = vc->vc_x; + start_x = vc->state.x; cnt = 0; while (count--) { c = *b++; if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) { if (cnt && con_is_visible(vc)) - vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x); + vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x); cnt = 0; if (c == 8) { /* backspace */ bs(vc); start = (ushort *)vc->vc_pos; - start_x = vc->vc_x; + start_x = vc->state.x; continue; } if (c != 13) lf(vc); cr(vc); start = (ushort *)vc->vc_pos; - start_x = vc->vc_x; + start_x = vc->state.x; if (c == 10 || c == 13) continue; } @@ -3004,15 +3088,15 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos); notify_write(vc, c); cnt++; - if (vc->vc_x == vc->vc_cols - 1) { + if (vc->state.x == vc->vc_cols - 1) { vc->vc_need_wrap = 1; } else { vc->vc_pos += 2; - vc->vc_x++; + vc->state.x++; } } if (cnt && con_is_visible(vc)) - vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x); + vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x); set_cursor(vc); notify_update(vc); @@ -3408,7 +3492,7 @@ static int __init con_init(void) master_display_fg = vc = vc_cons[currcons].d; set_origin(vc); save_screen(vc); - gotoxy(vc, vc->vc_x, vc->vc_y); + gotoxy(vc, vc->state.x, vc->state.y); csi_J(vc, 0); update_screen(vc); pr_info("Console: %s %s %dx%d\n", @@ -4687,8 +4771,8 @@ EXPORT_SYMBOL_GPL(screen_pos); void getconsxy(struct vc_data *vc, unsigned char *p) { /* clamp values if they don't fit */ - p[0] = min(vc->vc_x, 0xFFu); - p[1] = min(vc->vc_y, 0xFFu); + p[0] = min(vc->state.x, 0xFFu); + p[1] = min(vc->state.y, 0xFFu); } void putconsxy(struct vc_data *vc, unsigned char *p) diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index daf61c28ba7666f1a766f2b785ae09039f4cd4a2..91c3017750476d73ec9b193b9b8a7fe1995624fe 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -241,136 +241,56 @@ int vt_waitactive(int n) #define GPLAST 0x3df #define GPNUM (GPLAST - GPFIRST + 1) - - -static inline int -do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op) -{ - struct consolefontdesc cfdarg; - int i; - - if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) - return -EFAULT; - - switch (cmd) { - case PIO_FONTX: - if (!perm) - return -EPERM; - op->op = KD_FONT_OP_SET; - op->flags = KD_FONT_FLAG_OLD; - op->width = 8; - op->height = cfdarg.charheight; - op->charcount = cfdarg.charcount; - op->data = cfdarg.chardata; - return con_font_op(vc_cons[fg_console].d, op); - case GIO_FONTX: { - op->op = KD_FONT_OP_GET; - op->flags = KD_FONT_FLAG_OLD; - op->width = 8; - op->height = cfdarg.charheight; - op->charcount = cfdarg.charcount; - op->data = cfdarg.chardata; - i = con_font_op(vc_cons[fg_console].d, op); - if (i) - return i; - cfdarg.charheight = op->height; - cfdarg.charcount = op->charcount; - if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) - return -EFAULT; - return 0; - } - } - return -EINVAL; -} - -static inline int -do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc) +/* + * currently, setting the mode from KD_TEXT to KD_GRAPHICS doesn't do a whole + * lot. i'm not sure if it should do any restoration of modes or what... + * + * XXX It should at least call into the driver, fbdev's definitely need to + * restore their engine state. --BenH + */ +static int vt_kdsetmode(struct vc_data *vc, unsigned long mode) { - struct unimapdesc tmp; - - if (copy_from_user(&tmp, user_ud, sizeof tmp)) - return -EFAULT; - switch (cmd) { - case PIO_UNIMAP: - if (!perm) - return -EPERM; - return con_set_unimap(vc, tmp.entry_ct, tmp.entries); - case GIO_UNIMAP: - if (!perm && fg_console != vc->vc_num) - return -EPERM; - return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries); + switch (mode) { + case KD_GRAPHICS: + break; + case KD_TEXT0: + case KD_TEXT1: + mode = KD_TEXT; + fallthrough; + case KD_TEXT: + break; + default: + return -EINVAL; } - return 0; -} - -/* deallocate a single console, if possible (leave 0) */ -static int vt_disallocate(unsigned int vc_num) -{ - struct vc_data *vc = NULL; - int ret = 0; - - console_lock(); - if (vt_busy(vc_num)) - ret = -EBUSY; - else if (vc_num) - vc = vc_deallocate(vc_num); - console_unlock(); - if (vc && vc_num >= MIN_NR_CONSOLES) - tty_port_put(&vc->port); - - return ret; -} + /* FIXME: this needs the console lock extending */ + if (vc->vc_mode == mode) + return 0; -/* deallocate all unused consoles, but leave 0 */ -static void vt_disallocate_all(void) -{ - struct vc_data *vc[MAX_NR_CONSOLES]; - int i; + vc->vc_mode = mode; + if (vc->vc_num != fg_console) + return 0; + /* explicitly blank/unblank the screen if switching modes */ console_lock(); - for (i = 1; i < MAX_NR_CONSOLES; i++) - if (!vt_busy(i)) - vc[i] = vc_deallocate(i); - else - vc[i] = NULL; + if (mode == KD_TEXT) + do_unblank_screen(1); + else + do_blank_screen(1); console_unlock(); - for (i = 1; i < MAX_NR_CONSOLES; i++) { - if (vc[i] && i >= MIN_NR_CONSOLES) - tty_port_put(&vc[i]->port); - } + return 0; } - -/* - * We handle the console-specific ioctl's here. We allow the - * capability to modify any console, not just the fg_console. - */ -int vt_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) +static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd, + unsigned long arg, bool perm) { struct vc_data *vc = tty->driver_data; - struct console_font_op op; /* used in multiple places here */ - unsigned int console = vc->vc_num; - unsigned char ucval; - unsigned int uival; void __user *up = (void __user *)arg; - int i, perm; - int ret = 0; + unsigned int console = vc->vc_num; + int ret; - /* - * To have permissions to do most of the vt ioctls, we either have - * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. - */ - perm = 0; - if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) - perm = 1; - switch (cmd) { - case TIOCLINUX: - ret = tioclinux(tty, arg); - break; case KIOCSOUND: if (!perm) return -EPERM; @@ -390,7 +310,7 @@ int vt_ioctl(struct tty_struct *tty, return -EPERM; { unsigned int ticks, count; - + /* * Generate the tone for the appropriate number of ticks. * If the time is zero, turn off sound ourselves. @@ -407,9 +327,7 @@ int vt_ioctl(struct tty_struct *tty, /* * this is naïve. */ - ucval = KB_101; - ret = put_user(ucval, (char __user *)arg); - break; + return put_user(KB_101, (char __user *)arg); /* * These cannot be implemented on any machine that implements @@ -426,84 +344,45 @@ int vt_ioctl(struct tty_struct *tty, * * These are locked internally via sys_ioperm */ - if (arg < GPFIRST || arg > GPLAST) { - ret = -EINVAL; - break; - } - ret = ksys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0; - break; + if (arg < GPFIRST || arg > GPLAST) + return -EINVAL; + + return ksys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0; case KDENABIO: case KDDISABIO: - ret = ksys_ioperm(GPFIRST, GPNUM, + return ksys_ioperm(GPFIRST, GPNUM, (cmd == KDENABIO)) ? -ENXIO : 0; - break; #endif /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */ - + case KDKBDREP: { struct kbd_repeat kbrep; - + if (!capable(CAP_SYS_TTY_CONFIG)) return -EPERM; - if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) { - ret = -EFAULT; - break; - } + if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) + return -EFAULT; + ret = kbd_rate(&kbrep); if (ret) - break; + return ret; if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat))) - ret = -EFAULT; + return -EFAULT; break; } case KDSETMODE: - /* - * currently, setting the mode from KD_TEXT to KD_GRAPHICS - * doesn't do a whole lot. i'm not sure if it should do any - * restoration of modes or what... - * - * XXX It should at least call into the driver, fbdev's definitely - * need to restore their engine state. --BenH - */ if (!perm) return -EPERM; - switch (arg) { - case KD_GRAPHICS: - break; - case KD_TEXT0: - case KD_TEXT1: - arg = KD_TEXT; - case KD_TEXT: - break; - default: - ret = -EINVAL; - goto out; - } - /* FIXME: this needs the console lock extending */ - if (vc->vc_mode == (unsigned char) arg) - break; - vc->vc_mode = (unsigned char) arg; - if (console != fg_console) - break; - /* - * explicitly blank/unblank the screen if switching modes - */ - console_lock(); - if (arg == KD_TEXT) - do_unblank_screen(1); - else - do_blank_screen(1); - console_unlock(); - break; + + return vt_kdsetmode(vc, arg); case KDGETMODE: - uival = vc->vc_mode; - goto setint; + return put_user(vc->vc_mode, (int __user *)arg); case KDMAPDISP: case KDUNMAPDISP: @@ -511,51 +390,42 @@ int vt_ioctl(struct tty_struct *tty, * these work like a combination of mmap and KDENABIO. * this could be easily finished. */ - ret = -EINVAL; - break; + return -EINVAL; case KDSKBMODE: if (!perm) return -EPERM; ret = vt_do_kdskbmode(console, arg); - if (ret == 0) - tty_ldisc_flush(tty); + if (ret) + return ret; + tty_ldisc_flush(tty); break; case KDGKBMODE: - uival = vt_do_kdgkbmode(console); - ret = put_user(uival, (int __user *)arg); - break; + return put_user(vt_do_kdgkbmode(console), (int __user *)arg); /* this could be folded into KDSKBMODE, but for compatibility reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ case KDSKBMETA: - ret = vt_do_kdskbmeta(console, arg); - break; + return vt_do_kdskbmeta(console, arg); case KDGKBMETA: /* FIXME: should review whether this is worth locking */ - uival = vt_do_kdgkbmeta(console); - setint: - ret = put_user(uival, (int __user *)arg); - break; + return put_user(vt_do_kdgkbmeta(console), (int __user *)arg); case KDGETKEYCODE: case KDSETKEYCODE: if(!capable(CAP_SYS_TTY_CONFIG)) perm = 0; - ret = vt_do_kbkeycode_ioctl(cmd, up, perm); - break; + return vt_do_kbkeycode_ioctl(cmd, up, perm); case KDGKBENT: case KDSKBENT: - ret = vt_do_kdsk_ioctl(cmd, up, perm, console); - break; + return vt_do_kdsk_ioctl(cmd, up, perm, console); case KDGKBSENT: case KDSKBSENT: - ret = vt_do_kdgkb_ioctl(cmd, up, perm); - break; + return vt_do_kdgkb_ioctl(cmd, up, perm); /* Diacritical processing. Handled in keyboard.c as it has to operate on the keyboard locks and structures */ @@ -563,8 +433,7 @@ int vt_ioctl(struct tty_struct *tty, case KDGKBDIACRUC: case KDSKBDIACR: case KDSKBDIACRUC: - ret = vt_do_diacrit(cmd, up, perm); - break; + return vt_do_diacrit(cmd, up, perm); /* the ioctls below read/set the flags usually shown in the leds */ /* don't use them - they will go away without warning */ @@ -572,8 +441,7 @@ int vt_ioctl(struct tty_struct *tty, case KDSKBLED: case KDGETLED: case KDSETLED: - ret = vt_do_kdskled(console, cmd, arg, perm); - break; + return vt_do_kdskled(console, cmd, arg, perm); /* * A process can indicate its willingness to accept signals @@ -583,161 +451,504 @@ int vt_ioctl(struct tty_struct *tty, * See also the kbrequest field of inittab(5). */ case KDSIGACCEPT: - { if (!perm || !capable(CAP_KILL)) return -EPERM; if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) - ret = -EINVAL; - else { - spin_lock_irq(&vt_spawn_con.lock); - put_pid(vt_spawn_con.pid); - vt_spawn_con.pid = get_pid(task_pid(current)); - vt_spawn_con.sig = arg; - spin_unlock_irq(&vt_spawn_con.lock); - } + return -EINVAL; + + spin_lock_irq(&vt_spawn_con.lock); + put_pid(vt_spawn_con.pid); + vt_spawn_con.pid = get_pid(task_pid(current)); + vt_spawn_con.sig = arg; + spin_unlock_irq(&vt_spawn_con.lock); break; - } - case VT_SETMODE: - { - struct vt_mode tmp; + case KDFONTOP: { + struct console_font_op op; - if (!perm) + if (copy_from_user(&op, up, sizeof(op))) + return -EFAULT; + if (!perm && op.op != KD_FONT_OP_GET) return -EPERM; - if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) { - ret = -EFAULT; - goto out; - } - if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) { - ret = -EINVAL; - goto out; - } - console_lock(); - vc->vt_mode = tmp; - /* the frsig is ignored, so we set it to 0 */ - vc->vt_mode.frsig = 0; - put_pid(vc->vt_pid); - vc->vt_pid = get_pid(task_pid(current)); - /* no switch is required -- saw@shade.msu.ru */ - vc->vt_newvt = -1; - console_unlock(); + ret = con_font_op(vc, &op); + if (ret) + return ret; + if (copy_to_user(up, &op, sizeof(op))) + return -EFAULT; break; } - case VT_GETMODE: - { - struct vt_mode tmp; - int rc; + default: + return -ENOIOCTLCMD; + } - console_lock(); - memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode)); - console_unlock(); + return 0; +} - rc = copy_to_user(up, &tmp, sizeof(struct vt_mode)); - if (rc) - ret = -EFAULT; - break; - } +static inline int do_fontx_ioctl(int cmd, + struct consolefontdesc __user *user_cfd, + struct console_font_op *op) +{ + struct consolefontdesc cfdarg; + int i; - /* - * Returns global vt state. Note that VT 0 is always open, since - * it's an alias for the current VT, and people can't use it here. - * We cannot return state for more than 16 VTs, since v_state is short. - */ - case VT_GETSTATE: - { - struct vt_stat __user *vtstat = up; - unsigned short state, mask; + if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) + return -EFAULT; - if (put_user(fg_console + 1, &vtstat->v_active)) - ret = -EFAULT; - else { - state = 1; /* /dev/tty0 is always open */ - console_lock(); /* required by vt_in_use() */ - for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; - ++i, mask <<= 1) - if (vt_in_use(i)) - state |= mask; - console_unlock(); - ret = put_user(state, &vtstat->v_state); + switch (cmd) { + case PIO_FONTX: + op->op = KD_FONT_OP_SET; + op->flags = KD_FONT_FLAG_OLD; + op->width = 8; + op->height = cfdarg.charheight; + op->charcount = cfdarg.charcount; + op->data = cfdarg.chardata; + return con_font_op(vc_cons[fg_console].d, op); + case GIO_FONTX: { + op->op = KD_FONT_OP_GET; + op->flags = KD_FONT_FLAG_OLD; + op->width = 8; + op->height = cfdarg.charheight; + op->charcount = cfdarg.charcount; + op->data = cfdarg.chardata; + i = con_font_op(vc_cons[fg_console].d, op); + if (i) + return i; + cfdarg.charheight = op->height; + cfdarg.charcount = op->charcount; + if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) + return -EFAULT; + return 0; } - break; } + return -EINVAL; +} - /* - * Returns the first available (non-opened) console. - */ - case VT_OPENQRY: - console_lock(); /* required by vt_in_use() */ - for (i = 0; i < MAX_NR_CONSOLES; ++i) - if (!vt_in_use(i)) - break; - console_unlock(); - uival = i < MAX_NR_CONSOLES ? (i+1) : -1; - goto setint; +static int vt_io_fontreset(struct console_font_op *op) +{ + int ret; - /* - * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num, - * with num >= 1 (switches to vt 0, our console, are not allowed, just - * to preserve sanity). - */ - case VT_ACTIVATE: + if (__is_defined(BROKEN_GRAPHICS_PROGRAMS)) { + /* + * With BROKEN_GRAPHICS_PROGRAMS defined, the default font is + * not saved. + */ + return -ENOSYS; + } + + op->op = KD_FONT_OP_SET_DEFAULT; + op->data = NULL; + ret = con_font_op(vc_cons[fg_console].d, op); + if (ret) + return ret; + + console_lock(); + con_set_default_unimap(vc_cons[fg_console].d); + console_unlock(); + + return 0; +} + +static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, + struct vc_data *vc) +{ + struct unimapdesc tmp; + + if (copy_from_user(&tmp, user_ud, sizeof tmp)) + return -EFAULT; + switch (cmd) { + case PIO_UNIMAP: + return con_set_unimap(vc, tmp.entry_ct, tmp.entries); + case GIO_UNIMAP: + if (fg_console != vc->vc_num) + return -EPERM; + return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), + tmp.entries); + } + return 0; +} + +static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, + bool perm) +{ + struct console_font_op op; /* used in multiple places here */ + + switch (cmd) { + case PIO_FONT: if (!perm) return -EPERM; - if (arg == 0 || arg > MAX_NR_CONSOLES) - ret = -ENXIO; - else { - arg--; - console_lock(); - ret = vc_allocate(arg); - console_unlock(); - if (ret) - break; - set_console(arg); - } - break; + op.op = KD_FONT_OP_SET; + op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ + op.width = 8; + op.height = 0; + op.charcount = 256; + op.data = up; + return con_font_op(vc_cons[fg_console].d, &op); - case VT_SETACTIVATE: - { - struct vt_setactivate vsa; + case GIO_FONT: + op.op = KD_FONT_OP_GET; + op.flags = KD_FONT_FLAG_OLD; + op.width = 8; + op.height = 32; + op.charcount = 256; + op.data = up; + return con_font_op(vc_cons[fg_console].d, &op); + + case PIO_CMAP: + if (!perm) + return -EPERM; + return con_set_cmap(up); + case GIO_CMAP: + return con_get_cmap(up); + + case PIO_FONTX: + if (!perm) + return -EPERM; + + fallthrough; + case GIO_FONTX: + return do_fontx_ioctl(cmd, up, &op); + + case PIO_FONTRESET: + if (!perm) + return -EPERM; + + return vt_io_fontreset(&op); + + case PIO_SCRNMAP: + if (!perm) + return -EPERM; + return con_set_trans_old(up); + + case GIO_SCRNMAP: + return con_get_trans_old(up); + + case PIO_UNISCRNMAP: + if (!perm) + return -EPERM; + return con_set_trans_new(up); + + case GIO_UNISCRNMAP: + return con_get_trans_new(up); + + case PIO_UNIMAPCLR: if (!perm) return -EPERM; + con_clear_unimap(vc); + break; + + case PIO_UNIMAP: + case GIO_UNIMAP: + if (!perm) + return -EPERM; + + return do_unimap_ioctl(cmd, up, vc); + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static int vt_reldisp(struct vc_data *vc, unsigned int swtch) +{ + int newvt, ret; + + if (vc->vt_mode.mode != VT_PROCESS) + return -EINVAL; + + /* Switched-to response */ + if (vc->vt_newvt < 0) { + /* If it's just an ACK, ignore it */ + return swtch == VT_ACKACQ ? 0 : -EINVAL; + } + + /* Switching-from response */ + if (swtch == 0) { + /* Switch disallowed, so forget we were trying to do it. */ + vc->vt_newvt = -1; + return 0; + } + + /* The current vt has been released, so complete the switch. */ + newvt = vc->vt_newvt; + vc->vt_newvt = -1; + ret = vc_allocate(newvt); + if (ret) + return ret; - if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg, - sizeof(struct vt_setactivate))) { - ret = -EFAULT; - goto out; + /* + * When we actually do the console switch, make sure we are atomic with + * respect to other console switches.. + */ + complete_change_console(vc_cons[newvt].d); + + return 0; +} + +static int vt_setactivate(struct vt_setactivate __user *sa) +{ + struct vt_setactivate vsa; + struct vc_data *nvc; + int ret; + + if (copy_from_user(&vsa, sa, sizeof(vsa))) + return -EFAULT; + if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES) + return -ENXIO; + + vsa.console = array_index_nospec(vsa.console, MAX_NR_CONSOLES + 1); + vsa.console--; + console_lock(); + ret = vc_allocate(vsa.console); + if (ret) { + console_unlock(); + return ret; + } + + /* + * This is safe providing we don't drop the console sem between + * vc_allocate and finishing referencing nvc. + */ + nvc = vc_cons[vsa.console].d; + nvc->vt_mode = vsa.mode; + nvc->vt_mode.frsig = 0; + put_pid(nvc->vt_pid); + nvc->vt_pid = get_pid(task_pid(current)); + console_unlock(); + + /* Commence switch and lock */ + /* Review set_console locks */ + set_console(vsa.console); + + return 0; +} + +/* deallocate a single console, if possible (leave 0) */ +static int vt_disallocate(unsigned int vc_num) +{ + struct vc_data *vc = NULL; + int ret = 0; + + console_lock(); + if (vt_busy(vc_num)) + ret = -EBUSY; + else if (vc_num) + vc = vc_deallocate(vc_num); + console_unlock(); + + if (vc && vc_num >= MIN_NR_CONSOLES) + tty_port_put(&vc->port); + + return ret; +} + +/* deallocate all unused consoles, but leave 0 */ +static void vt_disallocate_all(void) +{ + struct vc_data *vc[MAX_NR_CONSOLES]; + int i; + + console_lock(); + for (i = 1; i < MAX_NR_CONSOLES; i++) + if (!vt_busy(i)) + vc[i] = vc_deallocate(i); + else + vc[i] = NULL; + console_unlock(); + + for (i = 1; i < MAX_NR_CONSOLES; i++) { + if (vc[i] && i >= MIN_NR_CONSOLES) + tty_port_put(&vc[i]->port); + } +} + +static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs) +{ + struct vt_consize v; + int i; + + if (copy_from_user(&v, cs, sizeof(struct vt_consize))) + return -EFAULT; + + /* FIXME: Should check the copies properly */ + if (!v.v_vlin) + v.v_vlin = vc->vc_scan_lines; + + if (v.v_clin) { + int rows = v.v_vlin / v.v_clin; + if (v.v_rows != rows) { + if (v.v_rows) /* Parameters don't add up */ + return -EINVAL; + v.v_rows = rows; } - if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES) - ret = -ENXIO; - else { - vsa.console = array_index_nospec(vsa.console, - MAX_NR_CONSOLES + 1); - vsa.console--; - console_lock(); - ret = vc_allocate(vsa.console); - if (ret == 0) { - struct vc_data *nvc; - /* This is safe providing we don't drop the - console sem between vc_allocate and - finishing referencing nvc */ - nvc = vc_cons[vsa.console].d; - nvc->vt_mode = vsa.mode; - nvc->vt_mode.frsig = 0; - put_pid(nvc->vt_pid); - nvc->vt_pid = get_pid(task_pid(current)); - } - console_unlock(); - if (ret) - break; - /* Commence switch and lock */ - /* Review set_console locks */ - set_console(vsa.console); + } + + if (v.v_vcol && v.v_ccol) { + int cols = v.v_vcol / v.v_ccol; + if (v.v_cols != cols) { + if (v.v_cols) + return -EINVAL; + v.v_cols = cols; } + } + + if (v.v_clin > 32) + return -EINVAL; + + for (i = 0; i < MAX_NR_CONSOLES; i++) { + struct vc_data *vcp; + + if (!vc_cons[i].d) + continue; + console_lock(); + vcp = vc_cons[i].d; + if (vcp) { + if (v.v_vlin) + vcp->vc_scan_lines = v.v_vlin; + if (v.v_clin) + vcp->vc_font.height = v.v_clin; + vcp->vc_resize_user = 1; + vc_resize(vcp, v.v_cols, v.v_rows); + } + console_unlock(); + } + + return 0; +} + +/* + * We handle the console-specific ioctl's here. We allow the + * capability to modify any console, not just the fg_console. + */ +int vt_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct vc_data *vc = tty->driver_data; + void __user *up = (void __user *)arg; + int i, perm; + int ret; + + /* + * To have permissions to do most of the vt ioctls, we either have + * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. + */ + perm = 0; + if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) + perm = 1; + + ret = vt_k_ioctl(tty, cmd, arg, perm); + if (ret != -ENOIOCTLCMD) + return ret; + + ret = vt_io_ioctl(vc, cmd, up, perm); + if (ret != -ENOIOCTLCMD) + return ret; + + switch (cmd) { + case TIOCLINUX: + return tioclinux(tty, arg); + case VT_SETMODE: + { + struct vt_mode tmp; + + if (!perm) + return -EPERM; + if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) + return -EFAULT; + if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) + return -EINVAL; + + console_lock(); + vc->vt_mode = tmp; + /* the frsig is ignored, so we set it to 0 */ + vc->vt_mode.frsig = 0; + put_pid(vc->vt_pid); + vc->vt_pid = get_pid(task_pid(current)); + /* no switch is required -- saw@shade.msu.ru */ + vc->vt_newvt = -1; + console_unlock(); + break; + } + + case VT_GETMODE: + { + struct vt_mode tmp; + int rc; + + console_lock(); + memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode)); + console_unlock(); + + rc = copy_to_user(up, &tmp, sizeof(struct vt_mode)); + if (rc) + return -EFAULT; break; } + /* + * Returns global vt state. Note that VT 0 is always open, since + * it's an alias for the current VT, and people can't use it here. + * We cannot return state for more than 16 VTs, since v_state is short. + */ + case VT_GETSTATE: + { + struct vt_stat __user *vtstat = up; + unsigned short state, mask; + + if (put_user(fg_console + 1, &vtstat->v_active)) + return -EFAULT; + + state = 1; /* /dev/tty0 is always open */ + console_lock(); /* required by vt_in_use() */ + for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; + ++i, mask <<= 1) + if (vt_in_use(i)) + state |= mask; + console_unlock(); + return put_user(state, &vtstat->v_state); + } + + /* + * Returns the first available (non-opened) console. + */ + case VT_OPENQRY: + console_lock(); /* required by vt_in_use() */ + for (i = 0; i < MAX_NR_CONSOLES; ++i) + if (!vt_in_use(i)) + break; + console_unlock(); + i = i < MAX_NR_CONSOLES ? (i+1) : -1; + return put_user(i, (int __user *)arg); + + /* + * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num, + * with num >= 1 (switches to vt 0, our console, are not allowed, just + * to preserve sanity). + */ + case VT_ACTIVATE: + if (!perm) + return -EPERM; + if (arg == 0 || arg > MAX_NR_CONSOLES) + return -ENXIO; + + arg--; + console_lock(); + ret = vc_allocate(arg); + console_unlock(); + if (ret) + return ret; + set_console(arg); + break; + + case VT_SETACTIVATE: + if (!perm) + return -EPERM; + + return vt_setactivate(up); + /* * wait until the specified VT has been activated */ @@ -745,10 +956,8 @@ int vt_ioctl(struct tty_struct *tty, if (!perm) return -EPERM; if (arg == 0 || arg > MAX_NR_CONSOLES) - ret = -ENXIO; - else - ret = vt_waitactive(arg); - break; + return -ENXIO; + return vt_waitactive(arg); /* * If a vt is under process control, the kernel will not switch to it @@ -765,258 +974,56 @@ int vt_ioctl(struct tty_struct *tty, return -EPERM; console_lock(); - if (vc->vt_mode.mode != VT_PROCESS) { - console_unlock(); - ret = -EINVAL; - break; - } - /* - * Switching-from response - */ - if (vc->vt_newvt >= 0) { - if (arg == 0) - /* - * Switch disallowed, so forget we were trying - * to do it. - */ - vc->vt_newvt = -1; - - else { - /* - * The current vt has been released, so - * complete the switch. - */ - int newvt; - newvt = vc->vt_newvt; - vc->vt_newvt = -1; - ret = vc_allocate(newvt); - if (ret) { - console_unlock(); - break; - } - /* - * When we actually do the console switch, - * make sure we are atomic with respect to - * other console switches.. - */ - complete_change_console(vc_cons[newvt].d); - } - } else { - /* - * Switched-to response - */ - /* - * If it's just an ACK, ignore it - */ - if (arg != VT_ACKACQ) - ret = -EINVAL; - } + ret = vt_reldisp(vc, arg); console_unlock(); - break; + + return ret; + /* * Disallocate memory associated to VT (but leave VT1) */ case VT_DISALLOCATE: - if (arg > MAX_NR_CONSOLES) { - ret = -ENXIO; - break; - } + if (arg > MAX_NR_CONSOLES) + return -ENXIO; + if (arg == 0) vt_disallocate_all(); else - ret = vt_disallocate(--arg); + return vt_disallocate(--arg); break; case VT_RESIZE: { struct vt_sizes __user *vtsizes = up; struct vc_data *vc; - ushort ll,cc; + if (!perm) return -EPERM; if (get_user(ll, &vtsizes->v_rows) || get_user(cc, &vtsizes->v_cols)) - ret = -EFAULT; - else { - console_lock(); - for (i = 0; i < MAX_NR_CONSOLES; i++) { - vc = vc_cons[i].d; - - if (vc) { - vc->vc_resize_user = 1; - /* FIXME: review v tty lock */ - vc_resize(vc_cons[i].d, cc, ll); - } - } - console_unlock(); - } - break; - } - - case VT_RESIZEX: - { - struct vt_consize v; - if (!perm) - return -EPERM; - if (copy_from_user(&v, up, sizeof(struct vt_consize))) return -EFAULT; - /* FIXME: Should check the copies properly */ - if (!v.v_vlin) - v.v_vlin = vc->vc_scan_lines; - if (v.v_clin) { - int rows = v.v_vlin/v.v_clin; - if (v.v_rows != rows) { - if (v.v_rows) /* Parameters don't add up */ - return -EINVAL; - v.v_rows = rows; - } - } - if (v.v_vcol && v.v_ccol) { - int cols = v.v_vcol/v.v_ccol; - if (v.v_cols != cols) { - if (v.v_cols) - return -EINVAL; - v.v_cols = cols; - } - } - - if (v.v_clin > 32) - return -EINVAL; + console_lock(); for (i = 0; i < MAX_NR_CONSOLES; i++) { - struct vc_data *vcp; - - if (!vc_cons[i].d) - continue; - console_lock(); - vcp = vc_cons[i].d; - if (vcp) { - if (v.v_vlin) - vcp->vc_scan_lines = v.v_vlin; - if (v.v_clin) - vcp->vc_font.height = v.v_clin; - vcp->vc_resize_user = 1; - vc_resize(vcp, v.v_cols, v.v_rows); + vc = vc_cons[i].d; + + if (vc) { + vc->vc_resize_user = 1; + /* FIXME: review v tty lock */ + vc_resize(vc_cons[i].d, cc, ll); } - console_unlock(); } - break; - } - - case PIO_FONT: { - if (!perm) - return -EPERM; - op.op = KD_FONT_OP_SET; - op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ - op.width = 8; - op.height = 0; - op.charcount = 256; - op.data = up; - ret = con_font_op(vc_cons[fg_console].d, &op); - break; - } - - case GIO_FONT: { - op.op = KD_FONT_OP_GET; - op.flags = KD_FONT_FLAG_OLD; - op.width = 8; - op.height = 32; - op.charcount = 256; - op.data = up; - ret = con_font_op(vc_cons[fg_console].d, &op); - break; - } - - case PIO_CMAP: - if (!perm) - ret = -EPERM; - else - ret = con_set_cmap(up); - break; - - case GIO_CMAP: - ret = con_get_cmap(up); - break; - - case PIO_FONTX: - case GIO_FONTX: - ret = do_fontx_ioctl(cmd, up, perm, &op); - break; - - case PIO_FONTRESET: - { - if (!perm) - return -EPERM; - -#ifdef BROKEN_GRAPHICS_PROGRAMS - /* With BROKEN_GRAPHICS_PROGRAMS defined, the default - font is not saved. */ - ret = -ENOSYS; - break; -#else - { - op.op = KD_FONT_OP_SET_DEFAULT; - op.data = NULL; - ret = con_font_op(vc_cons[fg_console].d, &op); - if (ret) - break; - console_lock(); - con_set_default_unimap(vc_cons[fg_console].d); console_unlock(); break; - } -#endif - } - - case KDFONTOP: { - if (copy_from_user(&op, up, sizeof(op))) { - ret = -EFAULT; - break; - } - if (!perm && op.op != KD_FONT_OP_GET) - return -EPERM; - ret = con_font_op(vc, &op); - if (ret) - break; - if (copy_to_user(up, &op, sizeof(op))) - ret = -EFAULT; - break; } - case PIO_SCRNMAP: - if (!perm) - ret = -EPERM; - else - ret = con_set_trans_old(up); - break; - - case GIO_SCRNMAP: - ret = con_get_trans_old(up); - break; - - case PIO_UNISCRNMAP: - if (!perm) - ret = -EPERM; - else - ret = con_set_trans_new(up); - break; - - case GIO_UNISCRNMAP: - ret = con_get_trans_new(up); - break; - - case PIO_UNIMAPCLR: + case VT_RESIZEX: if (!perm) return -EPERM; - con_clear_unimap(vc); - break; - case PIO_UNIMAP: - case GIO_UNIMAP: - ret = do_unimap_ioctl(cmd, up, perm, vc); - break; + return vt_resizex(vc, up); case VT_LOCKSWITCH: if (!capable(CAP_SYS_TTY_CONFIG)) @@ -1029,17 +1036,15 @@ int vt_ioctl(struct tty_struct *tty, vt_dont_switch = false; break; case VT_GETHIFONTMASK: - ret = put_user(vc->vc_hi_font_mask, + return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg); - break; case VT_WAITEVENT: - ret = vt_event_wait_ioctl((struct vt_event __user *)arg); - break; + return vt_event_wait_ioctl((struct vt_event __user *)arg); default: - ret = -ENOIOCTLCMD; + return -ENOIOCTLCMD; } -out: - return ret; + + return 0; } void reset_vc(struct vc_data *vc) diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 15e62a2e9b1b3fcd67b764ac5c736ec52c28af74..c63e545fb1051bab5f55bf519a97942a0c1ac904 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -302,14 +302,15 @@ sisusbcon_deinit(struct vc_data *c) /* interface routine */ static u8 -sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity, - u8 blink, u8 underline, u8 reverse, u8 unused) +sisusbcon_build_attr(struct vc_data *c, u8 color, enum vc_intensity intensity, + bool blink, bool underline, bool reverse, + bool unused) { u8 attr = color; if (underline) attr = (attr & 0xf0) | c->vc_ulcolor; - else if (intensity == 0) + else if (intensity == VCI_HALF_BRIGHT) attr = (attr & 0xf0) | c->vc_halfcolor; if (reverse) @@ -320,7 +321,7 @@ sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity, if (blink) attr ^= 0x80; - if (intensity == 2) + if (intensity == VCI_BOLD) attr ^= 0x08; return attr; @@ -726,7 +727,7 @@ sisusbcon_cursor(struct vc_data *c, int mode) baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2); - switch (c->vc_cursor_type & 0x0f) { + switch (CUR_SIZE(c->vc_cursor_type)) { case CUR_BLOCK: from = 1; to = c->vc_font.height; break; diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index d0d427a2f1a3e2dc70ca000331143c0acf65b5c6..ef29b321967f07353f92714f78a58522e907ddf5 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -394,8 +394,10 @@ static inline u16 mda_convert_attr(u16 ch) (ch & 0x00ff) | attr; } -static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, - u8 blink, u8 underline, u8 reverse, u8 italic) +static u8 mdacon_build_attr(struct vc_data *c, u8 color, + enum vc_intensity intensity, + bool blink, bool underline, bool reverse, + bool italic) { /* The attribute is just a bit vector: * @@ -405,11 +407,11 @@ static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, * Bit 7 : blink */ - return (intensity & 3) | - ((underline & 1) << 2) | - ((reverse & 1) << 3) | - (!!italic << 4) | - ((blink & 1) << 7); + return (intensity & VCI_MASK) | + (underline << 2) | + (reverse << 3) | + (italic << 4) | + (blink << 7); } static void mdacon_invert_region(struct vc_data *c, u16 *p, int count) @@ -488,9 +490,9 @@ static void mdacon_cursor(struct vc_data *c, int mode) return; } - mda_set_cursor(c->vc_y*mda_num_columns*2 + c->vc_x*2); + mda_set_cursor(c->state.y * mda_num_columns * 2 + c->state.x * 2); - switch (c->vc_cursor_type & 0x0f) { + switch (CUR_SIZE(c->vc_cursor_type)) { case CUR_LOWER_THIRD: mda_set_cursor_size(10, 13); break; case CUR_LOWER_HALF: mda_set_cursor_size(7, 13); break; diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index df3c52d7215970a165d11d8251332de57cb72718..72f146d047d93f62542b941671a924b27f2dc3a8 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -362,12 +362,12 @@ static void newport_clear(struct vc_data *vc, int sy, int sx, int height, if (ystart < yend) { newport_clear_screen(sx << 3, ystart, xend, yend, - (vc->vc_color & 0xf0) >> 4); + (vc->state.color & 0xf0) >> 4); } else { newport_clear_screen(sx << 3, ystart, xend, 1023, - (vc->vc_color & 0xf0) >> 4); + (vc->state.color & 0xf0) >> 4); newport_clear_screen(sx << 3, 0, xend, yend, - (vc->vc_color & 0xf0) >> 4); + (vc->state.color & 0xf0) >> 4); } } @@ -591,11 +591,11 @@ static bool newport_scroll(struct vc_data *vc, unsigned int t, unsigned int b, topscan = (topscan + (lines << 4)) & 0x3ff; newport_clear_lines(vc->vc_rows - lines, vc->vc_rows - 1, - (vc->vc_color & 0xf0) >> 4); + (vc->state.color & 0xf0) >> 4); } else { topscan = (topscan + (-lines << 4)) & 0x3ff; newport_clear_lines(0, lines - 1, - (vc->vc_color & 0xf0) >> 4); + (vc->state.color & 0xf0) >> 4); } npregs->cset.topscan = (topscan - 1) & 0x3ff; return false; diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 79c9bd8d30254a9001a0b139734b780a240041b2..21a5c280c8c95d0d7d64faa1d650b9fc9e800bfe 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -132,21 +132,21 @@ static void sticon_cursor(struct vc_data *conp, int mode) { unsigned short car1; - car1 = conp->vc_screenbuf[conp->vc_x + conp->vc_y * conp->vc_cols]; + car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols]; switch (mode) { case CM_ERASE: - sti_putc(sticon_sti, car1, conp->vc_y, conp->vc_x); + sti_putc(sticon_sti, car1, conp->state.y, conp->state.x); break; case CM_MOVE: case CM_DRAW: - switch (conp->vc_cursor_type & 0x0f) { + switch (CUR_SIZE(conp->vc_cursor_type)) { case CUR_UNDERLINE: case CUR_LOWER_THIRD: case CUR_LOWER_HALF: case CUR_TWO_THIRDS: case CUR_BLOCK: sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), - conp->vc_y, conp->vc_x); + conp->state.y, conp->state.x); break; } break; @@ -288,8 +288,10 @@ static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, return ret; } -static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, - u8 blink, u8 underline, u8 reverse, u8 italic) +static u8 sticon_build_attr(struct vc_data *conp, u8 color, + enum vc_intensity intens, + bool blink, bool underline, bool reverse, + bool italic) { u8 attr = ((color & 0x70) >> 1) | ((color & 7)); diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 998b0de1812f016e6439c1c07f753fea836230b8..a52bb374007342370e003f3e624ff789c5863a6b 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -251,6 +251,10 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count) p = (void *) (c->vc_origin + t * c->vc_size_row); while (count--) { + if ((vgacon_scrollback_cur->tail + c->vc_size_row) > + vgacon_scrollback_cur->size) + vgacon_scrollback_cur->tail = 0; + scr_memcpyw(vgacon_scrollback_cur->data + vgacon_scrollback_cur->tail, p, c->vc_size_row); @@ -629,8 +633,10 @@ static void vgacon_deinit(struct vc_data *c) con_set_default_unimap(c); } -static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, - u8 blink, u8 underline, u8 reverse, u8 italic) +static u8 vgacon_build_attr(struct vc_data *c, u8 color, + enum vc_intensity intensity, + bool blink, bool underline, bool reverse, + bool italic) { u8 attr = color; @@ -639,7 +645,7 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, attr = (attr & 0xF0) | c->vc_itcolor; else if (underline) attr = (attr & 0xf0) | c->vc_ulcolor; - else if (intensity == 0) + else if (intensity == VCI_HALF_BRIGHT) attr = (attr & 0xf0) | c->vc_halfcolor; } if (reverse) @@ -648,14 +654,14 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, 0x77); if (blink) attr ^= 0x80; - if (intensity == 2) + if (intensity == VCI_BOLD) attr ^= 0x08; if (!vga_can_do_color) { if (italic) attr = (attr & 0xF8) | 0x02; else if (underline) attr = (attr & 0xf8) | 0x01; - else if (intensity == 0) + else if (intensity == VCI_HALF_BRIGHT) attr = (attr & 0xf0) | 0x08; } return attr; @@ -718,17 +724,17 @@ static void vgacon_cursor(struct vc_data *c, int mode) case CM_ERASE: write_vga(14, (c->vc_pos - vga_vram_base) / 2); if (vga_video_type >= VIDEO_TYPE_VGAC) - vgacon_set_cursor_size(c->vc_x, 31, 30); + vgacon_set_cursor_size(c->state.x, 31, 30); else - vgacon_set_cursor_size(c->vc_x, 31, 31); + vgacon_set_cursor_size(c->state.x, 31, 31); break; case CM_MOVE: case CM_DRAW: write_vga(14, (c->vc_pos - vga_vram_base) / 2); - switch (c->vc_cursor_type & 0x0f) { + switch (CUR_SIZE(c->vc_cursor_type)) { case CUR_UNDERLINE: - vgacon_set_cursor_size(c->vc_x, + vgacon_set_cursor_size(c->state.x, c->vc_font.height - (c->vc_font.height < 10 ? 2 : 3), @@ -737,21 +743,21 @@ static void vgacon_cursor(struct vc_data *c, int mode) 10 ? 1 : 2)); break; case CUR_TWO_THIRDS: - vgacon_set_cursor_size(c->vc_x, + vgacon_set_cursor_size(c->state.x, c->vc_font.height / 3, c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2)); break; case CUR_LOWER_THIRD: - vgacon_set_cursor_size(c->vc_x, + vgacon_set_cursor_size(c->state.x, (c->vc_font.height * 2) / 3, c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2)); break; case CUR_LOWER_HALF: - vgacon_set_cursor_size(c->vc_x, + vgacon_set_cursor_size(c->state.x, c->vc_font.height / 2, c->vc_font.height - (c->vc_font.height < @@ -759,12 +765,12 @@ static void vgacon_cursor(struct vc_data *c, int mode) break; case CUR_NONE: if (vga_video_type >= VIDEO_TYPE_VGAC) - vgacon_set_cursor_size(c->vc_x, 31, 30); + vgacon_set_cursor_size(c->state.x, 31, 30); else - vgacon_set_cursor_size(c->vc_x, 31, 31); + vgacon_set_cursor_size(c->state.x, 31, 31); break; default: - vgacon_set_cursor_size(c->vc_x, 1, + vgacon_set_cursor_size(c->state.x, 1, c->vc_font.height); break; } @@ -1352,8 +1358,8 @@ static void vgacon_save_screen(struct vc_data *c) * console initialization routines. */ vga_bootup_console = 1; - c->vc_x = screen_info.orig_x; - c->vc_y = screen_info.orig_y; + c->state.x = screen_info.orig_x; + c->state.y = screen_info.orig_y; } /* We can't copy in more than the size of the video buffer, diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c index 35ebeeccde4dfda132c9e2c9dcd988f909d2d98a..4e6cbc24346d308a4042ea0b970fc8be5bdf5656 100644 --- a/drivers/video/fbdev/core/bitblit.c +++ b/drivers/video/fbdev/core/bitblit.c @@ -240,8 +240,8 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = DIV_ROUND_UP(vc->vc_font.width, 8), c; - int y = real_y(ops->p, vc->vc_y); - int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int y = real_y(ops->p, vc->state.y); + int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1; char *src; @@ -286,10 +286,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, cursor.set |= FB_CUR_SETCMAP; } - if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->vc_x)) || + if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->state.x)) || (ops->cursor_state.image.dy != (vc->vc_font.height * y)) || ops->cursor_reset) { - ops->cursor_state.image.dx = vc->vc_font.width * vc->vc_x; + ops->cursor_state.image.dx = vc->vc_font.width * vc->state.x; ops->cursor_state.image.dy = vc->vc_font.height * y; cursor.set |= FB_CUR_SETPOS; } @@ -325,7 +325,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (ops->p->cursor_shape & CUR_HWMASK) { + switch (CUR_SIZE(ops->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index af9f5ab96f74ff8a0838efcbdf90ac2d6a578316..8a31fc2b2258a79c969d1913a7b629daa6983fc7 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -655,11 +655,11 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, } if (!save) { int lines; - if (vc->vc_y + logo_lines >= rows) - lines = rows - vc->vc_y - 1; + if (vc->state.y + logo_lines >= rows) + lines = rows - vc->state.y - 1; else lines = logo_lines; - vc->vc_y += lines; + vc->state.y += lines; vc->vc_pos += lines * vc->vc_size_row; } } @@ -677,7 +677,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, vc->vc_size_row * rows); scr_memcpyw(q, save, array3_size(logo_lines, new_cols, 2)); - vc->vc_y += logo_lines; + vc->state.y += logo_lines; vc->vc_pos += logo_lines * vc->vc_size_row; kfree(save); } @@ -1393,7 +1393,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode) if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1) return; - if (vc->vc_cursor_type & 0x10) + if (vc->vc_cursor_type & CUR_SW) fbcon_del_cursor_timer(info); else fbcon_add_cursor_timer(info); diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c index 78f3a5621478228f139602405030da219ad95d21..5b177131e062d110de9ee4eb64790764e9fe5a92 100644 --- a/drivers/video/fbdev/core/fbcon_ccw.c +++ b/drivers/video/fbdev/core/fbcon_ccw.c @@ -225,8 +225,8 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.height + 7) >> 3, c; - int y = real_y(ops->p, vc->vc_y); - int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int y = real_y(ops->p, vc->state.y); + int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1, dx, dy; char *src; u32 vyres = GETVYRES(ops->p->scrollmode, info); @@ -284,7 +284,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, } dx = y * vc->vc_font.height; - dy = vyres - ((vc->vc_x + 1) * vc->vc_font.width); + dy = vyres - ((vc->state.x + 1) * vc->vc_font.width); if (ops->cursor_state.image.dx != dx || ops->cursor_state.image.dy != dy || @@ -325,7 +325,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (ops->p->cursor_shape & CUR_HWMASK) { + switch (CUR_SIZE(ops->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c index fd098ff17574b7c19042448d82f7a1e4238bc5a7..894d01a62f30d71f4056412035b0d8f76f2cb7d7 100644 --- a/drivers/video/fbdev/core/fbcon_cw.c +++ b/drivers/video/fbdev/core/fbcon_cw.c @@ -208,8 +208,8 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.height + 7) >> 3, c; - int y = real_y(ops->p, vc->vc_y); - int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int y = real_y(ops->p, vc->state.y); + int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1, dx, dy; char *src; u32 vxres = GETVXRES(ops->p->scrollmode, info); @@ -267,7 +267,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, } dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height); - dy = vc->vc_x * vc->vc_font.width; + dy = vc->state.x * vc->vc_font.width; if (ops->cursor_state.image.dx != dx || ops->cursor_state.image.dy != dy || @@ -308,7 +308,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (ops->p->cursor_shape & CUR_HWMASK) { + switch (CUR_SIZE(ops->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c index e165a3fad29adfdee870b6b737561b6bea938aa8..01b87f278d796aa9678651c0afc3a0f196adc2d9 100644 --- a/drivers/video/fbdev/core/fbcon_ud.c +++ b/drivers/video/fbdev/core/fbcon_ud.c @@ -255,8 +255,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.width + 7) >> 3, c; - int y = real_y(ops->p, vc->vc_y); - int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int y = real_y(ops->p, vc->state.y); + int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1, dx, dy; char *src; u32 vyres = GETVYRES(ops->p->scrollmode, info); @@ -315,7 +315,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, } dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height); - dx = vxres - ((vc->vc_x * vc->vc_font.width) + vc->vc_font.width); + dx = vxres - ((vc->state.x * vc->vc_font.width) + vc->vc_font.width); if (ops->cursor_state.image.dx != dx || ops->cursor_state.image.dy != dy || @@ -348,7 +348,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (ops->p->cursor_shape & CUR_HWMASK) { + switch (CUR_SIZE(ops->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c index 93390312957ffa3d89627deffc8eb6643cfb74f5..1dfaff0881fb9ded3138c01ee9a808c7035e5295 100644 --- a/drivers/video/fbdev/core/tileblit.c +++ b/drivers/video/fbdev/core/tileblit.c @@ -83,10 +83,10 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode, int softback_lines, int fg, int bg) { struct fb_tilecursor cursor; - int use_sw = (vc->vc_cursor_type & 0x10); + int use_sw = vc->vc_cursor_type & CUR_SW; - cursor.sx = vc->vc_x; - cursor.sy = vc->vc_y; + cursor.sx = vc->state.x; + cursor.sy = vc->state.y; cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1; cursor.fg = fg; cursor.bg = bg; diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index 17562ea00e18c030174ad7c5a716ba6834d0fc6f..45665ff87b6490958e38e5bb3408484ad3480a4d 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h @@ -132,7 +132,7 @@ struct cifs_ace { /* * The current SMB3 form of security descriptor is similar to what was used for * cifs (see above) but some fields are split, and fields in the struct below - * matches names of fields to the the spec, MS-DTYP (see sections 2.4.5 and + * matches names of fields to the spec, MS-DTYP (see sections 2.4.5 and * 2.4.6). Note that "CamelCase" fields are used in this struct in order to * match the MS-DTYP and MS-SMB2 specs which define the wire format. */ @@ -178,7 +178,7 @@ struct smb3_acl { /* * Used to store the special 'NFS SIDs' used to persist the POSIX uid and gid - * See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx + * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */ struct owner_sid { u8 Revision; diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index f4b88cd02662b04ec0937cd7f404015bef3d61d4..b296964b8afa6c4319d07b0593bbcfbbcc97a833 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1466,7 +1466,7 @@ struct cifsInodeInfo { struct list_head llist; /* locks helb by this inode */ /* * NOTE: Some code paths call down_read(lock_sem) twice, so - * we must always use use cifs_down_write() instead of down_write() + * we must always use cifs_down_write() instead of down_write() * for this semaphore to avoid deadlocks. */ struct rw_semaphore lock_sem; /* protect the fields above */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7a836ec0438e810ca3b39ea2e57960c30e124833..bb68cbf8107408a8f8f12d6a5e530cbe14336916 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -154,6 +154,7 @@ extern int decode_negTokenInit(unsigned char *security_blob, int length, extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); extern void cifs_set_port(struct sockaddr *addr, const unsigned short int port); extern int map_smb_to_linux_error(char *buf, bool logErr); +extern int map_and_check_smb_error(struct mid_q_entry *mid, bool logErr); extern void header_assemble(struct smb_hdr *, char /* command */ , const struct cifs_tcon *, int /* length of fixed section (word count) in two byte units */); @@ -271,6 +272,9 @@ extern void cifs_move_llist(struct list_head *source, struct list_head *dest); extern void cifs_free_llist(struct list_head *llist); extern void cifs_del_lock_waiters(struct cifsLockInfo *lock); +extern int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, + const struct nls_table *nlsc); + extern int cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses); extern int cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, @@ -344,7 +348,7 @@ extern int CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon, extern int CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, const char *fileName, const FILE_BASIC_INFO *data, const struct nls_table *nls_codepage, - int remap_special_chars); + struct cifs_sb_info *cifs_sb); extern int CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon, const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener); @@ -613,8 +617,7 @@ int smb2_parse_query_directory(struct cifs_tcon *tcon, struct kvec *rsp_iov, struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server); void cifs_put_tcp_super(struct super_block *sb); -int update_super_prepath(struct cifs_tcon *tcon, const char *prefix, - size_t prefix_len); +int update_super_prepath(struct cifs_tcon *tcon, char *prefix); #ifdef CONFIG_CIFS_DFS_UPCALL static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index bf41ee048396d09b5484e41823d5980553d61179..0e763d2dcf16648d6465febd8b5f079fd6486e2a 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -124,116 +124,6 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon) */ } -#ifdef CONFIG_CIFS_DFS_UPCALL -static int __cifs_reconnect_tcon(const struct nls_table *nlsc, - struct cifs_tcon *tcon) -{ - int rc; - struct TCP_Server_Info *server = tcon->ses->server; - struct dfs_cache_tgt_list tl; - struct dfs_cache_tgt_iterator *it = NULL; - char *tree; - const char *tcp_host; - size_t tcp_host_len; - const char *dfs_host; - size_t dfs_host_len; - - tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); - if (!tree) - return -ENOMEM; - - if (!tcon->dfs_path) { - if (tcon->ipc) { - scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", - server->hostname); - rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); - } else { - rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc); - } - goto out; - } - - rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl); - if (rc) - goto out; - - extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len); - - for (it = dfs_cache_get_tgt_iterator(&tl); it; - it = dfs_cache_get_next_tgt(&tl, it)) { - const char *share, *prefix; - size_t share_len, prefix_len; - bool target_match; - - rc = dfs_cache_get_tgt_share(it, &share, &share_len, &prefix, - &prefix_len); - if (rc) { - cifs_dbg(VFS, "%s: failed to parse target share %d\n", - __func__, rc); - continue; - } - - extract_unc_hostname(share, &dfs_host, &dfs_host_len); - - if (dfs_host_len != tcp_host_len - || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { - cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", - __func__, - (int)dfs_host_len, dfs_host, - (int)tcp_host_len, tcp_host); - - rc = match_target_ip(server, dfs_host, dfs_host_len, - &target_match); - if (rc) { - cifs_dbg(VFS, "%s: failed to match target ip: %d\n", - __func__, rc); - break; - } - - if (!target_match) { - cifs_dbg(FYI, "%s: skipping target\n", __func__); - continue; - } - } - - if (tcon->ipc) { - scnprintf(tree, MAX_TREE_SIZE, "\\\\%.*s\\IPC$", - (int)share_len, share); - rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); - } else { - scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len, - share); - rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); - if (!rc) { - rc = update_super_prepath(tcon, prefix, - prefix_len); - break; - } - } - if (rc == -EREMOTE) - break; - } - - if (!rc) { - if (it) - rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, - it); - else - rc = -ENOENT; - } - dfs_cache_free_tgts(&tl); -out: - kfree(tree); - return rc; -} -#else -static inline int __cifs_reconnect_tcon(const struct nls_table *nlsc, - struct cifs_tcon *tcon) -{ - return CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc); -} -#endif - /* reconnect the socket, tcon, and smb session if needed */ static int cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) @@ -338,7 +228,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) } cifs_mark_open_files_invalid(tcon); - rc = __cifs_reconnect_tcon(nls_codepage, tcon); + rc = cifs_tree_connect(0, tcon, nls_codepage); mutex_unlock(&ses->session_mutex); cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); @@ -5913,10 +5803,42 @@ CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon, return rc; } +static int +CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon, + const char *fileName, const FILE_BASIC_INFO *data, + const struct nls_table *nls_codepage, + struct cifs_sb_info *cifs_sb) +{ + int oplock = 0; + struct cifs_open_parms oparms; + struct cifs_fid fid; + int rc; + + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_WRITE; + oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.disposition = FILE_OPEN; + oparms.path = fileName; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); + if (rc) + goto out; + + rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid); + CIFSSMBClose(xid, tcon, fid.netfid); +out: + + return rc; +} + int CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, const char *fileName, const FILE_BASIC_INFO *data, - const struct nls_table *nls_codepage, int remap) + const struct nls_table *nls_codepage, + struct cifs_sb_info *cifs_sb) { TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL; @@ -5925,6 +5847,7 @@ CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, int bytes_returned = 0; char *data_offset; __u16 params, param_offset, offset, byte_count, count; + int remap = cifs_remap(cifs_sb); cifs_dbg(FYI, "In SetTimes\n"); @@ -5987,6 +5910,10 @@ SetTimesRetry: if (rc == -EAGAIN) goto SetTimesRetry; + if (rc == -EOPNOTSUPP) + return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data, + nls_codepage, cifs_sb); + return rc; } diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a61abde09ffe1f612b5d7bd23c8ef9773117c178..7e3e5e2098eb2afdad97984399e48219545c2d28 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -393,15 +393,14 @@ static inline int reconn_set_ipaddr(struct TCP_Server_Info *server) #ifdef CONFIG_CIFS_DFS_UPCALL /* These functions must be called with server->srv_mutex held */ -static void reconn_inval_dfs_target(struct TCP_Server_Info *server, - struct cifs_sb_info *cifs_sb, - struct dfs_cache_tgt_list *tgt_list, - struct dfs_cache_tgt_iterator **tgt_it) +static void reconn_set_next_dfs_target(struct TCP_Server_Info *server, + struct cifs_sb_info *cifs_sb, + struct dfs_cache_tgt_list *tgt_list, + struct dfs_cache_tgt_iterator **tgt_it) { const char *name; - if (!cifs_sb || !cifs_sb->origin_fullpath || !tgt_list || - !server->nr_targets) + if (!cifs_sb || !cifs_sb->origin_fullpath) return; if (!*tgt_it) { @@ -471,11 +470,13 @@ cifs_reconnect(struct TCP_Server_Info *server) sb = NULL; } else { cifs_sb = CIFS_SB(sb); - rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list); - if (rc && (rc != -EOPNOTSUPP)) { - cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n", - __func__); + if (rc) { + cifs_sb = NULL; + if (rc != -EOPNOTSUPP) { + cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n", + __func__); + } } else { server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list); } @@ -578,7 +579,7 @@ cifs_reconnect(struct TCP_Server_Info *server) * feature is disabled, then we will retry last server we * connected to before. */ - reconn_inval_dfs_target(server, cifs_sb, &tgt_list, &tgt_it); + reconn_set_next_dfs_target(server, cifs_sb, &tgt_list, &tgt_it); #endif rc = reconn_set_ipaddr(server); if (rc) { @@ -4422,11 +4423,11 @@ build_unc_path_to_root(const struct smb_vol *vol, static int expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses, struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb, - int check_prefix) + char *ref_path) { int rc; struct dfs_info3_param referral = {0}; - char *full_path = NULL, *ref_path = NULL, *mdata = NULL; + char *full_path = NULL, *mdata = NULL; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) return -EREMOTE; @@ -4435,9 +4436,6 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses, if (IS_ERR(full_path)) return PTR_ERR(full_path); - /* For DFS paths, skip the first '\' of the UNC */ - ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1; - rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), ref_path, &referral, NULL); if (!rc) { @@ -4500,13 +4498,10 @@ static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it, return 0; } -static int setup_dfs_tgt_conn(const char *path, +static int setup_dfs_tgt_conn(const char *path, const char *full_path, const struct dfs_cache_tgt_iterator *tgt_it, - struct cifs_sb_info *cifs_sb, - struct smb_vol *vol, - unsigned int *xid, - struct TCP_Server_Info **server, - struct cifs_ses **ses, + struct cifs_sb_info *cifs_sb, struct smb_vol *vol, unsigned int *xid, + struct TCP_Server_Info **server, struct cifs_ses **ses, struct cifs_tcon **tcon) { int rc; @@ -4520,8 +4515,7 @@ static int setup_dfs_tgt_conn(const char *path, if (rc) return rc; - mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref, - &fake_devname); + mdata = cifs_compose_mount_options(cifs_sb->mountdata, full_path + 1, &ref, &fake_devname); free_dfs_info_param(&ref); if (IS_ERR(mdata)) { @@ -4544,7 +4538,7 @@ static int setup_dfs_tgt_conn(const char *path, mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon); rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses, tcon); - if (!rc) { + if (!rc || (*server && *ses)) { /* * We were able to connect to new target server. * Update current volume info with new target server. @@ -4556,14 +4550,10 @@ static int setup_dfs_tgt_conn(const char *path, return rc; } -static int mount_do_dfs_failover(const char *path, - struct cifs_sb_info *cifs_sb, - struct smb_vol *vol, - struct cifs_ses *root_ses, - unsigned int *xid, - struct TCP_Server_Info **server, - struct cifs_ses **ses, - struct cifs_tcon **tcon) +static int do_dfs_failover(const char *path, const char *full_path, struct cifs_sb_info *cifs_sb, + struct smb_vol *vol, struct cifs_ses *root_ses, unsigned int *xid, + struct TCP_Server_Info **server, struct cifs_ses **ses, + struct cifs_tcon **tcon) { int rc; struct dfs_cache_tgt_list tgt_list; @@ -4582,9 +4572,9 @@ static int mount_do_dfs_failover(const char *path, if (rc) break; /* Connect to next DFS target */ - rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server, - ses, tcon); - if (!rc || rc == -EACCES || rc == -EOPNOTSUPP) + rc = setup_dfs_tgt_conn(path, full_path, tgt_it, cifs_sb, vol, xid, server, ses, + tcon); + if (!rc || (*server && *ses)) break; } if (!rc) { @@ -4754,207 +4744,210 @@ static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol, } #ifdef CONFIG_CIFS_DFS_UPCALL -static inline void set_root_tcon(struct cifs_sb_info *cifs_sb, - struct cifs_tcon *tcon, - struct cifs_tcon **root) +static void set_root_ses(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, + struct cifs_ses **root_ses) { - spin_lock(&cifs_tcp_ses_lock); - tcon->tc_count++; - tcon->remap = cifs_remap(cifs_sb); - spin_unlock(&cifs_tcp_ses_lock); - *root = tcon; + if (ses) { + spin_lock(&cifs_tcp_ses_lock); + ses->ses_count++; + ses->tcon_ipc->remap = cifs_remap(cifs_sb); + spin_unlock(&cifs_tcp_ses_lock); + } + *root_ses = ses; +} + +static void put_root_ses(struct cifs_ses *ses) +{ + if (ses) + cifs_put_smb_ses(ses); +} + +/* Check if a path component is remote and then update @dfs_path accordingly */ +static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb_vol *vol, + const unsigned int xid, struct TCP_Server_Info *server, + struct cifs_tcon *tcon, char **dfs_path) +{ + char *path, *s; + char sep = CIFS_DIR_SEP(cifs_sb), tmp; + char *npath; + int rc = 0; + int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS; + int skip = added_treename; + + path = cifs_build_path_to_root(vol, cifs_sb, tcon, added_treename); + if (!path) + return -ENOMEM; + + /* + * Walk through the path components in @path and check if they're accessible. In case any of + * the components is -EREMOTE, then update @dfs_path with the next DFS referral request path + * (NOT including the remaining components). + */ + s = path; + do { + /* skip separators */ + while (*s && *s == sep) + s++; + if (!*s) + break; + /* next separator */ + while (*s && *s != sep) + s++; + /* + * if the treename is added, we then have to skip the first + * part within the separators + */ + if (skip) { + skip = 0; + continue; + } + tmp = *s; + *s = 0; + rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path); + if (rc && rc == -EREMOTE) { + struct smb_vol v = {NULL}; + /* if @path contains a tree name, skip it in the prefix path */ + if (added_treename) { + rc = cifs_parse_devname(path, &v); + if (rc) + break; + rc = -EREMOTE; + npath = build_unc_path_to_root(&v, cifs_sb, true); + cifs_cleanup_volume_info_contents(&v); + } else { + v.UNC = vol->UNC; + v.prepath = path + 1; + npath = build_unc_path_to_root(&v, cifs_sb, true); + } + if (IS_ERR(npath)) { + rc = PTR_ERR(npath); + break; + } + kfree(*dfs_path); + *dfs_path = npath; + } + *s = tmp; + } while (rc == 0); + + kfree(path); + return rc; } int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) { int rc = 0; unsigned int xid; - struct cifs_ses *ses; - struct cifs_tcon *root_tcon = NULL; + struct TCP_Server_Info *server = NULL; + struct cifs_ses *ses = NULL, *root_ses = NULL; struct cifs_tcon *tcon = NULL; - struct TCP_Server_Info *server; - char *root_path = NULL, *full_path = NULL; - char *old_mountdata, *origin_mountdata = NULL; - int count; + int count = 0; + char *ref_path = NULL, *full_path = NULL; + char *oldmnt = NULL; + char *mntdata = NULL; rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon); - if (!rc && tcon) { - /* If not a standalone DFS root, then check if path is remote */ - rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, - cifs_remap(cifs_sb), vol->UNC + 1, NULL, - NULL); - if (rc) { - rc = is_path_remote(cifs_sb, vol, xid, server, tcon); - if (!rc) - goto out; - if (rc != -EREMOTE) - goto error; - } - } /* - * If first DFS target server went offline and we failed to connect it, - * server and ses pointers are NULL at this point, though we still have - * chance to get a cached DFS referral in expand_dfs_referral() and - * retry next target available in it. + * Unconditionally try to get an DFS referral (even cached) to determine whether it is an + * DFS mount. * - * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be - * performed against DFS path and *no* requests will be sent to server - * for any new DFS referrals. Hence it's safe to skip checking whether - * server or ses ptr is NULL. + * Skip prefix path to provide support for DFS referrals from w2k8 servers which don't seem + * to respond with PATH_NOT_COVERED to requests that include the prefix. */ - if (rc == -EACCES || rc == -EOPNOTSUPP) - goto error; - - root_path = build_unc_path_to_root(vol, cifs_sb, false); - if (IS_ERR(root_path)) { - rc = PTR_ERR(root_path); - root_path = NULL; - goto error; - } - - full_path = build_unc_path_to_root(vol, cifs_sb, true); - if (IS_ERR(full_path)) { - rc = PTR_ERR(full_path); - full_path = NULL; - goto error; - } - /* - * Perform an unconditional check for whether there are DFS - * referrals for this path without prefix, to provide support - * for DFS referrals from w2k8 servers which don't seem to respond - * with PATH_NOT_COVERED to requests that include the prefix. - * Chase the referral if found, otherwise continue normally. - */ - old_mountdata = cifs_sb->mountdata; - (void)expand_dfs_referral(xid, ses, vol, cifs_sb, false); - - if (cifs_sb->mountdata == NULL) { - rc = -ENOENT; - goto error; + if (dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), vol->UNC + 1, NULL, + NULL)) { + /* No DFS referral was returned. Looks like a regular share. */ + if (rc) + goto error; + /* Check if it is fully accessible and then mount it */ + rc = is_path_remote(cifs_sb, vol, xid, server, tcon); + if (!rc) + goto out; + if (rc != -EREMOTE) + goto error; } - - /* Save DFS root volume information for DFS refresh worker */ - origin_mountdata = kstrndup(cifs_sb->mountdata, - strlen(cifs_sb->mountdata), GFP_KERNEL); - if (!origin_mountdata) { + /* Save mount options */ + mntdata = kstrndup(cifs_sb->mountdata, strlen(cifs_sb->mountdata), GFP_KERNEL); + if (!mntdata) { rc = -ENOMEM; goto error; } - - if (cifs_sb->mountdata != old_mountdata) { - /* If we were redirected, reconnect to new target server */ - mount_put_conns(cifs_sb, xid, server, ses, tcon); - rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon); - } - if (rc) { - if (rc == -EACCES || rc == -EOPNOTSUPP) - goto error; - /* Perform DFS failover to any other DFS targets */ - rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL, - &xid, &server, &ses, &tcon); - if (rc) - goto error; - } - - kfree(root_path); - root_path = build_unc_path_to_root(vol, cifs_sb, false); - if (IS_ERR(root_path)) { - rc = PTR_ERR(root_path); - root_path = NULL; + /* Get path of DFS root */ + ref_path = build_unc_path_to_root(vol, cifs_sb, false); + if (IS_ERR(ref_path)) { + rc = PTR_ERR(ref_path); + ref_path = NULL; goto error; } - /* Cache out resolved root server */ - (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), - root_path + 1, NULL, NULL); - kfree(root_path); - root_path = NULL; - - set_root_tcon(cifs_sb, tcon, &root_tcon); - - for (count = 1; ;) { - if (!rc && tcon) { - rc = is_path_remote(cifs_sb, vol, xid, server, tcon); - if (!rc || rc != -EREMOTE) - break; - } - /* - * BB: when we implement proper loop detection, - * we will remove this check. But now we need it - * to prevent an indefinite loop if 'DFS tree' is - * misconfigured (i.e. has loops). - */ - if (count++ > MAX_NESTED_LINKS) { - rc = -ELOOP; - break; - } + set_root_ses(cifs_sb, ses, &root_ses); + do { + /* Save full path of last DFS path we used to resolve final target server */ kfree(full_path); - full_path = build_unc_path_to_root(vol, cifs_sb, true); + full_path = build_unc_path_to_root(vol, cifs_sb, !!count); if (IS_ERR(full_path)) { rc = PTR_ERR(full_path); - full_path = NULL; break; } - - old_mountdata = cifs_sb->mountdata; - rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb, - true); + /* Chase referral */ + oldmnt = cifs_sb->mountdata; + rc = expand_dfs_referral(xid, root_ses, vol, cifs_sb, ref_path + 1); if (rc) break; - - if (cifs_sb->mountdata != old_mountdata) { + /* Connect to new DFS target only if we were redirected */ + if (oldmnt != cifs_sb->mountdata) { mount_put_conns(cifs_sb, xid, server, ses, tcon); - rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, - &tcon); - /* - * Ensure that DFS referrals go through new root server. - */ - if (!rc && tcon && - (tcon->share_flags & (SHI1005_FLAGS_DFS | - SHI1005_FLAGS_DFS_ROOT))) { - cifs_put_tcon(root_tcon); - set_root_tcon(cifs_sb, tcon, &root_tcon); - } + rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon); } - if (rc) { - if (rc == -EACCES || rc == -EOPNOTSUPP) - break; - /* Perform DFS failover to any other DFS targets */ - rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol, - root_tcon->ses, &xid, - &server, &ses, &tcon); - if (rc == -EACCES || rc == -EOPNOTSUPP || !server || - !ses) - goto error; + if (rc && !server && !ses) { + /* Failed to connect. Try to connect to other targets in the referral. */ + rc = do_dfs_failover(ref_path + 1, full_path, cifs_sb, vol, root_ses, &xid, + &server, &ses, &tcon); } - } - cifs_put_tcon(root_tcon); + if (rc == -EACCES || rc == -EOPNOTSUPP || !server || !ses) + break; + if (!tcon) + continue; + /* Make sure that requests go through new root servers */ + if (tcon->share_flags & (SHI1005_FLAGS_DFS | SHI1005_FLAGS_DFS_ROOT)) { + put_root_ses(root_ses); + set_root_ses(cifs_sb, ses, &root_ses); + } + /* Check for remaining path components and then continue chasing them (-EREMOTE) */ + rc = check_dfs_prepath(cifs_sb, vol, xid, server, tcon, &ref_path); + /* Prevent recursion on broken link referrals */ + if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS) + rc = -ELOOP; + } while (rc == -EREMOTE); if (rc) goto error; - - spin_lock(&cifs_tcp_ses_lock); - if (!tcon->dfs_path) { - /* Save full path in new tcon to do failover when reconnecting tcons */ - tcon->dfs_path = full_path; - full_path = NULL; - tcon->remap = cifs_remap(cifs_sb); - } - cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path, - strlen(tcon->dfs_path), - GFP_ATOMIC); + put_root_ses(root_ses); + root_ses = NULL; + kfree(ref_path); + ref_path = NULL; + /* + * Store DFS full path in both superblock and tree connect structures. + * + * For DFS root mounts, the prefix path (cifs_sb->prepath) is preserved during reconnect so + * only the root path is set in cifs_sb->origin_fullpath and tcon->dfs_path. And for DFS + * links, the prefix path is included in both and may be changed during reconnect. See + * cifs_tree_connect(). + */ + cifs_sb->origin_fullpath = kstrndup(full_path, strlen(full_path), GFP_KERNEL); if (!cifs_sb->origin_fullpath) { - spin_unlock(&cifs_tcp_ses_lock); rc = -ENOMEM; goto error; } + spin_lock(&cifs_tcp_ses_lock); + tcon->dfs_path = full_path; + full_path = NULL; + tcon->remap = cifs_remap(cifs_sb); spin_unlock(&cifs_tcp_ses_lock); - rc = dfs_cache_add_vol(origin_mountdata, vol, cifs_sb->origin_fullpath); - if (rc) { - kfree(cifs_sb->origin_fullpath); + /* Add original volume information for DFS cache to be used when refreshing referrals */ + rc = dfs_cache_add_vol(mntdata, vol, cifs_sb->origin_fullpath); + if (rc) goto error; - } /* * After reconnecting to a different server, unique ids won't * match anymore, so we disable serverino. This prevents @@ -4976,9 +4969,11 @@ out: return mount_setup_tlink(cifs_sb, ses, tcon); error: + kfree(ref_path); kfree(full_path); - kfree(root_path); - kfree(origin_mountdata); + kfree(mntdata); + kfree(cifs_sb->origin_fullpath); + put_root_ses(root_ses); mount_put_conns(cifs_sb, xid, server, ses, tcon); return rc; } @@ -5114,8 +5109,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, bcc_ptr += strlen("?????"); bcc_ptr += 1; count = bcc_ptr - &pSMB->Password[0]; - pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu( - pSMB->hdr.smb_buf_length) + count); + be32_add_cpu(&pSMB->hdr.smb_buf_length, count); pSMB->ByteCount = cpu_to_le16(count); rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, @@ -5533,3 +5527,115 @@ cifs_prune_tlinks(struct work_struct *work) queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, TLINK_IDLE_EXPIRE); } + +#ifdef CONFIG_CIFS_DFS_UPCALL +int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc) +{ + int rc; + struct TCP_Server_Info *server = tcon->ses->server; + const struct smb_version_operations *ops = server->ops; + struct dfs_cache_tgt_list tl; + struct dfs_cache_tgt_iterator *it = NULL; + char *tree; + const char *tcp_host; + size_t tcp_host_len; + const char *dfs_host; + size_t dfs_host_len; + char *share = NULL, *prefix = NULL; + struct dfs_info3_param ref = {0}; + bool isroot; + + tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); + if (!tree) + return -ENOMEM; + + if (!tcon->dfs_path) { + if (tcon->ipc) { + scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname); + rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); + } else { + rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc); + } + goto out; + } + + rc = dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl); + if (rc) + goto out; + isroot = ref.server_type == DFS_TYPE_ROOT; + free_dfs_info_param(&ref); + + extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len); + + for (it = dfs_cache_get_tgt_iterator(&tl); it; it = dfs_cache_get_next_tgt(&tl, it)) { + bool target_match; + + kfree(share); + kfree(prefix); + share = NULL; + prefix = NULL; + + rc = dfs_cache_get_tgt_share(tcon->dfs_path + 1, it, &share, &prefix); + if (rc) { + cifs_dbg(VFS, "%s: failed to parse target share %d\n", + __func__, rc); + continue; + } + + extract_unc_hostname(share, &dfs_host, &dfs_host_len); + + if (dfs_host_len != tcp_host_len + || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { + cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len, + dfs_host, (int)tcp_host_len, tcp_host); + + rc = match_target_ip(server, dfs_host, dfs_host_len, &target_match); + if (rc) { + cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc); + break; + } + + if (!target_match) { + cifs_dbg(FYI, "%s: skipping target\n", __func__); + continue; + } + } + + if (tcon->ipc) { + scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", share); + rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); + } else { + scnprintf(tree, MAX_TREE_SIZE, "\\%s", share); + rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); + /* Only handle prefix paths of DFS link targets */ + if (!rc && !isroot) { + rc = update_super_prepath(tcon, prefix); + break; + } + } + if (rc == -EREMOTE) + break; + } + + kfree(share); + kfree(prefix); + + if (!rc) { + if (it) + rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, it); + else + rc = -ENOENT; + } + dfs_cache_free_tgts(&tl); +out: + kfree(tree); + return rc; +} +#else +int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc) +{ + const struct smb_version_operations *ops = tcon->ses->server->ops; + + return ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc); +} +#endif diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c index df81c718d2faec78a119b3314c7c6c31a9eec23f..a44f58bbf7abfce9c38ccb93466d9721610c06eb 100644 --- a/fs/cifs/dfs_cache.c +++ b/fs/cifs/dfs_cache.c @@ -29,6 +29,7 @@ struct cache_dfs_tgt { char *name; + int path_consumed; struct list_head list; }; @@ -350,7 +351,7 @@ static inline struct timespec64 get_expire_time(int ttl) } /* Allocate a new DFS target */ -static struct cache_dfs_tgt *alloc_target(const char *name) +static struct cache_dfs_tgt *alloc_target(const char *name, int path_consumed) { struct cache_dfs_tgt *t; @@ -362,6 +363,7 @@ static struct cache_dfs_tgt *alloc_target(const char *name) kfree(t); return ERR_PTR(-ENOMEM); } + t->path_consumed = path_consumed; INIT_LIST_HEAD(&t->list); return t; } @@ -384,7 +386,7 @@ static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs, for (i = 0; i < numrefs; i++) { struct cache_dfs_tgt *t; - t = alloc_target(refs[i].node_name); + t = alloc_target(refs[i].node_name, refs[i].path_consumed); if (IS_ERR(t)) { free_tgts(ce); return PTR_ERR(t); @@ -490,16 +492,7 @@ static int add_cache_entry(const char *path, unsigned int hash, return 0; } -/* - * Find a DFS cache entry in hash table and optionally check prefix path against - * @path. - * Use whole path components in the match. - * Must be called with htable_rw_lock held. - * - * Return ERR_PTR(-ENOENT) if the entry is not found. - */ -static struct cache_entry *lookup_cache_entry(const char *path, - unsigned int *hash) +static struct cache_entry *__lookup_cache_entry(const char *path) { struct cache_entry *ce; unsigned int h; @@ -517,9 +510,75 @@ static struct cache_entry *lookup_cache_entry(const char *path, if (!found) ce = ERR_PTR(-ENOENT); + return ce; +} + +/* + * Find a DFS cache entry in hash table and optionally check prefix path against + * @path. + * Use whole path components in the match. + * Must be called with htable_rw_lock held. + * + * Return ERR_PTR(-ENOENT) if the entry is not found. + */ +static struct cache_entry *lookup_cache_entry(const char *path, unsigned int *hash) +{ + struct cache_entry *ce = ERR_PTR(-ENOENT); + unsigned int h; + int cnt = 0; + char *npath; + char *s, *e; + char sep; + + npath = kstrndup(path, strlen(path), GFP_KERNEL); + if (!npath) + return ERR_PTR(-ENOMEM); + + s = npath; + sep = *npath; + while ((s = strchr(s, sep)) && ++cnt < 3) + s++; + + if (cnt < 3) { + h = cache_entry_hash(path, strlen(path)); + ce = __lookup_cache_entry(path); + goto out; + } + /* + * Handle paths that have more than two path components and are a complete prefix of the DFS + * referral request path (@path). + * + * See MS-DFSC 3.2.5.5 "Receiving a Root Referral Request or Link Referral Request". + */ + h = cache_entry_hash(npath, strlen(npath)); + e = npath + strlen(npath) - 1; + while (e > s) { + char tmp; + + /* skip separators */ + while (e > s && *e == sep) + e--; + if (e == s) + goto out; + + tmp = *(e+1); + *(e+1) = 0; + + ce = __lookup_cache_entry(npath); + if (!IS_ERR(ce)) { + h = cache_entry_hash(npath, strlen(npath)); + break; + } + + *(e+1) = tmp; + /* backward until separator */ + while (e > s && *e != sep) + e--; + } +out: if (hash) *hash = h; - + kfree(npath); return ce; } @@ -773,6 +832,7 @@ static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl) rc = -ENOMEM; goto err_free_it; } + it->it_path_consumed = t->path_consumed; if (ce->tgthint == t) list_add(&it->it_list, head); @@ -1263,23 +1323,26 @@ void dfs_cache_del_vol(const char *fullpath) /** * dfs_cache_get_tgt_share - parse a DFS target * + * @path: DFS full path * @it: DFS target iterator. * @share: tree name. - * @share_len: length of tree name. * @prefix: prefix path. - * @prefix_len: length of prefix path. * * Return zero if target was parsed correctly, otherwise non-zero. */ -int dfs_cache_get_tgt_share(const struct dfs_cache_tgt_iterator *it, - const char **share, size_t *share_len, - const char **prefix, size_t *prefix_len) +int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, + char **share, char **prefix) { - char *s, sep; + char *s, sep, *p; + size_t len; + size_t plen1, plen2; - if (!it || !share || !share_len || !prefix || !prefix_len) + if (!it || !path || !share || !prefix || strlen(path) < it->it_path_consumed) return -EINVAL; + *share = NULL; + *prefix = NULL; + sep = it->it_name[0]; if (sep != '\\' && sep != '/') return -EINVAL; @@ -1288,13 +1351,38 @@ int dfs_cache_get_tgt_share(const struct dfs_cache_tgt_iterator *it, if (!s) return -EINVAL; + /* point to prefix in target node */ s = strchrnul(s + 1, sep); - *share = it->it_name; - *share_len = s - it->it_name; - *prefix = *s ? s + 1 : s; - *prefix_len = &it->it_name[strlen(it->it_name)] - *prefix; + /* extract target share */ + *share = kstrndup(it->it_name, s - it->it_name, GFP_KERNEL); + if (!*share) + return -ENOMEM; + /* skip separator */ + if (*s) + s++; + /* point to prefix in DFS path */ + p = path + it->it_path_consumed; + if (*p == sep) + p++; + + /* merge prefix paths from DFS path and target node */ + plen1 = it->it_name + strlen(it->it_name) - s; + plen2 = path + strlen(path) - p; + if (plen1 || plen2) { + len = plen1 + plen2 + 2; + *prefix = kmalloc(len, GFP_KERNEL); + if (!*prefix) { + kfree(*share); + *share = NULL; + return -ENOMEM; + } + if (plen1) + scnprintf(*prefix, len, "%.*s%c%.*s", (int)plen1, s, sep, (int)plen2, p); + else + strscpy(*prefix, p, len); + } return 0; } diff --git a/fs/cifs/dfs_cache.h b/fs/cifs/dfs_cache.h index bf94d08cfb5a14d37488428027a629f061674741..3d7c05194536ee444689e5f7549873565495fa31 100644 --- a/fs/cifs/dfs_cache.h +++ b/fs/cifs/dfs_cache.h @@ -19,6 +19,7 @@ struct dfs_cache_tgt_list { struct dfs_cache_tgt_iterator { char *it_name; + int it_path_consumed; struct list_head it_list; }; @@ -48,10 +49,8 @@ extern int dfs_cache_add_vol(char *mntdata, struct smb_vol *vol, extern int dfs_cache_update_vol(const char *fullpath, struct TCP_Server_Info *server); extern void dfs_cache_del_vol(const char *fullpath); - -extern int dfs_cache_get_tgt_share(const struct dfs_cache_tgt_iterator *it, - const char **share, size_t *share_len, - const char **prefix, size_t *prefix_len); +extern int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, + char **share, char **prefix); static inline struct dfs_cache_tgt_iterator * dfs_cache_get_next_tgt(struct dfs_cache_tgt_list *tl, diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ce95801e9b6644dcd8d6e8ae79bcc3308b5a4491..3989d08396acb077512888e4954fea8964b3d7b5 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1086,7 +1086,6 @@ smb311_posix_get_inode_info(struct inode **inode, struct super_block *sb, unsigned int xid) { struct cifs_tcon *tcon; - struct TCP_Server_Info *server; struct tcon_link *tlink; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); bool adjust_tz = false; @@ -1100,7 +1099,6 @@ smb311_posix_get_inode_info(struct inode **inode, if (IS_ERR(tlink)) return PTR_ERR(tlink); tcon = tlink_tcon(tlink); - server = tcon->ses->server; /* * 1. Fetch file metadata diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index e44d049142d04054293b749fa55d2a013db03593..764234803071bf9dc4e2011b457e40584d6f7b19 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -1164,8 +1164,7 @@ static inline void cifs_put_tcon_super(struct super_block *sb) } #endif -int update_super_prepath(struct cifs_tcon *tcon, const char *prefix, - size_t prefix_len) +int update_super_prepath(struct cifs_tcon *tcon, char *prefix) { struct super_block *sb; struct cifs_sb_info *cifs_sb; @@ -1179,8 +1178,8 @@ int update_super_prepath(struct cifs_tcon *tcon, const char *prefix, kfree(cifs_sb->prepath); - if (*prefix && prefix_len) { - cifs_sb->prepath = kstrndup(prefix, prefix_len, GFP_ATOMIC); + if (prefix && *prefix) { + cifs_sb->prepath = kstrndup(prefix, strlen(prefix), GFP_ATOMIC); if (!cifs_sb->prepath) { rc = -ENOMEM; goto out; diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index b7ca4960d4ca654713247c9a1c2efd8eb4a30e73..0e728aac67e9f26c1294a95279d2d7a92139cc19 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -881,6 +881,33 @@ map_smb_to_linux_error(char *buf, bool logErr) return rc; } +int +map_and_check_smb_error(struct mid_q_entry *mid, bool logErr) +{ + int rc; + struct smb_hdr *smb = (struct smb_hdr *)mid->resp_buf; + + rc = map_smb_to_linux_error((char *)smb, logErr); + if (rc == -EACCES && !(smb->Flags2 & SMBFLG2_ERR_STATUS)) { + /* possible ERRBaduid */ + __u8 class = smb->Status.DosError.ErrorClass; + __u16 code = le16_to_cpu(smb->Status.DosError.Error); + + /* switch can be used to handle different errors */ + if (class == ERRSRV && code == ERRbaduid) { + cifs_dbg(FYI, "Server returned 0x%x, reconnecting session...\n", + code); + spin_lock(&GlobalMid_Lock); + if (mid->server->tcpStatus != CifsExiting) + mid->server->tcpStatus = CifsNeedReconnect; + spin_unlock(&GlobalMid_Lock); + } + } + + return rc; +} + + /* * calculate the size of the SMB message based on the fixed header * portion, the number of word parameters and the data portion of the message diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 5d05bd2822d292ae86a7eb7f2091b57c1e56e4c6..69cd5856621b8af2455f58f07b434ce1f9cee028 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -938,8 +938,7 @@ sess_sendreceive(struct sess_data *sess_data) struct kvec rsp_iov = { NULL, 0 }; count = sess_data->iov[1].iov_len + sess_data->iov[2].iov_len; - smb_buf->smb_buf_length = - cpu_to_be32(be32_to_cpu(smb_buf->smb_buf_length) + count); + be32_add_cpu(&smb_buf->smb_buf_length, count); put_bcc(count, smb_buf); rc = SendReceive2(sess_data->xid, sess_data->ses, @@ -1705,7 +1704,6 @@ static int select_sec(struct cifs_ses *ses, struct sess_data *sess_data) #else cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n"); return -ENOSYS; - break; #endif /* CONFIG_CIFS_UPCALL */ case RawNTLMSSP: sess_data->func = sess_auth_rawntlmssp_negotiate; diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 197ed455e6572777260897bafacdef2fa66495c8..80287c26cfac0cce1e0d514bdfa94bd5305a4486 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -688,7 +688,7 @@ cifs_mkdir_setinfo(struct inode *inode, const char *full_path, dosattrs = cifsInode->cifsAttrs|ATTR_READONLY; info.Attributes = cpu_to_le32(dosattrs); rc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, cifs_sb->local_nls, - cifs_remap(cifs_sb)); + cifs_sb); if (rc == 0) cifsInode->cifsAttrs = dosattrs; } @@ -783,7 +783,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, tcon = tlink_tcon(tlink); rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls, - cifs_remap(cifs_sb)); + cifs_sb); if (rc == 0) { cinode->cifsAttrs = le32_to_cpu(buf->Attributes); goto out; diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 157992864ce7e55b50805242ab1240f7d2db5171..d88e2683626e7eb9a3afdb20416f260c9f332311 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -508,15 +508,31 @@ cifs_ses_oplock_break(struct work_struct *work) kfree(lw); } +static void +smb2_queue_pending_open_break(struct tcon_link *tlink, __u8 *lease_key, + __le32 new_lease_state) +{ + struct smb2_lease_break_work *lw; + + lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL); + if (!lw) { + cifs_put_tlink(tlink); + return; + } + + INIT_WORK(&lw->lease_break, cifs_ses_oplock_break); + lw->tlink = tlink; + lw->lease_state = new_lease_state; + memcpy(lw->lease_key, lease_key, SMB2_LEASE_KEY_SIZE); + queue_work(cifsiod_wq, &lw->lease_break); +} + static bool -smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp, - struct smb2_lease_break_work *lw) +smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp) { - bool found; __u8 lease_state; struct list_head *tmp; struct cifsFileInfo *cfile; - struct cifs_pending_open *open; struct cifsInodeInfo *cinode; int ack_req = le32_to_cpu(rsp->Flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED); @@ -546,22 +562,29 @@ smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp, cfile->oplock_level = lease_state; cifs_queue_oplock_break(cfile); - kfree(lw); return true; } - found = false; + return false; +} + +static struct cifs_pending_open * +smb2_tcon_find_pending_open_lease(struct cifs_tcon *tcon, + struct smb2_lease_break *rsp) +{ + __u8 lease_state = le32_to_cpu(rsp->NewLeaseState); + int ack_req = le32_to_cpu(rsp->Flags & + SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED); + struct cifs_pending_open *open; + struct cifs_pending_open *found = NULL; + list_for_each_entry(open, &tcon->pending_opens, olist) { if (memcmp(open->lease_key, rsp->LeaseKey, SMB2_LEASE_KEY_SIZE)) continue; if (!found && ack_req) { - found = true; - memcpy(lw->lease_key, open->lease_key, - SMB2_LEASE_KEY_SIZE); - lw->tlink = cifs_get_tlink(open->tlink); - queue_work(cifsiod_wq, &lw->lease_break); + found = open; } cifs_dbg(FYI, "found in the pending open list\n"); @@ -582,14 +605,7 @@ smb2_is_valid_lease_break(char *buffer) struct TCP_Server_Info *server; struct cifs_ses *ses; struct cifs_tcon *tcon; - struct smb2_lease_break_work *lw; - - lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL); - if (!lw) - return false; - - INIT_WORK(&lw->lease_break, cifs_ses_oplock_break); - lw->lease_state = rsp->NewLeaseState; + struct cifs_pending_open *open; cifs_dbg(FYI, "Checking for lease break\n"); @@ -607,11 +623,27 @@ smb2_is_valid_lease_break(char *buffer) spin_lock(&tcon->open_file_lock); cifs_stats_inc( &tcon->stats.cifs_stats.num_oplock_brks); - if (smb2_tcon_has_lease(tcon, rsp, lw)) { + if (smb2_tcon_has_lease(tcon, rsp)) { spin_unlock(&tcon->open_file_lock); spin_unlock(&cifs_tcp_ses_lock); return true; } + open = smb2_tcon_find_pending_open_lease(tcon, + rsp); + if (open) { + __u8 lease_key[SMB2_LEASE_KEY_SIZE]; + struct tcon_link *tlink; + + tlink = cifs_get_tlink(open->tlink); + memcpy(lease_key, open->lease_key, + SMB2_LEASE_KEY_SIZE); + spin_unlock(&tcon->open_file_lock); + spin_unlock(&cifs_tcp_ses_lock); + smb2_queue_pending_open_break(tlink, + lease_key, + rsp->NewLeaseState); + return true; + } spin_unlock(&tcon->open_file_lock); if (tcon->crfid.is_valid && @@ -629,7 +661,6 @@ smb2_is_valid_lease_break(char *buffer) } } spin_unlock(&cifs_tcp_ses_lock); - kfree(lw); cifs_dbg(FYI, "Can not process lease break - no lease matched\n"); return false; } diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 2f4cdd290c464b47b75c8a105668cfd7817913db..24c2ac360591b8692cba07cbef034a1f6d5a9463 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -152,117 +152,6 @@ out: return; } -#ifdef CONFIG_CIFS_DFS_UPCALL -static int __smb2_reconnect(const struct nls_table *nlsc, - struct cifs_tcon *tcon) -{ - int rc; - struct TCP_Server_Info *server = tcon->ses->server; - struct dfs_cache_tgt_list tl; - struct dfs_cache_tgt_iterator *it = NULL; - char *tree; - const char *tcp_host; - size_t tcp_host_len; - const char *dfs_host; - size_t dfs_host_len; - - tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); - if (!tree) - return -ENOMEM; - - if (!tcon->dfs_path) { - if (tcon->ipc) { - scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", - server->hostname); - rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); - } else { - rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, - nlsc); - } - goto out; - } - - rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl); - if (rc) - goto out; - - extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len); - - for (it = dfs_cache_get_tgt_iterator(&tl); it; - it = dfs_cache_get_next_tgt(&tl, it)) { - const char *share, *prefix; - size_t share_len, prefix_len; - bool target_match; - - rc = dfs_cache_get_tgt_share(it, &share, &share_len, &prefix, - &prefix_len); - if (rc) { - cifs_dbg(VFS, "%s: failed to parse target share %d\n", - __func__, rc); - continue; - } - - extract_unc_hostname(share, &dfs_host, &dfs_host_len); - - if (dfs_host_len != tcp_host_len - || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { - cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", - __func__, - (int)dfs_host_len, dfs_host, - (int)tcp_host_len, tcp_host); - - rc = match_target_ip(server, dfs_host, dfs_host_len, - &target_match); - if (rc) { - cifs_dbg(VFS, "%s: failed to match target ip: %d\n", - __func__, rc); - break; - } - - if (!target_match) { - cifs_dbg(FYI, "%s: skipping target\n", __func__); - continue; - } - } - - if (tcon->ipc) { - scnprintf(tree, MAX_TREE_SIZE, "\\\\%.*s\\IPC$", - (int)share_len, share); - rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); - } else { - scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len, - share); - rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); - if (!rc) { - rc = update_super_prepath(tcon, prefix, - prefix_len); - break; - } - } - if (rc == -EREMOTE) - break; - } - - if (!rc) { - if (it) - rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, - it); - else - rc = -ENOENT; - } - dfs_cache_free_tgts(&tl); -out: - kfree(tree); - return rc; -} -#else -static inline int __smb2_reconnect(const struct nls_table *nlsc, - struct cifs_tcon *tcon) -{ - return SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nlsc); -} -#endif - static int smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, struct TCP_Server_Info *server) @@ -409,7 +298,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, if (tcon->use_persistent) tcon->need_reopen_files = true; - rc = __smb2_reconnect(nls_codepage, tcon); + rc = cifs_tree_connect(0, tcon, nls_codepage); mutex_unlock(&tcon->ses->session_mutex); cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); @@ -1387,6 +1276,8 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) spnego_key = cifs_get_spnego_key(ses); if (IS_ERR(spnego_key)) { rc = PTR_ERR(spnego_key); + if (rc == -ENOKEY) + cifs_dbg(VFS, "Verify user has a krb5 ticket and keyutils is installed\n"); spnego_key = NULL; goto out; } diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 236814d612487b59942fa5143231686e75024769..c3f1baf5bde28fa30631553223ca0d01215a601f 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -31,7 +31,7 @@ * Note that, due to trying to use names similar to the protocol specifications, * there are many mixed case field names in the structures below. Although * this does not match typical Linux kernel style, it is necessary to be - * be able to match against the protocol specfication. + * able to match against the protocol specfication. * * SMB2 commands * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 84433d0653f92a896eba0a063eecdec1b3321b6d..ac7632482736711b33a468de8986eb6173578373 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -936,7 +936,7 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, } /* BB special case reconnect tid and uid here? */ - return map_smb_to_linux_error(mid->resp_buf, log_error); + return map_and_check_smb_error(mid, log_error); } struct mid_q_entry * diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 3b21082e1b550f9d99fa88ad11bdf44113b73996..47f0b98b707f89a81ef2a55886569b3a92b13baa 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -73,6 +73,7 @@ struct dlm_cluster { unsigned int cl_log_debug; unsigned int cl_log_info; unsigned int cl_protocol; + unsigned int cl_mark; unsigned int cl_timewarn_cs; unsigned int cl_waitwarn_us; unsigned int cl_new_rsb_count; @@ -96,6 +97,7 @@ enum { CLUSTER_ATTR_LOG_DEBUG, CLUSTER_ATTR_LOG_INFO, CLUSTER_ATTR_PROTOCOL, + CLUSTER_ATTR_MARK, CLUSTER_ATTR_TIMEWARN_CS, CLUSTER_ATTR_WAITWARN_US, CLUSTER_ATTR_NEW_RSB_COUNT, @@ -168,6 +170,7 @@ CLUSTER_ATTR(scan_secs, 1); CLUSTER_ATTR(log_debug, 0); CLUSTER_ATTR(log_info, 0); CLUSTER_ATTR(protocol, 0); +CLUSTER_ATTR(mark, 0); CLUSTER_ATTR(timewarn_cs, 1); CLUSTER_ATTR(waitwarn_us, 0); CLUSTER_ATTR(new_rsb_count, 0); @@ -183,6 +186,7 @@ static struct configfs_attribute *cluster_attrs[] = { [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug, [CLUSTER_ATTR_LOG_INFO] = &cluster_attr_log_info, [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol, + [CLUSTER_ATTR_MARK] = &cluster_attr_mark, [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs, [CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us, [CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count, @@ -196,6 +200,7 @@ enum { COMM_ATTR_LOCAL, COMM_ATTR_ADDR, COMM_ATTR_ADDR_LIST, + COMM_ATTR_MARK, }; enum { @@ -228,6 +233,7 @@ struct dlm_comm { int nodeid; int local; int addr_count; + unsigned int mark; struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT]; }; @@ -465,6 +471,7 @@ static struct config_item *make_comm(struct config_group *g, const char *name) cm->nodeid = -1; cm->local = 0; cm->addr_count = 0; + cm->mark = 0; return &cm->item; } @@ -660,8 +667,28 @@ static ssize_t comm_addr_list_show(struct config_item *item, char *buf) return 4096 - allowance; } +static ssize_t comm_mark_show(struct config_item *item, char *buf) +{ + return sprintf(buf, "%u\n", config_item_to_comm(item)->mark); +} + +static ssize_t comm_mark_store(struct config_item *item, const char *buf, + size_t len) +{ + unsigned int mark; + int rc; + + rc = kstrtouint(buf, 0, &mark); + if (rc) + return rc; + + config_item_to_comm(item)->mark = mark; + return len; +} + CONFIGFS_ATTR(comm_, nodeid); CONFIGFS_ATTR(comm_, local); +CONFIGFS_ATTR(comm_, mark); CONFIGFS_ATTR_WO(comm_, addr); CONFIGFS_ATTR_RO(comm_, addr_list); @@ -670,6 +697,7 @@ static struct configfs_attribute *comm_attrs[] = { [COMM_ATTR_LOCAL] = &comm_attr_local, [COMM_ATTR_ADDR] = &comm_attr_addr, [COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list, + [COMM_ATTR_MARK] = &comm_attr_mark, NULL, }; @@ -829,6 +857,20 @@ int dlm_comm_seq(int nodeid, uint32_t *seq) return 0; } +int dlm_comm_mark(int nodeid, unsigned int *mark) +{ + struct dlm_comm *cm; + + cm = get_comm(nodeid); + if (!cm) + return -ENOENT; + + *mark = cm->mark; + put_comm(cm); + + return 0; +} + int dlm_our_nodeid(void) { return local_comm ? local_comm->nodeid : 0; @@ -855,6 +897,7 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num) #define DEFAULT_LOG_DEBUG 0 #define DEFAULT_LOG_INFO 1 #define DEFAULT_PROTOCOL 0 +#define DEFAULT_MARK 0 #define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */ #define DEFAULT_WAITWARN_US 0 #define DEFAULT_NEW_RSB_COUNT 128 @@ -871,6 +914,7 @@ struct dlm_config_info dlm_config = { .ci_log_debug = DEFAULT_LOG_DEBUG, .ci_log_info = DEFAULT_LOG_INFO, .ci_protocol = DEFAULT_PROTOCOL, + .ci_mark = DEFAULT_MARK, .ci_timewarn_cs = DEFAULT_TIMEWARN_CS, .ci_waitwarn_us = DEFAULT_WAITWARN_US, .ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT, diff --git a/fs/dlm/config.h b/fs/dlm/config.h index 2b471aae4e61cede203975c777270ae566d20498..f62996cad5616e6db68ede6fd9792300ebf39986 100644 --- a/fs/dlm/config.h +++ b/fs/dlm/config.h @@ -31,6 +31,7 @@ struct dlm_config_info { int ci_log_debug; int ci_log_info; int ci_protocol; + int ci_mark; int ci_timewarn_cs; int ci_waitwarn_us; int ci_new_rsb_count; @@ -45,6 +46,7 @@ void dlm_config_exit(void); int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, int *count_out); int dlm_comm_seq(int nodeid, uint32_t *seq); +int dlm_comm_mark(int nodeid, unsigned int *mark); int dlm_our_nodeid(void); int dlm_our_addr(struct sockaddr_storage *addr, int num); diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index e93670ecfae5b9194d9d9e68b46f5b235b5f9116..624617c12250ad81e7591ee7dc31d697d89e2b75 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -622,6 +622,9 @@ static int new_lockspace(const char *name, const char *cluster, wait_event(ls->ls_recover_lock_wait, test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags)); + /* let kobject handle freeing of ls if there's an error */ + do_unreg = 1; + ls->ls_kobj.kset = dlm_kset; error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL, "%s", ls->ls_name); @@ -629,9 +632,6 @@ static int new_lockspace(const char *name, const char *cluster, goto out_recoverd; kobject_uevent(&ls->ls_kobj, KOBJ_ADD); - /* let kobject handle freeing of ls if there's an error */ - do_unreg = 1; - /* This uevent triggers dlm_controld in userspace to add us to the group of nodes that are members of this lockspace (managed by the cluster infrastructure.) Once it's done that, it tells us who the diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 3543a8fec9075bd2ba05f5f80dacb204d409ea2c..5050fe05769b4d4c8e01bd96a050e095480830ad 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -63,6 +63,7 @@ /* Number of messages to send before rescheduling */ #define MAX_SEND_MSG_COUNT 25 +#define DLM_SHUTDOWN_WAIT_TIMEOUT msecs_to_jiffies(10000) struct cbuf { unsigned int base; @@ -110,10 +111,12 @@ struct connection { #define CF_CLOSE 6 #define CF_APP_LIMITED 7 #define CF_CLOSING 8 +#define CF_SHUTDOWN 9 struct list_head writequeue; /* List of outgoing writequeue_entries */ spinlock_t writequeue_lock; int (*rx_action) (struct connection *); /* What to do when active */ void (*connect_action) (struct connection *); /* What to do to connect */ + void (*shutdown_action)(struct connection *con); /* What to do to shutdown */ struct page *rx_page; struct cbuf cb; int retries; @@ -122,6 +125,7 @@ struct connection { struct connection *othercon; struct work_struct rwork; /* Receive workqueue */ struct work_struct swork; /* Send workqueue */ + wait_queue_head_t shutdown_wait; /* wait for graceful shutdown */ }; #define sock2con(x) ((struct connection *)(x)->sk_user_data) @@ -218,6 +222,7 @@ static struct connection *__nodeid2con(int nodeid, gfp_t alloc) spin_lock_init(&con->writequeue_lock); INIT_WORK(&con->swork, process_send_sockets); INIT_WORK(&con->rwork, process_recv_sockets); + init_waitqueue_head(&con->shutdown_wait); /* Setup action pointers for child sockets */ if (con->nodeid) { @@ -619,6 +624,54 @@ static void close_connection(struct connection *con, bool and_other, clear_bit(CF_CLOSING, &con->flags); } +static void shutdown_connection(struct connection *con) +{ + int ret; + + if (cancel_work_sync(&con->swork)) { + log_print("canceled swork for node %d", con->nodeid); + clear_bit(CF_WRITE_PENDING, &con->flags); + } + + mutex_lock(&con->sock_mutex); + /* nothing to shutdown */ + if (!con->sock) { + mutex_unlock(&con->sock_mutex); + return; + } + + set_bit(CF_SHUTDOWN, &con->flags); + ret = kernel_sock_shutdown(con->sock, SHUT_WR); + mutex_unlock(&con->sock_mutex); + if (ret) { + log_print("Connection %p failed to shutdown: %d will force close", + con, ret); + goto force_close; + } else { + ret = wait_event_timeout(con->shutdown_wait, + !test_bit(CF_SHUTDOWN, &con->flags), + DLM_SHUTDOWN_WAIT_TIMEOUT); + if (ret == 0) { + log_print("Connection %p shutdown timed out, will force close", + con); + goto force_close; + } + } + + return; + +force_close: + clear_bit(CF_SHUTDOWN, &con->flags); + close_connection(con, false, true, true); +} + +static void dlm_tcp_shutdown(struct connection *con) +{ + if (con->othercon) + shutdown_connection(con->othercon); + shutdown_connection(con); +} + /* Data received from remote end */ static int receive_from_sock(struct connection *con) { @@ -685,14 +738,14 @@ static int receive_from_sock(struct connection *con) page_address(con->rx_page), con->cb.base, con->cb.len, PAGE_SIZE); - if (ret == -EBADMSG) { - log_print("lowcomms: addr=%p, base=%u, len=%u, read=%d", - page_address(con->rx_page), con->cb.base, + if (ret < 0) { + log_print("lowcomms err %d: addr=%p, base=%u, len=%u, read=%d", + ret, page_address(con->rx_page), con->cb.base, con->cb.len, r); + cbuf_eat(&con->cb, r); + } else { + cbuf_eat(&con->cb, ret); } - if (ret < 0) - goto out_close; - cbuf_eat(&con->cb, ret); if (cbuf_empty(&con->cb) && !call_again_soon) { __free_page(con->rx_page); @@ -713,13 +766,18 @@ out_resched: out_close: mutex_unlock(&con->sock_mutex); if (ret != -EAGAIN) { - close_connection(con, true, true, false); /* Reconnect when there is something to send */ + close_connection(con, false, true, false); + if (ret == 0) { + log_print("connection %p got EOF from %d", + con, con->nodeid); + /* handling for tcp shutdown */ + clear_bit(CF_SHUTDOWN, &con->flags); + wake_up(&con->shutdown_wait); + /* signal to breaking receive worker */ + ret = -1; + } } - /* Don't return success if we really got EOF */ - if (ret == 0) - ret = -EAGAIN; - return ret; } @@ -803,22 +861,18 @@ static int accept_from_sock(struct connection *con) spin_lock_init(&othercon->writequeue_lock); INIT_WORK(&othercon->swork, process_send_sockets); INIT_WORK(&othercon->rwork, process_recv_sockets); + init_waitqueue_head(&othercon->shutdown_wait); set_bit(CF_IS_OTHERCON, &othercon->flags); + } else { + /* close other sock con if we have something new */ + close_connection(othercon, false, true, false); } + mutex_lock_nested(&othercon->sock_mutex, 2); - if (!othercon->sock) { - newcon->othercon = othercon; - add_sock(newsock, othercon); - addcon = othercon; - mutex_unlock(&othercon->sock_mutex); - } - else { - printk("Extra connection from node %d attempted\n", nodeid); - result = -EAGAIN; - mutex_unlock(&othercon->sock_mutex); - mutex_unlock(&newcon->sock_mutex); - goto accept_err; - } + newcon->othercon = othercon; + add_sock(newsock, othercon); + addcon = othercon; + mutex_unlock(&othercon->sock_mutex); } else { newcon->rx_action = receive_from_sock; @@ -914,6 +968,7 @@ static void sctp_connect_to_sock(struct connection *con) int result; int addr_len; struct socket *sock; + unsigned int mark; if (con->nodeid == 0) { log_print("attempt to connect sock 0 foiled"); @@ -944,6 +999,13 @@ static void sctp_connect_to_sock(struct connection *con) if (result < 0) goto socket_err; + /* set skb mark */ + result = dlm_comm_mark(con->nodeid, &mark); + if (result < 0) + goto bind_err; + + sock_set_mark(sock->sk, mark); + con->rx_action = receive_from_sock; con->connect_action = sctp_connect_to_sock; add_sock(sock, con); @@ -1006,6 +1068,7 @@ static void tcp_connect_to_sock(struct connection *con) struct sockaddr_storage saddr, src_addr; int addr_len; struct socket *sock = NULL; + unsigned int mark; int result; if (con->nodeid == 0) { @@ -1027,6 +1090,13 @@ static void tcp_connect_to_sock(struct connection *con) if (result < 0) goto out_err; + /* set skb mark */ + result = dlm_comm_mark(con->nodeid, &mark); + if (result < 0) + goto out_err; + + sock_set_mark(sock->sk, mark); + memset(&saddr, 0, sizeof(saddr)); result = nodeid_to_addr(con->nodeid, &saddr, NULL, false); if (result < 0) { @@ -1036,6 +1106,7 @@ static void tcp_connect_to_sock(struct connection *con) con->rx_action = receive_from_sock; con->connect_action = tcp_connect_to_sock; + con->shutdown_action = dlm_tcp_shutdown; add_sock(sock, con); /* Bind to our cluster-known address connecting to avoid @@ -1111,6 +1182,8 @@ static struct socket *tcp_create_listen_sock(struct connection *con, goto create_out; } + sock_set_mark(sock->sk, dlm_config.ci_mark); + /* Turn off Nagle's algorithm */ tcp_sock_set_nodelay(sock->sk); @@ -1185,6 +1258,7 @@ static int sctp_listen_for_all(void) } sock_set_rcvbuf(sock->sk, NEEDED_RMEM); + sock_set_mark(sock->sk, dlm_config.ci_mark); sctp_sock_set_nodelay(sock->sk); write_lock_bh(&sock->sk->sk_callback_lock); @@ -1396,7 +1470,7 @@ out: send_error: mutex_unlock(&con->sock_mutex); - close_connection(con, true, false, true); + close_connection(con, false, false, true); /* Requeue the send work. When the work daemon runs again, it will try a new connection, then call this function again. */ queue_work(send_workqueue, &con->swork); @@ -1528,6 +1602,12 @@ static void stop_conn(struct connection *con) _stop_conn(con, true); } +static void shutdown_conn(struct connection *con) +{ + if (con->shutdown_action) + con->shutdown_action(con); +} + static void free_conn(struct connection *con) { close_connection(con, true, true, true); @@ -1579,6 +1659,7 @@ void dlm_lowcomms_stop(void) mutex_lock(&connections_lock); dlm_allow_conn = 0; mutex_unlock(&connections_lock); + foreach_conn(shutdown_conn); work_flush(); clean_writequeues(); foreach_conn(free_conn); diff --git a/fs/erofs/compress.h b/fs/erofs/compress.h index 07d279fd5d67dce831e8cde1df59a9905624da7b..3d452443c545bb928d857eb2f933cb2fdf5dae73 100644 --- a/fs/erofs/compress.h +++ b/fs/erofs/compress.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2019 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_COMPRESS_H diff --git a/fs/erofs/data.c b/fs/erofs/data.c index d0542151e8c4acab509e60d30d3405bd05f9122e..459ecb42cbd3b43b63f85e9fc2f0ff375484e0cc 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c index 7628816f245378f5fa3e196bbb56d09d92043a82..cbadbf55c6c20ec88cf54b053d1d40b86ed34bf8 100644 --- a/fs/erofs/decompressor.c +++ b/fs/erofs/decompressor.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2019 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "compress.h" diff --git a/fs/erofs/dir.c b/fs/erofs/dir.c index d28c623dfef9e851c35f111114030c8692f1d52b..2776bb832127d79d55c91da1b0a1a6fe4705a27e 100644 --- a/fs/erofs/dir.c +++ b/fs/erofs/dir.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h index 385fa49c7749fd7897fe91f13ab9c7823dabb714..9ad1615f447437209dd5c7e4a5af00c5b5232907 100644 --- a/fs/erofs/erofs_fs.h +++ b/fs/erofs/erofs_fs.h @@ -3,7 +3,7 @@ * EROFS (Enhanced ROM File System) on-disk format definition * * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_H diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index 7dd4bbe9674f7797c02832c8436e1dc07fde96cb..139d0bed42f8865d705bc4e18dc16a936e2a6b8c 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -1,38 +1,87 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "xattr.h" #include -/* no locking */ -static int erofs_read_inode(struct inode *inode, void *data) +/* + * if inode is successfully read, return its inode page (or sometimes + * the inode payload page if it's an extended inode) in order to fill + * inline data if possible. + */ +static struct page *erofs_read_inode(struct inode *inode, + unsigned int *ofs) { + struct super_block *sb = inode->i_sb; + struct erofs_sb_info *sbi = EROFS_SB(sb); struct erofs_inode *vi = EROFS_I(inode); - struct erofs_inode_compact *dic = data; - struct erofs_inode_extended *die; + const erofs_off_t inode_loc = iloc(sbi, vi->nid); + + erofs_blk_t blkaddr, nblks = 0; + struct page *page; + struct erofs_inode_compact *dic; + struct erofs_inode_extended *die, *copied = NULL; + unsigned int ifmt; + int err; - const unsigned int ifmt = le16_to_cpu(dic->i_format); - struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); - erofs_blk_t nblks = 0; + blkaddr = erofs_blknr(inode_loc); + *ofs = erofs_blkoff(inode_loc); - vi->datalayout = erofs_inode_datalayout(ifmt); + erofs_dbg("%s, reading inode nid %llu at %u of blkaddr %u", + __func__, vi->nid, *ofs, blkaddr); + + page = erofs_get_meta_page(sb, blkaddr); + if (IS_ERR(page)) { + erofs_err(sb, "failed to get inode (nid: %llu) page, err %ld", + vi->nid, PTR_ERR(page)); + return page; + } + dic = page_address(page) + *ofs; + ifmt = le16_to_cpu(dic->i_format); + + vi->datalayout = erofs_inode_datalayout(ifmt); if (vi->datalayout >= EROFS_INODE_DATALAYOUT_MAX) { erofs_err(inode->i_sb, "unsupported datalayout %u of nid %llu", vi->datalayout, vi->nid); - DBG_BUGON(1); - return -EOPNOTSUPP; + err = -EOPNOTSUPP; + goto err_out; } switch (erofs_inode_version(ifmt)) { case EROFS_INODE_LAYOUT_EXTENDED: - die = data; - vi->inode_isize = sizeof(struct erofs_inode_extended); + /* check if the inode acrosses page boundary */ + if (*ofs + vi->inode_isize <= PAGE_SIZE) { + *ofs += vi->inode_isize; + die = (struct erofs_inode_extended *)dic; + } else { + const unsigned int gotten = PAGE_SIZE - *ofs; + + copied = kmalloc(vi->inode_isize, GFP_NOFS); + if (!copied) { + err = -ENOMEM; + goto err_out; + } + memcpy(copied, dic, gotten); + unlock_page(page); + put_page(page); + + page = erofs_get_meta_page(sb, blkaddr + 1); + if (IS_ERR(page)) { + erofs_err(sb, "failed to get inode payload page (nid: %llu), err %ld", + vi->nid, PTR_ERR(page)); + kfree(copied); + return page; + } + *ofs = vi->inode_isize - gotten; + memcpy((u8 *)copied + gotten, page_address(page), *ofs); + die = copied; + } vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount); inode->i_mode = le16_to_cpu(die->i_mode); @@ -69,9 +118,12 @@ static int erofs_read_inode(struct inode *inode, void *data) /* total blocks for compressed files */ if (erofs_inode_is_data_compressed(vi->datalayout)) nblks = le32_to_cpu(die->i_u.compressed_blocks); + + kfree(copied); break; case EROFS_INODE_LAYOUT_COMPACT: vi->inode_isize = sizeof(struct erofs_inode_compact); + *ofs += vi->inode_isize; vi->xattr_isize = erofs_xattr_ibody_size(dic->i_xattr_icount); inode->i_mode = le16_to_cpu(dic->i_mode); @@ -111,8 +163,8 @@ static int erofs_read_inode(struct inode *inode, void *data) erofs_err(inode->i_sb, "unsupported on-disk inode version %u of nid %llu", erofs_inode_version(ifmt), vi->nid); - DBG_BUGON(1); - return -EOPNOTSUPP; + err = -EOPNOTSUPP; + goto err_out; } if (!nblks) @@ -120,13 +172,18 @@ static int erofs_read_inode(struct inode *inode, void *data) inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9; else inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK; - return 0; + return page; bogusimode: erofs_err(inode->i_sb, "bogus i_mode (%o) @ nid %llu", inode->i_mode, vi->nid); + err = -EFSCORRUPTED; +err_out: DBG_BUGON(1); - return -EFSCORRUPTED; + kfree(copied); + unlock_page(page); + put_page(page); + return ERR_PTR(err); } static int erofs_fill_symlink(struct inode *inode, void *data, @@ -146,7 +203,7 @@ static int erofs_fill_symlink(struct inode *inode, void *data, if (!lnk) return -ENOMEM; - m_pofs += vi->inode_isize + vi->xattr_isize; + m_pofs += vi->xattr_isize; /* inline symlink data shouldn't cross page boundary as well */ if (m_pofs + inode->i_size > PAGE_SIZE) { kfree(lnk); @@ -167,37 +224,17 @@ static int erofs_fill_symlink(struct inode *inode, void *data, static int erofs_fill_inode(struct inode *inode, int isdir) { - struct super_block *sb = inode->i_sb; struct erofs_inode *vi = EROFS_I(inode); struct page *page; - void *data; - int err; - erofs_blk_t blkaddr; unsigned int ofs; - erofs_off_t inode_loc; + int err = 0; trace_erofs_fill_inode(inode, isdir); - inode_loc = iloc(EROFS_SB(sb), vi->nid); - blkaddr = erofs_blknr(inode_loc); - ofs = erofs_blkoff(inode_loc); - - erofs_dbg("%s, reading inode nid %llu at %u of blkaddr %u", - __func__, vi->nid, ofs, blkaddr); - page = erofs_get_meta_page(sb, blkaddr); - - if (IS_ERR(page)) { - erofs_err(sb, "failed to get inode (nid: %llu) page, err %ld", - vi->nid, PTR_ERR(page)); + /* read inode base data from disk */ + page = erofs_read_inode(inode, &ofs); + if (IS_ERR(page)) return PTR_ERR(page); - } - - DBG_BUGON(!PageUptodate(page)); - data = page_address(page); - - err = erofs_read_inode(inode, data + ofs); - if (err) - goto out_unlock; /* setup the new inode */ switch (inode->i_mode & S_IFMT) { @@ -210,7 +247,7 @@ static int erofs_fill_inode(struct inode *inode, int isdir) inode->i_fop = &erofs_dir_fops; break; case S_IFLNK: - err = erofs_fill_symlink(inode, data, ofs); + err = erofs_fill_symlink(inode, page_address(page), ofs); if (err) goto out_unlock; inode_nohighmem(inode); diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 1c077b7bb43db0e3fa27022e0f1a30a8feb0892c..67a7ec9456866bf691e9b4b2af55c52181f1e087 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_INTERNAL_H diff --git a/fs/erofs/namei.c b/fs/erofs/namei.c index 52f201e03c6286a96903f73352b9fc6f9e75055f..5f8cc7346c69415409e554c34d22f25f2879737f 100644 --- a/fs/erofs/namei.c +++ b/fs/erofs/namei.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "xattr.h" diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 7a13ffb07c23c759eae181f4798f38f206583ed1..ddaa516c008af417e03f680e94741e82333570a3 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include diff --git a/fs/erofs/utils.c b/fs/erofs/utils.c index 52d0be10f1aa1ad4645810dfad4aacfbc56c5719..de9986d2f82fd5f46b16c90e14fbb4024569e9fa 100644 --- a/fs/erofs/utils.c +++ b/fs/erofs/utils.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" @@ -127,12 +127,6 @@ int erofs_workgroup_put(struct erofs_workgroup *grp) return count; } -static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp) -{ - erofs_workgroup_unfreeze(grp, 0); - __erofs_workgroup_free(grp); -} - static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, struct erofs_workgroup *grp) { @@ -162,11 +156,9 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, */ DBG_BUGON(xa_erase(&sbi->managed_pslots, grp->index) != grp); - /* - * If managed cache is on, last refcount should indicate - * the related workstation. - */ - erofs_workgroup_unfreeze_final(grp); + /* last refcount should be connected with its managed pslot. */ + erofs_workgroup_unfreeze(grp, 0); + __erofs_workgroup_free(grp); return true; } diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c index e1a0695ccf4d0c7dddba9690e3e04a9a8d0a5d25..0416f3437b951fd8697c1fed6168176dd3278792 100644 --- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include diff --git a/fs/erofs/xattr.h b/fs/erofs/xattr.h index e4e5093f012cc5f5233988f1ff46f2656e0bb6ab..815304bd335f53286e4b1a826e7373538b270324 100644 --- a/fs/erofs/xattr.h +++ b/fs/erofs/xattr.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_XATTR_H diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 24a26aaf847fd2063aba3624b2883a174b08d1f8..6c939def00f9563340cdfaf85685f48706a42e42 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "zdata.h" @@ -43,13 +43,13 @@ void z_erofs_exit_zip_subsystem(void) static inline int z_erofs_init_workqueue(void) { const unsigned int onlinecpus = num_possible_cpus(); - const unsigned int flags = WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE; /* * no need to spawn too many threads, limiting threads could minimum * scheduling overhead, perhaps per-CPU threads should be better? */ - z_erofs_workqueue = alloc_workqueue("erofs_unzipd", flags, + z_erofs_workqueue = alloc_workqueue("erofs_unzipd", + WQ_UNBOUND | WQ_HIGHPRI, onlinecpus + onlinecpus / 4); return z_erofs_workqueue ? 0 : -ENOMEM; } diff --git a/fs/erofs/zdata.h b/fs/erofs/zdata.h index 9b66c28b3ae9dafa98a827b915a6549199b45a14..68c9b29fc0ca51cfd822d352e5d1bf8cd2ccf4d2 100644 --- a/fs/erofs/zdata.h +++ b/fs/erofs/zdata.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_ZDATA_H diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c index 736db3a4cdeff9c38c0365ba5f59fa09da55ec73..7d40d78ea8648ecdd11f8ee85f899232c2c5d4ab 100644 --- a/fs/erofs/zmap.c +++ b/fs/erofs/zmap.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2018-2019 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" diff --git a/fs/erofs/zpvec.h b/fs/erofs/zpvec.h index 58556903aa94517c997038073469214600c4e808..1d67cbd3870421429dc7ac06c878001a873a8755 100644 --- a/fs/erofs/zpvec.h +++ b/fs/erofs/zpvec.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_ZPVEC_H diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 13318e255ebf7c4870cade0e26bdad640bc5265d..70355ab6740ee94e752fd2b034f32a236444369a 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -348,7 +348,6 @@ struct ext2_dir_entry_2 *ext2_find_entry (struct inode *dir, struct page *page = NULL; struct ext2_inode_info *ei = EXT2_I(dir); ext2_dirent * de; - int dir_has_error = 0; if (npages == 0) goto out; @@ -362,25 +361,25 @@ struct ext2_dir_entry_2 *ext2_find_entry (struct inode *dir, n = start; do { char *kaddr; - page = ext2_get_page(dir, n, dir_has_error); - if (!IS_ERR(page)) { - kaddr = page_address(page); - de = (ext2_dirent *) kaddr; - kaddr += ext2_last_byte(dir, n) - reclen; - while ((char *) de <= kaddr) { - if (de->rec_len == 0) { - ext2_error(dir->i_sb, __func__, - "zero-length directory entry"); - ext2_put_page(page); - goto out; - } - if (ext2_match (namelen, name, de)) - goto found; - de = ext2_next_entry(de); + page = ext2_get_page(dir, n, 0); + if (IS_ERR(page)) + return ERR_CAST(page); + + kaddr = page_address(page); + de = (ext2_dirent *) kaddr; + kaddr += ext2_last_byte(dir, n) - reclen; + while ((char *) de <= kaddr) { + if (de->rec_len == 0) { + ext2_error(dir->i_sb, __func__, + "zero-length directory entry"); + ext2_put_page(page); + goto out; } - ext2_put_page(page); - } else - dir_has_error = 1; + if (ext2_match(namelen, name, de)) + goto found; + de = ext2_next_entry(de); + } + ext2_put_page(page); if (++n >= npages) n = 0; @@ -394,7 +393,7 @@ struct ext2_dir_entry_2 *ext2_find_entry (struct inode *dir, } } while (n != start); out: - return NULL; + return ERR_PTR(-ENOENT); found: *res_page = page; @@ -414,18 +413,18 @@ struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p) return de; } -ino_t ext2_inode_by_name(struct inode *dir, const struct qstr *child) +int ext2_inode_by_name(struct inode *dir, const struct qstr *child, ino_t *ino) { - ino_t res = 0; struct ext2_dir_entry_2 *de; struct page *page; - de = ext2_find_entry (dir, child, &page); - if (de) { - res = le32_to_cpu(de->inode); - ext2_put_page(page); - } - return res; + de = ext2_find_entry(dir, child, &page); + if (IS_ERR(de)) + return PTR_ERR(de); + + *ino = le32_to_cpu(de->inode); + ext2_put_page(page); + return 0; } static int ext2_prepare_chunk(struct page *page, loff_t pos, unsigned len) diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 8178bd38a9d699c3a2f3145590887f00d12eca76..5136b7289e8daf7ac50ff26ce22df9d26e65ccc2 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -52,8 +52,8 @@ struct ext2_block_alloc_info { /* * Was i_next_alloc_goal in ext2_inode_info * is the *physical* companion to i_next_alloc_block. - * it the the physical block number of the block which was most-recentl - * allocated to this file. This give us the goal (target) for the next + * it is the physical block number of the block which was most-recently + * allocated to this file. This gives us the goal (target) for the next * allocation when we detect linearly ascending requests. */ ext2_fsblk_t last_alloc_physical_block; @@ -374,7 +374,6 @@ struct ext2_inode { /* * Mount flags */ -#define EXT2_MOUNT_CHECK 0x000001 /* Do mount-time checks */ #define EXT2_MOUNT_OLDALLOC 0x000002 /* Don't use the new Orlov allocator */ #define EXT2_MOUNT_GRPID 0x000004 /* Create files with directory's group */ #define EXT2_MOUNT_DEBUG 0x000008 /* Some debugging messages */ @@ -738,7 +737,8 @@ extern void ext2_rsv_window_add(struct super_block *sb, struct ext2_reserve_wind /* dir.c */ extern int ext2_add_link (struct dentry *, struct inode *); -extern ino_t ext2_inode_by_name(struct inode *, const struct qstr *); +extern int ext2_inode_by_name(struct inode *dir, + const struct qstr *child, ino_t *ino); extern int ext2_make_empty(struct inode *, struct inode *); extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,const struct qstr *, struct page **); extern int ext2_delete_entry (struct ext2_dir_entry_2 *, struct page *); diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index fda7d3f5b4be53161b725a0b6b8a5660027242a7..432c3febea6df969c53ac7ec5b1b76578b93baa0 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -80,6 +80,7 @@ static void ext2_release_inode(struct super_block *sb, int group, int dir) if (dir) le16_add_cpu(&desc->bg_used_dirs_count, -1); spin_unlock(sb_bgl_lock(EXT2_SB(sb), group)); + percpu_counter_inc(&EXT2_SB(sb)->s_freeinodes_counter); if (dir) percpu_counter_dec(&EXT2_SB(sb)->s_dirs_counter); mark_buffer_dirty(bh); @@ -528,7 +529,7 @@ got: goto fail; } - percpu_counter_add(&sbi->s_freeinodes_counter, -1); + percpu_counter_dec(&sbi->s_freeinodes_counter); if (S_ISDIR(mode)) percpu_counter_inc(&sbi->s_dirs_counter); diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index c8b371c82b4fb45f4e63f2e0d3633f2a38624c21..80662e1f7889f532bb061479d87d4174712fbc63 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -356,8 +356,7 @@ static inline ext2_fsblk_t ext2_find_goal(struct inode *inode, long block, * @blks: number of data blocks to be mapped. * @blocks_to_boundary: the offset in the indirect block * - * return the total number of blocks to be allocate, including the - * direct and indirect blocks. + * return the number of direct blocks to allocate. */ static int ext2_blks_to_allocate(Indirect * branch, int k, unsigned long blks, @@ -390,11 +389,9 @@ ext2_blks_to_allocate(Indirect * branch, int k, unsigned long blks, * ext2_alloc_blocks: multiple allocate blocks needed for a branch * @indirect_blks: the number of blocks need to allocate for indirect * blocks - * + * @blks: the number of blocks need to allocate for direct blocks * @new_blocks: on return it will store the new block numbers for * the indirect blocks(if needed) and the first direct block, - * @blks: on return it will store the total number of allocated - * direct blocks */ static int ext2_alloc_blocks(struct inode *inode, ext2_fsblk_t goal, int indirect_blks, int blks, diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index ba3e3e0758913b110dbd1ca31311df137d8eafea..5bf2c145643b839fe5f05df0ee61bd16b82475e1 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -57,13 +57,17 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, uns { struct inode * inode; ino_t ino; + int res; if (dentry->d_name.len > EXT2_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); - ino = ext2_inode_by_name(dir, &dentry->d_name); - inode = NULL; - if (ino) { + res = ext2_inode_by_name(dir, &dentry->d_name, &ino); + if (res) { + if (res != -ENOENT) + return ERR_PTR(res); + inode = NULL; + } else { inode = ext2_iget(dir->i_sb, ino); if (inode == ERR_PTR(-ESTALE)) { ext2_error(dir->i_sb, __func__, @@ -78,9 +82,13 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, uns struct dentry *ext2_get_parent(struct dentry *child) { struct qstr dotdot = QSTR_INIT("..", 2); - unsigned long ino = ext2_inode_by_name(d_inode(child), &dotdot); - if (!ino) - return ERR_PTR(-ENOENT); + ino_t ino; + int res; + + res = ext2_inode_by_name(d_inode(child), &dotdot, &ino); + if (res) + return ERR_PTR(res); + return d_obtain_alias(ext2_iget(child->d_sb, ino)); } @@ -274,9 +282,9 @@ static int ext2_unlink(struct inode * dir, struct dentry *dentry) if (err) goto out; - de = ext2_find_entry (dir, &dentry->d_name, &page); - if (!de) { - err = -ENOENT; + de = ext2_find_entry(dir, &dentry->d_name, &page); + if (IS_ERR(de)) { + err = PTR_ERR(de); goto out; } @@ -330,9 +338,9 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, if (err) goto out; - old_de = ext2_find_entry (old_dir, &old_dentry->d_name, &old_page); - if (!old_de) { - err = -ENOENT; + old_de = ext2_find_entry(old_dir, &old_dentry->d_name, &old_page); + if (IS_ERR(old_de)) { + err = PTR_ERR(old_de); goto out; } @@ -351,10 +359,11 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, if (dir_de && !ext2_empty_dir (new_inode)) goto out_dir; - err = -ENOENT; - new_de = ext2_find_entry (new_dir, &new_dentry->d_name, &new_page); - if (!new_de) + new_de = ext2_find_entry(new_dir, &new_dentry->d_name, &new_page); + if (IS_ERR(new_de)) { + err = PTR_ERR(new_de); goto out_dir; + } ext2_set_link(new_dir, new_de, new_page, old_inode, 1); new_inode->i_ctime = current_time(new_inode); if (dir_de) diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 4a4ab683250df231a31f1713c30b3633e3eb7043..dda860562ca346683d88b91e1be889dff6eef9e7 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -431,7 +431,7 @@ static unsigned long get_sb_block(void **data) enum { Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid, Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, - Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug, + Opt_err_ro, Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_xip, Opt_dax, Opt_ignore, Opt_err, Opt_quota, Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation @@ -451,8 +451,6 @@ static const match_table_t tokens = { {Opt_err_panic, "errors=panic"}, {Opt_err_ro, "errors=remount-ro"}, {Opt_nouid32, "nouid32"}, - {Opt_nocheck, "check=none"}, - {Opt_nocheck, "nocheck"}, {Opt_debug, "debug"}, {Opt_oldalloc, "oldalloc"}, {Opt_orlov, "orlov"}, @@ -546,12 +544,6 @@ static int parse_options(char *options, struct super_block *sb, case Opt_nouid32: set_opt (opts->s_mount_opt, NO_UID32); break; - case Opt_nocheck: - ext2_msg(sb, KERN_WARNING, - "Option nocheck/check=none is deprecated and" - " will be removed in June 2020."); - clear_opt (opts->s_mount_opt, CHECK); - break; case Opt_debug: set_opt (opts->s_mount_opt, DEBUG); break; diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 943cc469f42ffebaf4102339de1528fa372bf71a..841fa6d9d744b7712f0ad89dbc423a1f5dc2ae28 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -437,6 +437,9 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name, name_len = strlen(name); if (name_len > 255 || value_len > sb->s_blocksize) return -ERANGE; + error = dquot_initialize(inode); + if (error) + return error; down_write(&EXT2_I(inode)->xattr_sem); if (EXT2_I(inode)->i_file_acl) { /* The inode already has an extended attribute block. */ @@ -588,7 +591,6 @@ bad_block: /* Remove the old value. */ memmove(first_val + size, first_val, val - first_val); memset(first_val, 0, size); - here->e_value_offs = 0; min_offs += size; /* Adjust all value offsets. */ @@ -600,6 +602,8 @@ bad_block: cpu_to_le16(o + size); last = EXT2_XATTR_NEXT(last); } + + here->e_value_offs = 0; } if (value == NULL) { /* Remove the old name. */ diff --git a/fs/ext4/file.c b/fs/ext4/file.c index d534f72675d96f7bf2c9a3e464906d1e8817e2ba..f0ac0c1ba17d60e3995bea23307c7c22365a1350 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -546,6 +546,8 @@ static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from) iomap_ops = &ext4_iomap_overwrite_ops; ret = iomap_dio_rw(iocb, from, iomap_ops, &ext4_dio_write_ops, is_sync_kiocb(iocb) || unaligned_io || extend); + if (ret == -ENOTBLK) + ret = 0; if (extend) ret = ext4_handle_inode_extension(inode, offset, ret, count); diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index bebde537ac8cf26d3329b817dccfb356f6e4e2c3..b085a3bea4f0fdbc5f5c878e73064cdd93bde816 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -835,7 +835,8 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from) ret = iomap_dio_rw(iocb, from, &gfs2_iomap_ops, NULL, is_sync_kiocb(iocb)); - + if (ret == -ENOTBLK) + ret = 0; out: gfs2_glock_dq(&gh); out_uninit: diff --git a/fs/iomap/apply.c b/fs/iomap/apply.c index 76925b40b5fd25aaa72cbaba466a33857af7bcdb..26ab6563181fc63491ec7f744c1ec0eadce056ab 100644 --- a/fs/iomap/apply.c +++ b/fs/iomap/apply.c @@ -46,10 +46,14 @@ iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags, ret = ops->iomap_begin(inode, pos, length, flags, &iomap, &srcmap); if (ret) return ret; - if (WARN_ON(iomap.offset > pos)) - return -EIO; - if (WARN_ON(iomap.length == 0)) - return -EIO; + if (WARN_ON(iomap.offset > pos)) { + written = -EIO; + goto out; + } + if (WARN_ON(iomap.length == 0)) { + written = -EIO; + goto out; + } trace_iomap_apply_dstmap(inode, &iomap); if (srcmap.type != IOMAP_HOLE) @@ -80,6 +84,7 @@ iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags, written = actor(inode, pos, length, data, &iomap, srcmap.type != IOMAP_HOLE ? &srcmap : &iomap); +out: /* * Now the data has been copied, commit the range we've copied. This * should not fail unless the filesystem has had a fatal error. diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c index 1e123d78519923c78b565179577854eb8578f539..c9ec3e9d59a39b46e16973efeee832f3765bab09 100644 --- a/fs/iomap/direct-io.c +++ b/fs/iomap/direct-io.c @@ -11,6 +11,7 @@ #include #include #include +#include "trace.h" #include "../internal.h" @@ -409,6 +410,9 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length, * can be mapped into multiple disjoint IOs and only a subset of the IOs issued * may be pure data writes. In that case, we still need to do a full data sync * completion. + * + * Returns -ENOTBLK In case of a page invalidation invalidation failure for + * writes. The callers needs to fall back to buffered I/O in this case. */ ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, @@ -483,23 +487,24 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, if (ret) goto out_free_dio; - /* - * Try to invalidate cache pages for the range we're direct - * writing. If this invalidation fails, tough, the write will - * still work, but racing two incompatible write paths is a - * pretty crazy thing to do, so we don't support it 100%. - */ - ret = invalidate_inode_pages2_range(mapping, - pos >> PAGE_SHIFT, end >> PAGE_SHIFT); - if (ret) - dio_warn_stale_pagecache(iocb->ki_filp); - ret = 0; - - if (iov_iter_rw(iter) == WRITE && !wait_for_completion && - !inode->i_sb->s_dio_done_wq) { - ret = sb_init_dio_done_wq(inode->i_sb); - if (ret < 0) + if (iov_iter_rw(iter) == WRITE) { + /* + * Try to invalidate cache pages for the range we are writing. + * If this invalidation fails, let the caller fall back to + * buffered I/O. + */ + if (invalidate_inode_pages2_range(mapping, pos >> PAGE_SHIFT, + end >> PAGE_SHIFT)) { + trace_iomap_dio_invalidate_fail(inode, pos, count); + ret = -ENOTBLK; goto out_free_dio; + } + + if (!wait_for_completion && !inode->i_sb->s_dio_done_wq) { + ret = sb_init_dio_done_wq(inode->i_sb); + if (ret < 0) + goto out_free_dio; + } } inode_dio_begin(inode); diff --git a/fs/iomap/trace.h b/fs/iomap/trace.h index 5693a39d52fb630edf688ef58426c782632be759..fdc7ae388476f50071e8232bdc4c1bf472a7934b 100644 --- a/fs/iomap/trace.h +++ b/fs/iomap/trace.h @@ -74,6 +74,7 @@ DEFINE_EVENT(iomap_range_class, name, \ DEFINE_RANGE_EVENT(iomap_writepage); DEFINE_RANGE_EVENT(iomap_releasepage); DEFINE_RANGE_EVENT(iomap_invalidatepage); +DEFINE_RANGE_EVENT(iomap_dio_invalidate_fail); #define IOMAP_TYPE_STRINGS \ { IOMAP_HOLE, "HOLE" }, \ diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c index 06b342d8462bf36e85fe91dd189a58aa1279bf9b..f277d023ebcd14b44454906cc5b776600151013b 100644 --- a/fs/kernfs/file.c +++ b/fs/kernfs/file.c @@ -883,6 +883,7 @@ repeat: list_for_each_entry(info, &kernfs_root(kn)->supers, node) { struct kernfs_node *parent; + struct inode *p_inode = NULL; struct inode *inode; struct qstr name; @@ -899,20 +900,20 @@ repeat: name = (struct qstr)QSTR_INIT(kn->name, strlen(kn->name)); parent = kernfs_get_parent(kn); if (parent) { - struct inode *p_inode; - p_inode = ilookup(info->sb, kernfs_ino(parent)); if (p_inode) { - fsnotify(p_inode, FS_MODIFY | FS_EVENT_ON_CHILD, - inode, FSNOTIFY_EVENT_INODE, &name, 0); + fsnotify(FS_MODIFY | FS_EVENT_ON_CHILD, + inode, FSNOTIFY_EVENT_INODE, + p_inode, &name, inode, 0); iput(p_inode); } kernfs_put(parent); } - fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE, - &name, 0); + if (!p_inode) + fsnotify_inode(inode, FS_MODIFY); + iput(inode); } diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 82198d747c4c9d14784ce40f968c3916e8bccdb9..c8b9d2667ee6f4fb7c0918b5e72673602fe6d863 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -598,11 +598,9 @@ static struct notifier_block nfsd_file_lease_notifier = { }; static int -nfsd_file_fsnotify_handle_event(struct fsnotify_group *group, - struct inode *inode, - u32 mask, const void *data, int data_type, - const struct qstr *file_name, u32 cookie, - struct fsnotify_iter_info *iter_info) +nfsd_file_fsnotify_handle_event(struct fsnotify_mark *mark, u32 mask, + struct inode *inode, struct inode *dir, + const struct qstr *name) { trace_nfsd_file_fsnotify_handle_event(inode, mask); @@ -624,7 +622,7 @@ nfsd_file_fsnotify_handle_event(struct fsnotify_group *group, static const struct fsnotify_ops nfsd_file_fsnotify_ops = { - .handle_event = nfsd_file_fsnotify_handle_event, + .handle_inode_event = nfsd_file_fsnotify_handle_event, .free_mark = nfsd_file_mark_free, }; diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 7a42c2ebe28d76c1d376e9192ae0373412dc3bac..5dcda8f20c04f9eaa5d917c9324f2ef8e43fa4dc 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -70,13 +70,10 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark) * destroy the dnotify struct if it was not registered to receive multiple * events. */ -static int dnotify_handle_event(struct fsnotify_group *group, - struct inode *inode, - u32 mask, const void *data, int data_type, - const struct qstr *file_name, u32 cookie, - struct fsnotify_iter_info *iter_info) +static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask, + struct inode *inode, struct inode *dir, + const struct qstr *name) { - struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); struct dnotify_mark *dn_mark; struct dnotify_struct *dn; struct dnotify_struct **prev; @@ -84,10 +81,7 @@ static int dnotify_handle_event(struct fsnotify_group *group, __u32 test_mask = mask & ~FS_EVENT_ON_CHILD; /* not a dir, dnotify doesn't care */ - if (!S_ISDIR(inode->i_mode)) - return 0; - - if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info))) + if (!dir && !(mask & FS_ISDIR)) return 0; dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark); @@ -127,7 +121,7 @@ static void dnotify_free_mark(struct fsnotify_mark *fsn_mark) } static const struct fsnotify_ops dnotify_fsnotify_ops = { - .handle_event = dnotify_handle_event, + .handle_inode_event = dnotify_handle_event, .free_mark = dnotify_free_mark, }; diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 85eda539b35f9556a829cd5ed481da55a97a209d..c942910a864967659756bd06c67f97866d0dc02e 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -34,10 +34,6 @@ static bool fanotify_fh_equal(struct fanotify_fh *fh1, if (fh1->type != fh2->type || fh1->len != fh2->len) return false; - /* Do not merge events if we failed to encode fh */ - if (fh1->type == FILEID_INVALID) - return false; - return !fh1->len || !memcmp(fanotify_fh_buf(fh1), fanotify_fh_buf(fh2), fh1->len); } @@ -53,25 +49,47 @@ static bool fanotify_fid_event_equal(struct fanotify_fid_event *ffe1, fanotify_fh_equal(&ffe1->object_fh, &ffe2->object_fh); } +static bool fanotify_info_equal(struct fanotify_info *info1, + struct fanotify_info *info2) +{ + if (info1->dir_fh_totlen != info2->dir_fh_totlen || + info1->file_fh_totlen != info2->file_fh_totlen || + info1->name_len != info2->name_len) + return false; + + if (info1->dir_fh_totlen && + !fanotify_fh_equal(fanotify_info_dir_fh(info1), + fanotify_info_dir_fh(info2))) + return false; + + if (info1->file_fh_totlen && + !fanotify_fh_equal(fanotify_info_file_fh(info1), + fanotify_info_file_fh(info2))) + return false; + + return !info1->name_len || + !memcmp(fanotify_info_name(info1), fanotify_info_name(info2), + info1->name_len); +} + static bool fanotify_name_event_equal(struct fanotify_name_event *fne1, struct fanotify_name_event *fne2) { - /* - * Do not merge name events without dir fh. - * FAN_DIR_MODIFY does not encode object fh, so it may be empty. - */ - if (!fne1->dir_fh.len) + struct fanotify_info *info1 = &fne1->info; + struct fanotify_info *info2 = &fne2->info; + + /* Do not merge name events without dir fh */ + if (!info1->dir_fh_totlen) return false; - if (fne1->name_len != fne2->name_len || - !fanotify_fh_equal(&fne1->dir_fh, &fne2->dir_fh)) + if (!fanotify_fsid_equal(&fne1->fsid, &fne2->fsid)) return false; - return !memcmp(fne1->name, fne2->name, fne1->name_len); + return fanotify_info_equal(info1, info2); } static bool fanotify_should_merge(struct fsnotify_event *old_fsn, - struct fsnotify_event *new_fsn) + struct fsnotify_event *new_fsn) { struct fanotify_event *old, *new; @@ -83,22 +101,22 @@ static bool fanotify_should_merge(struct fsnotify_event *old_fsn, old->type != new->type || old->pid != new->pid) return false; + /* + * We want to merge many dirent events in the same dir (i.e. + * creates/unlinks/renames), but we do not want to merge dirent + * events referring to subdirs with dirent events referring to + * non subdirs, otherwise, user won't be able to tell from a + * mask FAN_CREATE|FAN_DELETE|FAN_ONDIR if it describes mkdir+ + * unlink pair or rmdir+create pair of events. + */ + if ((old->mask & FS_ISDIR) != (new->mask & FS_ISDIR)) + return false; + switch (old->type) { case FANOTIFY_EVENT_TYPE_PATH: return fanotify_path_equal(fanotify_event_path(old), fanotify_event_path(new)); case FANOTIFY_EVENT_TYPE_FID: - /* - * We want to merge many dirent events in the same dir (i.e. - * creates/unlinks/renames), but we do not want to merge dirent - * events referring to subdirs with dirent events referring to - * non subdirs, otherwise, user won't be able to tell from a - * mask FAN_CREATE|FAN_DELETE|FAN_ONDIR if it describes mkdir+ - * unlink pair or rmdir+create pair of events. - */ - if ((old->mask & FS_ISDIR) != (new->mask & FS_ISDIR)) - return false; - return fanotify_fid_event_equal(FANOTIFY_FE(old), FANOTIFY_FE(new)); case FANOTIFY_EVENT_TYPE_FID_NAME: @@ -208,24 +226,30 @@ out: static u32 fanotify_group_event_mask(struct fsnotify_group *group, struct fsnotify_iter_info *iter_info, u32 event_mask, const void *data, - int data_type) + int data_type, struct inode *dir) { __u32 marks_mask = 0, marks_ignored_mask = 0; - __u32 test_mask, user_mask = FANOTIFY_OUTGOING_EVENTS; + __u32 test_mask, user_mask = FANOTIFY_OUTGOING_EVENTS | + FANOTIFY_EVENT_FLAGS; const struct path *path = fsnotify_data_path(data, data_type); + unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS); struct fsnotify_mark *mark; int type; pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n", __func__, iter_info->report_mask, event_mask, data, data_type); - if (!FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { + if (!fid_mode) { /* Do we have path to open a file descriptor? */ if (!path) return 0; /* Path type events are only relevant for files and dirs */ if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry)) return 0; + } else if (!(fid_mode & FAN_REPORT_FID)) { + /* Do we have a directory inode to report? */ + if (!dir && !(event_mask & FS_ISDIR)) + return 0; } fsnotify_foreach_obj_type(type) { @@ -244,12 +268,12 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, continue; /* - * If the event is for a child and this mark doesn't care about - * events on a child, don't send it! + * If the event is for a child and this mark is on a parent not + * watching children, don't send it! */ if (event_mask & FS_EVENT_ON_CHILD && - (type != FSNOTIFY_OBJ_TYPE_INODE || - !(mark->mask & FS_EVENT_ON_CHILD))) + type == FSNOTIFY_OBJ_TYPE_INODE && + !(mark->mask & FS_EVENT_ON_CHILD)) continue; marks_mask |= mark->mask; @@ -264,67 +288,102 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, * * For backward compatibility and consistency, do not report FAN_ONDIR * to user in legacy fanotify mode (reporting fd) and report FAN_ONDIR - * to user in FAN_REPORT_FID mode for all event types. + * to user in fid mode for all event types. + * + * We never report FAN_EVENT_ON_CHILD to user, but we do pass it in to + * fanotify_alloc_event() when group is reporting fid as indication + * that event happened on child. */ - if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { - /* Do not report FAN_ONDIR without any event */ - if (!(test_mask & ~FAN_ONDIR)) + if (fid_mode) { + /* Do not report event flags without any event */ + if (!(test_mask & ~FANOTIFY_EVENT_FLAGS)) return 0; } else { - user_mask &= ~FAN_ONDIR; + user_mask &= ~FANOTIFY_EVENT_FLAGS; } return test_mask & user_mask; } -static void fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode, - gfp_t gfp) +/* + * Check size needed to encode fanotify_fh. + * + * Return size of encoded fh without fanotify_fh header. + * Return 0 on failure to encode. + */ +static int fanotify_encode_fh_len(struct inode *inode) { - int dwords, type, bytes = 0; + int dwords = 0; + + if (!inode) + return 0; + + exportfs_encode_inode_fh(inode, NULL, &dwords, NULL); + + return dwords << 2; +} + +/* + * Encode fanotify_fh. + * + * Return total size of encoded fh including fanotify_fh header. + * Return 0 on failure to encode. + */ +static int fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode, + unsigned int fh_len, gfp_t gfp) +{ + int dwords, type = 0; char *ext_buf = NULL; void *buf = fh->buf; int err; + fh->type = FILEID_ROOT; + fh->len = 0; + fh->flags = 0; if (!inode) - goto out; + return 0; - dwords = 0; + /* + * !gpf means preallocated variable size fh, but fh_len could + * be zero in that case if encoding fh len failed. + */ err = -ENOENT; - type = exportfs_encode_inode_fh(inode, NULL, &dwords, NULL); - if (!dwords) + if (fh_len < 4 || WARN_ON_ONCE(fh_len % 4)) goto out_err; - bytes = dwords << 2; - if (bytes > FANOTIFY_INLINE_FH_LEN) { - /* Treat failure to allocate fh as failure to allocate event */ + /* No external buffer in a variable size allocated fh */ + if (gfp && fh_len > FANOTIFY_INLINE_FH_LEN) { + /* Treat failure to allocate fh as failure to encode fh */ err = -ENOMEM; - ext_buf = kmalloc(bytes, gfp); + ext_buf = kmalloc(fh_len, gfp); if (!ext_buf) goto out_err; *fanotify_fh_ext_buf_ptr(fh) = ext_buf; buf = ext_buf; + fh->flags |= FANOTIFY_FH_FLAG_EXT_BUF; } + dwords = fh_len >> 2; type = exportfs_encode_inode_fh(inode, buf, &dwords, NULL); err = -EINVAL; - if (!type || type == FILEID_INVALID || bytes != dwords << 2) + if (!type || type == FILEID_INVALID || fh_len != dwords << 2) goto out_err; fh->type = type; - fh->len = bytes; + fh->len = fh_len; - return; + return FANOTIFY_FH_HDR_LEN + fh_len; out_err: pr_warn_ratelimited("fanotify: failed to encode fid (type=%d, len=%d, err=%i)\n", - type, bytes, err); + type, fh_len, err); kfree(ext_buf); *fanotify_fh_ext_buf_ptr(fh) = NULL; -out: /* Report the event without a file identifier on encode error */ fh->type = FILEID_INVALID; fh->len = 0; + return 0; } /* @@ -335,27 +394,179 @@ out: * FS_ATTRIB reports the child inode even if reported on a watched parent. * FS_CREATE reports the modified dir inode and not the created inode. */ -static struct inode *fanotify_fid_inode(struct inode *to_tell, u32 event_mask, - const void *data, int data_type) +static struct inode *fanotify_fid_inode(u32 event_mask, const void *data, + int data_type, struct inode *dir) { if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS) - return to_tell; + return dir; + + return fsnotify_data_inode(data, data_type); +} + +/* + * The inode to use as identifier when reporting dir fid depends on the event. + * Report the modified directory inode on dirent modification events. + * Report the "victim" inode if "victim" is a directory. + * Report the parent inode if "victim" is not a directory and event is + * reported to parent. + * Otherwise, do not report dir fid. + */ +static struct inode *fanotify_dfid_inode(u32 event_mask, const void *data, + int data_type, struct inode *dir) +{ + struct inode *inode = fsnotify_data_inode(data, data_type); + + if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS) + return dir; + + if (S_ISDIR(inode->i_mode)) + return inode; + + return dir; +} + +static struct fanotify_event *fanotify_alloc_path_event(const struct path *path, + gfp_t gfp) +{ + struct fanotify_path_event *pevent; + + pevent = kmem_cache_alloc(fanotify_path_event_cachep, gfp); + if (!pevent) + return NULL; + + pevent->fae.type = FANOTIFY_EVENT_TYPE_PATH; + pevent->path = *path; + path_get(path); + + return &pevent->fae; +} - return (struct inode *)fsnotify_data_inode(data, data_type); +static struct fanotify_event *fanotify_alloc_perm_event(const struct path *path, + gfp_t gfp) +{ + struct fanotify_perm_event *pevent; + + pevent = kmem_cache_alloc(fanotify_perm_event_cachep, gfp); + if (!pevent) + return NULL; + + pevent->fae.type = FANOTIFY_EVENT_TYPE_PATH_PERM; + pevent->response = 0; + pevent->state = FAN_EVENT_INIT; + pevent->path = *path; + path_get(path); + + return &pevent->fae; } -struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, - struct inode *inode, u32 mask, - const void *data, int data_type, - const struct qstr *file_name, - __kernel_fsid_t *fsid) +static struct fanotify_event *fanotify_alloc_fid_event(struct inode *id, + __kernel_fsid_t *fsid, + gfp_t gfp) +{ + struct fanotify_fid_event *ffe; + + ffe = kmem_cache_alloc(fanotify_fid_event_cachep, gfp); + if (!ffe) + return NULL; + + ffe->fae.type = FANOTIFY_EVENT_TYPE_FID; + ffe->fsid = *fsid; + fanotify_encode_fh(&ffe->object_fh, id, fanotify_encode_fh_len(id), + gfp); + + return &ffe->fae; +} + +static struct fanotify_event *fanotify_alloc_name_event(struct inode *id, + __kernel_fsid_t *fsid, + const struct qstr *file_name, + struct inode *child, + gfp_t gfp) +{ + struct fanotify_name_event *fne; + struct fanotify_info *info; + struct fanotify_fh *dfh, *ffh; + unsigned int dir_fh_len = fanotify_encode_fh_len(id); + unsigned int child_fh_len = fanotify_encode_fh_len(child); + unsigned int size; + + size = sizeof(*fne) + FANOTIFY_FH_HDR_LEN + dir_fh_len; + if (child_fh_len) + size += FANOTIFY_FH_HDR_LEN + child_fh_len; + if (file_name) + size += file_name->len + 1; + fne = kmalloc(size, gfp); + if (!fne) + return NULL; + + fne->fae.type = FANOTIFY_EVENT_TYPE_FID_NAME; + fne->fsid = *fsid; + info = &fne->info; + fanotify_info_init(info); + dfh = fanotify_info_dir_fh(info); + info->dir_fh_totlen = fanotify_encode_fh(dfh, id, dir_fh_len, 0); + if (child_fh_len) { + ffh = fanotify_info_file_fh(info); + info->file_fh_totlen = fanotify_encode_fh(ffh, child, child_fh_len, 0); + } + if (file_name) + fanotify_info_copy_name(info, file_name); + + pr_debug("%s: ino=%lu size=%u dir_fh_len=%u child_fh_len=%u name_len=%u name='%.*s'\n", + __func__, id->i_ino, size, dir_fh_len, child_fh_len, + info->name_len, info->name_len, fanotify_info_name(info)); + + return &fne->fae; +} + +static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, + u32 mask, const void *data, + int data_type, struct inode *dir, + const struct qstr *file_name, + __kernel_fsid_t *fsid) { struct fanotify_event *event = NULL; - struct fanotify_fid_event *ffe = NULL; - struct fanotify_name_event *fne = NULL; gfp_t gfp = GFP_KERNEL_ACCOUNT; - struct inode *id = fanotify_fid_inode(inode, mask, data, data_type); + struct inode *id = fanotify_fid_inode(mask, data, data_type, dir); + struct inode *dirid = fanotify_dfid_inode(mask, data, data_type, dir); const struct path *path = fsnotify_data_path(data, data_type); + unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS); + struct inode *child = NULL; + bool name_event = false; + + if ((fid_mode & FAN_REPORT_DIR_FID) && dirid) { + /* + * With both flags FAN_REPORT_DIR_FID and FAN_REPORT_FID, we + * report the child fid for events reported on a non-dir child + * in addition to reporting the parent fid and maybe child name. + */ + if ((fid_mode & FAN_REPORT_FID) && + id != dirid && !(mask & FAN_ONDIR)) + child = id; + + id = dirid; + + /* + * We record file name only in a group with FAN_REPORT_NAME + * and when we have a directory inode to report. + * + * For directory entry modification event, we record the fid of + * the directory and the name of the modified entry. + * + * For event on non-directory that is reported to parent, we + * record the fid of the parent and the name of the child. + * + * Even if not reporting name, we need a variable length + * fanotify_name_event if reporting both parent and child fids. + */ + if (!(fid_mode & FAN_REPORT_NAME)) { + name_event = !!child; + file_name = NULL; + } else if ((mask & ALL_FSNOTIFY_DIRENT_EVENTS) || + !(mask & FAN_ONDIR)) { + name_event = true; + } + } /* * For queues with unlimited length lost events are not expected and @@ -372,87 +583,30 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, memalloc_use_memcg(group->memcg); if (fanotify_is_perm_event(mask)) { - struct fanotify_perm_event *pevent; - - pevent = kmem_cache_alloc(fanotify_perm_event_cachep, gfp); - if (!pevent) - goto out; - - event = &pevent->fae; - event->type = FANOTIFY_EVENT_TYPE_PATH_PERM; - pevent->response = 0; - pevent->state = FAN_EVENT_INIT; - goto init; - } - - /* - * For FAN_DIR_MODIFY event, we report the fid of the directory and - * the name of the modified entry. - * Allocate an fanotify_name_event struct and copy the name. - */ - if (mask & FAN_DIR_MODIFY && !(WARN_ON_ONCE(!file_name))) { - fne = kmalloc(sizeof(*fne) + file_name->len + 1, gfp); - if (!fne) - goto out; - - event = &fne->fae; - event->type = FANOTIFY_EVENT_TYPE_FID_NAME; - fne->name_len = file_name->len; - strcpy(fne->name, file_name->name); - goto init; - } - - if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { - ffe = kmem_cache_alloc(fanotify_fid_event_cachep, gfp); - if (!ffe) - goto out; - - event = &ffe->fae; - event->type = FANOTIFY_EVENT_TYPE_FID; + event = fanotify_alloc_perm_event(path, gfp); + } else if (name_event && (file_name || child)) { + event = fanotify_alloc_name_event(id, fsid, file_name, child, + gfp); + } else if (fid_mode) { + event = fanotify_alloc_fid_event(id, fsid, gfp); } else { - struct fanotify_path_event *pevent; - - pevent = kmem_cache_alloc(fanotify_path_event_cachep, gfp); - if (!pevent) - goto out; - - event = &pevent->fae; - event->type = FANOTIFY_EVENT_TYPE_PATH; + event = fanotify_alloc_path_event(path, gfp); } -init: + if (!event) + goto out; + /* * Use the victim inode instead of the watching inode as the id for * event queue, so event reported on parent is merged with event * reported on child when both directory and child watches exist. */ - fsnotify_init_event(&event->fse, (unsigned long)id); - event->mask = mask; + fanotify_init_event(event, (unsigned long)id, mask); if (FAN_GROUP_FLAG(group, FAN_REPORT_TID)) event->pid = get_pid(task_pid(current)); else event->pid = get_pid(task_tgid(current)); - if (fsid && fanotify_event_fsid(event)) - *fanotify_event_fsid(event) = *fsid; - - if (fanotify_event_object_fh(event)) - fanotify_encode_fh(fanotify_event_object_fh(event), id, gfp); - - if (fanotify_event_dir_fh(event)) - fanotify_encode_fh(fanotify_event_dir_fh(event), id, gfp); - - if (fanotify_event_has_path(event)) { - struct path *p = fanotify_event_path(event); - - if (path) { - *p = *path; - path_get(path); - } else { - p->mnt = NULL; - p->dentry = NULL; - } - } out: memalloc_unuse_memcg(); return event; @@ -491,9 +645,9 @@ static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info) return fsid; } -static int fanotify_handle_event(struct fsnotify_group *group, - struct inode *inode, - u32 mask, const void *data, int data_type, +static int fanotify_handle_event(struct fsnotify_group *group, u32 mask, + const void *data, int data_type, + struct inode *dir, const struct qstr *file_name, u32 cookie, struct fsnotify_iter_info *iter_info) { @@ -512,7 +666,6 @@ static int fanotify_handle_event(struct fsnotify_group *group, BUILD_BUG_ON(FAN_MOVED_FROM != FS_MOVED_FROM); BUILD_BUG_ON(FAN_CREATE != FS_CREATE); BUILD_BUG_ON(FAN_DELETE != FS_DELETE); - BUILD_BUG_ON(FAN_DIR_MODIFY != FS_DIR_MODIFY); BUILD_BUG_ON(FAN_DELETE_SELF != FS_DELETE_SELF); BUILD_BUG_ON(FAN_MOVE_SELF != FS_MOVE_SELF); BUILD_BUG_ON(FAN_EVENT_ON_CHILD != FS_EVENT_ON_CHILD); @@ -526,12 +679,11 @@ static int fanotify_handle_event(struct fsnotify_group *group, BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 19); mask = fanotify_group_event_mask(group, iter_info, mask, data, - data_type); + data_type, dir); if (!mask) return 0; - pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode, - mask); + pr_debug("%s: group=%p mask=%x\n", __func__, group, mask); if (fanotify_is_perm_event(mask)) { /* @@ -542,14 +694,14 @@ static int fanotify_handle_event(struct fsnotify_group *group, return 0; } - if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { + if (FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS)) { fsid = fanotify_get_fsid(iter_info); /* Racing with mark destruction or creation? */ if (!fsid.val[0] && !fsid.val[1]) return 0; } - event = fanotify_alloc_event(group, inode, mask, data, data_type, + event = fanotify_alloc_event(group, mask, data, data_type, dir, file_name, &fsid); ret = -ENOMEM; if (unlikely(!event)) { @@ -614,11 +766,7 @@ static void fanotify_free_fid_event(struct fanotify_event *event) static void fanotify_free_name_event(struct fanotify_event *event) { - struct fanotify_name_event *fne = FANOTIFY_NE(event); - - if (fanotify_fh_has_ext_buf(&fne->dir_fh)) - kfree(fanotify_fh_ext_buf(&fne->dir_fh)); - kfree(fne); + kfree(FANOTIFY_NE(event)); } static void fanotify_free_event(struct fsnotify_event *fsn_event) @@ -640,6 +788,9 @@ static void fanotify_free_event(struct fsnotify_event *fsn_event) case FANOTIFY_EVENT_TYPE_FID_NAME: fanotify_free_name_event(event); break; + case FANOTIFY_EVENT_TYPE_OVERFLOW: + kfree(event); + break; default: WARN_ON_ONCE(1); } diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h index 8ce7ccfc4b0dcbf28ec747570df10155362c4ae6..896c819a17863ad1b0b8f357cf78edcbd49d1246 100644 --- a/fs/notify/fanotify/fanotify.h +++ b/fs/notify/fanotify/fanotify.h @@ -23,20 +23,41 @@ enum { * stored in either the first or last 2 dwords. */ #define FANOTIFY_INLINE_FH_LEN (3 << 2) +#define FANOTIFY_FH_HDR_LEN offsetof(struct fanotify_fh, buf) +/* Fixed size struct for file handle */ struct fanotify_fh { - unsigned char buf[FANOTIFY_INLINE_FH_LEN]; u8 type; u8 len; +#define FANOTIFY_FH_FLAG_EXT_BUF 1 + u8 flags; + u8 pad; + unsigned char buf[]; +} __aligned(4); + +/* Variable size struct for dir file handle + child file handle + name */ +struct fanotify_info { + /* size of dir_fh/file_fh including fanotify_fh hdr size */ + u8 dir_fh_totlen; + u8 file_fh_totlen; + u8 name_len; + u8 pad; + unsigned char buf[]; + /* + * (struct fanotify_fh) dir_fh starts at buf[0] + * (optional) file_fh starts at buf[dir_fh_totlen] + * name starts at buf[dir_fh_totlen + file_fh_totlen] + */ } __aligned(4); static inline bool fanotify_fh_has_ext_buf(struct fanotify_fh *fh) { - return fh->len > FANOTIFY_INLINE_FH_LEN; + return (fh->flags & FANOTIFY_FH_FLAG_EXT_BUF); } static inline char **fanotify_fh_ext_buf_ptr(struct fanotify_fh *fh) { + BUILD_BUG_ON(FANOTIFY_FH_HDR_LEN % 4); BUILD_BUG_ON(__alignof__(char *) - 4 + sizeof(char *) > FANOTIFY_INLINE_FH_LEN); return (char **)ALIGN((unsigned long)(fh->buf), __alignof__(char *)); @@ -52,6 +73,56 @@ static inline void *fanotify_fh_buf(struct fanotify_fh *fh) return fanotify_fh_has_ext_buf(fh) ? fanotify_fh_ext_buf(fh) : fh->buf; } +static inline int fanotify_info_dir_fh_len(struct fanotify_info *info) +{ + if (!info->dir_fh_totlen || + WARN_ON_ONCE(info->dir_fh_totlen < FANOTIFY_FH_HDR_LEN)) + return 0; + + return info->dir_fh_totlen - FANOTIFY_FH_HDR_LEN; +} + +static inline struct fanotify_fh *fanotify_info_dir_fh(struct fanotify_info *info) +{ + BUILD_BUG_ON(offsetof(struct fanotify_info, buf) % 4); + + return (struct fanotify_fh *)info->buf; +} + +static inline int fanotify_info_file_fh_len(struct fanotify_info *info) +{ + if (!info->file_fh_totlen || + WARN_ON_ONCE(info->file_fh_totlen < FANOTIFY_FH_HDR_LEN)) + return 0; + + return info->file_fh_totlen - FANOTIFY_FH_HDR_LEN; +} + +static inline struct fanotify_fh *fanotify_info_file_fh(struct fanotify_info *info) +{ + return (struct fanotify_fh *)(info->buf + info->dir_fh_totlen); +} + +static inline const char *fanotify_info_name(struct fanotify_info *info) +{ + return info->buf + info->dir_fh_totlen + info->file_fh_totlen; +} + +static inline void fanotify_info_init(struct fanotify_info *info) +{ + info->dir_fh_totlen = 0; + info->file_fh_totlen = 0; + info->name_len = 0; +} + +static inline void fanotify_info_copy_name(struct fanotify_info *info, + const struct qstr *name) +{ + info->name_len = name->len; + strcpy(info->buf + info->dir_fh_totlen + info->file_fh_totlen, + name->name); +} + /* * Common structure for fanotify events. Concrete structs are allocated in * fanotify_handle_event() and freed when the information is retrieved by @@ -63,6 +134,7 @@ enum fanotify_event_type { FANOTIFY_EVENT_TYPE_FID_NAME, /* variable length */ FANOTIFY_EVENT_TYPE_PATH, FANOTIFY_EVENT_TYPE_PATH_PERM, + FANOTIFY_EVENT_TYPE_OVERFLOW, /* struct fanotify_event */ }; struct fanotify_event { @@ -72,10 +144,20 @@ struct fanotify_event { struct pid *pid; }; +static inline void fanotify_init_event(struct fanotify_event *event, + unsigned long id, u32 mask) +{ + fsnotify_init_event(&event->fse, id); + event->mask = mask; + event->pid = NULL; +} + struct fanotify_fid_event { struct fanotify_event fae; __kernel_fsid_t fsid; struct fanotify_fh object_fh; + /* Reserve space in object_fh.buf[] - access with fanotify_fh_buf() */ + unsigned char _inline_fh_buf[FANOTIFY_INLINE_FH_LEN]; }; static inline struct fanotify_fid_event * @@ -87,9 +169,7 @@ FANOTIFY_FE(struct fanotify_event *event) struct fanotify_name_event { struct fanotify_event fae; __kernel_fsid_t fsid; - struct fanotify_fh dir_fh; - u8 name_len; - char name[]; + struct fanotify_info info; }; static inline struct fanotify_name_event * @@ -113,35 +193,37 @@ static inline struct fanotify_fh *fanotify_event_object_fh( { if (event->type == FANOTIFY_EVENT_TYPE_FID) return &FANOTIFY_FE(event)->object_fh; + else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) + return fanotify_info_file_fh(&FANOTIFY_NE(event)->info); else return NULL; } -static inline struct fanotify_fh *fanotify_event_dir_fh( +static inline struct fanotify_info *fanotify_event_info( struct fanotify_event *event) { if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) - return &FANOTIFY_NE(event)->dir_fh; + return &FANOTIFY_NE(event)->info; else return NULL; } static inline int fanotify_event_object_fh_len(struct fanotify_event *event) { + struct fanotify_info *info = fanotify_event_info(event); struct fanotify_fh *fh = fanotify_event_object_fh(event); - return fh ? fh->len : 0; + if (info) + return info->file_fh_totlen ? fh->len : 0; + else + return fh ? fh->len : 0; } -static inline bool fanotify_event_has_name(struct fanotify_event *event) +static inline int fanotify_event_dir_fh_len(struct fanotify_event *event) { - return event->type == FANOTIFY_EVENT_TYPE_FID_NAME; -} + struct fanotify_info *info = fanotify_event_info(event); -static inline int fanotify_event_name_len(struct fanotify_event *event) -{ - return fanotify_event_has_name(event) ? - FANOTIFY_NE(event)->name_len : 0; + return info ? fanotify_info_dir_fh_len(info) : 0; } struct fanotify_path_event { @@ -202,9 +284,3 @@ static inline struct path *fanotify_event_path(struct fanotify_event *event) else return NULL; } - -struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, - struct inode *inode, u32 mask, - const void *data, int data_type, - const struct qstr *file_name, - __kernel_fsid_t *fsid); diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 63b5dffdca9edbdaf4a51bb1b3cfa5fa534e13fe..559de311deca96e29cb07853e050c4ceefb6dcab 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -64,21 +64,28 @@ static int fanotify_fid_info_len(int fh_len, int name_len) return roundup(FANOTIFY_INFO_HDR_LEN + info_len, FANOTIFY_EVENT_ALIGN); } -static int fanotify_event_info_len(struct fanotify_event *event) +static int fanotify_event_info_len(unsigned int fid_mode, + struct fanotify_event *event) { - int info_len = 0; + struct fanotify_info *info = fanotify_event_info(event); + int dir_fh_len = fanotify_event_dir_fh_len(event); int fh_len = fanotify_event_object_fh_len(event); + int info_len = 0; + int dot_len = 0; - if (fh_len) - info_len += fanotify_fid_info_len(fh_len, 0); - - if (fanotify_event_name_len(event)) { - struct fanotify_name_event *fne = FANOTIFY_NE(event); - - info_len += fanotify_fid_info_len(fne->dir_fh.len, - fne->name_len); + if (dir_fh_len) { + info_len += fanotify_fid_info_len(dir_fh_len, info->name_len); + } else if ((fid_mode & FAN_REPORT_NAME) && (event->mask & FAN_ONDIR)) { + /* + * With group flag FAN_REPORT_NAME, if name was not recorded in + * event on a directory, we will report the name ".". + */ + dot_len = 1; } + if (fh_len) + info_len += fanotify_fid_info_len(fh_len, dot_len); + return info_len; } @@ -93,6 +100,7 @@ static struct fanotify_event *get_one_event(struct fsnotify_group *group, { size_t event_size = FAN_EVENT_METADATA_LEN; struct fanotify_event *event = NULL; + unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS); pr_debug("%s: group=%p count=%zd\n", __func__, group, count); @@ -100,8 +108,8 @@ static struct fanotify_event *get_one_event(struct fsnotify_group *group, if (fsnotify_notify_queue_is_empty(group)) goto out; - if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { - event_size += fanotify_event_info_len( + if (fid_mode) { + event_size += fanotify_event_info_len(fid_mode, FANOTIFY_E(fsnotify_peek_first_event(group))); } @@ -218,7 +226,7 @@ static int process_access_response(struct fsnotify_group *group, } static int copy_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, - const char *name, size_t name_len, + int info_type, const char *name, size_t name_len, char __user *buf, size_t count) { struct fanotify_event_info_fid info = { }; @@ -231,7 +239,7 @@ static int copy_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, pr_debug("%s: fh_len=%zu name_len=%zu, info_len=%zu, count=%zu\n", __func__, fh_len, name_len, info_len, count); - if (!fh_len || (name && !name_len)) + if (!fh_len) return 0; if (WARN_ON_ONCE(len < sizeof(info) || len > count)) @@ -241,8 +249,21 @@ static int copy_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, * Copy event info fid header followed by variable sized file handle * and optionally followed by variable sized filename. */ - info.hdr.info_type = name_len ? FAN_EVENT_INFO_TYPE_DFID_NAME : - FAN_EVENT_INFO_TYPE_FID; + switch (info_type) { + case FAN_EVENT_INFO_TYPE_FID: + case FAN_EVENT_INFO_TYPE_DFID: + if (WARN_ON_ONCE(name_len)) + return -EFAULT; + break; + case FAN_EVENT_INFO_TYPE_DFID_NAME: + if (WARN_ON_ONCE(!name || !name_len)) + return -EFAULT; + break; + default: + return -EFAULT; + } + + info.hdr.info_type = info_type; info.hdr.len = len; info.fsid = *fsid; if (copy_to_user(buf, &info, sizeof(info))) @@ -305,13 +326,16 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, { struct fanotify_event_metadata metadata; struct path *path = fanotify_event_path(event); + struct fanotify_info *info = fanotify_event_info(event); + unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS); struct file *f = NULL; int ret, fd = FAN_NOFD; + int info_type = 0; pr_debug("%s: group=%p event=%p\n", __func__, group, event); metadata.event_len = FAN_EVENT_METADATA_LEN + - fanotify_event_info_len(event); + fanotify_event_info_len(fid_mode, event); metadata.metadata_len = FAN_EVENT_METADATA_LEN; metadata.vers = FANOTIFY_METADATA_VERSION; metadata.reserved = 0; @@ -346,13 +370,13 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, fd_install(fd, f); /* Event info records order is: dir fid + name, child fid */ - if (fanotify_event_name_len(event)) { - struct fanotify_name_event *fne = FANOTIFY_NE(event); - + if (fanotify_event_dir_fh_len(event)) { + info_type = info->name_len ? FAN_EVENT_INFO_TYPE_DFID_NAME : + FAN_EVENT_INFO_TYPE_DFID; ret = copy_info_to_user(fanotify_event_fsid(event), - fanotify_event_dir_fh(event), - fne->name, fne->name_len, - buf, count); + fanotify_info_dir_fh(info), + info_type, fanotify_info_name(info), + info->name_len, buf, count); if (ret < 0) return ret; @@ -361,9 +385,46 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, } if (fanotify_event_object_fh_len(event)) { + const char *dot = NULL; + int dot_len = 0; + + if (fid_mode == FAN_REPORT_FID || info_type) { + /* + * With only group flag FAN_REPORT_FID only type FID is + * reported. Second info record type is always FID. + */ + info_type = FAN_EVENT_INFO_TYPE_FID; + } else if ((fid_mode & FAN_REPORT_NAME) && + (event->mask & FAN_ONDIR)) { + /* + * With group flag FAN_REPORT_NAME, if name was not + * recorded in an event on a directory, report the + * name "." with info type DFID_NAME. + */ + info_type = FAN_EVENT_INFO_TYPE_DFID_NAME; + dot = "."; + dot_len = 1; + } else if ((event->mask & ALL_FSNOTIFY_DIRENT_EVENTS) || + (event->mask & FAN_ONDIR)) { + /* + * With group flag FAN_REPORT_DIR_FID, a single info + * record has type DFID for directory entry modification + * event and for event on a directory. + */ + info_type = FAN_EVENT_INFO_TYPE_DFID; + } else { + /* + * With group flags FAN_REPORT_DIR_FID|FAN_REPORT_FID, + * a single info record has type FID for event on a + * non-directory, when there is no directory to report. + * For example, on FAN_DELETE_SELF event. + */ + info_type = FAN_EVENT_INFO_TYPE_FID; + } + ret = copy_info_to_user(fanotify_event_fsid(event), fanotify_event_object_fh(event), - NULL, 0, buf, count); + info_type, dot, dot_len, buf, count); if (ret < 0) return ret; @@ -412,6 +473,11 @@ static ssize_t fanotify_read(struct file *file, char __user *buf, add_wait_queue(&group->notification_waitq, &wait); while (1) { + /* + * User can supply arbitrarily large buffer. Avoid softlockups + * in case there are lots of available events. + */ + cond_resched(); event = get_one_event(group, count); if (IS_ERR(event)) { ret = PTR_ERR(event); @@ -651,12 +717,13 @@ out: } static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, - __u32 mask, - unsigned int flags, - int *destroy) + __u32 mask, unsigned int flags, + __u32 umask, int *destroy) { __u32 oldmask = 0; + /* umask bits cannot be removed by user */ + mask &= ~umask; spin_lock(&fsn_mark->lock); if (!(flags & FAN_MARK_IGNORED_MASK)) { oldmask = fsn_mark->mask; @@ -664,7 +731,13 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, } else { fsn_mark->ignored_mask &= ~mask; } - *destroy = !(fsn_mark->mask | fsn_mark->ignored_mask); + /* + * We need to keep the mark around even if remaining mask cannot + * result in any events (e.g. mask == FAN_ONDIR) to support incremenal + * changes to the mask. + * Destroy mark when only umask bits remain. + */ + *destroy = !((fsn_mark->mask | fsn_mark->ignored_mask) & ~umask); spin_unlock(&fsn_mark->lock); return mask & oldmask; @@ -672,7 +745,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, static int fanotify_remove_mark(struct fsnotify_group *group, fsnotify_connp_t *connp, __u32 mask, - unsigned int flags) + unsigned int flags, __u32 umask) { struct fsnotify_mark *fsn_mark = NULL; __u32 removed; @@ -686,7 +759,7 @@ static int fanotify_remove_mark(struct fsnotify_group *group, } removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags, - &destroy_mark); + umask, &destroy_mark); if (removed & fsnotify_conn_mask(fsn_mark->connector)) fsnotify_recalc_mask(fsn_mark->connector); if (destroy_mark) @@ -702,25 +775,26 @@ static int fanotify_remove_mark(struct fsnotify_group *group, static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, struct vfsmount *mnt, __u32 mask, - unsigned int flags) + unsigned int flags, __u32 umask) { return fanotify_remove_mark(group, &real_mount(mnt)->mnt_fsnotify_marks, - mask, flags); + mask, flags, umask); } static int fanotify_remove_sb_mark(struct fsnotify_group *group, - struct super_block *sb, __u32 mask, - unsigned int flags) + struct super_block *sb, __u32 mask, + unsigned int flags, __u32 umask) { - return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask, flags); + return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask, + flags, umask); } static int fanotify_remove_inode_mark(struct fsnotify_group *group, struct inode *inode, __u32 mask, - unsigned int flags) + unsigned int flags, __u32 umask) { return fanotify_remove_mark(group, &inode->i_fsnotify_marks, mask, - flags); + flags, umask); } static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, @@ -831,13 +905,28 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group, FSNOTIFY_OBJ_TYPE_INODE, mask, flags, fsid); } +static struct fsnotify_event *fanotify_alloc_overflow_event(void) +{ + struct fanotify_event *oevent; + + oevent = kmalloc(sizeof(*oevent), GFP_KERNEL_ACCOUNT); + if (!oevent) + return NULL; + + fanotify_init_event(oevent, 0, FS_Q_OVERFLOW); + oevent->type = FANOTIFY_EVENT_TYPE_OVERFLOW; + + return &oevent->fse; +} + /* fanotify syscalls */ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) { struct fsnotify_group *group; int f_flags, fd; struct user_struct *user; - struct fanotify_event *oevent; + unsigned int fid_mode = flags & FANOTIFY_FID_BITS; + unsigned int class = flags & FANOTIFY_CLASS_BITS; pr_debug("%s: flags=%x event_f_flags=%x\n", __func__, flags, event_f_flags); @@ -864,8 +953,14 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) return -EINVAL; } - if ((flags & FAN_REPORT_FID) && - (flags & FANOTIFY_CLASS_BITS) != FAN_CLASS_NOTIF) + if (fid_mode && class != FAN_CLASS_NOTIF) + return -EINVAL; + + /* + * Child name is reported with parent fid so requires dir fid. + * We can report both child fid and dir fid with or without name. + */ + if ((fid_mode & FAN_REPORT_NAME) && !(fid_mode & FAN_REPORT_DIR_FID)) return -EINVAL; user = get_current_user(); @@ -892,20 +987,18 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) atomic_inc(&user->fanotify_listeners); group->memcg = get_mem_cgroup_from_mm(current->mm); - oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL, - FSNOTIFY_EVENT_NONE, NULL, NULL); - if (unlikely(!oevent)) { + group->overflow_event = fanotify_alloc_overflow_event(); + if (unlikely(!group->overflow_event)) { fd = -ENOMEM; goto out_destroy_group; } - group->overflow_event = &oevent->fse; if (force_o_largefile()) event_f_flags |= O_LARGEFILE; group->fanotify_data.f_flags = event_f_flags; init_waitqueue_head(&group->fanotify_data.access_waitq); INIT_LIST_HEAD(&group->fanotify_data.access_list); - switch (flags & FANOTIFY_CLASS_BITS) { + switch (class) { case FAN_CLASS_NOTIF: group->priority = FS_PRIO_0; break; @@ -1024,7 +1117,9 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, __kernel_fsid_t __fsid, *fsid = NULL; u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS; unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS; - unsigned int obj_type; + bool ignored = flags & FAN_MARK_IGNORED_MASK; + unsigned int obj_type, fid_mode; + u32 umask = 0; int ret; pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n", @@ -1071,6 +1166,10 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, if (mask & ~valid_mask) return -EINVAL; + /* Event flags (ONDIR, ON_CHILD) are meaningless in ignored mask */ + if (ignored) + mask &= ~FANOTIFY_EVENT_FLAGS; + f = fdget(fanotify_fd); if (unlikely(!f.file)) return -EBADF; @@ -1097,9 +1196,9 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, * inode events are not supported on a mount mark, because they do not * carry enough information (i.e. path) to be filtered by mount point. */ + fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS); if (mask & FANOTIFY_INODE_EVENTS && - (!FAN_GROUP_FLAG(group, FAN_REPORT_FID) || - mark_type == FAN_MARK_MOUNT)) + (!fid_mode || mark_type == FAN_MARK_MOUNT)) goto fput_and_out; if (flags & FAN_MARK_FLUSH) { @@ -1124,7 +1223,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, goto path_put_and_out; } - if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { + if (fid_mode) { ret = fanotify_test_fid(&path, &__fsid); if (ret) goto path_put_and_out; @@ -1138,6 +1237,19 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, else mnt = path.mnt; + /* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */ + if (mnt || !S_ISDIR(inode->i_mode)) { + mask &= ~FAN_EVENT_ON_CHILD; + umask = FAN_EVENT_ON_CHILD; + /* + * If group needs to report parent fid, register for getting + * events with parent/name info for non-directory. + */ + if ((fid_mode & FAN_REPORT_DIR_FID) && + (flags & FAN_MARK_ADD) && !ignored) + mask |= FAN_EVENT_ON_CHILD; + } + /* create/update an inode mark */ switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) { case FAN_MARK_ADD: @@ -1154,13 +1266,13 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, case FAN_MARK_REMOVE: if (mark_type == FAN_MARK_MOUNT) ret = fanotify_remove_vfsmount_mark(group, mnt, mask, - flags); + flags, umask); else if (mark_type == FAN_MARK_FILESYSTEM) ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask, - flags); + flags, umask); else ret = fanotify_remove_inode_mark(group, inode, mask, - flags); + flags, umask); break; default: ret = -EINVAL; @@ -1203,7 +1315,7 @@ COMPAT_SYSCALL_DEFINE6(fanotify_mark, */ static int __init fanotify_user_setup(void) { - BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 8); + BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 10); BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 9); fanotify_mark_cache = KMEM_CACHE(fsnotify_mark, diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 72d332ce8e123a36df032b6f2ab57ede3ea14771..a960ec3a569ad319ea2f1a44c81fa05e9c1c5a0a 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -74,7 +74,7 @@ static void fsnotify_unmount_inodes(struct super_block *sb) iput(iput_inode); /* for each watch, send FS_UNMOUNT and then remove it */ - fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 0); + fsnotify_inode(inode, FS_UNMOUNT); fsnotify_inode_delete(inode); @@ -142,45 +142,140 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) spin_unlock(&inode->i_lock); } -/* Notify this dentry's parent about a child's events. */ -int fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, - int data_type) +/* Are inode/sb/mount interested in parent and name info with this event? */ +static bool fsnotify_event_needs_parent(struct inode *inode, struct mount *mnt, + __u32 mask) { + __u32 marks_mask = 0; + + /* We only send parent/name to inode/sb/mount for events on non-dir */ + if (mask & FS_ISDIR) + return false; + + /* Did either inode/sb/mount subscribe for events with parent/name? */ + marks_mask |= fsnotify_parent_needed_mask(inode->i_fsnotify_mask); + marks_mask |= fsnotify_parent_needed_mask(inode->i_sb->s_fsnotify_mask); + if (mnt) + marks_mask |= fsnotify_parent_needed_mask(mnt->mnt_fsnotify_mask); + + /* Did they subscribe for this event with parent/name info? */ + return mask & marks_mask; +} + +/* + * Notify this dentry's parent about a child's events with child name info + * if parent is watching or if inode/sb/mount are interested in events with + * parent and name info. + * + * Notify only the child without name info if parent is not watching and + * inode/sb/mount are not interested in events with parent and name info. + */ +int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, + int data_type) +{ + const struct path *path = fsnotify_data_path(data, data_type); + struct mount *mnt = path ? real_mount(path->mnt) : NULL; + struct inode *inode = d_inode(dentry); struct dentry *parent; - struct inode *p_inode; + bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED; + __u32 p_mask; + struct inode *p_inode = NULL; + struct name_snapshot name; + struct qstr *file_name = NULL; int ret = 0; - if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) + /* + * Do inode/sb/mount care about parent and name info on non-dir? + * Do they care about any event at all? + */ + if (!inode->i_fsnotify_marks && !inode->i_sb->s_fsnotify_marks && + (!mnt || !mnt->mnt_fsnotify_marks) && !parent_watched) return 0; + parent = NULL; + if (!parent_watched && !fsnotify_event_needs_parent(inode, mnt, mask)) + goto notify; + + /* Does parent inode care about events on children? */ parent = dget_parent(dentry); p_inode = parent->d_inode; - - if (unlikely(!fsnotify_inode_watches_children(p_inode))) { + p_mask = fsnotify_inode_watches_children(p_inode); + if (unlikely(parent_watched && !p_mask)) __fsnotify_update_child_dentry_flags(p_inode); - } else if (p_inode->i_fsnotify_mask & mask & ALL_FSNOTIFY_EVENTS) { - struct name_snapshot name; - /* we are notifying a parent so come up with the new mask which - * specifies these are events which came from a child. */ - mask |= FS_EVENT_ON_CHILD; + /* + * Include parent/name in notification either if some notification + * groups require parent info (!parent_watched case) or the parent is + * interested in this event. + */ + if (!parent_watched || (mask & p_mask & ALL_FSNOTIFY_EVENTS)) { + /* When notifying parent, child should be passed as data */ + WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type)); + /* Notify both parent and child with child name info */ take_dentry_name_snapshot(&name, dentry); - ret = fsnotify(p_inode, mask, data, data_type, &name.name, 0); - release_dentry_name_snapshot(&name); + file_name = &name.name; + if (parent_watched) + mask |= FS_EVENT_ON_CHILD; } +notify: + ret = fsnotify(mask, data, data_type, p_inode, file_name, inode, 0); + + if (file_name) + release_dentry_name_snapshot(&name); dput(parent); return ret; } -EXPORT_SYMBOL_GPL(fsnotify_parent); +EXPORT_SYMBOL_GPL(__fsnotify_parent); + +static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask, + const void *data, int data_type, + struct inode *dir, const struct qstr *name, + u32 cookie, struct fsnotify_iter_info *iter_info) +{ + struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); + struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info); + struct inode *inode = fsnotify_data_inode(data, data_type); + const struct fsnotify_ops *ops = group->ops; + int ret; + + if (WARN_ON_ONCE(!ops->handle_inode_event)) + return 0; + + if (WARN_ON_ONCE(fsnotify_iter_sb_mark(iter_info)) || + WARN_ON_ONCE(fsnotify_iter_vfsmount_mark(iter_info))) + return 0; + + /* + * An event can be sent on child mark iterator instead of inode mark + * iterator because of other groups that have interest of this inode + * and have marks on both parent and child. We can simplify this case. + */ + if (!inode_mark) { + inode_mark = child_mark; + child_mark = NULL; + dir = NULL; + name = NULL; + } + + ret = ops->handle_inode_event(inode_mark, mask, inode, dir, name); + if (ret || !child_mark) + return ret; + + /* + * Some events can be sent on both parent dir and child marks + * (e.g. FS_ATTRIB). If both parent dir and child are watching, + * report the event once to parent dir with name and once to child + * without name. + */ + return ops->handle_inode_event(child_mark, mask, inode, NULL, NULL); +} -static int send_to_group(struct inode *to_tell, - __u32 mask, const void *data, - int data_is, u32 cookie, - const struct qstr *file_name, - struct fsnotify_iter_info *iter_info) +static int send_to_group(__u32 mask, const void *data, int data_type, + struct inode *dir, const struct qstr *file_name, + u32 cookie, struct fsnotify_iter_info *iter_info) { struct fsnotify_group *group = NULL; __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS); @@ -216,16 +311,20 @@ static int send_to_group(struct inode *to_tell, } } - pr_debug("%s: group=%p to_tell=%p mask=%x marks_mask=%x marks_ignored_mask=%x" - " data=%p data_is=%d cookie=%d\n", - __func__, group, to_tell, mask, marks_mask, marks_ignored_mask, - data, data_is, cookie); + pr_debug("%s: group=%p mask=%x marks_mask=%x marks_ignored_mask=%x data=%p data_type=%d dir=%p cookie=%d\n", + __func__, group, mask, marks_mask, marks_ignored_mask, + data, data_type, dir, cookie); if (!(test_mask & marks_mask & ~marks_ignored_mask)) return 0; - return group->ops->handle_event(group, to_tell, mask, data, data_is, - file_name, cookie, iter_info); + if (group->ops->handle_event) { + return group->ops->handle_event(group, mask, data, data_type, dir, + file_name, cookie, iter_info); + } + + return fsnotify_handle_event(group, mask, data, data_type, dir, + file_name, cookie, iter_info); } static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector **connp) @@ -303,29 +402,51 @@ static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info) } /* - * This is the main call to fsnotify. The VFS calls into hook specific functions - * in linux/fsnotify.h. Those functions then in turn call here. Here will call - * out to all of the registered fsnotify_group. Those groups can then use the - * notification event in whatever means they feel necessary. + * fsnotify - This is the main call to fsnotify. + * + * The VFS calls into hook specific functions in linux/fsnotify.h. + * Those functions then in turn call here. Here will call out to all of the + * registered fsnotify_group. Those groups can then use the notification event + * in whatever means they feel necessary. + * + * @mask: event type and flags + * @data: object that event happened on + * @data_type: type of object for fanotify_data_XXX() accessors + * @dir: optional directory associated with event - + * if @file_name is not NULL, this is the directory that + * @file_name is relative to + * @file_name: optional file name associated with event + * @inode: optional inode associated with event - + * either @dir or @inode must be non-NULL. + * if both are non-NULL event may be reported to both. + * @cookie: inotify rename cookie */ -int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, - const struct qstr *file_name, u32 cookie) +int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, + const struct qstr *file_name, struct inode *inode, u32 cookie) { - const struct path *path = fsnotify_data_path(data, data_is); + const struct path *path = fsnotify_data_path(data, data_type); struct fsnotify_iter_info iter_info = {}; - struct super_block *sb = to_tell->i_sb; + struct super_block *sb; struct mount *mnt = NULL; - __u32 mnt_or_sb_mask = sb->s_fsnotify_mask; + struct inode *child = NULL; int ret = 0; - __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS); + __u32 test_mask, marks_mask; - if (path) { + if (path) mnt = real_mount(path->mnt); - mnt_or_sb_mask |= mnt->mnt_fsnotify_mask; + + if (!inode) { + /* Dirent event - report on TYPE_INODE to dir */ + inode = dir; + } else if (mask & FS_EVENT_ON_CHILD) { + /* + * Event on child - report on TYPE_INODE to dir if it is + * watching children and on TYPE_CHILD to child. + */ + child = inode; + inode = dir; } - /* An event "on child" is not intended for a mount/sb mark */ - if (mask & FS_EVENT_ON_CHILD) - mnt_or_sb_mask = 0; + sb = inode->i_sb; /* * Optimization: srcu_read_lock() has a memory barrier which can @@ -334,28 +455,45 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, * SRCU because we have no references to any objects and do not * need SRCU to keep them "alive". */ - if (!to_tell->i_fsnotify_marks && !sb->s_fsnotify_marks && - (!mnt || !mnt->mnt_fsnotify_marks)) + if (!sb->s_fsnotify_marks && + (!mnt || !mnt->mnt_fsnotify_marks) && + (!inode || !inode->i_fsnotify_marks) && + (!child || !child->i_fsnotify_marks)) return 0; + + marks_mask = sb->s_fsnotify_mask; + if (mnt) + marks_mask |= mnt->mnt_fsnotify_mask; + if (inode) + marks_mask |= inode->i_fsnotify_mask; + if (child) + marks_mask |= child->i_fsnotify_mask; + + /* * if this is a modify event we may need to clear the ignored masks - * otherwise return if neither the inode nor the vfsmount/sb care about - * this type of event. + * otherwise return if none of the marks care about this type of event. */ - if (!(mask & FS_MODIFY) && - !(test_mask & (to_tell->i_fsnotify_mask | mnt_or_sb_mask))) + test_mask = (mask & ALL_FSNOTIFY_EVENTS); + if (!(mask & FS_MODIFY) && !(test_mask & marks_mask)) return 0; iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); - iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] = - fsnotify_first_mark(&to_tell->i_fsnotify_marks); iter_info.marks[FSNOTIFY_OBJ_TYPE_SB] = fsnotify_first_mark(&sb->s_fsnotify_marks); if (mnt) { iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] = fsnotify_first_mark(&mnt->mnt_fsnotify_marks); } + if (inode) { + iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] = + fsnotify_first_mark(&inode->i_fsnotify_marks); + } + if (child) { + iter_info.marks[FSNOTIFY_OBJ_TYPE_CHILD] = + fsnotify_first_mark(&child->i_fsnotify_marks); + } /* * We need to merge inode/vfsmount/sb mark lists so that e.g. inode mark @@ -363,8 +501,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, * That's why this traversal is so complicated... */ while (fsnotify_iter_select_report_types(&iter_info)) { - ret = send_to_group(to_tell, mask, data, data_is, cookie, - file_name, &iter_info); + ret = send_to_group(mask, data, data_type, dir, file_name, + cookie, &iter_info); if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS)) goto out; @@ -383,7 +521,7 @@ static __init int fsnotify_init(void) { int ret; - BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 26); + BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 25); ret = init_srcu_struct(&fsnotify_mark_srcu); if (ret) diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h index 3f246f7b8a92b2199469f3a76f35f5783af1cc79..4327d0e9c3645932f3bb4e87d49a25c849141eb5 100644 --- a/fs/notify/inotify/inotify.h +++ b/fs/notify/inotify/inotify.h @@ -24,9 +24,9 @@ static inline struct inotify_event_info *INOTIFY_E(struct fsnotify_event *fse) extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group); -extern int inotify_handle_event(struct fsnotify_group *group, - struct inode *inode, - u32 mask, const void *data, int data_type, +extern int inotify_handle_event(struct fsnotify_group *group, u32 mask, + const void *data, int data_type, + struct inode *dir, const struct qstr *file_name, u32 cookie, struct fsnotify_iter_info *iter_info); diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 2ebc890471533737a5f33695e6e1cb90f20316da..a65cf8c9f60068f00ba4dddbf505dfbea8088483 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -39,7 +39,7 @@ static bool event_compare(struct fsnotify_event *old_fsn, if (old->mask & FS_IN_IGNORED) return false; if ((old->mask == new->mask) && - (old_fsn->objectid == new_fsn->objectid) && + (old->wd == new->wd) && (old->name_len == new->name_len) && (!old->name_len || !strcmp(old->name, new->name))) return true; @@ -55,14 +55,11 @@ static int inotify_merge(struct list_head *list, return event_compare(last_event, event); } -int inotify_handle_event(struct fsnotify_group *group, - struct inode *inode, - u32 mask, const void *data, int data_type, - const struct qstr *file_name, u32 cookie, - struct fsnotify_iter_info *iter_info) +static int inotify_one_event(struct fsnotify_group *group, u32 mask, + struct fsnotify_mark *inode_mark, + const struct path *path, + const struct qstr *file_name, u32 cookie) { - const struct path *path = fsnotify_data_path(data, data_type); - struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); struct inotify_inode_mark *i_mark; struct inotify_event_info *event; struct fsnotify_event *fsn_event; @@ -70,9 +67,6 @@ int inotify_handle_event(struct fsnotify_group *group, int len = 0; int alloc_len = sizeof(struct inotify_event_info); - if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info))) - return 0; - if ((inode_mark->mask & FS_EXCL_UNLINK) && path && d_unlinked(path->dentry)) return 0; @@ -82,7 +76,7 @@ int inotify_handle_event(struct fsnotify_group *group, alloc_len += len + 1; } - pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode, + pr_debug("%s: group=%p mark=%p mask=%x\n", __func__, group, inode_mark, mask); i_mark = container_of(inode_mark, struct inotify_inode_mark, @@ -116,7 +110,7 @@ int inotify_handle_event(struct fsnotify_group *group, mask &= ~IN_ISDIR; fsn_event = &event->fse; - fsnotify_init_event(fsn_event, (unsigned long)inode); + fsnotify_init_event(fsn_event, 0); event->mask = mask; event->wd = i_mark->wd; event->sync_cookie = cookie; @@ -136,6 +130,37 @@ int inotify_handle_event(struct fsnotify_group *group, return 0; } +int inotify_handle_event(struct fsnotify_group *group, u32 mask, + const void *data, int data_type, struct inode *dir, + const struct qstr *file_name, u32 cookie, + struct fsnotify_iter_info *iter_info) +{ + const struct path *path = fsnotify_data_path(data, data_type); + struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); + struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info); + int ret = 0; + + if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info))) + return 0; + + /* + * Some events cannot be sent on both parent and child marks + * (e.g. IN_CREATE). Those events are always sent on inode_mark. + * For events that are possible on both parent and child (e.g. IN_OPEN), + * event is sent on inode_mark with name if the parent is watching and + * is sent on child_mark without name if child is watching. + * If both parent and child are watching, report the event with child's + * name here and report another event without child's name below. + */ + if (inode_mark) + ret = inotify_one_event(group, mask, inode_mark, path, + file_name, cookie); + if (ret || !child_mark) + return ret; + + return inotify_one_event(group, mask, child_mark, path, NULL, 0); +} + static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group) { inotify_ignored_and_remove_idr(fsn_mark, group); diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index f88bbcc9efeb30c4330110c664834cb817179897..186722ba389476bee8dd5c17e597767ae130e26d 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -75,15 +75,17 @@ struct ctl_table inotify_table[] = { }; #endif /* CONFIG_SYSCTL */ -static inline __u32 inotify_arg_to_mask(u32 arg) +static inline __u32 inotify_arg_to_mask(struct inode *inode, u32 arg) { __u32 mask; /* - * everything should accept their own ignored, cares about children, - * and should receive events when the inode is unmounted + * Everything should accept their own ignored and should receive events + * when the inode is unmounted. All directories care about children. */ - mask = (FS_IN_IGNORED | FS_EVENT_ON_CHILD | FS_UNMOUNT); + mask = (FS_IN_IGNORED | FS_UNMOUNT); + if (S_ISDIR(inode->i_mode)) + mask |= FS_EVENT_ON_CHILD; /* mask off the flags used to open the fd */ mask |= (arg & (IN_ALL_EVENTS | IN_ONESHOT | IN_EXCL_UNLINK)); @@ -490,8 +492,8 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, fsn_mark); /* Queue ignore event for the watch */ - inotify_handle_event(group, NULL, FS_IN_IGNORED, NULL, - FSNOTIFY_EVENT_NONE, NULL, 0, &iter_info); + inotify_handle_event(group, FS_IN_IGNORED, NULL, FSNOTIFY_EVENT_NONE, + NULL, NULL, 0, &iter_info); i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); /* remove this mark from the idr */ @@ -512,7 +514,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group, int create = (arg & IN_MASK_CREATE); int ret; - mask = inotify_arg_to_mask(arg); + mask = inotify_arg_to_mask(inode, arg); fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, group); if (!fsn_mark) @@ -565,7 +567,7 @@ static int inotify_new_watch(struct fsnotify_group *group, struct idr *idr = &group->inotify_data.idr; spinlock_t *idr_lock = &group->inotify_data.idr_lock; - mask = inotify_arg_to_mask(arg); + mask = inotify_arg_to_mask(inode, arg); tmp_i_mark = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL); if (unlikely(!tmp_i_mark)) diff --git a/fs/quota/Kconfig b/fs/quota/Kconfig index 7218314ca13f0053bed2c34470459355673d01b6..d1ceb76adb71e71e69e78464e795376b51899f4e 100644 --- a/fs/quota/Kconfig +++ b/fs/quota/Kconfig @@ -15,7 +15,7 @@ config QUOTA Ext3, ext4 and reiserfs also support journaled quotas for which you don't need to run quotacheck(8) after an unclean shutdown. For further details, read the Quota mini-HOWTO, available from - , or the documentation provided + , or the documentation provided with the quota tools. Probably the quota support is only useful for multi user systems. If unsure, say N. diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index 5b50689d853964dd40a71997c1968f9d4357070d..79ee2b4366851a83e1b970a34970c55ddd9721ff 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c @@ -289,7 +289,7 @@ void make_empty_dir_item_v1(char *body, __le32 dirid, __le32 objid, /* direntry header of "." */ put_deh_offset(dot, DOT_OFFSET); - /* these two are from make_le_item_head, and are are LE */ + /* these two are from make_le_item_head, and are LE */ dot->deh_dir_id = dirid; dot->deh_objectid = objid; dot->deh_state = 0; /* Endian safe if 0 */ @@ -299,7 +299,7 @@ void make_empty_dir_item_v1(char *body, __le32 dirid, __le32 objid, /* direntry header of ".." */ put_deh_offset(dotdot, DOT_DOT_OFFSET); /* key of ".." for the root directory */ - /* these two are from the inode, and are are LE */ + /* these two are from the inode, and are LE */ dotdot->deh_dir_id = par_dirid; dotdot->deh_objectid = par_objid; dotdot->deh_state = 0; /* Endian safe if 0 */ @@ -323,7 +323,7 @@ void make_empty_dir_item(char *body, __le32 dirid, __le32 objid, /* direntry header of "." */ put_deh_offset(dot, DOT_OFFSET); - /* these two are from make_le_item_head, and are are LE */ + /* these two are from make_le_item_head, and are LE */ dot->deh_dir_id = dirid; dot->deh_objectid = objid; dot->deh_state = 0; /* Endian safe if 0 */ @@ -333,7 +333,7 @@ void make_empty_dir_item(char *body, __le32 dirid, __le32 objid, /* direntry header of ".." */ put_deh_offset(dotdot, DOT_DOT_OFFSET); /* key of ".." for the root directory */ - /* these two are from the inode, and are are LE */ + /* these two are from the inode, and are LE */ dotdot->deh_dir_id = par_dirid; dotdot->deh_objectid = par_objid; dotdot->deh_state = 0; /* Endian safe if 0 */ diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c index 1170922241111c6278b04c61ac78f6584ae3826f..fefe87e1c099063927abf757d02ee50086b67233 100644 --- a/fs/reiserfs/fix_node.c +++ b/fs/reiserfs/fix_node.c @@ -611,9 +611,9 @@ static int get_num_ver(int mode, struct tree_balance *tb, int h, * blk_num number of blocks that S[h] will be splitted into; * s012 number of items that fall into splitted nodes. * lbytes number of bytes which flow to the left neighbor from the - * item that is not not shifted entirely + * item that is not shifted entirely * rbytes number of bytes which flow to the right neighbor from the - * item that is not not shifted entirely + * item that is not shifted entirely * s1bytes number of bytes which flow to the first new node when * S[0] splits (this number is contained in s012 array) */ diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 5c766330e493bdd43be1ee7615cd98d9d2430bcc..e98f99338f8f8b992b51f5f313adcb9ce5b3fca6 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -32,7 +32,7 @@ * to disk for all backgrounded commits that have been * around too long. * -- Note, if you call this as an immediate flush from - * from within kupdate, it will ignore the immediate flag + * within kupdate, it will ignore the immediate flag */ #include diff --git a/fs/reiserfs/reiserfs.h b/fs/reiserfs/reiserfs.h index 726580114d55659d686d1f3c6d945486fadeb9f7..f698715161679207bab25a6a40e184659ebb72e2 100644 --- a/fs/reiserfs/reiserfs.h +++ b/fs/reiserfs/reiserfs.h @@ -1109,7 +1109,7 @@ int is_reiserfs_jr(struct reiserfs_super_block *rs); * ReiserFS leaves the first 64k unused, so that partition labels have * enough space. If someone wants to write a fancy bootloader that * needs more than 64k, let us know, and this will be increased in size. - * This number must be larger than than the largest block size on any + * This number must be larger than the largest block size on any * platform, or code will break. -Hans */ #define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024) diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 05f666794561c8fdfbd44f4df9af8f5288626336..ccd40df6eb458a51bdcfcdc993865f1c71b523f6 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -373,7 +373,7 @@ int reiserfs_cache_default_acl(struct inode *inode) /* Other xattrs can be created during inode creation. We don't * want to claim too many blocks, so we check to see if we - * we need to create the tree to the xattrs, and then we + * need to create the tree to the xattrs, and then we * just want two files. */ nblocks = reiserfs_xattr_jcreate_nblocks(inode); nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb); diff --git a/fs/udf/ecma_167.h b/fs/udf/ecma_167.h index 736ebc5dc4418b3d02c501deeccd7fa4a00681b3..185c3e24764875e36957d5d9776798936334e892 100644 --- a/fs/udf/ecma_167.h +++ b/fs/udf/ecma_167.h @@ -2,7 +2,7 @@ * ecma_167.h * * This file is based on ECMA-167 3rd edition (June 1997) - * http://www.ecma.ch + * https://www.ecma.ch * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2017-2019 Pali Rohár diff --git a/fs/udf/osta_udf.h b/fs/udf/osta_udf.h index d5fbfab3ddb68e113eecb63e2d20c26b574791fa..22bc4fb2feb90173cc8bc5c7f17873a89fff1150 100644 --- a/fs/udf/osta_udf.h +++ b/fs/udf/osta_udf.h @@ -226,7 +226,7 @@ struct sparingTable { #define ICBTAG_FILE_TYPE_MIRROR 0xFB #define ICBTAG_FILE_TYPE_BITMAP 0xFC -/* struct struct long_ad ICB - ADImpUse (UDF 2.60 2.2.4.3) */ +/* struct long_ad ICB - ADImpUse (UDF 2.60 2.2.4.3) */ struct allocDescImpUse { __le16 flags; uint8_t impUse[4]; diff --git a/fs/udf/super.c b/fs/udf/super.c index f747bf72edbe05b52851fc89f5e40988e06ad147..1c42f544096d806ac20d26e376b8e02f80e0c2ee 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -11,8 +11,8 @@ * This code is based on version 2.00 of the UDF specification, * and revision 3 of the ECMA 167 standard [equivalent to ISO 13346]. * http://www.osta.org/ - * http://www.ecma.ch/ - * http://www.iso.org/ + * https://www.ecma.ch/ + * https://www.iso.org/ * * COPYRIGHT * This file is distributed under the terms of the GNU General Public diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index fdbff4860d61c6a1f31443c2d5e5a55cb806ea25..d538411c37911110612cdc83661eac0803bd1a8a 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -505,7 +505,7 @@ xfs_file_dio_aio_write( */ if (xfs_is_cow_inode(ip)) { trace_xfs_reflink_bounce_dio_write(ip, iocb->ki_pos, count); - return -EREMCHG; + return -ENOTBLK; } iolock = XFS_IOLOCK_EXCL; } else { @@ -553,8 +553,8 @@ out: xfs_iunlock(ip, iolock); /* - * No fallback to buffered IO on errors for XFS, direct IO will either - * complete fully or fail. + * No fallback to buffered IO after short writes for XFS, direct I/O + * will either complete fully or return an error. */ ASSERT(ret < 0 || ret == count); return ret; @@ -714,7 +714,7 @@ xfs_file_write_iter( * allow an operation to fall back to buffered mode. */ ret = xfs_file_dio_aio_write(iocb, from); - if (ret != -EREMCHG) + if (ret != -ENOTBLK) return ret; } diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c index abfb17f88f9a222ac2189de08d872a69b206c6f2..4a0bff65d3d652c77c2bcb3ea560e62da29c8a48 100644 --- a/fs/zonefs/super.c +++ b/fs/zonefs/super.c @@ -786,8 +786,11 @@ static ssize_t zonefs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) if (iocb->ki_pos >= ZONEFS_I(inode)->i_max_size) return -EFBIG; - if (iocb->ki_flags & IOCB_DIRECT) - return zonefs_file_dio_write(iocb, from); + if (iocb->ki_flags & IOCB_DIRECT) { + ssize_t ret = zonefs_file_dio_write(iocb, from); + if (ret != -ENOTBLK) + return ret; + } return zonefs_file_buffered_write(iocb, from); } diff --git a/include/asm-generic/kvm_types.h b/include/asm-generic/kvm_types.h new file mode 100644 index 0000000000000000000000000000000000000000..2a82daf110f1a688121e7a1c8684dcbaef04fa6f --- /dev/null +++ b/include/asm-generic/kvm_types.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_GENERIC_KVM_TYPES_H +#define _ASM_GENERIC_KVM_TYPES_H + +#endif diff --git a/include/dt-bindings/iio/adc/ingenic,adc.h b/include/dt-bindings/iio/adc/ingenic,adc.h index 42f871ab3272b60f351b21907c8ce0a3f5986df9..4627a00e369ea87a4f64d2a734922c68c29ec631 100644 --- a/include/dt-bindings/iio/adc/ingenic,adc.h +++ b/include/dt-bindings/iio/adc/ingenic,adc.h @@ -7,5 +7,11 @@ #define INGENIC_ADC_AUX 0 #define INGENIC_ADC_BATTERY 1 #define INGENIC_ADC_AUX2 2 +#define INGENIC_ADC_TOUCH_XP 3 +#define INGENIC_ADC_TOUCH_YP 4 +#define INGENIC_ADC_TOUCH_XN 5 +#define INGENIC_ADC_TOUCH_YN 6 +#define INGENIC_ADC_TOUCH_XD 7 +#define INGENIC_ADC_TOUCH_YD 8 #endif diff --git a/include/dt-bindings/iio/qcom,spmi-adc7-pm8350.h b/include/dt-bindings/iio/qcom,spmi-adc7-pm8350.h new file mode 100644 index 0000000000000000000000000000000000000000..9426f27a19466758163fd533e2b363c5d332be23 --- /dev/null +++ b/include/dt-bindings/iio/qcom,spmi-adc7-pm8350.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_PM8350_H +#define _DT_BINDINGS_QCOM_SPMI_VADC_PM8350_H + +#ifndef PM8350_SID +#define PM8350_SID 1 +#endif + +/* ADC channels for PM8350_ADC for PMIC7 */ +#define PM8350_ADC7_REF_GND (PM8350_SID << 8 | 0x0) +#define PM8350_ADC7_1P25VREF (PM8350_SID << 8 | 0x01) +#define PM8350_ADC7_VREF_VADC (PM8350_SID << 8 | 0x02) +#define PM8350_ADC7_DIE_TEMP (PM8350_SID << 8 | 0x03) + +#define PM8350_ADC7_AMUX_THM1 (PM8350_SID << 8 | 0x04) +#define PM8350_ADC7_AMUX_THM2 (PM8350_SID << 8 | 0x05) +#define PM8350_ADC7_AMUX_THM3 (PM8350_SID << 8 | 0x06) +#define PM8350_ADC7_AMUX_THM4 (PM8350_SID << 8 | 0x07) +#define PM8350_ADC7_AMUX_THM5 (PM8350_SID << 8 | 0x08) +#define PM8350_ADC7_GPIO1 (PM8350_SID << 8 | 0x0a) +#define PM8350_ADC7_GPIO2 (PM8350_SID << 8 | 0x0b) +#define PM8350_ADC7_GPIO3 (PM8350_SID << 8 | 0x0c) +#define PM8350_ADC7_GPIO4 (PM8350_SID << 8 | 0x0d) + +/* 30k pull-up1 */ +#define PM8350_ADC7_AMUX_THM1_30K_PU (PM8350_SID << 8 | 0x24) +#define PM8350_ADC7_AMUX_THM2_30K_PU (PM8350_SID << 8 | 0x25) +#define PM8350_ADC7_AMUX_THM3_30K_PU (PM8350_SID << 8 | 0x26) +#define PM8350_ADC7_AMUX_THM4_30K_PU (PM8350_SID << 8 | 0x27) +#define PM8350_ADC7_AMUX_THM5_30K_PU (PM8350_SID << 8 | 0x28) +#define PM8350_ADC7_GPIO1_30K_PU (PM8350_SID << 8 | 0x2a) +#define PM8350_ADC7_GPIO2_30K_PU (PM8350_SID << 8 | 0x2b) +#define PM8350_ADC7_GPIO3_30K_PU (PM8350_SID << 8 | 0x2c) +#define PM8350_ADC7_GPIO4_30K_PU (PM8350_SID << 8 | 0x2d) + +/* 100k pull-up2 */ +#define PM8350_ADC7_AMUX_THM1_100K_PU (PM8350_SID << 8 | 0x44) +#define PM8350_ADC7_AMUX_THM2_100K_PU (PM8350_SID << 8 | 0x45) +#define PM8350_ADC7_AMUX_THM3_100K_PU (PM8350_SID << 8 | 0x46) +#define PM8350_ADC7_AMUX_THM4_100K_PU (PM8350_SID << 8 | 0x47) +#define PM8350_ADC7_AMUX_THM5_100K_PU (PM8350_SID << 8 | 0x48) +#define PM8350_ADC7_GPIO1_100K_PU (PM8350_SID << 8 | 0x4a) +#define PM8350_ADC7_GPIO2_100K_PU (PM8350_SID << 8 | 0x4b) +#define PM8350_ADC7_GPIO3_100K_PU (PM8350_SID << 8 | 0x4c) +#define PM8350_ADC7_GPIO4_100K_PU (PM8350_SID << 8 | 0x4d) + +/* 400k pull-up3 */ +#define PM8350_ADC7_AMUX_THM1_400K_PU (PM8350_SID << 8 | 0x64) +#define PM8350_ADC7_AMUX_THM2_400K_PU (PM8350_SID << 8 | 0x65) +#define PM8350_ADC7_AMUX_THM3_400K_PU (PM8350_SID << 8 | 0x66) +#define PM8350_ADC7_AMUX_THM4_400K_PU (PM8350_SID << 8 | 0x67) +#define PM8350_ADC7_AMUX_THM5_400K_PU (PM8350_SID << 8 | 0x68) +#define PM8350_ADC7_GPIO1_400K_PU (PM8350_SID << 8 | 0x6a) +#define PM8350_ADC7_GPIO2_400K_PU (PM8350_SID << 8 | 0x6b) +#define PM8350_ADC7_GPIO3_400K_PU (PM8350_SID << 8 | 0x6c) +#define PM8350_ADC7_GPIO4_400K_PU (PM8350_SID << 8 | 0x6d) + +/* 1/3 Divider */ +#define PM8350_ADC7_GPIO4_DIV3 (PM8350_SID << 8 | 0x8d) + +#define PM8350_ADC7_VPH_PWR (PM8350_SID << 8 | 0x8e) + +#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_PM8350_H */ diff --git a/include/dt-bindings/iio/qcom,spmi-adc7-pm8350b.h b/include/dt-bindings/iio/qcom,spmi-adc7-pm8350b.h new file mode 100644 index 0000000000000000000000000000000000000000..dc2497c27e16f991904af4a598e89a2c63b1e2d2 --- /dev/null +++ b/include/dt-bindings/iio/qcom,spmi-adc7-pm8350b.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020 The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_PM8350B_H +#define _DT_BINDINGS_QCOM_SPMI_VADC_PM8350B_H + +#ifndef PM8350B_SID +#define PM8350B_SID 3 +#endif + +/* ADC channels for PM8350B_ADC for PMIC7 */ +#define PM8350B_ADC7_REF_GND (PM8350B_SID << 8 | 0x0) +#define PM8350B_ADC7_1P25VREF (PM8350B_SID << 8 | 0x01) +#define PM8350B_ADC7_VREF_VADC (PM8350B_SID << 8 | 0x02) +#define PM8350B_ADC7_DIE_TEMP (PM8350B_SID << 8 | 0x03) + +#define PM8350B_ADC7_AMUX_THM1 (PM8350B_SID << 8 | 0x04) +#define PM8350B_ADC7_AMUX_THM2 (PM8350B_SID << 8 | 0x05) +#define PM8350B_ADC7_AMUX_THM3 (PM8350B_SID << 8 | 0x06) +#define PM8350B_ADC7_AMUX_THM4 (PM8350B_SID << 8 | 0x07) +#define PM8350B_ADC7_AMUX_THM5 (PM8350B_SID << 8 | 0x08) +#define PM8350B_ADC7_AMUX_THM6 (PM8350B_SID << 8 | 0x09) +#define PM8350B_ADC7_GPIO1 (PM8350B_SID << 8 | 0x0a) +#define PM8350B_ADC7_GPIO2 (PM8350B_SID << 8 | 0x0b) +#define PM8350B_ADC7_GPIO3 (PM8350B_SID << 8 | 0x0c) +#define PM8350B_ADC7_GPIO4 (PM8350B_SID << 8 | 0x0d) + +#define PM8350B_ADC7_CHG_TEMP (PM8350B_SID << 8 | 0x10) +#define PM8350B_ADC7_USB_IN_V_16 (PM8350B_SID << 8 | 0x11) +#define PM8350B_ADC7_VDC_16 (PM8350B_SID << 8 | 0x12) +#define PM8350B_ADC7_CC1_ID (PM8350B_SID << 8 | 0x13) +#define PM8350B_ADC7_VREF_BAT_THERM (PM8350B_SID << 8 | 0x15) +#define PM8350B_ADC7_IIN_FB (PM8350B_SID << 8 | 0x17) + +/* 30k pull-up1 */ +#define PM8350B_ADC7_AMUX_THM1_30K_PU (PM8350B_SID << 8 | 0x24) +#define PM8350B_ADC7_AMUX_THM2_30K_PU (PM8350B_SID << 8 | 0x25) +#define PM8350B_ADC7_AMUX_THM3_30K_PU (PM8350B_SID << 8 | 0x26) +#define PM8350B_ADC7_AMUX_THM4_30K_PU (PM8350B_SID << 8 | 0x27) +#define PM8350B_ADC7_AMUX_THM5_30K_PU (PM8350B_SID << 8 | 0x28) +#define PM8350B_ADC7_AMUX_THM6_30K_PU (PM8350B_SID << 8 | 0x29) +#define PM8350B_ADC7_GPIO1_30K_PU (PM8350B_SID << 8 | 0x2a) +#define PM8350B_ADC7_GPIO2_30K_PU (PM8350B_SID << 8 | 0x2b) +#define PM8350B_ADC7_GPIO3_30K_PU (PM8350B_SID << 8 | 0x2c) +#define PM8350B_ADC7_GPIO4_30K_PU (PM8350B_SID << 8 | 0x2d) +#define PM8350B_ADC7_CC1_ID_30K_PU (PM8350B_SID << 8 | 0x33) + +/* 100k pull-up2 */ +#define PM8350B_ADC7_AMUX_THM1_100K_PU (PM8350B_SID << 8 | 0x44) +#define PM8350B_ADC7_AMUX_THM2_100K_PU (PM8350B_SID << 8 | 0x45) +#define PM8350B_ADC7_AMUX_THM3_100K_PU (PM8350B_SID << 8 | 0x46) +#define PM8350B_ADC7_AMUX_THM4_100K_PU (PM8350B_SID << 8 | 0x47) +#define PM8350B_ADC7_AMUX_THM5_100K_PU (PM8350B_SID << 8 | 0x48) +#define PM8350B_ADC7_AMUX_THM6_100K_PU (PM8350B_SID << 8 | 0x49) +#define PM8350B_ADC7_GPIO1_100K_PU (PM8350B_SID << 8 | 0x4a) +#define PM8350B_ADC7_GPIO2_100K_PU (PM8350B_SID << 8 | 0x4b) +#define PM8350B_ADC7_GPIO3_100K_PU (PM8350B_SID << 8 | 0x4c) +#define PM8350B_ADC7_GPIO4_100K_PU (PM8350B_SID << 8 | 0x4d) +#define PM8350B_ADC7_CC1_ID_100K_PU (PM8350B_SID << 8 | 0x53) + +/* 400k pull-up3 */ +#define PM8350B_ADC7_AMUX_THM1_400K_PU (PM8350B_SID << 8 | 0x64) +#define PM8350B_ADC7_AMUX_THM2_400K_PU (PM8350B_SID << 8 | 0x65) +#define PM8350B_ADC7_AMUX_THM3_400K_PU (PM8350B_SID << 8 | 0x66) +#define PM8350B_ADC7_AMUX_THM4_400K_PU (PM8350B_SID << 8 | 0x67) +#define PM8350B_ADC7_AMUX_THM5_400K_PU (PM8350B_SID << 8 | 0x68) +#define PM8350B_ADC7_AMUX_THM6_400K_PU (PM8350B_SID << 8 | 0x69) +#define PM8350B_ADC7_GPIO1_400K_PU (PM8350B_SID << 8 | 0x6a) +#define PM8350B_ADC7_GPIO2_400K_PU (PM8350B_SID << 8 | 0x6b) +#define PM8350B_ADC7_GPIO3_400K_PU (PM8350B_SID << 8 | 0x6c) +#define PM8350B_ADC7_GPIO4_400K_PU (PM8350B_SID << 8 | 0x6d) +#define PM8350B_ADC7_CC1_ID_400K_PU (PM8350B_SID << 8 | 0x73) + +/* 1/3 Divider */ +#define PM8350B_ADC7_GPIO1_DIV3 (PM8350B_SID << 8 | 0x8a) +#define PM8350B_ADC7_GPIO2_DIV3 (PM8350B_SID << 8 | 0x8b) +#define PM8350B_ADC7_GPIO3_DIV3 (PM8350B_SID << 8 | 0x8c) +#define PM8350B_ADC7_GPIO4_DIV3 (PM8350B_SID << 8 | 0x8d) + +#define PM8350B_ADC7_VPH_PWR (PM8350B_SID << 8 | 0x8e) +#define PM8350B_ADC7_VBAT_SNS (PM8350B_SID << 8 | 0x8f) + +#define PM8350B_ADC7_SBUx (PM8350B_SID << 8 | 0x94) +#define PM8350B_ADC7_VBAT_2S_MID (PM8350B_SID << 8 | 0x96) + +#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_PM8350B_H */ diff --git a/include/dt-bindings/iio/qcom,spmi-adc7-pmk8350.h b/include/dt-bindings/iio/qcom,spmi-adc7-pmk8350.h new file mode 100644 index 0000000000000000000000000000000000000000..6c296870e95bd4611e7bb32e48d176494c8c746a --- /dev/null +++ b/include/dt-bindings/iio/qcom,spmi-adc7-pmk8350.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020 The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_PMK8350_H +#define _DT_BINDINGS_QCOM_SPMI_VADC_PMK8350_H + +#ifndef PMK8350_SID +#define PMK8350_SID 0 +#endif + +/* ADC channels for PMK8350_ADC for PMIC7 */ +#define PMK8350_ADC7_REF_GND (PMK8350_SID << 8 | 0x0) +#define PMK8350_ADC7_1P25VREF (PMK8350_SID << 8 | 0x01) +#define PMK8350_ADC7_VREF_VADC (PMK8350_SID << 8 | 0x02) +#define PMK8350_ADC7_DIE_TEMP (PMK8350_SID << 8 | 0x03) + +#define PMK8350_ADC7_AMUX_THM1 (PMK8350_SID << 8 | 0x04) +#define PMK8350_ADC7_AMUX_THM2 (PMK8350_SID << 8 | 0x05) +#define PMK8350_ADC7_AMUX_THM3 (PMK8350_SID << 8 | 0x06) +#define PMK8350_ADC7_AMUX_THM4 (PMK8350_SID << 8 | 0x07) +#define PMK8350_ADC7_AMUX_THM5 (PMK8350_SID << 8 | 0x08) + +/* 30k pull-up1 */ +#define PMK8350_ADC7_AMUX_THM1_30K_PU (PMK8350_SID << 8 | 0x24) +#define PMK8350_ADC7_AMUX_THM2_30K_PU (PMK8350_SID << 8 | 0x25) +#define PMK8350_ADC7_AMUX_THM3_30K_PU (PMK8350_SID << 8 | 0x26) +#define PMK8350_ADC7_AMUX_THM4_30K_PU (PMK8350_SID << 8 | 0x27) +#define PMK8350_ADC7_AMUX_THM5_30K_PU (PMK8350_SID << 8 | 0x28) + +/* 100k pull-up2 */ +#define PMK8350_ADC7_AMUX_THM1_100K_PU (PMK8350_SID << 8 | 0x44) +#define PMK8350_ADC7_AMUX_THM2_100K_PU (PMK8350_SID << 8 | 0x45) +#define PMK8350_ADC7_AMUX_THM3_100K_PU (PMK8350_SID << 8 | 0x46) +#define PMK8350_ADC7_AMUX_THM4_100K_PU (PMK8350_SID << 8 | 0x47) +#define PMK8350_ADC7_AMUX_THM5_100K_PU (PMK8350_SID << 8 | 0x48) + +/* 400k pull-up3 */ +#define PMK8350_ADC7_AMUX_THM1_400K_PU (PMK8350_SID << 8 | 0x64) +#define PMK8350_ADC7_AMUX_THM2_400K_PU (PMK8350_SID << 8 | 0x65) +#define PMK8350_ADC7_AMUX_THM3_400K_PU (PMK8350_SID << 8 | 0x66) +#define PMK8350_ADC7_AMUX_THM4_400K_PU (PMK8350_SID << 8 | 0x67) +#define PMK8350_ADC7_AMUX_THM5_400K_PU (PMK8350_SID << 8 | 0x68) + +#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_PMK8350_H */ diff --git a/include/dt-bindings/iio/qcom,spmi-adc7-pmr735a.h b/include/dt-bindings/iio/qcom,spmi-adc7-pmr735a.h new file mode 100644 index 0000000000000000000000000000000000000000..d6df1b19e5ff01d15a21c42dfa9af569647a2842 --- /dev/null +++ b/include/dt-bindings/iio/qcom,spmi-adc7-pmr735a.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020 The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_PMR735A_H +#define _DT_BINDINGS_QCOM_SPMI_VADC_PMR735A_H + +#ifndef PMR735A_SID +#define PMR735A_SID 4 +#endif + +/* ADC channels for PMR735A_ADC for PMIC7 */ +#define PMR735A_ADC7_REF_GND (PMR735A_SID << 8 | 0x0) +#define PMR735A_ADC7_1P25VREF (PMR735A_SID << 8 | 0x01) +#define PMR735A_ADC7_VREF_VADC (PMR735A_SID << 8 | 0x02) +#define PMR735A_ADC7_DIE_TEMP (PMR735A_SID << 8 | 0x03) + +#define PMR735A_ADC7_GPIO1 (PMR735A_SID << 8 | 0x0a) +#define PMR735A_ADC7_GPIO2 (PMR735A_SID << 8 | 0x0b) +#define PMR735A_ADC7_GPIO3 (PMR735A_SID << 8 | 0x0c) + +/* 100k pull-up2 */ +#define PMR735A_ADC7_GPIO1_100K_PU (PMR735A_SID << 8 | 0x4a) +#define PMR735A_ADC7_GPIO2_100K_PU (PMR735A_SID << 8 | 0x4b) +#define PMR735A_ADC7_GPIO3_100K_PU (PMR735A_SID << 8 | 0x4c) + +#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_PMR735A_H */ diff --git a/include/dt-bindings/iio/qcom,spmi-adc7-pmr735b.h b/include/dt-bindings/iio/qcom,spmi-adc7-pmr735b.h new file mode 100644 index 0000000000000000000000000000000000000000..8da0e7dab315af244f73ae27231a5fc0a1e876b2 --- /dev/null +++ b/include/dt-bindings/iio/qcom,spmi-adc7-pmr735b.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020 The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_PMR735B_H +#define _DT_BINDINGS_QCOM_SPMI_VADC_PMR735B_H + +#ifndef PMR735B_SID +#define PMR735B_SID 5 +#endif + +/* ADC channels for PMR735B_ADC for PMIC7 */ +#define PMR735B_ADC7_REF_GND (PMR735B_SID << 8 | 0x0) +#define PMR735B_ADC7_1P25VREF (PMR735B_SID << 8 | 0x01) +#define PMR735B_ADC7_VREF_VADC (PMR735B_SID << 8 | 0x02) +#define PMR735B_ADC7_DIE_TEMP (PMR735B_SID << 8 | 0x03) + +#define PMR735B_ADC7_GPIO1 (PMR735B_SID << 8 | 0x0a) +#define PMR735B_ADC7_GPIO2 (PMR735B_SID << 8 | 0x0b) +#define PMR735B_ADC7_GPIO3 (PMR735B_SID << 8 | 0x0c) + +/* 100k pull-up2 */ +#define PMR735B_ADC7_GPIO1_100K_PU (PMR735B_SID << 8 | 0x4a) +#define PMR735B_ADC7_GPIO2_100K_PU (PMR735B_SID << 8 | 0x4b) +#define PMR735B_ADC7_GPIO3_100K_PU (PMR735B_SID << 8 | 0x4c) + +#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_PMR735B_H */ diff --git a/include/dt-bindings/iio/qcom,spmi-vadc.h b/include/dt-bindings/iio/qcom,spmi-vadc.h index 61d556db154276abef5f103629d15369ed60a3d2..08adfe25964c9313bcf16f364367639672c3f8ce 100644 --- a/include/dt-bindings/iio/qcom,spmi-vadc.h +++ b/include/dt-bindings/iio/qcom,spmi-vadc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2012-2014,2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014,2018,2020 The Linux Foundation. All rights reserved. */ #ifndef _DT_BINDINGS_QCOM_SPMI_VADC_H @@ -221,4 +221,80 @@ #define ADC5_MAX_CHANNEL 0xc0 +/* ADC channels for ADC for PMIC7 */ + +#define ADC7_REF_GND 0x00 +#define ADC7_1P25VREF 0x01 +#define ADC7_VREF_VADC 0x02 +#define ADC7_DIE_TEMP 0x03 + +#define ADC7_AMUX_THM1 0x04 +#define ADC7_AMUX_THM2 0x05 +#define ADC7_AMUX_THM3 0x06 +#define ADC7_AMUX_THM4 0x07 +#define ADC7_AMUX_THM5 0x08 +#define ADC7_AMUX_THM6 0x09 +#define ADC7_GPIO1 0x0a +#define ADC7_GPIO2 0x0b +#define ADC7_GPIO3 0x0c +#define ADC7_GPIO4 0x0d + +#define ADC7_CHG_TEMP 0x10 +#define ADC7_USB_IN_V_16 0x11 +#define ADC7_VDC_16 0x12 +#define ADC7_CC1_ID 0x13 +#define ADC7_VREF_BAT_THERM 0x15 +#define ADC7_IIN_FB 0x17 + +/* 30k pull-up1 */ +#define ADC7_AMUX_THM1_30K_PU 0x24 +#define ADC7_AMUX_THM2_30K_PU 0x25 +#define ADC7_AMUX_THM3_30K_PU 0x26 +#define ADC7_AMUX_THM4_30K_PU 0x27 +#define ADC7_AMUX_THM5_30K_PU 0x28 +#define ADC7_AMUX_THM6_30K_PU 0x29 +#define ADC7_GPIO1_30K_PU 0x2a +#define ADC7_GPIO2_30K_PU 0x2b +#define ADC7_GPIO3_30K_PU 0x2c +#define ADC7_GPIO4_30K_PU 0x2d +#define ADC7_CC1_ID_30K_PU 0x33 + +/* 100k pull-up2 */ +#define ADC7_AMUX_THM1_100K_PU 0x44 +#define ADC7_AMUX_THM2_100K_PU 0x45 +#define ADC7_AMUX_THM3_100K_PU 0x46 +#define ADC7_AMUX_THM4_100K_PU 0x47 +#define ADC7_AMUX_THM5_100K_PU 0x48 +#define ADC7_AMUX_THM6_100K_PU 0x49 +#define ADC7_GPIO1_100K_PU 0x4a +#define ADC7_GPIO2_100K_PU 0x4b +#define ADC7_GPIO3_100K_PU 0x4c +#define ADC7_GPIO4_100K_PU 0x4d +#define ADC7_CC1_ID_100K_PU 0x53 + +/* 400k pull-up3 */ +#define ADC7_AMUX_THM1_400K_PU 0x64 +#define ADC7_AMUX_THM2_400K_PU 0x65 +#define ADC7_AMUX_THM3_400K_PU 0x66 +#define ADC7_AMUX_THM4_400K_PU 0x67 +#define ADC7_AMUX_THM5_400K_PU 0x68 +#define ADC7_AMUX_THM6_400K_PU 0x69 +#define ADC7_GPIO1_400K_PU 0x6a +#define ADC7_GPIO2_400K_PU 0x6b +#define ADC7_GPIO3_400K_PU 0x6c +#define ADC7_GPIO4_400K_PU 0x6d +#define ADC7_CC1_ID_400K_PU 0x73 + +/* 1/3 Divider */ +#define ADC7_GPIO1_DIV3 0x8a +#define ADC7_GPIO2_DIV3 0x8b +#define ADC7_GPIO3_DIV3 0x8c +#define ADC7_GPIO4_DIV3 0x8d + +#define ADC7_VPH_PWR 0x8e +#define ADC7_VBAT_SNS 0x8f + +#define ADC7_SBUx 0x94 +#define ADC7_VBAT_2S_MID 0x96 + #endif /* _DT_BINDINGS_QCOM_SPMI_VADC_H */ diff --git a/include/dt-bindings/sound/qcom,q6asm.h b/include/dt-bindings/sound/qcom,q6asm.h index 1eb77d87c2e815ded01cbc8a4df14f5024de190a..f59d74f14395b72991ae8c1663591d5df60a49af 100644 --- a/include/dt-bindings/sound/qcom,q6asm.h +++ b/include/dt-bindings/sound/qcom,q6asm.h @@ -19,4 +19,8 @@ #define MSM_FRONTEND_DAI_MULTIMEDIA15 14 #define MSM_FRONTEND_DAI_MULTIMEDIA16 15 +#define Q6ASM_DAI_TX_RX 0 +#define Q6ASM_DAI_TX 1 +#define Q6ASM_DAI_RX 2 + #endif /* __DT_BINDINGS_Q6_ASM_H__ */ diff --git a/include/linux/clock_cooling.h b/include/linux/clock_cooling.h deleted file mode 100644 index 4b0a69863656cb840fbc387bf78a2e175ab06835..0000000000000000000000000000000000000000 --- a/include/linux/clock_cooling.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/include/linux/clock_cooling.h - * - * Copyright (C) 2014 Eduardo Valentin - * - * Copyright (C) 2013 Texas Instruments Inc. - * Contact: Eduardo Valentin - * - * Highly based on cpufreq_cooling.c. - * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) - * Copyright (C) 2012 Amit Daniel - */ - -#ifndef __CPU_COOLING_H__ -#define __CPU_COOLING_H__ - -#include -#include -#include - -#ifdef CONFIG_CLOCK_THERMAL -/** - * clock_cooling_register - function to create clock cooling device. - * @dev: struct device pointer to the device used as clock cooling device. - * @clock_name: string containing the clock used as cooling mechanism. - */ -struct thermal_cooling_device * -clock_cooling_register(struct device *dev, const char *clock_name); - -/** - * clock_cooling_unregister - function to remove clock cooling device. - * @cdev: thermal cooling device pointer. - */ -void clock_cooling_unregister(struct thermal_cooling_device *cdev); - -unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev, - unsigned long freq); -#else /* !CONFIG_CLOCK_THERMAL */ -static inline struct thermal_cooling_device * -clock_cooling_register(struct device *dev, const char *clock_name) -{ - return NULL; -} -static inline -void clock_cooling_unregister(struct thermal_cooling_device *cdev) -{ -} -static inline -unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev, - unsigned long freq) -{ - return THERMAL_CSTATE_INVALID; -} -#endif /* CONFIG_CLOCK_THERMAL */ - -#endif /* __CPU_COOLING_H__ */ diff --git a/include/linux/console.h b/include/linux/console.h index 75dd20650fbe4d1af4b7633f8eb873ae049a52a9..0670d3491e0eabef09e0080b86f15bb12df11975 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -24,17 +24,13 @@ struct module; struct tty_struct; struct notifier_block; -/* - * this is what the terminal answers to a ESC-Z or csi0c query. - */ -#define VT100ID "\033[?1;2c" -#define VT102ID "\033[?6c" - enum con_scroll { SM_UP, SM_DOWN, }; +enum vc_intensity; + /** * struct consw - callbacks for consoles * @@ -74,8 +70,9 @@ struct consw { void (*con_scrolldelta)(struct vc_data *vc, int lines); int (*con_set_origin)(struct vc_data *vc); void (*con_save_screen)(struct vc_data *vc); - u8 (*con_build_attr)(struct vc_data *vc, u8 color, u8 intensity, - u8 blink, u8 underline, u8 reverse, u8 italic); + u8 (*con_build_attr)(struct vc_data *vc, u8 color, + enum vc_intensity intensity, + bool blink, bool underline, bool reverse, bool italic); void (*con_invert_region)(struct vc_data *vc, u16 *p, int count); u16 *(*con_screen_pos)(struct vc_data *vc, int offset); unsigned long (*con_getxy)(struct vc_data *vc, unsigned long position, diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index 24d4c16e3ae039f2f25033686f2bc15d5f1a1429..153734816b49cfdc534d8138e576f174a78d0218 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -21,6 +21,43 @@ struct uni_pagedir; struct uni_screen; #define NPAR 16 +#define VC_TABSTOPS_COUNT 256U + +enum vc_intensity { + VCI_HALF_BRIGHT, + VCI_NORMAL, + VCI_BOLD, + VCI_MASK = 0x3, +}; + +/** + * struct vc_state -- state of a VC + * @x: cursor's x-position + * @y: cursor's y-position + * @color: foreground & background colors + * @Gx_charset: what's G0/G1 slot set to (like GRAF_MAP, LAT1_MAP) + * @charset: what character set to use (0=G0 or 1=G1) + * @intensity: see enum vc_intensity for values + * @reverse: reversed foreground/background colors + * + * These members are defined separately from struct vc_data as we save & + * restore them at times. + */ +struct vc_state { + unsigned int x, y; + + unsigned char color; + + unsigned char Gx_charset[2]; + unsigned int charset : 1; + + /* attribute flags */ + enum vc_intensity intensity; + bool italic; + bool underline; + bool blink; + bool reverse; +}; /* * Example: vc_data of a console that was scrolled 3 lines down. @@ -57,6 +94,8 @@ struct uni_screen; struct vc_data { struct tty_port port; /* Upper level data */ + struct vc_state state, saved_state; + unsigned short vc_num; /* Console number */ unsigned int vc_cols; /* [#] Console size */ unsigned int vc_rows; @@ -73,8 +112,6 @@ struct vc_data { /* attributes for all characters on screen */ unsigned char vc_attr; /* Current attributes */ unsigned char vc_def_color; /* Default colors */ - unsigned char vc_color; /* Foreground & background */ - unsigned char vc_s_color; /* Saved foreground & background */ unsigned char vc_ulcolor; /* Color for underline mode */ unsigned char vc_itcolor; unsigned char vc_halfcolor; /* Color for half intensity mode */ @@ -82,8 +119,6 @@ struct vc_data { unsigned int vc_cursor_type; unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */ unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */ - unsigned int vc_x, vc_y; /* Cursor position */ - unsigned int vc_saved_x, vc_saved_y; unsigned long vc_pos; /* Cursor address */ /* fonts */ unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */ @@ -98,8 +133,6 @@ struct vc_data { int vt_newvt; wait_queue_head_t paste_wait; /* mode flags */ - unsigned int vc_charset : 1; /* Character set G0 / G1 */ - unsigned int vc_s_charset : 1; /* Saved character set */ unsigned int vc_disp_ctrl : 1; /* Display chars < 32? */ unsigned int vc_toggle_meta : 1; /* Toggle high bit? */ unsigned int vc_decscnm : 1; /* Screen Mode */ @@ -107,17 +140,6 @@ struct vc_data { unsigned int vc_decawm : 1; /* Autowrap Mode */ unsigned int vc_deccm : 1; /* Cursor Visible */ unsigned int vc_decim : 1; /* Insert Mode */ - /* attribute flags */ - unsigned int vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */ - unsigned int vc_italic:1; - unsigned int vc_underline : 1; - unsigned int vc_blink : 1; - unsigned int vc_reverse : 1; - unsigned int vc_s_intensity : 2; /* saved rendition */ - unsigned int vc_s_italic:1; - unsigned int vc_s_underline : 1; - unsigned int vc_s_blink : 1; - unsigned int vc_s_reverse : 1; /* misc */ unsigned int vc_priv : 3; unsigned int vc_need_wrap : 1; @@ -126,13 +148,9 @@ struct vc_data { unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */ unsigned char vc_utf_count; int vc_utf_char; - unsigned int vc_tab_stop[8]; /* Tab stops. 256 columns. */ + DECLARE_BITMAP(vc_tab_stop, VC_TABSTOPS_COUNT); /* Tab stops. 256 columns. */ unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */ unsigned short * vc_translate; - unsigned char vc_G0_charset; - unsigned char vc_G1_charset; - unsigned char vc_saved_G0; - unsigned char vc_saved_G1; unsigned int vc_resize_user; /* resize request from user */ unsigned int vc_bell_pitch; /* Console bell pitch */ unsigned int vc_bell_duration; /* Console bell duration */ @@ -149,24 +167,29 @@ struct vc { struct work_struct SAK_work; /* might add scrmem, kbd at some time, - to have everything in one place - the disadvantage - would be that vc_cons etc can no longer be static */ + to have everything in one place */ }; extern struct vc vc_cons [MAX_NR_CONSOLES]; extern void vc_SAK(struct work_struct *work); -#define CUR_DEF 0 -#define CUR_NONE 1 -#define CUR_UNDERLINE 2 -#define CUR_LOWER_THIRD 3 -#define CUR_LOWER_HALF 4 -#define CUR_TWO_THIRDS 5 -#define CUR_BLOCK 6 -#define CUR_HWMASK 0x0f -#define CUR_SWMASK 0xfff0 - -#define CUR_DEFAULT CUR_UNDERLINE +#define CUR_MAKE(size, change, set) ((size) | ((change) << 8) | \ + ((set) << 16)) +#define CUR_SIZE(c) ((c) & 0x00000f) +# define CUR_DEF 0 +# define CUR_NONE 1 +# define CUR_UNDERLINE 2 +# define CUR_LOWER_THIRD 3 +# define CUR_LOWER_HALF 4 +# define CUR_TWO_THIRDS 5 +# define CUR_BLOCK 6 +#define CUR_SW 0x000010 +#define CUR_ALWAYS_BG 0x000020 +#define CUR_INVERT_FG_BG 0x000040 +#define CUR_FG 0x000700 +#define CUR_BG 0x007000 +#define CUR_CHANGE(c) ((c) & 0x00ff00) +#define CUR_SET(c) (((c) & 0xff0000) >> 8) bool con_is_visible(const struct vc_data *vc); diff --git a/include/linux/devfreq_cooling.h b/include/linux/devfreq_cooling.h index 79a6e37a1d6f641bcd56e15af8d2b009cb321f88..9df2dfca68dd967aa449bc409282de0297f4b3a6 100644 --- a/include/linux/devfreq_cooling.h +++ b/include/linux/devfreq_cooling.h @@ -1,17 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * devfreq_cooling: Thermal cooling device implementation for devices using * devfreq * * Copyright (C) 2014-2015 ARM Limited * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #ifndef __DEVFREQ_COOLING_H__ diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index b79fa9bb7359531f294dafb7550bd9fc0208987c..3e9c56ee651f79a797acc4eea6a807d7d32acf82 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -18,8 +18,10 @@ #define FANOTIFY_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \ FAN_CLASS_PRE_CONTENT) -#define FANOTIFY_INIT_FLAGS (FANOTIFY_CLASS_BITS | \ - FAN_REPORT_TID | FAN_REPORT_FID | \ +#define FANOTIFY_FID_BITS (FAN_REPORT_FID | FAN_REPORT_DFID_NAME) + +#define FANOTIFY_INIT_FLAGS (FANOTIFY_CLASS_BITS | FANOTIFY_FID_BITS | \ + FAN_REPORT_TID | \ FAN_CLOEXEC | FAN_NONBLOCK | \ FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS) diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 5ab28f6c7d260cdad7324333748a02c9035690ef..f8acddcf54fb4ce2e7b03dda41f52dd936b591e8 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -23,19 +23,14 @@ * have changed (i.e. renamed over). * * Unlike fsnotify_parent(), the event will be reported regardless of the - * FS_EVENT_ON_CHILD mask on the parent inode. + * FS_EVENT_ON_CHILD mask on the parent inode and will not be reported if only + * the child is interested and not the parent. */ static inline void fsnotify_name(struct inode *dir, __u32 mask, struct inode *child, const struct qstr *name, u32 cookie) { - fsnotify(dir, mask, child, FSNOTIFY_EVENT_INODE, name, cookie); - /* - * Send another flavor of the event without child inode data and - * without the specific event type (e.g. FS_CREATE|FS_IS_DIR). - * The name is relative to the dir inode the event is reported to. - */ - fsnotify(dir, FS_DIR_MODIFY, dir, FSNOTIFY_EVENT_INODE, name, 0); + fsnotify(mask, child, FSNOTIFY_EVENT_INODE, dir, name, NULL, cookie); } static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry, @@ -44,38 +39,55 @@ static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry, fsnotify_name(dir, mask, d_inode(dentry), &dentry->d_name, 0); } -/* - * Simple wrappers to consolidate calls fsnotify_parent()/fsnotify() when - * an event is on a file/dentry. - */ -static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask) +static inline void fsnotify_inode(struct inode *inode, __u32 mask) +{ + if (S_ISDIR(inode->i_mode)) + mask |= FS_ISDIR; + + fsnotify(mask, inode, FSNOTIFY_EVENT_INODE, NULL, NULL, inode, 0); +} + +/* Notify this dentry's parent about a child's events. */ +static inline int fsnotify_parent(struct dentry *dentry, __u32 mask, + const void *data, int data_type) { struct inode *inode = d_inode(dentry); - if (S_ISDIR(inode->i_mode)) + if (S_ISDIR(inode->i_mode)) { mask |= FS_ISDIR; - fsnotify_parent(dentry, mask, inode, FSNOTIFY_EVENT_INODE); - fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); + /* sb/mount marks are not interested in name of directory */ + if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) + goto notify_child; + } + + /* disconnected dentry cannot notify parent */ + if (IS_ROOT(dentry)) + goto notify_child; + + return __fsnotify_parent(dentry, mask, data, data_type); + +notify_child: + return fsnotify(mask, data, data_type, NULL, NULL, inode, 0); +} + +/* + * Simple wrappers to consolidate calls to fsnotify_parent() when an event + * is on a file/dentry. + */ +static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask) +{ + fsnotify_parent(dentry, mask, d_inode(dentry), FSNOTIFY_EVENT_INODE); } static inline int fsnotify_file(struct file *file, __u32 mask) { const struct path *path = &file->f_path; - struct inode *inode = file_inode(file); - int ret; if (file->f_mode & FMODE_NONOTIFY) return 0; - if (S_ISDIR(inode->i_mode)) - mask |= FS_ISDIR; - - ret = fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH); - if (ret) - return ret; - - return fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); + return fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH); } /* Simple call site for access decisions */ @@ -108,12 +120,7 @@ static inline int fsnotify_perm(struct file *file, int mask) */ static inline void fsnotify_link_count(struct inode *inode) { - __u32 mask = FS_ATTRIB; - - if (S_ISDIR(inode->i_mode)) - mask |= FS_ISDIR; - - fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); + fsnotify_inode(inode, FS_ATTRIB); } /* @@ -128,7 +135,6 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, u32 fs_cookie = fsnotify_get_cookie(); __u32 old_dir_mask = FS_MOVED_FROM; __u32 new_dir_mask = FS_MOVED_TO; - __u32 mask = FS_MOVE_SELF; const struct qstr *new_name = &moved->d_name; if (old_dir == new_dir) @@ -137,7 +143,6 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, if (isdir) { old_dir_mask |= FS_ISDIR; new_dir_mask |= FS_ISDIR; - mask |= FS_ISDIR; } fsnotify_name(old_dir, old_dir_mask, source, old_name, fs_cookie); @@ -145,9 +150,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, if (target) fsnotify_link_count(target); - - if (source) - fsnotify(source, mask, source, FSNOTIFY_EVENT_INODE, NULL, 0); + fsnotify_inode(source, FS_MOVE_SELF); audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE); } @@ -172,12 +175,7 @@ static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt) */ static inline void fsnotify_inoderemove(struct inode *inode) { - __u32 mask = FS_DELETE_SELF; - - if (S_ISDIR(inode->i_mode)) - mask |= FS_ISDIR; - - fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); + fsnotify_inode(inode, FS_DELETE_SELF); __fsnotify_inode_delete(inode); } diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index f0c506405b543713b2f7296810be5af2a5e3d640..f8529a3a29234b0a1753c0e5f01d0e3ba0bc1594 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -47,11 +47,13 @@ #define FS_OPEN_PERM 0x00010000 /* open event in an permission hook */ #define FS_ACCESS_PERM 0x00020000 /* access event in a permissions hook */ #define FS_OPEN_EXEC_PERM 0x00040000 /* open/exec event in a permission hook */ -#define FS_DIR_MODIFY 0x00080000 /* Directory entry was modified */ #define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */ -/* This inode cares about things that happen to its children. Always set for - * dnotify and inotify. */ +/* + * Set on inode mark that cares about things that happen to its children. + * Always set for dnotify and inotify. + * Set on inode/sb/mount marks that care about parent/name info. + */ #define FS_EVENT_ON_CHILD 0x08000000 #define FS_DN_RENAME 0x10000000 /* file renamed */ @@ -67,21 +69,28 @@ * The watching parent may get an FS_ATTRIB|FS_EVENT_ON_CHILD event * when a directory entry inside a child subdir changes. */ -#define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE | \ - FS_DIR_MODIFY) +#define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE) #define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM | \ FS_OPEN_EXEC_PERM) /* - * This is a list of all events that may get sent to a parent based on fs event - * happening to inodes inside that directory. + * This is a list of all events that may get sent to a parent that is watching + * with flag FS_EVENT_ON_CHILD based on fs event on a child of that directory. */ #define FS_EVENTS_POSS_ON_CHILD (ALL_FSNOTIFY_PERM_EVENTS | \ FS_ACCESS | FS_MODIFY | FS_ATTRIB | \ FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | \ FS_OPEN | FS_OPEN_EXEC) +/* + * This is a list of all events that may get sent with the parent inode as the + * @to_tell argument of fsnotify(). + * It may include events that can be sent to an inode/sb/mount mark, but cannot + * be sent to a parent watching children. + */ +#define FS_EVENTS_POSS_TO_PARENT (FS_EVENTS_POSS_ON_CHILD) + /* Events that can be reported to backends */ #define ALL_FSNOTIFY_EVENTS (ALL_FSNOTIFY_DIRENT_EVENTS | \ FS_EVENTS_POSS_ON_CHILD | \ @@ -108,18 +117,41 @@ struct mem_cgroup; * these operations for each relevant group. * * handle_event - main call for a group to handle an fs event + * @group: group to notify + * @mask: event type and flags + * @data: object that event happened on + * @data_type: type of object for fanotify_data_XXX() accessors + * @dir: optional directory associated with event - + * if @file_name is not NULL, this is the directory that + * @file_name is relative to + * @file_name: optional file name associated with event + * @cookie: inotify rename cookie + * @iter_info: array of marks from this group that are interested in the event + * + * handle_inode_event - simple variant of handle_event() for groups that only + * have inode marks and don't have ignore mask + * @mark: mark to notify + * @mask: event type and flags + * @inode: inode that event happened on + * @dir: optional directory associated with event - + * if @file_name is not NULL, this is the directory that + * @file_name is relative to. + * @file_name: optional file name associated with event + * * free_group_priv - called when a group refcnt hits 0 to clean up the private union * freeing_mark - called when a mark is being destroyed for some reason. The group - * MUST be holding a reference on each mark and that reference must be - * dropped in this function. inotify uses this function to send - * userspace messages that marks have been removed. + * MUST be holding a reference on each mark and that reference must be + * dropped in this function. inotify uses this function to send + * userspace messages that marks have been removed. */ struct fsnotify_ops { - int (*handle_event)(struct fsnotify_group *group, - struct inode *inode, - u32 mask, const void *data, int data_type, + int (*handle_event)(struct fsnotify_group *group, u32 mask, + const void *data, int data_type, struct inode *dir, const struct qstr *file_name, u32 cookie, struct fsnotify_iter_info *iter_info); + int (*handle_inode_event)(struct fsnotify_mark *mark, u32 mask, + struct inode *inode, struct inode *dir, + const struct qstr *file_name); void (*free_group_priv)(struct fsnotify_group *group); void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group); void (*free_event)(struct fsnotify_event *event); @@ -220,12 +252,11 @@ enum fsnotify_data_type { FSNOTIFY_EVENT_INODE, }; -static inline const struct inode *fsnotify_data_inode(const void *data, - int data_type) +static inline struct inode *fsnotify_data_inode(const void *data, int data_type) { switch (data_type) { case FSNOTIFY_EVENT_INODE: - return data; + return (struct inode *)data; case FSNOTIFY_EVENT_PATH: return d_inode(((const struct path *)data)->dentry); default: @@ -246,6 +277,7 @@ static inline const struct path *fsnotify_data_path(const void *data, enum fsnotify_obj_type { FSNOTIFY_OBJ_TYPE_INODE, + FSNOTIFY_OBJ_TYPE_CHILD, FSNOTIFY_OBJ_TYPE_VFSMOUNT, FSNOTIFY_OBJ_TYPE_SB, FSNOTIFY_OBJ_TYPE_COUNT, @@ -253,6 +285,7 @@ enum fsnotify_obj_type { }; #define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) +#define FSNOTIFY_OBJ_TYPE_CHILD_FL (1U << FSNOTIFY_OBJ_TYPE_CHILD) #define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) #define FSNOTIFY_OBJ_TYPE_SB_FL (1U << FSNOTIFY_OBJ_TYPE_SB) #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) @@ -297,6 +330,7 @@ static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ } FSNOTIFY_ITER_FUNCS(inode, INODE) +FSNOTIFY_ITER_FUNCS(child, CHILD) FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) FSNOTIFY_ITER_FUNCS(sb, SB) @@ -377,15 +411,29 @@ struct fsnotify_mark { /* called from the vfs helpers */ /* main fsnotify call to send events */ -extern int fsnotify(struct inode *to_tell, __u32 mask, const void *data, - int data_type, const struct qstr *name, u32 cookie); -extern int fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, +extern int fsnotify(__u32 mask, const void *data, int data_type, + struct inode *dir, const struct qstr *name, + struct inode *inode, u32 cookie); +extern int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, int data_type); extern void __fsnotify_inode_delete(struct inode *inode); extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); extern void fsnotify_sb_delete(struct super_block *sb); extern u32 fsnotify_get_cookie(void); +static inline __u32 fsnotify_parent_needed_mask(__u32 mask) +{ + /* FS_EVENT_ON_CHILD is set on marks that want parent/name info */ + if (!(mask & FS_EVENT_ON_CHILD)) + return 0; + /* + * This object might be watched by a mark that cares about parent/name + * info, does it care about the specific set of events that can be + * reported with parent/name info? + */ + return mask & FS_EVENTS_POSS_TO_PARENT; +} + static inline int fsnotify_inode_watches_children(struct inode *inode) { /* FS_EVENT_ON_CHILD is set if the inode may care */ @@ -535,13 +583,14 @@ static inline void fsnotify_init_event(struct fsnotify_event *event, #else -static inline int fsnotify(struct inode *to_tell, __u32 mask, const void *data, - int data_type, const struct qstr *name, u32 cookie) +static inline int fsnotify(__u32 mask, const void *data, int data_type, + struct inode *dir, const struct qstr *name, + struct inode *inode, u32 cookie) { return 0; } -static inline int fsnotify_parent(struct dentry *dentry, __u32 mask, +static inline int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, int data_type) { return 0; diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index 7bc961defa87e09226decae9b982cc7c8271de22..caa8bb279a3467bf8b25be280807f8d6174f3fd9 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -42,6 +42,10 @@ typedef irqreturn_t (*cros_ec_sensors_capture_t)(int irq, void *p); * @resp: motion sensor response structure * @type: type of motion sensor * @loc: location where the motion sensor is placed + * @range_updated: True if the range of the sensor has been + * updated. + * @curr_range: If updated, the current range value. + * It will be reapplied at every resume. * @calib: calibration parameters. Note that trigger * captured data will always provide the calibrated * data @@ -65,6 +69,9 @@ struct cros_ec_sensors_core_state { enum motionsensor_type type; enum motionsensor_location loc; + bool range_updated; + int curr_range; + struct calib_data { s16 offset; u16 scale; @@ -114,7 +121,9 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int val, int val2, long mask); -/* List of extended channel specification for all sensors */ +extern const struct dev_pm_ops cros_ec_sensors_pm_ops; + +/* List of extended channel specification for all sensors. */ extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[]; extern const struct attribute *cros_ec_sensor_fifo_attributes[]; diff --git a/include/linux/iio/iio-opaque.h b/include/linux/iio/iio-opaque.h new file mode 100644 index 0000000000000000000000000000000000000000..f2e94196d31f0ecefb5c094263ac6153da547711 --- /dev/null +++ b/include/linux/iio/iio-opaque.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _INDUSTRIAL_IO_OPAQUE_H_ +#define _INDUSTRIAL_IO_OPAQUE_H_ + +/** + * struct iio_dev_opaque - industrial I/O device opaque information + * @indio_dev: public industrial I/O device information + * @event_interface: event chrdevs associated with interrupt lines + * @buffer_list: list of all buffers currently attached + * @channel_attr_list: keep track of automatically created channel + * attributes + * @chan_attr_group: group for all attrs in base directory + * @debugfs_dentry: device specific debugfs dentry + * @cached_reg_addr: cached register address for debugfs reads + * @read_buf: read buffer to be used for the initial reg read + * @read_buf_len: data length in @read_buf + */ +struct iio_dev_opaque { + struct iio_dev indio_dev; + struct iio_event_interface *event_interface; + struct list_head buffer_list; + struct list_head channel_attr_list; + struct attribute_group chan_attr_group; +#if defined(CONFIG_DEBUG_FS) + struct dentry *debugfs_dentry; + unsigned cached_reg_addr; + char read_buf[20]; + unsigned int read_buf_len; +#endif +}; + +#define to_iio_dev_opaque(indio_dev) \ + container_of(indio_dev, struct iio_dev_opaque, indio_dev) + +#endif diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index a1be82e74c9383fdcdee310f5da4658605d1a1b4..e2df67a3b9abfb34606c23cec500c3be35359fda 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -488,9 +488,7 @@ struct iio_buffer_setup_ops { * @currentmode: [DRIVER] current operating mode * @dev: [DRIVER] device structure, should be assigned a parent * and owner - * @event_interface: [INTERN] event chrdevs associated with interrupt lines * @buffer: [DRIVER] any buffer present - * @buffer_list: [INTERN] list of all buffers currently attached * @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux * @mlock: [INTERN] lock used to prevent simultaneous device state * changes @@ -506,9 +504,6 @@ struct iio_buffer_setup_ops { * @pollfunc_event: [DRIVER] function run on events trigger being received * @channels: [DRIVER] channel specification structure table * @num_channels: [DRIVER] number of channels specified in @channels. - * @channel_attr_list: [INTERN] keep track of automatically created channel - * attributes - * @chan_attr_group: [INTERN] group for all attrs in base directory * @name: [DRIVER] name of the device. * @label: [DRIVER] unique name to identify which device this is * @info: [DRIVER] callbacks and constant info from driver @@ -520,8 +515,8 @@ struct iio_buffer_setup_ops { * @groups: [INTERN] attribute groups * @groupcounter: [INTERN] index of next attribute group * @flags: [INTERN] file ops related flags including busy flag. - * @debugfs_dentry: [INTERN] device specific debugfs dentry. - * @cached_reg_addr: [INTERN] cached register address for debugfs reads. + * @priv: [DRIVER] reference to driver's private information + * **MUST** be accessed **ONLY** via iio_priv() helper */ struct iio_dev { int id; @@ -531,10 +526,7 @@ struct iio_dev { int currentmode; struct device dev; - struct iio_event_interface *event_interface; - struct iio_buffer *buffer; - struct list_head buffer_list; int scan_bytes; struct mutex mlock; @@ -551,8 +543,6 @@ struct iio_dev { struct iio_chan_spec const *channels; int num_channels; - struct list_head channel_attr_list; - struct attribute_group chan_attr_group; const char *name; const char *label; const struct iio_info *info; @@ -565,12 +555,7 @@ struct iio_dev { int groupcounter; unsigned long flags; -#if defined(CONFIG_DEBUG_FS) - struct dentry *debugfs_dentry; - unsigned cached_reg_addr; - char read_buf[20]; - unsigned int read_buf_len; -#endif + void *priv; }; const struct iio_chan_spec @@ -649,6 +634,26 @@ static inline struct iio_dev *iio_device_get(struct iio_dev *indio_dev) return indio_dev ? dev_to_iio_dev(get_device(&indio_dev->dev)) : NULL; } +/** + * iio_device_set_parent() - assign parent device to the IIO device object + * @indio_dev: IIO device structure + * @parent: reference to parent device object + * + * This utility must be called between IIO device allocation + * (via devm_iio_device_alloc()) & IIO device registration + * (via {devm_}iio_device_register()). + * By default, the device allocation will also assign a parent device to + * the IIO device object. In cases where devm_iio_device_alloc() is used, + * sometimes the parent device must be different than the device used to + * manage the allocation. + * In that case, this helper should be used to change the parent, hence the + * requirement to call this between allocation & registration. + **/ +static inline void iio_device_set_parent(struct iio_dev *indio_dev, + struct device *parent) +{ + indio_dev->dev.parent = parent; +} /** * iio_device_set_drvdata() - Set device driver data @@ -669,28 +674,23 @@ static inline void iio_device_set_drvdata(struct iio_dev *indio_dev, void *data) * * Returns the data previously set with iio_device_set_drvdata() */ -static inline void *iio_device_get_drvdata(struct iio_dev *indio_dev) +static inline void *iio_device_get_drvdata(const struct iio_dev *indio_dev) { return dev_get_drvdata(&indio_dev->dev); } /* Can we make this smaller? */ #define IIO_ALIGN L1_CACHE_BYTES -struct iio_dev *iio_device_alloc(int sizeof_priv); +struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv); +/* The information at the returned address is guaranteed to be cacheline aligned */ static inline void *iio_priv(const struct iio_dev *indio_dev) { - return (char *)indio_dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN); -} - -static inline struct iio_dev *iio_priv_to_dev(void *priv) -{ - return (struct iio_dev *)((char *)priv - - ALIGN(sizeof(struct iio_dev), IIO_ALIGN)); + return indio_dev->priv; } void iio_device_free(struct iio_dev *indio_dev); -struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv); +struct iio_dev *devm_iio_device_alloc(struct device *parent, int sizeof_priv); struct iio_trigger *devm_iio_trigger_alloc(struct device *dev, const char *fmt, ...); /** @@ -709,10 +709,7 @@ static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) * @indio_dev: IIO device structure for device **/ #if defined(CONFIG_DEBUG_FS) -static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) -{ - return indio_dev->debugfs_dentry; -} +struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev); #else static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) { diff --git a/include/linux/iio/trigger_consumer.h b/include/linux/iio/trigger_consumer.h index c3c6ba5ec423fb76ef6cf08d1240dfba8f5db73a..3aa2f132dd67d26b645be8105aeb569588504ba3 100644 --- a/include/linux/iio/trigger_consumer.h +++ b/include/linux/iio/trigger_consumer.h @@ -50,11 +50,4 @@ irqreturn_t iio_pollfunc_store_time(int irq, void *p); void iio_trigger_notify_done(struct iio_trigger *trig); -/* - * Two functions for common case where all that happens is a pollfunc - * is attached and detached from a trigger - */ -int iio_triggered_buffer_postenable(struct iio_dev *indio_dev); -int iio_triggered_buffer_predisable(struct iio_dev *indio_dev); - #endif diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index ac83e9c1d82c76a9752989f7cd3aefc6c98ca1c9..a23076765b4cc26040bd6b3110f06c1d14724e7b 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -211,8 +211,8 @@ struct kvm_async_pf { void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu); void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu); -int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, - unsigned long hva, struct kvm_arch_async_pf *arch); +bool kvm_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, + unsigned long hva, struct kvm_arch_async_pf *arch); int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu); #endif @@ -774,6 +774,7 @@ int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); bool kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn); +bool kvm_vcpu_is_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn); unsigned long kvm_host_page_size(struct kvm_vcpu *vcpu, gfn_t gfn); void mark_page_dirty(struct kvm *kvm, gfn_t gfn); @@ -816,6 +817,13 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *vcpu, bool usermode_vcpu_not_eligible); void kvm_flush_remote_tlbs(struct kvm *kvm); void kvm_reload_remote_mmus(struct kvm *kvm); +#ifdef KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE +int kvm_mmu_topup_memory_cache(struct kvm_mmu_memory_cache *mc, int min); +int kvm_mmu_memory_cache_nr_free_objects(struct kvm_mmu_memory_cache *mc); +void kvm_mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc); +void *kvm_mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc); +#endif + bool kvm_make_vcpus_request_mask(struct kvm *kvm, unsigned int req, struct kvm_vcpu *except, unsigned long *vcpu_bitmap, cpumask_var_t tmp); diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h index 68e84cf42a3f94f2bcb6bf1b35d494f34ddeedad..a7580f69dda02e681228785c5c3cfa49b207d88c 100644 --- a/include/linux/kvm_types.h +++ b/include/linux/kvm_types.h @@ -20,6 +20,8 @@ enum kvm_mr_change; #include +#include + /* * Address types: * @@ -58,4 +60,21 @@ struct gfn_to_pfn_cache { bool dirty; }; +#ifdef KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE +/* + * Memory caches are used to preallocate memory ahead of various MMU flows, + * e.g. page fault handlers. Gracefully handling allocation failures deep in + * MMU flows is problematic, as is triggering reclaim, I/O, etc... while + * holding MMU locks. Note, these caches act more like prefetch buffers than + * classical caches, i.e. objects are not returned to the cache on being freed. + */ +struct kvm_mmu_memory_cache { + int nobjs; + gfp_t gfp_zero; + struct kmem_cache *kmem_cache; + void *objects[KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE]; +}; +#endif + + #endif /* __KVM_TYPES_H__ */ diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 57db125e580212acd3a02b3df3b6933c84a252d2..4d3376e20f5e64ac141538919f2c44607f07e4d7 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -276,7 +276,9 @@ enum { MLX5_MKEY_MASK_RW = 1ull << 20, MLX5_MKEY_MASK_A = 1ull << 21, MLX5_MKEY_MASK_SMALL_FENCE = 1ull << 23, - MLX5_MKEY_MASK_FREE = 1ull << 29, + MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE = 1ull << 25, + MLX5_MKEY_MASK_FREE = 1ull << 29, + MLX5_MKEY_MASK_RELAXED_ORDERING_READ = 1ull << 47, }; enum { @@ -1007,7 +1009,6 @@ enum { MLX5_MKEY_REMOTE_INVAL = 1 << 24, MLX5_MKEY_FLAG_SYNC_UMR = 1 << 29, MLX5_MKEY_BSF_EN = 1 << 30, - MLX5_MKEY_LEN64 = 1 << 31, }; struct mlx5_mkey_seg { @@ -1361,11 +1362,11 @@ enum mlx5_qcam_feature_groups { MLX5_ADDR_OF(device_event_cap, (mdev)->caps.hca_cur[MLX5_CAP_DEV_EVENT], cap) #define MLX5_CAP_DEV_VDPA_EMULATION(mdev, cap)\ - MLX5_GET(device_virtio_emulation_cap, \ + MLX5_GET(virtio_emulation_cap, \ (mdev)->caps.hca_cur[MLX5_CAP_VDPA_EMULATION], cap) #define MLX5_CAP64_DEV_VDPA_EMULATION(mdev, cap)\ - MLX5_GET64(device_virtio_emulation_cap, \ + MLX5_GET64(virtio_emulation_cap, \ (mdev)->caps.hca_cur[MLX5_CAP_VDPA_EMULATION], cap) #define MLX5_CAP_IPSEC(mdev, cap)\ diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index a0fcc4d13e93aaec54a1e01f4be267f4627ecfc0..c145de0473bc1643261205c36c69a0e2db7e2d6d 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -975,6 +975,7 @@ void mlx5_register_debugfs(void); void mlx5_unregister_debugfs(void); void mlx5_fill_page_array(struct mlx5_frag_buf *buf, __be64 *pas); +void mlx5_fill_page_frag_array_perm(struct mlx5_frag_buf *buf, __be64 *pas, u8 perm); void mlx5_fill_page_frag_array(struct mlx5_frag_buf *frag_buf, __be64 *pas); int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, unsigned int *irqn); @@ -1057,6 +1058,7 @@ enum { enum { MLX5_INTERFACE_PROTOCOL_IB = 0, MLX5_INTERFACE_PROTOCOL_ETH = 1, + MLX5_INTERFACE_PROTOCOL_VDPA = 2, }; struct mlx5_interface { diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 35e4dc66b3260a87bb73d1277c3bfcd2b89622e7..de1ffb4804d6be8beca264c9fb446b8181f9c69c 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -93,6 +93,7 @@ enum { enum { MLX5_OBJ_TYPE_GENEVE_TLV_OPT = 0x000b, + MLX5_OBJ_TYPE_VIRTIO_NET_Q = 0x000d, MLX5_OBJ_TYPE_MKEY = 0xff01, MLX5_OBJ_TYPE_QP = 0xff02, MLX5_OBJ_TYPE_PSV = 0xff03, @@ -985,17 +986,40 @@ struct mlx5_ifc_device_event_cap_bits { u8 user_unaffiliated_events[4][0x40]; }; -struct mlx5_ifc_device_virtio_emulation_cap_bits { - u8 reserved_at_0[0x20]; +struct mlx5_ifc_virtio_emulation_cap_bits { + u8 desc_tunnel_offload_type[0x1]; + u8 eth_frame_offload_type[0x1]; + u8 virtio_version_1_0[0x1]; + u8 device_features_bits_mask[0xd]; + u8 event_mode[0x8]; + u8 virtio_queue_type[0x8]; - u8 reserved_at_20[0x13]; + u8 max_tunnel_desc[0x10]; + u8 reserved_at_30[0x3]; u8 log_doorbell_stride[0x5]; u8 reserved_at_38[0x3]; u8 log_doorbell_bar_size[0x5]; u8 doorbell_bar_offset[0x40]; - u8 reserved_at_80[0x780]; + u8 max_emulated_devices[0x8]; + u8 max_num_virtio_queues[0x18]; + + u8 reserved_at_a0[0x60]; + + u8 umem_1_buffer_param_a[0x20]; + + u8 umem_1_buffer_param_b[0x20]; + + u8 umem_2_buffer_param_a[0x20]; + + u8 umem_2_buffer_param_b[0x20]; + + u8 umem_3_buffer_param_a[0x20]; + + u8 umem_3_buffer_param_b[0x20]; + + u8 reserved_at_1c0[0x640]; }; enum { @@ -1220,7 +1244,11 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 max_sgl_for_optimized_performance[0x8]; u8 log_max_cq_sz[0x8]; - u8 reserved_at_d0[0xb]; + u8 relaxed_ordering_write_umr[0x1]; + u8 relaxed_ordering_read_umr[0x1]; + u8 reserved_at_d2[0x7]; + u8 virtio_net_device_emualtion_manager[0x1]; + u8 virtio_blk_device_emualtion_manager[0x1]; u8 log_max_cq[0x5]; u8 log_max_eq_sz[0x8]; @@ -1396,7 +1424,10 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 bf[0x1]; u8 driver_version[0x1]; u8 pad_tx_eth_packet[0x1]; - u8 reserved_at_263[0x8]; + u8 reserved_at_263[0x3]; + u8 mkey_by_name[0x1]; + u8 reserved_at_267[0x4]; + u8 log_bf_reg_size[0x5]; u8 reserved_at_270[0x8]; @@ -2953,7 +2984,7 @@ union mlx5_ifc_hca_cap_union_bits { struct mlx5_ifc_fpga_cap_bits fpga_cap; struct mlx5_ifc_tls_cap_bits tls_cap; struct mlx5_ifc_device_mem_cap_bits device_mem_cap; - struct mlx5_ifc_device_virtio_emulation_cap_bits virtio_emulation_cap; + struct mlx5_ifc_virtio_emulation_cap_bits virtio_emulation_cap; u8 reserved_at_0[0x8000]; }; @@ -3302,15 +3333,18 @@ struct mlx5_ifc_scheduling_context_bits { }; struct mlx5_ifc_rqtc_bits { - u8 reserved_at_0[0xa0]; + u8 reserved_at_0[0xa0]; - u8 reserved_at_a0[0x10]; - u8 rqt_max_size[0x10]; + u8 reserved_at_a0[0x5]; + u8 list_q_type[0x3]; + u8 reserved_at_a8[0x8]; + u8 rqt_max_size[0x10]; - u8 reserved_at_c0[0x10]; - u8 rqt_actual_size[0x10]; + u8 rq_vhca_id_format[0x1]; + u8 reserved_at_c1[0xf]; + u8 rqt_actual_size[0x10]; - u8 reserved_at_e0[0x6a0]; + u8 reserved_at_e0[0x6a0]; struct mlx5_ifc_rq_num_bits rq_num[]; }; @@ -7092,7 +7126,7 @@ struct mlx5_ifc_destroy_mkey_out_bits { struct mlx5_ifc_destroy_mkey_in_bits { u8 opcode[0x10]; - u8 reserved_at_10[0x10]; + u8 uid[0x10]; u8 reserved_at_20[0x10]; u8 op_mod[0x10]; @@ -7723,8 +7757,10 @@ struct mlx5_ifc_create_qp_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x40]; + u8 reserved_at_40[0x8]; + u8 input_qpn[0x18]; + u8 reserved_at_60[0x20]; u8 opt_param_mask[0x20]; u8 ece[0x20]; @@ -7788,7 +7824,7 @@ struct mlx5_ifc_create_mkey_out_bits { struct mlx5_ifc_create_mkey_in_bits { u8 opcode[0x10]; - u8 reserved_at_10[0x10]; + u8 uid[0x10]; u8 reserved_at_20[0x10]; u8 op_mod[0x10]; @@ -10346,6 +10382,40 @@ struct mlx5_ifc_create_umem_in_bits { struct mlx5_ifc_umem_bits umem; }; +struct mlx5_ifc_create_umem_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x8]; + u8 umem_id[0x18]; + + u8 reserved_at_60[0x20]; +}; + +struct mlx5_ifc_destroy_umem_in_bits { + u8 opcode[0x10]; + u8 uid[0x10]; + + u8 reserved_at_20[0x10]; + u8 op_mod[0x10]; + + u8 reserved_at_40[0x8]; + u8 umem_id[0x18]; + + u8 reserved_at_60[0x20]; +}; + +struct mlx5_ifc_destroy_umem_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x40]; +}; + struct mlx5_ifc_create_uctx_in_bits { u8 opcode[0x10]; u8 reserved_at_10[0x10]; @@ -10358,6 +10428,18 @@ struct mlx5_ifc_create_uctx_in_bits { struct mlx5_ifc_uctx_bits uctx; }; +struct mlx5_ifc_create_uctx_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x10]; + u8 uid[0x10]; + + u8 reserved_at_60[0x20]; +}; + struct mlx5_ifc_destroy_uctx_in_bits { u8 opcode[0x10]; u8 reserved_at_10[0x10]; @@ -10371,6 +10453,15 @@ struct mlx5_ifc_destroy_uctx_in_bits { u8 reserved_at_60[0x20]; }; +struct mlx5_ifc_destroy_uctx_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x40]; +}; + struct mlx5_ifc_create_sw_icm_in_bits { struct mlx5_ifc_general_obj_in_cmd_hdr_bits hdr; struct mlx5_ifc_sw_icm_bits sw_icm; @@ -10687,4 +10778,10 @@ struct mlx5_ifc_tls_progress_params_bits { u8 hw_offset_record_number[0x18]; }; +enum { + MLX5_MTT_PERM_READ = 1 << 0, + MLX5_MTT_PERM_WRITE = 1 << 1, + MLX5_MTT_PERM_RW = MLX5_MTT_PERM_READ | MLX5_MTT_PERM_WRITE, +}; + #endif /* MLX5_IFC_H */ diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 3d6a246977615350d732d2ff1e89be80aced1dca..2e1193a3fb5f064bca42c9cf44f6b0ef74e01bc9 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -44,6 +44,13 @@ enum qcom_scm_sec_dev_id { QCOM_SCM_ICE_DEV_ID = 20, }; +enum qcom_scm_ice_cipher { + QCOM_SCM_ICE_CIPHER_AES_128_XTS = 0, + QCOM_SCM_ICE_CIPHER_AES_128_CBC = 1, + QCOM_SCM_ICE_CIPHER_AES_256_XTS = 3, + QCOM_SCM_ICE_CIPHER_AES_256_CBC = 4, +}; + #define QCOM_SCM_VMID_HLOS 0x3 #define QCOM_SCM_VMID_MSS_MSA 0xF #define QCOM_SCM_VMID_WLAN 0x18 @@ -88,6 +95,12 @@ extern int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, extern int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, u32 size); +extern bool qcom_scm_ice_available(void); +extern int qcom_scm_ice_invalidate_key(u32 index); +extern int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, + enum qcom_scm_ice_cipher cipher, + u32 data_unit_size); + extern bool qcom_scm_hdcp_available(void); extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); @@ -138,6 +151,12 @@ static inline int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, static inline int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, u32 size) { return -ENODEV; } +static inline bool qcom_scm_ice_available(void) { return false; } +static inline int qcom_scm_ice_invalidate_key(u32 index) { return -ENODEV; } +static inline int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, + enum qcom_scm_ice_cipher cipher, + u32 data_unit_size) { return -ENODEV; } + static inline bool qcom_scm_hdcp_available(void) { return false; } static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { return -ENODEV; } diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 6545f8cfc8fa23709c026c523089b09a4dae5efe..2b70f736b091dde3bf1898d96a16e8ca6d90f752 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -155,6 +155,8 @@ extern int early_serial_setup(struct uart_port *port); extern int early_serial8250_setup(struct earlycon_device *device, const char *options); +extern void serial8250_update_uartclk(struct uart_port *port, + unsigned int uartclk); extern void serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old); extern void serial8250_do_set_ldisc(struct uart_port *port, diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 791f4844efeb9d8d88cd71b74670b96b816c722d..01fc4d9c9c5406c11988fd21376f7730472225d5 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -30,6 +29,7 @@ struct uart_port; struct serial_struct; struct device; +struct gpio_desc; /* * This structure describes all the operations that can be done on the diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 216185bb3014a510122aea63a99edf877fb36890..42ef807e5d84eb6dc2457a9c13f15342ff18f4ed 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -37,18 +37,6 @@ struct thermal_cooling_device; struct thermal_instance; struct thermal_attr; -enum thermal_device_mode { - THERMAL_DEVICE_DISABLED = 0, - THERMAL_DEVICE_ENABLED, -}; - -enum thermal_trip_type { - THERMAL_TRIP_ACTIVE = 0, - THERMAL_TRIP_PASSIVE, - THERMAL_TRIP_HOT, - THERMAL_TRIP_CRITICAL, -}; - enum thermal_trend { THERMAL_TREND_STABLE, /* temperature is stable */ THERMAL_TREND_RAISING, /* temperature is raising */ @@ -76,9 +64,7 @@ struct thermal_zone_device_ops { struct thermal_cooling_device *); int (*get_temp) (struct thermal_zone_device *, int *); int (*set_trips) (struct thermal_zone_device *, int, int); - int (*get_mode) (struct thermal_zone_device *, - enum thermal_device_mode *); - int (*set_mode) (struct thermal_zone_device *, + int (*change_mode) (struct thermal_zone_device *, enum thermal_device_mode); int (*get_trip_type) (struct thermal_zone_device *, int, enum thermal_trip_type *); @@ -128,6 +114,7 @@ struct thermal_cooling_device { * @trip_temp_attrs: attributes for trip points for sysfs: trip temperature * @trip_type_attrs: attributes for trip points for sysfs: trip type * @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis + * @mode: current mode of this thermal zone * @devdata: private pointer for device private data * @trips: number of trip points the thermal zone supports * @trips_disabled; bitmap for disabled trips @@ -170,6 +157,7 @@ struct thermal_zone_device { struct thermal_attr *trip_temp_attrs; struct thermal_attr *trip_type_attrs; struct thermal_attr *trip_hyst_attrs; + enum thermal_device_mode mode; void *devdata; int trips; unsigned long trips_disabled; /* bitmap for disabled trips */ @@ -303,11 +291,6 @@ struct thermal_zone_params { int offset; }; -struct thermal_genl_event { - u32 orig; - enum events event; -}; - /** * struct thermal_zone_of_device_ops - scallbacks for handling DT based zones * @@ -416,6 +399,8 @@ int thermal_zone_get_offset(struct thermal_zone_device *tz); void thermal_cdev_update(struct thermal_cooling_device *); void thermal_notify_framework(struct thermal_zone_device *, int); +int thermal_zone_device_enable(struct thermal_zone_device *tz); +int thermal_zone_device_disable(struct thermal_zone_device *tz); #else static inline struct thermal_zone_device *thermal_zone_device_register( const char *type, int trips, int mask, void *devdata, @@ -463,6 +448,12 @@ static inline void thermal_cdev_update(struct thermal_cooling_device *cdev) static inline void thermal_notify_framework(struct thermal_zone_device *tz, int trip) { } + +static inline int thermal_zone_device_enable(struct thermal_zone_device *tz) +{ return -ENODEV; } + +static inline int thermal_zone_device_disable(struct thermal_zone_device *tz) +{ return -ENODEV; } #endif /* CONFIG_THERMAL */ #endif /* __THERMAL_H__ */ diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index abf5bccf906a59140ec6500f805b3db70aac73a3..349e39c3ab604d3b66af1997251df4429dc60a47 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -74,8 +74,6 @@ int con_set_default_unimap(struct vc_data *vc); void con_free_unimap(struct vc_data *vc); int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc); -#define vc_translate(vc, c) ((vc)->vc_translate[(c) | \ - ((vc)->vc_toggle_meta ? 0x80 : 0)]) #else static inline int con_set_trans_old(unsigned char __user *table) { @@ -124,7 +122,6 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc) return 0; } -#define vc_translate(vc, c) (c) #endif /* vt.c */ diff --git a/include/net/sock.h b/include/net/sock.h index 497c64ff8bdaf2b1ac3da604df26034f7703a614..064637d1ddf60e8ebc950f4aa14bda06da0d57f3 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2696,6 +2696,7 @@ void sock_no_linger(struct sock *sk); void sock_set_keepalive(struct sock *sk); void sock_set_priority(struct sock *sk, u32 priority); void sock_set_rcvbuf(struct sock *sk, int val); +void sock_set_mark(struct sock *sk, u32 val); void sock_set_reuseaddr(struct sock *sk); void sock_set_reuseport(struct sock *sk); void sock_set_sndtimeo(struct sock *sk, s64 secs); diff --git a/include/rdma/ib.h b/include/rdma/ib.h index fe2fc9e91588de93a1c58b55194b3d974a09d9da..83139b9ce409c71c4fcf5b4a2fae32f5693fbf77 100644 --- a/include/rdma/ib.h +++ b/include/rdma/ib.h @@ -1,36 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2010 Intel Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ -#if !defined(_RDMA_IB_H) +#ifndef _RDMA_IB_H #define _RDMA_IB_H #include diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h index 2734c895c1bf465ec7f1869511c341b0c4b215a5..b0e636ac6690099f1c21c17707748f7baae2acb8 100644 --- a/include/rdma/ib_addr.h +++ b/include/rdma/ib_addr.h @@ -1,37 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2005 Voltaire Inc. All rights reserved. * Copyright (c) 2005 Intel Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ -#if !defined(IB_ADDR_H) +#ifndef IB_ADDR_H #define IB_ADDR_H #include diff --git a/include/rdma/ib_cache.h b/include/rdma/ib_cache.h index e06d13388ae716ddd65640c26dd64599ed71ed81..66a8f369a2fa52892118897bbf92a8187d7e4da9 100644 --- a/include/rdma/ib_cache.h +++ b/include/rdma/ib_cache.h @@ -1,35 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2004 Topspin Communications. All rights reserved. * Copyright (c) 2005 Intel Corporation. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #ifndef _IB_CACHE_H diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h index 0f1ea5f2d01cd6adfa090e80ceebf32e04c0a40c..382427add67743e9331c7803ea793bb87e55714b 100644 --- a/include/rdma/ib_cm.h +++ b/include/rdma/ib_cm.h @@ -6,6 +6,7 @@ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2019, Mellanox Technologies inc. All rights reserved. */ + #ifndef IB_CM_H #define IB_CM_H diff --git a/include/rdma/ib_hdrs.h b/include/rdma/ib_hdrs.h index 9a90bd031e8c94a4757e3a875261f90acb9f2061..57c1ac881d08fbff3bd0063adf99a77b0716a886 100644 --- a/include/rdma/ib_hdrs.h +++ b/include/rdma/ib_hdrs.h @@ -1,48 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright(c) 2016 - 2018 Intel Corporation. - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * BSD LICENSE - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * */ #ifndef IB_HDRS_H diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h index 8c093fc1bb9f3d4d81b33037d4104f2355748e2f..8dfb1ddf345a127b92c0dafe98fcc47adabebcb0 100644 --- a/include/rdma/ib_mad.h +++ b/include/rdma/ib_mad.h @@ -1,40 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved. * Copyright (c) 2004 Infinicon Corporation. All rights reserved. * Copyright (c) 2004 Intel Corporation. All rights reserved. * Copyright (c) 2004 Topspin Corporation. All rights reserved. * Copyright (c) 2004-2006 Voltaire Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ -#if !defined(IB_MAD_H) +#ifndef IB_MAD_H #define IB_MAD_H #include diff --git a/include/rdma/ib_marshall.h b/include/rdma/ib_marshall.h index 8ebf84ae9ed161a73d061515a80b1f7d198ba48a..1838869aad28a7610b8626145190a764cd944b8e 100644 --- a/include/rdma/ib_marshall.h +++ b/include/rdma/ib_marshall.h @@ -1,36 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2005-2006 Intel Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ -#if !defined(IB_USER_MARSHALL_H) +#ifndef IB_USER_MARSHALL_H #define IB_USER_MARSHALL_H #include diff --git a/include/rdma/ib_pack.h b/include/rdma/ib_pack.h index 7ea1382ad0e59b8280834b77221a089e88e0e433..a9162f25beaf531184fe36e431989e3ece5ebb41 100644 --- a/include/rdma/ib_pack.h +++ b/include/rdma/ib_pack.h @@ -1,33 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2004 Topspin Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #ifndef IB_PACK_H diff --git a/include/rdma/ib_pma.h b/include/rdma/ib_pma.h index 2f8a65c1fca7b77bc03c20e3b886036448645ad1..44c61820378556b8dc2c7b942d69cf28e68fe94b 100644 --- a/include/rdma/ib_pma.h +++ b/include/rdma/ib_pma.h @@ -1,38 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation. * All rights reserved. * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ -#if !defined(IB_PMA_H) +#ifndef IB_PMA_H #define IB_PMA_H #include diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h index 19520979b84c21fffcff25865fe4c7f002604a80..693285e76f13fa59cf12b11f99b3a857a0a7e21d 100644 --- a/include/rdma/ib_sa.h +++ b/include/rdma/ib_sa.h @@ -1,35 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2004 Topspin Communications. All rights reserved. * Copyright (c) 2005 Voltaire, Inc. All rights reserved. * Copyright (c) 2006 Intel Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #ifndef IB_SA_H diff --git a/include/rdma/ib_smi.h b/include/rdma/ib_smi.h index 7be0028f155cefbbce9239fecb3997ee842aca9e..fdb8633cbaff6630829ae25cab852ef23477fd4e 100644 --- a/include/rdma/ib_smi.h +++ b/include/rdma/ib_smi.h @@ -1,40 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved. * Copyright (c) 2004 Infinicon Corporation. All rights reserved. * Copyright (c) 2004 Intel Corporation. All rights reserved. * Copyright (c) 2004 Topspin Corporation. All rights reserved. * Copyright (c) 2004 Voltaire Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ -#if !defined(IB_SMI_H) +#ifndef IB_SMI_H #define IB_SMI_H #include diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h index e3518fd6b95b14bd63b288dc1657d75435e15b29..71f573a418bf06ddef0bf5468dc680239c0cf3ff 100644 --- a/include/rdma/ib_umem.h +++ b/include/rdma/ib_umem.h @@ -1,33 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2007 Cisco Systems. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #ifndef IB_UMEM_H diff --git a/include/rdma/ib_umem_odp.h b/include/rdma/ib_umem_odp.h index 64314ff76612961eb157ff2e2fc1bcace744b252..d16d2c17e7337b0dcd9a724bb775a256e3c73903 100644 --- a/include/rdma/ib_umem_odp.h +++ b/include/rdma/ib_umem_odp.h @@ -1,33 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2014 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #ifndef IB_UMEM_ODP_H diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index ef2f3986c4933434d27b482e20747c2e8c491456..c0b2fa7e9b959f4faad51c33bf18726e8e39f836 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved. * Copyright (c) 2004 Infinicon Corporation. All rights reserved. @@ -6,37 +7,9 @@ * Copyright (c) 2004 Voltaire Corporation. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2005, 2006, 2007 Cisco Systems. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ -#if !defined(IB_VERBS_H) +#ifndef IB_VERBS_H #define IB_VERBS_H #include @@ -75,6 +48,7 @@ struct ib_umem_odp; struct ib_uqp_object; struct ib_usrq_object; struct ib_uwq_object; +struct rdma_cm_id; extern struct workqueue_struct *ib_wq; extern struct workqueue_struct *ib_comp_wq; @@ -1566,9 +1540,8 @@ struct ib_xrcd { struct ib_device *device; atomic_t usecnt; /* count all exposed resources */ struct inode *inode; - - struct mutex tgt_qp_mutex; - struct list_head tgt_qp_list; + struct rw_semaphore tgt_qps_rwsem; + struct xarray tgt_qps; }; struct ib_ah { @@ -2270,6 +2243,7 @@ struct rdma_netdev_alloc_params { struct ib_odp_counters { atomic64_t faults; atomic64_t invalidations; + atomic64_t prefetch; }; struct ib_counters { @@ -2476,7 +2450,7 @@ struct ib_device_ops { struct ib_pd *pd, struct ib_udata *udata); int (*dereg_mr)(struct ib_mr *mr, struct ib_udata *udata); struct ib_mr *(*alloc_mr)(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata); + u32 max_num_sg); struct ib_mr *(*alloc_mr_integrity)(struct ib_pd *pd, u32 max_num_data_sg, u32 max_num_meta_sg); @@ -2493,9 +2467,8 @@ struct ib_device_ops { int (*dealloc_mw)(struct ib_mw *mw); int (*attach_mcast)(struct ib_qp *qp, union ib_gid *gid, u16 lid); int (*detach_mcast)(struct ib_qp *qp, union ib_gid *gid, u16 lid); - struct ib_xrcd *(*alloc_xrcd)(struct ib_device *device, - struct ib_udata *udata); - int (*dealloc_xrcd)(struct ib_xrcd *xrcd, struct ib_udata *udata); + int (*alloc_xrcd)(struct ib_xrcd *xrcd, struct ib_udata *udata); + void (*dealloc_xrcd)(struct ib_xrcd *xrcd, struct ib_udata *udata); struct ib_flow *(*create_flow)(struct ib_qp *qp, struct ib_flow_attr *flow_attr, int domain, struct ib_udata *udata); @@ -2539,9 +2512,9 @@ struct ib_device_ops { struct ib_mr *(*reg_dm_mr)(struct ib_pd *pd, struct ib_dm *dm, struct ib_dm_mr_attr *attr, struct uverbs_attr_bundle *attrs); - struct ib_counters *(*create_counters)( - struct ib_device *device, struct uverbs_attr_bundle *attrs); - int (*destroy_counters)(struct ib_counters *counters); + int (*create_counters)(struct ib_counters *counters, + struct uverbs_attr_bundle *attrs); + void (*destroy_counters)(struct ib_counters *counters); int (*read_counters)(struct ib_counters *counters, struct ib_counters_read_attr *counters_read_attr, struct uverbs_attr_bundle *attrs); @@ -2581,8 +2554,13 @@ struct ib_device_ops { /** * Allows rdma drivers to add their own restrack attributes. */ - int (*fill_res_entry)(struct sk_buff *msg, - struct rdma_restrack_entry *entry); + int (*fill_res_mr_entry)(struct sk_buff *msg, struct ib_mr *ibmr); + int (*fill_res_mr_entry_raw)(struct sk_buff *msg, struct ib_mr *ibmr); + int (*fill_res_cq_entry)(struct sk_buff *msg, struct ib_cq *ibcq); + int (*fill_res_cq_entry_raw)(struct sk_buff *msg, struct ib_cq *ibcq); + int (*fill_res_qp_entry)(struct sk_buff *msg, struct ib_qp *ibqp); + int (*fill_res_qp_entry_raw)(struct sk_buff *msg, struct ib_qp *ibqp); + int (*fill_res_cm_id_entry)(struct sk_buff *msg, struct rdma_cm_id *id); /* Device lifecycle callbacks */ /* @@ -2637,14 +2615,19 @@ struct ib_device_ops { * Allows rdma drivers to add their own restrack attributes * dumped via 'rdma stat' iproute2 command. */ - int (*fill_stat_entry)(struct sk_buff *msg, - struct rdma_restrack_entry *entry); + int (*fill_stat_mr_entry)(struct sk_buff *msg, struct ib_mr *ibmr); + + /* query driver for its ucontext properties */ + int (*query_ucontext)(struct ib_ucontext *context, + struct uverbs_attr_bundle *attrs); DECLARE_RDMA_OBJ_SIZE(ib_ah); + DECLARE_RDMA_OBJ_SIZE(ib_counters); DECLARE_RDMA_OBJ_SIZE(ib_cq); DECLARE_RDMA_OBJ_SIZE(ib_pd); DECLARE_RDMA_OBJ_SIZE(ib_srq); DECLARE_RDMA_OBJ_SIZE(ib_ucontext); + DECLARE_RDMA_OBJ_SIZE(ib_xrcd); }; struct ib_core_device { @@ -4263,14 +4246,8 @@ static inline int ib_dereg_mr(struct ib_mr *mr) return ib_dereg_mr_user(mr, NULL); } -struct ib_mr *ib_alloc_mr_user(struct ib_pd *pd, enum ib_mr_type mr_type, - u32 max_num_sg, struct ib_udata *udata); - -static inline struct ib_mr *ib_alloc_mr(struct ib_pd *pd, - enum ib_mr_type mr_type, u32 max_num_sg) -{ - return ib_alloc_mr_user(pd, mr_type, max_num_sg, NULL); -} +struct ib_mr *ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, + u32 max_num_sg); struct ib_mr *ib_alloc_mr_integrity(struct ib_pd *pd, u32 max_num_data_sg, @@ -4321,21 +4298,9 @@ int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid); */ int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid); -/** - * ib_alloc_xrcd - Allocates an XRC domain. - * @device: The device on which to allocate the XRC domain. - * @caller: Module name for kernel consumers - */ -struct ib_xrcd *__ib_alloc_xrcd(struct ib_device *device, const char *caller); -#define ib_alloc_xrcd(device) \ - __ib_alloc_xrcd((device), KBUILD_MODNAME) - -/** - * ib_dealloc_xrcd - Deallocates an XRC domain. - * @xrcd: The XRC domain to deallocate. - * @udata: Valid user data or NULL for kernel object - */ -int ib_dealloc_xrcd(struct ib_xrcd *xrcd, struct ib_udata *udata); +struct ib_xrcd *ib_alloc_xrcd_user(struct ib_device *device, + struct inode *inode, struct ib_udata *udata); +int ib_dealloc_xrcd_user(struct ib_xrcd *xrcd, struct ib_udata *udata); static inline int ib_check_mr_access(int flags) { @@ -4417,9 +4382,6 @@ struct ib_wq *ib_create_wq(struct ib_pd *pd, int ib_destroy_wq(struct ib_wq *wq, struct ib_udata *udata); int ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *attr, u32 wq_attr_mask); -struct ib_rwq_ind_table *ib_create_rwq_ind_table(struct ib_device *device, - struct ib_rwq_ind_table_init_attr* - wq_ind_table_init_attr); int ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *wq_ind_table); int ib_map_mr_sg(struct ib_mr *mr, struct scatterlist *sg, int sg_nents, diff --git a/include/rdma/iw_cm.h b/include/rdma/iw_cm.h index 5aa8a9c76aa0de04b50576180f27c87dfd6b6ac6..91975400e1b35d015c0f26ab6690bfa7cc4449c5 100644 --- a/include/rdma/iw_cm.h +++ b/include/rdma/iw_cm.h @@ -1,35 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2005 Network Appliance, Inc. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ + #ifndef IW_CM_H #define IW_CM_H diff --git a/include/rdma/iw_portmap.h b/include/rdma/iw_portmap.h index c89535047c42cd8b363786ae6a65bf37c771d79d..6dbc1a2359746cd4b61e5a33fb9119c8e4967c3c 100644 --- a/include/rdma/iw_portmap.h +++ b/include/rdma/iw_portmap.h @@ -1,35 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2014 Intel Corporation. All rights reserved. * Copyright (c) 2014 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ + #ifndef _IW_PORTMAP_H #define _IW_PORTMAP_H diff --git a/include/rdma/opa_addr.h b/include/rdma/opa_addr.h index 66d4393d339ccedfd2eea1c416d677b126631bd3..c6bfa2640bacc2a7c61303ce556adf5b9629f5ec 100644 --- a/include/rdma/opa_addr.h +++ b/include/rdma/opa_addr.h @@ -1,48 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright(c) 2017 Intel Corporation. - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * BSD LICENSE - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * */ #ifndef OPA_ADDR_H diff --git a/include/rdma/opa_port_info.h b/include/rdma/opa_port_info.h index 0d9e6d74c38577975be12ebfca1ebb5a75399760..73bcac90a048675a2429e3158dda711e1abe7ab0 100644 --- a/include/rdma/opa_port_info.h +++ b/include/rdma/opa_port_info.h @@ -1,36 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2014-2020 Intel Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ -#if !defined(OPA_PORT_INFO_H) +#ifndef OPA_PORT_INFO_H #define OPA_PORT_INFO_H #include diff --git a/include/rdma/opa_smi.h b/include/rdma/opa_smi.h index c7b2ef12792d1201316b99a3b0dd23c5eed8e775..a9f1b5700e98b3b541acdeb2f0b81663f2d1e320 100644 --- a/include/rdma/opa_smi.h +++ b/include/rdma/opa_smi.h @@ -1,36 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2014 Intel Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ -#if !defined(OPA_SMI_H) +#ifndef OPA_SMI_H #define OPA_SMI_H #include diff --git a/include/rdma/opa_vnic.h b/include/rdma/opa_vnic.h index 6f244e759b4f0e3bb19fe9b61affb6d1b5d0fd7a..cbe3c2811455014eaf9e8e6dc3d0f1e397c2059c 100644 --- a/include/rdma/opa_vnic.h +++ b/include/rdma/opa_vnic.h @@ -1,52 +1,11 @@ -#ifndef _OPA_VNIC_H -#define _OPA_VNIC_H +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright(c) 2017 - 2020 Intel Corporation. - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * BSD LICENSE - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * */ +#ifndef _OPA_VNIC_H +#define _OPA_VNIC_H + /* * This file contains Intel Omni-Path (OPA) Virtual Network Interface * Controller (VNIC) specific declarations. diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h index 939d7abe026f09ef7b22867f8abf8b321320940d..cf5da2ae49bfc204e0f756894aed215ddb679eec 100644 --- a/include/rdma/rdma_cm.h +++ b/include/rdma/rdma_cm.h @@ -1,37 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2005 Voltaire Inc. All rights reserved. * Copyright (c) 2005 Intel Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ -#if !defined(RDMA_CM_H) +#ifndef RDMA_CM_H #define RDMA_CM_H #include diff --git a/include/rdma/rdma_cm_ib.h b/include/rdma/rdma_cm_ib.h index 6a69d71a21a51cd41e06f9cd2fe013340c1d4b98..8354e7de7815d77577b3136e28f670e504a2b1da 100644 --- a/include/rdma/rdma_cm_ib.h +++ b/include/rdma/rdma_cm_ib.h @@ -1,36 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2006 Intel Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ -#if !defined(RDMA_CM_IB_H) +#ifndef RDMA_CM_IB_H #define RDMA_CM_IB_H #include diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h index ab22759de7ea087adff0b5b570383f61eccd4133..2758d9df71ee9187ea6019855b2cfd9c929c91f1 100644 --- a/include/rdma/rdma_netlink.h +++ b/include/rdma/rdma_netlink.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 */ + #ifndef _RDMA_NETLINK_H #define _RDMA_NETLINK_H - #include #include diff --git a/include/rdma/rdma_vt.h b/include/rdma/rdma_vt.h index ac5a9430abb6c14e658ecb25ae31f53906eebcb1..9fd217b249167e03838bf0cf0057a45223bb8d4f 100644 --- a/include/rdma/rdma_vt.h +++ b/include/rdma/rdma_vt.h @@ -1,53 +1,11 @@ -#ifndef DEF_RDMA_VT_H -#define DEF_RDMA_VT_H - +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright(c) 2016 - 2019 Intel Corporation. - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * BSD LICENSE - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * */ +#ifndef DEF_RDMA_VT_H +#define DEF_RDMA_VT_H + /* * Structure that low level drivers will populate in order to register with the * rdmavt layer. diff --git a/include/rdma/rdmavt_cq.h b/include/rdma/rdmavt_cq.h index 574eb7278f468f797a9dbe10e14a2492c6d88ac7..1fe2bb5a63b03b61fc8b997937b2e2903d13516d 100644 --- a/include/rdma/rdmavt_cq.h +++ b/include/rdma/rdmavt_cq.h @@ -1,56 +1,11 @@ -#ifndef DEF_RDMAVT_INCCQ_H -#define DEF_RDMAVT_INCCQ_H - +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * * Copyright(c) 2016 - 2018 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * */ +#ifndef DEF_RDMAVT_INCCQ_H +#define DEF_RDMAVT_INCCQ_H + #include #include #include diff --git a/include/rdma/rdmavt_mr.h b/include/rdma/rdmavt_mr.h index ce6c888f7fe754d76ca3518d21b1fc7f20e8d8da..c3367e9833efd118a66659579615e4e0cddf871b 100644 --- a/include/rdma/rdmavt_mr.h +++ b/include/rdma/rdmavt_mr.h @@ -1,53 +1,11 @@ -#ifndef DEF_RDMAVT_INCMR_H -#define DEF_RDMAVT_INCMR_H - +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright(c) 2016 Intel Corporation. - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * BSD LICENSE - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * */ +#ifndef DEF_RDMAVT_INCMR_H +#define DEF_RDMAVT_INCMR_H + /* * For Memory Regions. This stuff should probably be moved into rdmavt/mr.h once * drivers no longer need access to the MR directly. diff --git a/include/rdma/rdmavt_qp.h b/include/rdma/rdmavt_qp.h index 2f1fc23602cb6e0116dfa8414b72c00026f00a1a..8275954f5ce6b69014691afbabedeada0a327984 100644 --- a/include/rdma/rdmavt_qp.h +++ b/include/rdma/rdmavt_qp.h @@ -1,53 +1,11 @@ -#ifndef DEF_RDMAVT_INCQP_H -#define DEF_RDMAVT_INCQP_H - +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright(c) 2016 - 2020 Intel Corporation. - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * BSD LICENSE - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * */ +#ifndef DEF_RDMAVT_INCQP_H +#define DEF_RDMAVT_INCQP_H + #include #include #include diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h index 86de10ea30afb150cd2a81f387442e568bf370e2..b00270c72740f5f4c91fb20ce69fa0382a35a9f1 100644 --- a/include/rdma/uverbs_ioctl.h +++ b/include/rdma/uverbs_ioctl.h @@ -1,33 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #ifndef _UVERBS_IOCTL_ @@ -652,6 +625,7 @@ struct uverbs_attr_bundle { struct ib_udata ucore; struct ib_uverbs_file *ufile; struct ib_ucontext *context; + struct ib_uobject *uobject; DECLARE_BITMAP(attr_present, UVERBS_API_ATTR_BKEY_LEN); struct uverbs_attr attrs[]; }; diff --git a/include/rdma/uverbs_named_ioctl.h b/include/rdma/uverbs_named_ioctl.h index 6ae6cf8e4c2e13b73d87e16f27c90fbd80c3d5a7..f04f5126f61ebc498c8f4728f58799503aec23dc 100644 --- a/include/rdma/uverbs_named_ioctl.h +++ b/include/rdma/uverbs_named_ioctl.h @@ -1,33 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #ifndef _UVERBS_NAMED_IOCTL_ diff --git a/include/rdma/uverbs_std_types.h b/include/rdma/uverbs_std_types.h index bf0392ae15ebcfc19c4feab670d91cec24463c85..fe05121169589f3cdf6622dfe24e461119f73614 100644 --- a/include/rdma/uverbs_std_types.h +++ b/include/rdma/uverbs_std_types.h @@ -1,33 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #ifndef _UVERBS_STD_TYPES__ @@ -110,6 +83,20 @@ static inline void uobj_alloc_abort(struct ib_uobject *uobj, rdma_alloc_abort_uobject(uobj, attrs, false); } +static inline void uobj_finalize_uobj_create(struct ib_uobject *uobj, + struct uverbs_attr_bundle *attrs) +{ + /* + * Tell the core code that the write() handler has completed + * initializing the object and that the core should commit or + * abort this object based upon the return code from the write() + * method. Similar to what uverbs_finalize_uobj_create() does for + * ioctl() + */ + WARN_ON(attrs->uobject); + attrs->uobject = uobj; +} + static inline struct ib_uobject * __uobj_alloc(const struct uverbs_api_object *obj, struct uverbs_attr_bundle *attrs, struct ib_device **ib_dev) diff --git a/include/rdma/uverbs_types.h b/include/rdma/uverbs_types.h index c15b298aa62f11685201ea15d1685507b366a080..06db27e35f405aefbd624a00aede507a3f2c74a7 100644 --- a/include/rdma/uverbs_types.h +++ b/include/rdma/uverbs_types.h @@ -1,33 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #ifndef _UVERBS_TYPES_ diff --git a/include/scsi/fc/fc_ms.h b/include/scsi/fc/fc_ms.h index 800d53dc94705eee89833e7db341a179490e14a5..9e273fed0a85fccfefac6bb8460d0b76396763ba 100644 --- a/include/scsi/fc/fc_ms.h +++ b/include/scsi/fc/fc_ms.h @@ -63,8 +63,8 @@ enum fc_fdmi_hba_attr_type { * HBA Attribute Length */ #define FC_FDMI_HBA_ATTR_NODENAME_LEN 8 -#define FC_FDMI_HBA_ATTR_MANUFACTURER_LEN 64 -#define FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN 64 +#define FC_FDMI_HBA_ATTR_MANUFACTURER_LEN 80 +#define FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN 80 #define FC_FDMI_HBA_ATTR_MODEL_LEN 256 #define FC_FDMI_HBA_ATTR_MODELDESCR_LEN 256 #define FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN 256 diff --git a/include/scsi/scsi_tcq.h b/include/scsi/scsi_tcq.h index 6053d46e794e1319c9c940ef145f341e93cc59da..ea7848e74d257e21764c74fe866a5c94a2149a9d 100644 --- a/include/scsi/scsi_tcq.h +++ b/include/scsi/scsi_tcq.h @@ -34,7 +34,7 @@ static inline struct scsi_cmnd *scsi_host_find_tag(struct Scsi_Host *shost, blk_mq_unique_tag_to_tag(tag)); } - if (!req) + if (!req || !blk_mq_request_started(req)) return NULL; return blk_mq_rq_to_pdu(req); } diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index bdcb6d69d1549ae0359cd1f100ae1ba1aa52f733..8a26a2ffa95234e9ce1a31492af236f774f71244 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -57,7 +57,7 @@ struct iscsi_bus_flash_conn; * When not offloading the data path, this is called * from the scsi work queue without the session lock. * @xmit_task Requests LLD to transfer cmd task. Returns 0 or the - * the number of bytes transferred on success, and -Exyz + * number of bytes transferred on success, and -Exyz * value on error. When offloading the data path, this * is called from queuecommand with the session lock, or * from the iscsi_conn_send_pdu context with the session diff --git a/include/sound/control.h b/include/sound/control.h index aeaed2a05baeeb3dc28c60c7d67a7238fdf87ad5..e128cff10dfaf3f60c48a5f9fe48441b9ca37c2d 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -188,20 +188,21 @@ int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels, */ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, const unsigned int *tlv); -int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, - unsigned int flags); -/* optional flags for slave */ -#define SND_CTL_SLAVE_NEED_UPDATE (1 << 0) +int _snd_ctl_add_follower(struct snd_kcontrol *master, + struct snd_kcontrol *follower, + unsigned int flags); +/* optional flags for follower */ +#define SND_CTL_FOLLOWER_NEED_UPDATE (1 << 0) /** - * snd_ctl_add_slave - Add a virtual slave control + * snd_ctl_add_follower - Add a virtual follower control * @master: vmaster element - * @slave: slave element to add + * @follower: follower element to add * - * Add a virtual slave control to the given master element created via + * Add a virtual follower control to the given master element created via * snd_ctl_create_virtual_master() beforehand. * - * All slaves must be the same type (returning the same information + * All followers must be the same type (returning the same information * via info callback). The function doesn't check it, so it's your * responsibility. * @@ -213,18 +214,18 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, * Return: Zero if successful or a negative error code. */ static inline int -snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) +snd_ctl_add_follower(struct snd_kcontrol *master, struct snd_kcontrol *follower) { - return _snd_ctl_add_slave(master, slave, 0); + return _snd_ctl_add_follower(master, follower, 0); } /** - * snd_ctl_add_slave_uncached - Add a virtual slave control + * snd_ctl_add_follower_uncached - Add a virtual follower control * @master: vmaster element - * @slave: slave element to add + * @follower: follower element to add * - * Add a virtual slave control to the given master. - * Unlike snd_ctl_add_slave(), the element added via this function + * Add a virtual follower control to the given master. + * Unlike snd_ctl_add_follower(), the element added via this function * is supposed to have volatile values, and get callback is called * at each time queried from the master. * @@ -235,10 +236,10 @@ snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) * Return: Zero if successful or a negative error code. */ static inline int -snd_ctl_add_slave_uncached(struct snd_kcontrol *master, - struct snd_kcontrol *slave) +snd_ctl_add_follower_uncached(struct snd_kcontrol *master, + struct snd_kcontrol *follower) { - return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE); + return _snd_ctl_add_follower(master, follower, SND_CTL_FOLLOWER_NEED_UPDATE); } int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl, @@ -246,11 +247,11 @@ int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl, void *private_data); void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only); #define snd_ctl_sync_vmaster_hook(kctl) snd_ctl_sync_vmaster(kctl, true) -int snd_ctl_apply_vmaster_slaves(struct snd_kcontrol *kctl, - int (*func)(struct snd_kcontrol *vslave, - struct snd_kcontrol *slave, - void *arg), - void *arg); +int snd_ctl_apply_vmaster_followers(struct snd_kcontrol *kctl, + int (*func)(struct snd_kcontrol *vfollower, + struct snd_kcontrol *follower, + void *arg), + void *arg); /* * Helper functions for jack-detection controls diff --git a/include/sound/gus.h b/include/sound/gus.h index 410939ecf3a5d299b397217936db0855f96f3bce..cd8da68cab9216599ea51ca9f0020f6249cb0fbc 100644 --- a/include/sound/gus.h +++ b/include/sound/gus.h @@ -613,4 +613,8 @@ int snd_gus_dram_write(struct snd_gus_card *gus, char __user *ptr, int snd_gus_dram_read(struct snd_gus_card *gus, char __user *ptr, unsigned int addr, unsigned int size, int rom); +/* gus_timer.c */ +void snd_gf1_timers_init(struct snd_gus_card *gus); +void snd_gf1_timers_done(struct snd_gus_card *gus); + #endif /* __SOUND_GUS_H */ diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index d16a4229209b282137f61f396ee407c91e0b705f..0fea49bfc5e8641080971f69897e32ebc1921ac1 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -208,7 +208,7 @@ struct hda_codec { struct mutex control_mutex; struct snd_array spdif_out; unsigned int spdif_in_enable; /* SPDIF input enable? */ - const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ + const hda_nid_t *follower_dig_outs; /* optional digital out follower widgets */ struct snd_array init_pins; /* initial (BIOS) pin configurations */ struct snd_array driver_pins; /* pin configs set by codec parser */ struct snd_array cvt_setups; /* audio convert setups */ @@ -415,6 +415,8 @@ __printf(2, 3) struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec, const char *fmt, ...); +void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec); + static inline void snd_hda_codec_pcm_get(struct hda_pcm *pcm) { kref_get(&pcm->kref); diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index c1f78d9a6e47d66590caafe0b86f045f731c1bdd..6eed61e6cf8accecfb12569455d8658f46532780 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -347,6 +347,9 @@ struct hdac_bus { int bdl_pos_adj; /* BDL position adjustment */ + /* delay time in us for dma stop */ + unsigned int dma_stop_delay; + /* locks */ spinlock_t reg_lock; struct mutex cmd_mutex; diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h index 83b17682e01cc88493c9a46730939fa5d61529bb..7754631a310253e60e0d414ded502335b04a7477 100644 --- a/include/sound/hdmi-codec.h +++ b/include/sound/hdmi-codec.h @@ -2,7 +2,7 @@ /* * hdmi-codec.h - HDMI Codec driver API * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com * * Author: Jyri Sarha */ @@ -76,7 +76,8 @@ struct hdmi_codec_ops { * Mute/unmute HDMI audio stream. * Optional */ - int (*digital_mute)(struct device *dev, void *data, bool enable); + int (*mute_stream)(struct device *dev, void *data, + bool enable, int direction); /* * Provides EDID-Like-Data from connected HDMI device. @@ -99,6 +100,9 @@ struct hdmi_codec_ops { int (*hook_plugged_cb)(struct device *dev, void *data, hdmi_codec_plugged_cb fn, struct device *codec_dev); + + /* bit field */ + unsigned int no_capture_mute:1; }; /* HDMI codec initalization data */ diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h index 3b47832b1c1f7f060032e7ef722ae40bf9f754af..5daa937684a46dfb967d74ee55c22f4f1f3bab96 100644 --- a/include/sound/memalloc.h +++ b/include/sound/memalloc.h @@ -94,7 +94,11 @@ static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, size_t offset) { struct snd_sg_buf *sgbuf = dmab->private_data; - dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr; + dma_addr_t addr; + + if (!sgbuf) + return dmab->addr + offset; + addr = sgbuf->table[offset >> PAGE_SHIFT].addr; addr &= ~((dma_addr_t)PAGE_SIZE - 1); return addr + offset % PAGE_SIZE; } @@ -106,6 +110,9 @@ static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab, size_t offset) { struct snd_sg_buf *sgbuf = dmab->private_data; + + if (!sgbuf) + return dmab->area + offset; return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE; } diff --git a/include/sound/omap-hdmi-audio.h b/include/sound/omap-hdmi-audio.h index 16c007b651f47b5e977a17680e6ad1f03ec4d100..e5f82044a4049650fcca6c0e152a52fbcf5b184d 100644 --- a/include/sound/omap-hdmi-audio.h +++ b/include/sound/omap-hdmi-audio.h @@ -2,7 +2,7 @@ /* * hdmi-audio.c -- OMAP4+ DSS HDMI audio support library * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com * * Author: Jyri Sarha */ diff --git a/include/sound/rt5670.h b/include/sound/rt5670.h deleted file mode 100644 index 02e1d777835495b1d1726bc9eed10715df6c0b36..0000000000000000000000000000000000000000 --- a/include/sound/rt5670.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/sound/rt5670.h -- Platform data for RT5670 - * - * Copyright 2014 Realtek Microelectronics - */ - -#ifndef __LINUX_SND_RT5670_H -#define __LINUX_SND_RT5670_H - -struct rt5670_platform_data { - int jd_mode; - bool in2_diff; - bool dev_gpio; - bool gpio1_is_ext_spk_en; - - bool dmic_en; - unsigned int dmic1_data_pin; - /* 0 = GPIO6; 1 = IN2P; 3 = GPIO7*/ - unsigned int dmic2_data_pin; - /* 0 = GPIO8; 1 = IN3N; */ - unsigned int dmic3_data_pin; - /* 0 = GPIO9; 1 = GPIO10; 2 = GPIO5*/ -}; - -#endif diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index bbdd1542d6f130a5efdf44378bde5e950d0f61b0..86a1e956991eec36ef699fc860bff14a6a430cb8 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -12,9 +12,9 @@ #include #define asoc_simple_init_hp(card, sjack, prefix) \ - asoc_simple_init_jack(card, sjack, 1, prefix) + asoc_simple_init_jack(card, sjack, 1, prefix, NULL) #define asoc_simple_init_mic(card, sjack, prefix) \ - asoc_simple_init_jack(card, sjack, 0, prefix) + asoc_simple_init_jack(card, sjack, 0, prefix, NULL) struct asoc_simple_dai { const char *name; @@ -131,7 +131,7 @@ int asoc_simple_parse_pin_switches(struct snd_soc_card *card, int asoc_simple_init_jack(struct snd_soc_card *card, struct asoc_simple_jack *sjack, - int is_hp, char *prefix); + int is_hp, char *prefix, char *pin); int asoc_simple_init_priv(struct asoc_simple_priv *priv, struct link_info *li); diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 5663891148e3c22b2e44dd03754d196926294c1f..089ea9441fd1aa30256b7626e86514cc35e2a120 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -2,7 +2,8 @@ * * soc-component.h * - * Copyright (c) 2019 Kuninori Morimoto + * Copyright (C) 2019 Renesas Electronics Corp. + * Kuninori Morimoto */ #ifndef __SOC_COMPONENT_H #define __SOC_COMPONENT_H @@ -324,10 +325,12 @@ static inline int snd_soc_component_cache_sync( return regcache_sync(component->regmap); } +void snd_soc_component_set_aux(struct snd_soc_component *component, + struct snd_soc_aux_dev *aux); +int snd_soc_component_init(struct snd_soc_component *component); + /* component IO */ -int snd_soc_component_read(struct snd_soc_component *component, - unsigned int reg, unsigned int *val); -unsigned int snd_soc_component_read32(struct snd_soc_component *component, +unsigned int snd_soc_component_read(struct snd_soc_component *component, unsigned int reg); int snd_soc_component_write(struct snd_soc_component *component, unsigned int reg, unsigned int val); @@ -359,6 +362,7 @@ int snd_soc_component_stream_event(struct snd_soc_component *component, int snd_soc_component_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level); +void snd_soc_component_setup_regmap(struct snd_soc_component *component); #ifdef CONFIG_REGMAP void snd_soc_component_init_regmap(struct snd_soc_component *component, struct regmap *regmap); @@ -421,16 +425,6 @@ int snd_soc_component_open(struct snd_soc_component *component, struct snd_pcm_substream *substream); int snd_soc_component_close(struct snd_soc_component *component, struct snd_pcm_substream *substream); -int snd_soc_component_prepare(struct snd_soc_component *component, - struct snd_pcm_substream *substream); -int snd_soc_component_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params); -int snd_soc_component_hw_free(struct snd_soc_component *component, - struct snd_pcm_substream *substream); -int snd_soc_component_trigger(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - int cmd); void snd_soc_component_suspend(struct snd_soc_component *component); void snd_soc_component_resume(struct snd_soc_component *component); int snd_soc_component_is_suspended(struct snd_soc_component *component); @@ -455,5 +449,13 @@ int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma); int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd); void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd); +int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream); +int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_component **last); +void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_component *last); +int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream, + int cmd); #endif /* __SOC_COMPONENT_H */ diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 71e178c897932863c535f00bafb0d2111b6f9784..776a60529e70a9a638cb26f50755d71b3740c388 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -39,7 +39,7 @@ struct snd_compr_stream; /* * DAI Clock gating. * - * DAI bit clocks can be be gated (disabled) when the DAI is not + * DAI bit clocks can be gated (disabled) when the DAI is not * sending or receiving PCM data in a frame. This can be used to save power. */ #define SND_SOC_DAIFMT_CONT (1 << 4) /* continuous clock */ @@ -76,12 +76,12 @@ struct snd_compr_stream; * * This is wrt the codec, the inverse is true for the interface * i.e. if the codec is clk and FRM master then the interface is - * clk and frame slave. + * clk and frame secondary. */ #define SND_SOC_DAIFMT_CBM_CFM (1 << 12) /* codec clk & FRM master */ -#define SND_SOC_DAIFMT_CBS_CFM (2 << 12) /* codec clk slave & FRM master */ -#define SND_SOC_DAIFMT_CBM_CFS (3 << 12) /* codec clk master & frame slave */ -#define SND_SOC_DAIFMT_CBS_CFS (4 << 12) /* codec clk & FRM slave */ +#define SND_SOC_DAIFMT_CBS_CFM (2 << 12) /* codec clk secondary & FRM master */ +#define SND_SOC_DAIFMT_CBM_CFS (3 << 12) /* codec clk master & frame secondary */ +#define SND_SOC_DAIFMT_CBS_CFS (4 << 12) /* codec clk & FRM secondary */ #define SND_SOC_DAIFMT_FORMAT_MASK 0x000f #define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0 @@ -247,7 +247,6 @@ struct snd_soc_dai_ops { * DAI digital mute - optional. * Called by soc-core to minimise any pops. */ - int (*digital_mute)(struct snd_soc_dai *dai, int mute); int (*mute_stream)(struct snd_soc_dai *dai, int mute, int stream); /* @@ -281,6 +280,9 @@ struct snd_soc_dai_ops { */ snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *, struct snd_soc_dai *); + + /* bit field */ + unsigned int no_capture_mute:1; }; struct snd_soc_cdai_ops { diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index cc3dcb8152821ecb19ade598e6199c10045863b5..c3039e97929a5db27de8d6f86131a9910752d5ae 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -16,6 +16,8 @@ #include struct device; +struct snd_soc_pcm_runtime; +struct soc_enum; /* widget has no PM register bit */ #define SND_SOC_NOPM -1 @@ -376,6 +378,24 @@ struct snd_soc_dapm_widget_list; struct snd_soc_dapm_update; enum snd_soc_dapm_direction; +/* + * Bias levels + * + * @ON: Bias is fully on for audio playback and capture operations. + * @PREPARE: Prepare for audio operations. Called before DAPM switching for + * stream start and stop operations. + * @STANDBY: Low power standby state when no playback/capture operations are + * in progress. NOTE: The transition time between STANDBY and ON + * should be as fast as possible and no longer than 10ms. + * @OFF: Power Off. No restrictions on transition times. + */ +enum snd_soc_bias_level { + SND_SOC_BIAS_OFF = 0, + SND_SOC_BIAS_STANDBY = 1, + SND_SOC_BIAS_PREPARE = 2, + SND_SOC_BIAS_ON = 3, +}; + int dapm_regulator_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); int dapm_clock_event(struct snd_soc_dapm_widget *w, diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index 3dd6e33e94ecd350b61b5dbc65eeb18711057bf3..337ac566675789c07fb941a9cdc158060e6f6791 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -9,6 +9,7 @@ #define __SOC_LINK_H int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd); +void snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd); int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); diff --git a/include/sound/soc.h b/include/sound/soc.h index 1b85d5a961634a21c81773c4f815c5b880da605c..7fba9cd9adf541f4ebb2ba5ed51093ca3934042d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -376,24 +376,6 @@ #define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) -/* - * Bias levels - * - * @ON: Bias is fully on for audio playback and capture operations. - * @PREPARE: Prepare for audio operations. Called before DAPM switching for - * stream start and stop operations. - * @STANDBY: Low power standby state when no playback/capture operations are - * in progress. NOTE: The transition time between STANDBY and ON - * should be as fast as possible and no longer than 10ms. - * @OFF: Power Off. No restrictions on transition times. - */ -enum snd_soc_bias_level { - SND_SOC_BIAS_OFF = 0, - SND_SOC_BIAS_STANDBY = 1, - SND_SOC_BIAS_PREPARE = 2, - SND_SOC_BIAS_ON = 3, -}; - struct device_node; struct snd_jack; struct snd_soc_card; @@ -440,11 +422,12 @@ static inline int snd_soc_resume(struct device *dev) } #endif int snd_soc_poweroff(struct device *dev); -int snd_soc_add_component(struct device *dev, - struct snd_soc_component *component, - const struct snd_soc_component_driver *component_driver, - struct snd_soc_dai_driver *dai_drv, - int num_dai); +int snd_soc_component_initialize(struct snd_soc_component *component, + const struct snd_soc_component_driver *driver, + struct device *dev); +int snd_soc_add_component(struct snd_soc_component *component, + struct snd_soc_dai_driver *dai_drv, + int num_dai); int snd_soc_register_component(struct device *dev, const struct snd_soc_component_driver *component_driver, struct snd_soc_dai_driver *dai_drv, int num_dai); @@ -811,6 +794,9 @@ struct snd_soc_dai_link { /* codec/machine specific init - e.g. add machine controls */ int (*init)(struct snd_soc_pcm_runtime *rtd); + /* codec/machine specific exit - dual of init() */ + void (*exit)(struct snd_soc_pcm_runtime *rtd); + /* optional hw_params re-writing for BE and FE sync */ int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); @@ -1193,6 +1179,8 @@ struct snd_soc_pcm_runtime { /* see soc_new_pcm_runtime() */ #define asoc_rtd_to_cpu(rtd, n) (rtd)->dais[n] #define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->num_cpus] +#define asoc_substream_to_rtd(substream) \ + (struct snd_soc_pcm_runtime *)snd_pcm_substream_chip(substream) #define for_each_rtd_components(rtd, i, component) \ for ((i) = 0, component = NULL; \ diff --git a/include/sound/wm8960.h b/include/sound/wm8960.h index d22e848050259cb6e73fa47ea8da7b6e7495a32b..275fd5b201ce6bb3202a601785a6f995a578f21c 100644 --- a/include/sound/wm8960.h +++ b/include/sound/wm8960.h @@ -16,6 +16,23 @@ struct wm8960_data { bool capless; /* Headphone outputs configured in capless mode */ bool shared_lrclk; /* DAC and ADC LRCLKs are wired together */ + + /* + * Setup for headphone detection + * + * hp_cfg[0]: HPSEL[1:0] of R48 (Additional Control 4) + * hp_cfg[1]: {HPSWEN:HPSWPOL} of R24 (Additional Control 2). + * hp_cfg[2]: {TOCLKSEL:TOEN} of R23 (Additional Control 1). + */ + u32 hp_cfg[3]; + + /* + * Setup for gpio configuration + * + * gpio_cfg[0]: ALRCGPIO of R9 (Audio interface) + * gpio_cfg[1]: {GPIOPOL:GPIOSEL[2:0]} of R48 (Additional Control 4). + */ + u32 gpio_cfg[2]; }; #endif diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 4fda324f4b356394d206116d0fb4599aa807b200..1eccb2ac7d0298c25e80056101aca1313835e396 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -556,10 +556,11 @@ struct iscsi_conn { struct socket *sock; void (*orig_data_ready)(struct sock *); void (*orig_state_change)(struct sock *); -#define LOGIN_FLAGS_READ_ACTIVE 1 -#define LOGIN_FLAGS_CLOSED 2 -#define LOGIN_FLAGS_READY 4 -#define LOGIN_FLAGS_INITIAL_PDU 8 +#define LOGIN_FLAGS_READY 0 +#define LOGIN_FLAGS_INITIAL_PDU 1 +#define LOGIN_FLAGS_READ_ACTIVE 2 +#define LOGIN_FLAGS_WRITE_ACTIVE 3 +#define LOGIN_FLAGS_CLOSED 4 unsigned long login_flags; struct delayed_work login_work; struct iscsi_login *login; diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index f51452e3b984f8ce24aa58ccbb3374426ffe552f..6336780d83a7525085e3fdc86d209e179af37abc 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -40,6 +40,8 @@ struct target_backend_ops { ssize_t (*show_configfs_dev_params)(struct se_device *, char *); sense_reason_t (*parse_cdb)(struct se_cmd *cmd); + void (*tmr_notify)(struct se_device *se_dev, enum tcm_tmreq_table, + struct list_head *aborted_cmds); u32 (*get_device_type)(struct se_device *); sector_t (*get_blocks)(struct se_device *); sector_t (*get_alignment_offset_lbas)(struct se_device *); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 18c3f277b7708f4c895775d9e83a6e750ccc0a78..549947d407cfd2f55455748ebde55d3d4860b531 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -207,6 +207,7 @@ enum tcm_tmreq_table { TMR_LUN_RESET = 5, TMR_TARGET_WARM_RESET = 6, TMR_TARGET_COLD_RESET = 7, + TMR_LUN_RESET_PRO = 0x80, TMR_UNKNOWN = 0xff, }; diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h index 5f300739240d24b26f463510ae2115694c99b323..84841b3a7ffd59ef1808b1d273bc76fdf4fdbcb5 100644 --- a/include/trace/events/ufs.h +++ b/include/trace/events/ufs.h @@ -249,6 +249,37 @@ TRACE_EVENT(ufshcd_command, ) ); +TRACE_EVENT(ufshcd_uic_command, + TP_PROTO(const char *dev_name, const char *str, u32 cmd, + u32 arg1, u32 arg2, u32 arg3), + + TP_ARGS(dev_name, str, cmd, arg1, arg2, arg3), + + TP_STRUCT__entry( + __string(dev_name, dev_name) + __string(str, str) + __field(u32, cmd) + __field(u32, arg1) + __field(u32, arg2) + __field(u32, arg3) + ), + + TP_fast_assign( + __assign_str(dev_name, dev_name); + __assign_str(str, str); + __entry->cmd = cmd; + __entry->arg1 = arg1; + __entry->arg2 = arg2; + __entry->arg3 = arg3; + ), + + TP_printk( + "%s: %s: cmd: 0x%x, arg1: 0x%x, arg2: 0x%x, arg3: 0x%x", + __get_str(str), __get_str(dev_name), __entry->cmd, + __entry->arg1, __entry->arg2, __entry->arg3 + ) +); + TRACE_EVENT(ufshcd_upiu, TP_PROTO(const char *dev_name, const char *str, void *hdr, void *tsf), diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h index a88c7c6d0692eab0aa1d862af2aab7045ece6fca..fbf9c5c7dd59ab6eb765c35e0ef9040d56e07c02 100644 --- a/include/uapi/linux/fanotify.h +++ b/include/uapi/linux/fanotify.h @@ -24,7 +24,6 @@ #define FAN_OPEN_PERM 0x00010000 /* File open in perm check */ #define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */ #define FAN_OPEN_EXEC_PERM 0x00040000 /* File open/exec in perm check */ -#define FAN_DIR_MODIFY 0x00080000 /* Directory entry was modified */ #define FAN_EVENT_ON_CHILD 0x08000000 /* Interested in child events */ @@ -54,6 +53,11 @@ /* Flags to determine fanotify event format */ #define FAN_REPORT_TID 0x00000100 /* event->pid is thread id */ #define FAN_REPORT_FID 0x00000200 /* Report unique file id */ +#define FAN_REPORT_DIR_FID 0x00000400 /* Report unique directory id */ +#define FAN_REPORT_NAME 0x00000800 /* Report events with name */ + +/* Convenience macro - FAN_REPORT_NAME requires FAN_REPORT_DIR_FID */ +#define FAN_REPORT_DFID_NAME (FAN_REPORT_DIR_FID | FAN_REPORT_NAME) /* Deprecated - do not use this in programs and do not add new flags here! */ #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \ @@ -118,6 +122,7 @@ struct fanotify_event_metadata { #define FAN_EVENT_INFO_TYPE_FID 1 #define FAN_EVENT_INFO_TYPE_DFID_NAME 2 +#define FAN_EVENT_INFO_TYPE_DFID 3 /* Variable length info record following event metadata */ struct fanotify_event_info_header { @@ -127,10 +132,11 @@ struct fanotify_event_info_header { }; /* - * Unique file identifier info record. This is used both for - * FAN_EVENT_INFO_TYPE_FID records and for FAN_EVENT_INFO_TYPE_DFID_NAME - * records. For FAN_EVENT_INFO_TYPE_DFID_NAME there is additionally a null - * terminated name immediately after the file handle. + * Unique file identifier info record. + * This structure is used for records of types FAN_EVENT_INFO_TYPE_FID, + * FAN_EVENT_INFO_TYPE_DFID and FAN_EVENT_INFO_TYPE_DFID_NAME. + * For FAN_EVENT_INFO_TYPE_DFID_NAME there is additionally a null terminated + * name immediately after the file handle. */ struct fanotify_event_info_fid { struct fanotify_event_info_header hdr; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 4fdf30316582709be3a35ea5f047fcca2dbaaef6..f6d86033c4fa3d21cc7c643c85d443b053c704c9 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -289,6 +289,7 @@ struct kvm_run { /* KVM_EXIT_FAIL_ENTRY */ struct { __u64 hardware_entry_failure_reason; + __u32 cpu; } fail_entry; /* KVM_EXIT_EXCEPTION */ struct { @@ -1031,6 +1032,9 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_PPC_SECURE_GUEST 181 #define KVM_CAP_HALT_POLL 182 #define KVM_CAP_ASYNC_PF_INT 183 +#define KVM_CAP_LAST_CPU 184 +#define KVM_CAP_SMALLER_MAXPHYADDR 185 +#define KVM_CAP_S390_DIAG318 186 #ifdef KVM_CAP_IRQ_ROUTING diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 8ec3dd742ea4559a0a540c6c2f62ac425cf5f30b..851b982f8c4b8235f35af0b6be89bca0843d163f 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -26,20 +26,6 @@ /* * The type definitions. These are from Ted Ts'o's serial.h */ -#define PORT_UNKNOWN 0 -#define PORT_8250 1 -#define PORT_16450 2 -#define PORT_16550 3 -#define PORT_16550A 4 -#define PORT_CIRRUS 5 -#define PORT_16650 6 -#define PORT_16650V2 7 -#define PORT_16750 8 -#define PORT_STARTECH 9 -#define PORT_16C950 10 -#define PORT_16654 11 -#define PORT_16850 12 -#define PORT_RSA 13 #define PORT_NS16550A 14 #define PORT_XSCALE 15 #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */ diff --git a/include/uapi/linux/target_core_user.h b/include/uapi/linux/target_core_user.h index b7b57967d90f09cd428d90e12b0035e3ecbcfc67..95b1597f16aeb03ce76bfb02cbc0a288b03d3e61 100644 --- a/include/uapi/linux/target_core_user.h +++ b/include/uapi/linux/target_core_user.h @@ -45,6 +45,7 @@ #define ALIGN_SIZE 64 /* Should be enough for most CPUs */ #define TCMU_MAILBOX_FLAG_CAP_OOOC (1 << 0) /* Out-of-order completions */ #define TCMU_MAILBOX_FLAG_CAP_READ_LEN (1 << 1) /* Read data length */ +#define TCMU_MAILBOX_FLAG_CAP_TMR (1 << 2) /* TMR notifications */ struct tcmu_mailbox { __u16 version; @@ -62,6 +63,7 @@ struct tcmu_mailbox { enum tcmu_opcode { TCMU_OP_PAD = 0, TCMU_OP_CMD, + TCMU_OP_TMR, }; /* @@ -128,6 +130,29 @@ struct tcmu_cmd_entry { } __packed; +struct tcmu_tmr_entry { + struct tcmu_cmd_entry_hdr hdr; + +#define TCMU_TMR_UNKNOWN 0 +#define TCMU_TMR_ABORT_TASK 1 +#define TCMU_TMR_ABORT_TASK_SET 2 +#define TCMU_TMR_CLEAR_ACA 3 +#define TCMU_TMR_CLEAR_TASK_SET 4 +#define TCMU_TMR_LUN_RESET 5 +#define TCMU_TMR_TARGET_WARM_RESET 6 +#define TCMU_TMR_TARGET_COLD_RESET 7 +/* Pseudo reset due to received PR OUT */ +#define TCMU_TMR_LUN_RESET_PRO 128 + __u8 tmr_type; + + __u8 __pad1; + __u16 __pad2; + __u32 cmd_cnt; + __u64 __pad3; + __u64 __pad4; + __u16 cmd_ids[0]; +} __packed; + #define TCMU_OP_ALIGN_SIZE sizeof(__u64) enum tcmu_genl_cmd { diff --git a/include/uapi/linux/thermal.h b/include/uapi/linux/thermal.h index 96218378dda8c581115b93e640b3d718d3f0f5ac..c105054cbb57acb9dbef29790822c9f6830a0969 100644 --- a/include/uapi/linux/thermal.h +++ b/include/uapi/linux/thermal.h @@ -4,31 +4,86 @@ #define THERMAL_NAME_LENGTH 20 -/* Adding event notification support elements */ -#define THERMAL_GENL_FAMILY_NAME "thermal_event" -#define THERMAL_GENL_VERSION 0x01 -#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_grp" - -/* Events supported by Thermal Netlink */ -enum events { - THERMAL_AUX0, - THERMAL_AUX1, - THERMAL_CRITICAL, - THERMAL_DEV_FAULT, +enum thermal_device_mode { + THERMAL_DEVICE_DISABLED = 0, + THERMAL_DEVICE_ENABLED, +}; + +enum thermal_trip_type { + THERMAL_TRIP_ACTIVE = 0, + THERMAL_TRIP_PASSIVE, + THERMAL_TRIP_HOT, + THERMAL_TRIP_CRITICAL, }; -/* attributes of thermal_genl_family */ -enum { +/* Adding event notification support elements */ +#define THERMAL_GENL_FAMILY_NAME "thermal" +#define THERMAL_GENL_VERSION 0x01 +#define THERMAL_GENL_SAMPLING_GROUP_NAME "sampling" +#define THERMAL_GENL_EVENT_GROUP_NAME "event" + +/* Attributes of thermal_genl_family */ +enum thermal_genl_attr { THERMAL_GENL_ATTR_UNSPEC, - THERMAL_GENL_ATTR_EVENT, + THERMAL_GENL_ATTR_TZ, + THERMAL_GENL_ATTR_TZ_ID, + THERMAL_GENL_ATTR_TZ_TEMP, + THERMAL_GENL_ATTR_TZ_TRIP, + THERMAL_GENL_ATTR_TZ_TRIP_ID, + THERMAL_GENL_ATTR_TZ_TRIP_TYPE, + THERMAL_GENL_ATTR_TZ_TRIP_TEMP, + THERMAL_GENL_ATTR_TZ_TRIP_HYST, + THERMAL_GENL_ATTR_TZ_MODE, + THERMAL_GENL_ATTR_TZ_NAME, + THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT, + THERMAL_GENL_ATTR_TZ_GOV, + THERMAL_GENL_ATTR_TZ_GOV_NAME, + THERMAL_GENL_ATTR_CDEV, + THERMAL_GENL_ATTR_CDEV_ID, + THERMAL_GENL_ATTR_CDEV_CUR_STATE, + THERMAL_GENL_ATTR_CDEV_MAX_STATE, + THERMAL_GENL_ATTR_CDEV_NAME, + THERMAL_GENL_ATTR_GOV_NAME, + __THERMAL_GENL_ATTR_MAX, }; #define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1) -/* commands supported by the thermal_genl_family */ -enum { +enum thermal_genl_sampling { + THERMAL_GENL_SAMPLING_TEMP, + __THERMAL_GENL_SAMPLING_MAX, +}; +#define THERMAL_GENL_SAMPLING_MAX (__THERMAL_GENL_SAMPLING_MAX - 1) + +/* Events of thermal_genl_family */ +enum thermal_genl_event { + THERMAL_GENL_EVENT_UNSPEC, + THERMAL_GENL_EVENT_TZ_CREATE, /* Thermal zone creation */ + THERMAL_GENL_EVENT_TZ_DELETE, /* Thermal zone deletion */ + THERMAL_GENL_EVENT_TZ_DISABLE, /* Thermal zone disabed */ + THERMAL_GENL_EVENT_TZ_ENABLE, /* Thermal zone enabled */ + THERMAL_GENL_EVENT_TZ_TRIP_UP, /* Trip point crossed the way up */ + THERMAL_GENL_EVENT_TZ_TRIP_DOWN, /* Trip point crossed the way down */ + THERMAL_GENL_EVENT_TZ_TRIP_CHANGE, /* Trip point changed */ + THERMAL_GENL_EVENT_TZ_TRIP_ADD, /* Trip point added */ + THERMAL_GENL_EVENT_TZ_TRIP_DELETE, /* Trip point deleted */ + THERMAL_GENL_EVENT_CDEV_ADD, /* Cdev bound to the thermal zone */ + THERMAL_GENL_EVENT_CDEV_DELETE, /* Cdev unbound */ + THERMAL_GENL_EVENT_CDEV_STATE_UPDATE, /* Cdev state updated */ + THERMAL_GENL_EVENT_TZ_GOV_CHANGE, /* Governor policy changed */ + __THERMAL_GENL_EVENT_MAX, +}; +#define THERMAL_GENL_EVENT_MAX (__THERMAL_GENL_EVENT_MAX - 1) + +/* Commands supported by the thermal_genl_family */ +enum thermal_genl_cmd { THERMAL_GENL_CMD_UNSPEC, - THERMAL_GENL_CMD_EVENT, + THERMAL_GENL_CMD_TZ_GET_ID, /* List of thermal zones id */ + THERMAL_GENL_CMD_TZ_GET_TRIP, /* List of thermal trips */ + THERMAL_GENL_CMD_TZ_GET_TEMP, /* Get the thermal zone temperature */ + THERMAL_GENL_CMD_TZ_GET_GOV, /* Get the thermal zone governor */ + THERMAL_GENL_CMD_TZ_GET_MODE, /* Get the thermal zone mode */ + THERMAL_GENL_CMD_CDEV_GET, /* List of cdev id */ __THERMAL_GENL_CMD_MAX, }; #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1) diff --git a/include/uapi/rdma/efa-abi.h b/include/uapi/rdma/efa-abi.h index 53b6e2036a9bea74c5102f2e9403f95d75fcd9dd..507a2862bedb7528d3103aaeba5ae55af966f834 100644 --- a/include/uapi/rdma/efa-abi.h +++ b/include/uapi/rdma/efa-abi.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */ /* - * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved. + * Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All rights reserved. */ #ifndef EFA_ABI_USER_H @@ -20,6 +20,16 @@ * hex bit offset of the field. */ +enum { + EFA_ALLOC_UCONTEXT_CMD_COMP_TX_BATCH = 1 << 0, + EFA_ALLOC_UCONTEXT_CMD_COMP_MIN_SQ_WR = 1 << 1, +}; + +struct efa_ibv_alloc_ucontext_cmd { + __u32 comp_mask; + __u8 reserved_20[4]; +}; + enum efa_ibv_user_cmds_supp_udata { EFA_USER_CMDS_SUPP_UDATA_QUERY_DEVICE = 1 << 0, EFA_USER_CMDS_SUPP_UDATA_CREATE_AH = 1 << 1, @@ -31,6 +41,9 @@ struct efa_ibv_alloc_ucontext_resp { __u16 sub_cqs_per_cq; __u16 inline_buf_size; __u32 max_llq_size; /* bytes */ + __u16 max_tx_batch; /* units of 64 bytes */ + __u16 min_sq_wr; + __u8 reserved_a0[4]; }; struct efa_ibv_alloc_pd_resp { diff --git a/include/uapi/rdma/ib_user_ioctl_cmds.h b/include/uapi/rdma/ib_user_ioctl_cmds.h index 4961d5e858eb577a7aeb16247eb8d00baed53929..99dcabf61a7111707a4ecfa15ec5d432b6f9d051 100644 --- a/include/uapi/rdma/ib_user_ioctl_cmds.h +++ b/include/uapi/rdma/ib_user_ioctl_cmds.h @@ -69,6 +69,7 @@ enum uverbs_methods_device { UVERBS_METHOD_INFO_HANDLES, UVERBS_METHOD_QUERY_PORT, UVERBS_METHOD_GET_CONTEXT, + UVERBS_METHOD_QUERY_CONTEXT, }; enum uverbs_attrs_invoke_write_cmd_attr_ids { @@ -87,6 +88,11 @@ enum uverbs_attrs_get_context_attr_ids { UVERBS_ATTR_GET_CONTEXT_CORE_SUPPORT, }; +enum uverbs_attrs_query_context_attr_ids { + UVERBS_ATTR_QUERY_CONTEXT_NUM_COMP_VECTORS, + UVERBS_ATTR_QUERY_CONTEXT_CORE_SUPPORT, +}; + enum uverbs_attrs_create_cq_cmd_attr_ids { UVERBS_ATTR_CREATE_CQ_HANDLE, UVERBS_ATTR_CREATE_CQ_CQE, @@ -242,6 +248,7 @@ enum uverbs_methods_mr { UVERBS_METHOD_DM_MR_REG, UVERBS_METHOD_MR_DESTROY, UVERBS_METHOD_ADVISE_MR, + UVERBS_METHOD_QUERY_MR, }; enum uverbs_attrs_mr_destroy_ids { @@ -255,6 +262,14 @@ enum uverbs_attrs_advise_mr_cmd_attr_ids { UVERBS_ATTR_ADVISE_MR_SGE_LIST, }; +enum uverbs_attrs_query_mr_cmd_attr_ids { + UVERBS_ATTR_QUERY_MR_HANDLE, + UVERBS_ATTR_QUERY_MR_RESP_LKEY, + UVERBS_ATTR_QUERY_MR_RESP_RKEY, + UVERBS_ATTR_QUERY_MR_RESP_LENGTH, + UVERBS_ATTR_QUERY_MR_RESP_IOVA, +}; + enum uverbs_attrs_create_counters_cmd_attr_ids { UVERBS_ATTR_CREATE_COUNTERS_HANDLE, }; diff --git a/include/uapi/rdma/mlx5_user_ioctl_cmds.h b/include/uapi/rdma/mlx5_user_ioctl_cmds.h index 8e316ef896b5fc1b1c77f51470d9b26ef26c3fa0..e24d66d278cf558ca65b2133d867b16513f87715 100644 --- a/include/uapi/rdma/mlx5_user_ioctl_cmds.h +++ b/include/uapi/rdma/mlx5_user_ioctl_cmds.h @@ -228,6 +228,10 @@ enum mlx5_ib_flow_matcher_methods { MLX5_IB_METHOD_FLOW_MATCHER_DESTROY, }; +enum mlx5_ib_device_query_context_attrs { + MLX5_IB_ATTR_QUERY_CONTEXT_RESP_UCTX = (1U << UVERBS_ID_NS_SHIFT), +}; + #define MLX5_IB_DW_MATCH_PARAM 0x80 struct mlx5_ib_match_params { @@ -259,7 +263,7 @@ enum mlx5_ib_create_flow_attrs { MLX5_IB_ATTR_CREATE_FLOW_FLAGS, }; -enum mlx5_ib_destoy_flow_attrs { +enum mlx5_ib_destroy_flow_attrs { MLX5_IB_ATTR_DESTROY_FLOW_HANDLE = (1U << UVERBS_ID_NS_SHIFT), }; @@ -286,4 +290,14 @@ enum mlx5_ib_create_flow_action_create_packet_reformat_attrs { MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF, }; +enum mlx5_ib_query_pd_attrs { + MLX5_IB_ATTR_QUERY_PD_HANDLE = (1U << UVERBS_ID_NS_SHIFT), + MLX5_IB_ATTR_QUERY_PD_RESP_PDN, +}; + +enum mlx5_ib_pd_methods { + MLX5_IB_METHOD_PD_QUERY = (1U << UVERBS_ID_NS_SHIFT), + +}; + #endif diff --git a/include/uapi/rdma/qedr-abi.h b/include/uapi/rdma/qedr-abi.h index a0b83c9d4498ba9cd638f0585d333720b2451f75..bf7333b2b5d71e67f2ddfc9eadaed58ab5dc551f 100644 --- a/include/uapi/rdma/qedr-abi.h +++ b/include/uapi/rdma/qedr-abi.h @@ -39,8 +39,9 @@ /* user kernel communication data structures. */ enum qedr_alloc_ucontext_flags { - QEDR_ALLOC_UCTX_RESERVED = 1 << 0, - QEDR_ALLOC_UCTX_DB_REC = 1 << 1 + QEDR_ALLOC_UCTX_EDPM_MODE = 1 << 0, + QEDR_ALLOC_UCTX_DB_REC = 1 << 1, + QEDR_SUPPORT_DPM_SIZES = 1 << 2, }; struct qedr_alloc_ucontext_req { @@ -50,13 +51,14 @@ struct qedr_alloc_ucontext_req { #define QEDR_LDPM_MAX_SIZE (8192) #define QEDR_EDPM_TRANS_SIZE (64) +#define QEDR_EDPM_MAX_SIZE (ROCE_REQ_MAX_INLINE_DATA_SIZE) enum qedr_rdma_dpm_type { QEDR_DPM_TYPE_NONE = 0, QEDR_DPM_TYPE_ROCE_ENHANCED = 1 << 0, QEDR_DPM_TYPE_ROCE_LEGACY = 1 << 1, QEDR_DPM_TYPE_IWARP_LEGACY = 1 << 2, - QEDR_DPM_TYPE_RESERVED = 1 << 3, + QEDR_DPM_TYPE_ROCE_EDPM_MODE = 1 << 3, QEDR_DPM_SIZES_SET = 1 << 4, }; @@ -77,6 +79,8 @@ struct qedr_alloc_ucontext_resp { __u16 ldpm_limit_size; __u8 edpm_trans_size; __u8 reserved; + __u16 edpm_limit_size; + __u8 padding[6]; }; struct qedr_alloc_pd_ureq { diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h index 8e277783fa9610d79629e73c69df658959914c3b..d2f5b839624320ffa1ce1cded227729cd4a57c49 100644 --- a/include/uapi/rdma/rdma_netlink.h +++ b/include/uapi/rdma/rdma_netlink.h @@ -287,6 +287,12 @@ enum rdma_nldev_command { RDMA_NLDEV_CMD_STAT_DEL, + RDMA_NLDEV_CMD_RES_QP_GET_RAW, + + RDMA_NLDEV_CMD_RES_CQ_GET_RAW, + + RDMA_NLDEV_CMD_RES_MR_GET_RAW, + RDMA_NLDEV_NUM_OPS }; @@ -525,6 +531,8 @@ enum rdma_nldev_attr { */ RDMA_NLDEV_ATTR_DEV_DIM, /* u8 */ + RDMA_NLDEV_ATTR_RES_RAW, /* binary */ + /* * Always the end */ @@ -561,5 +569,6 @@ enum rdma_nl_counter_mode { */ enum rdma_nl_counter_mask { RDMA_COUNTER_MASK_QP_TYPE = 1, + RDMA_COUNTER_MASK_PID = 1 << 1, }; #endif /* _UAPI_RDMA_NETLINK_H */ diff --git a/include/uapi/rdma/rdma_user_ioctl.h b/include/uapi/rdma/rdma_user_ioctl.h index d92d2721b28c5bd4afbdcf9a9264ead02441dbff..53c55188dd2aa4a07b91d5092394c50a3fc08b65 100644 --- a/include/uapi/rdma/rdma_user_ioctl.h +++ b/include/uapi/rdma/rdma_user_ioctl.h @@ -43,7 +43,7 @@ /* * General blocks assignments - * It is closed on purpose do not expose it it user space + * It is closed on purpose - do not expose it to user space * #define MAD_CMD_BASE 0x00 * #define HFI1_CMD_BAS 0xE0 */ diff --git a/include/uapi/scsi/fc/fc_els.h b/include/uapi/scsi/fc/fc_els.h index 66318c44acd731dcf945d32b012a420e63a637a3..8c704e510e39857fe5413261667a3a217672a2ba 100644 --- a/include/uapi/scsi/fc/fc_els.h +++ b/include/uapi/scsi/fc/fc_els.h @@ -41,6 +41,7 @@ enum fc_els_cmd { ELS_REC = 0x13, /* read exchange concise */ ELS_SRR = 0x14, /* sequence retransmission request */ ELS_FPIN = 0x16, /* Fabric Performance Impact Notification */ + ELS_RDP = 0x18, /* Read Diagnostic Parameters */ ELS_RDF = 0x19, /* Register Diagnostic Functions */ ELS_PRLI = 0x20, /* process login */ ELS_PRLO = 0x21, /* process logout */ @@ -110,6 +111,7 @@ enum fc_els_cmd { [ELS_REC] = "REC", \ [ELS_SRR] = "SRR", \ [ELS_FPIN] = "FPIN", \ + [ELS_RDP] = "RDP", \ [ELS_RDF] = "RDF", \ [ELS_PRLI] = "PRLI", \ [ELS_PRLO] = "PRLO", \ diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c index 3596448bfdabc605590e326c05ef6c67cdbe807d..bfcfcd61adb64aa5ed55a66a19b5b5754de30966 100644 --- a/kernel/audit_fsnotify.c +++ b/kernel/audit_fsnotify.c @@ -36,7 +36,7 @@ static struct fsnotify_group *audit_fsnotify_group; /* fsnotify events we care about. */ #define AUDIT_FS_EVENTS (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\ - FS_MOVE_SELF | FS_EVENT_ON_CHILD) + FS_MOVE_SELF) static void audit_fsnotify_mark_free(struct audit_fsnotify_mark *audit_mark) { @@ -152,35 +152,31 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark) } /* Update mark data in audit rules based on fsnotify events. */ -static int audit_mark_handle_event(struct fsnotify_group *group, - struct inode *to_tell, - u32 mask, const void *data, int data_type, - const struct qstr *dname, u32 cookie, - struct fsnotify_iter_info *iter_info) +static int audit_mark_handle_event(struct fsnotify_mark *inode_mark, u32 mask, + struct inode *inode, struct inode *dir, + const struct qstr *dname) { - struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); struct audit_fsnotify_mark *audit_mark; - const struct inode *inode = fsnotify_data_inode(data, data_type); audit_mark = container_of(inode_mark, struct audit_fsnotify_mark, mark); - BUG_ON(group != audit_fsnotify_group); - - if (WARN_ON(!inode)) + if (WARN_ON_ONCE(inode_mark->group != audit_fsnotify_group) || + WARN_ON_ONCE(!inode)) return 0; if (mask & (FS_CREATE|FS_MOVED_TO|FS_DELETE|FS_MOVED_FROM)) { if (audit_compare_dname_path(dname, audit_mark->path, AUDIT_NAME_FULL)) return 0; audit_update_mark(audit_mark, inode); - } else if (mask & (FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF)) + } else if (mask & (FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF)) { audit_autoremove_mark_rule(audit_mark); + } return 0; } static const struct fsnotify_ops audit_mark_fsnotify_ops = { - .handle_event = audit_mark_handle_event, + .handle_inode_event = audit_mark_handle_event, .free_mark = audit_fsnotify_free_mark, }; diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 1b7a2f04179369d05d37d308d567a64a19da4cb8..83e1c07fc99e1e838e781e5245d7778d323c9812 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -1035,11 +1035,9 @@ static void evict_chunk(struct audit_chunk *chunk) audit_schedule_prune(); } -static int audit_tree_handle_event(struct fsnotify_group *group, - struct inode *to_tell, - u32 mask, const void *data, int data_type, - const struct qstr *file_name, u32 cookie, - struct fsnotify_iter_info *iter_info) +static int audit_tree_handle_event(struct fsnotify_mark *mark, u32 mask, + struct inode *inode, struct inode *dir, + const struct qstr *file_name) { return 0; } @@ -1068,7 +1066,7 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *mark, } static const struct fsnotify_ops audit_tree_ops = { - .handle_event = audit_tree_handle_event, + .handle_inode_event = audit_tree_handle_event, .freeing_mark = audit_tree_freeing_mark, .free_mark = audit_tree_destroy_watch, }; diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index e09c551ae52d49f4f78460d8e84d47e420a9cc3d..246e5ba704c00652bc9dc421303c0c8774036004 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -53,7 +53,7 @@ static struct fsnotify_group *audit_watch_group; /* fsnotify events we care about. */ #define AUDIT_FS_WATCH (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\ - FS_MOVE_SELF | FS_EVENT_ON_CHILD | FS_UNMOUNT) + FS_MOVE_SELF | FS_UNMOUNT) static void audit_free_parent(struct audit_parent *parent) { @@ -464,20 +464,17 @@ void audit_remove_watch_rule(struct audit_krule *krule) } /* Update watch data in audit rules based on fsnotify events. */ -static int audit_watch_handle_event(struct fsnotify_group *group, - struct inode *to_tell, - u32 mask, const void *data, int data_type, - const struct qstr *dname, u32 cookie, - struct fsnotify_iter_info *iter_info) +static int audit_watch_handle_event(struct fsnotify_mark *inode_mark, u32 mask, + struct inode *inode, struct inode *dir, + const struct qstr *dname) { - struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); - const struct inode *inode = fsnotify_data_inode(data, data_type); struct audit_parent *parent; parent = container_of(inode_mark, struct audit_parent, mark); - BUG_ON(group != audit_watch_group); - WARN_ON(!inode); + if (WARN_ON_ONCE(inode_mark->group != audit_watch_group) || + WARN_ON_ONCE(!inode)) + return 0; if (mask & (FS_CREATE|FS_MOVED_TO) && inode) audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0); @@ -490,7 +487,7 @@ static int audit_watch_handle_event(struct fsnotify_group *group, } static const struct fsnotify_ops audit_watch_fsnotify_ops = { - .handle_event = audit_watch_handle_event, + .handle_inode_event = audit_watch_handle_event, .free_mark = audit_watch_free_mark, }; diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c index b9515fcc9b297147a34adbe62b0d86d6168e7fac..cbff6ba53d563634791e27ad8d11e7a683065679 100644 --- a/kernel/locking/qspinlock.c +++ b/kernel/locking/qspinlock.c @@ -581,4 +581,11 @@ EXPORT_SYMBOL(queued_spin_lock_slowpath); #include "qspinlock_paravirt.h" #include "qspinlock.c" +bool nopvspin __initdata; +static __init int parse_nopvspin(char *arg) +{ + nopvspin = true; + return 0; +} +early_param("nopvspin", parse_nopvspin); #endif diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 848f67a5f16d3e1733cee56abff951edcebf2e7d..b0c338ecc3180b4979c05c6fc4c48c9abc78da92 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1543,8 +1543,7 @@ static void latency_fsnotify_workfn(struct work_struct *work) { struct trace_array *tr = container_of(work, struct trace_array, fsnotify_work); - fsnotify(tr->d_max_latency->d_inode, FS_MODIFY, - tr->d_max_latency->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0); + fsnotify_inode(tr->d_max_latency->d_inode, FS_MODIFY); } static void latency_fsnotify_workfn_irq(struct irq_work *iwork) diff --git a/net/core/sock.c b/net/core/sock.c index 49cd5ffe673ef943d30323c19baff81763f87cac..d29709e0790dd249cff538164d11e899387aaaa9 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -820,6 +820,14 @@ void sock_set_rcvbuf(struct sock *sk, int val) } EXPORT_SYMBOL(sock_set_rcvbuf); +void sock_set_mark(struct sock *sk, u32 val) +{ + lock_sock(sk); + sk->sk_mark = val; + release_sock(sk); +} +EXPORT_SYMBOL(sock_set_mark); + /* * This is meant for all protocols to use and covers goings on * at the socket level. Everything here is generic. diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 9395ee8a868dbedba93547cb7d948c53b21ec9cb..1eb65a7a27fdf301b97cc3f15d27fb35d3c02b93 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1192,7 +1192,7 @@ problem: panic("GENL: Cannot register controller: %d\n", err); } -subsys_initcall(genl_init); +core_initcall(genl_init); static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group, gfp_t flags) diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index a1dce9725b98e48442f44bef421fc1ac62f12d76..1006458f7f8515120b0fd09bae25e28c4878b1d2 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -219,7 +219,7 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) switch (runtime->format) { case SNDRV_PCM_FORMAT_S16_LE: break; - case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ + case SNDRV_PCM_FORMAT_S16_BE: word &= ~(AC97C_CMR_CEM_LITTLE); break; default: @@ -301,7 +301,7 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) switch (runtime->format) { case SNDRV_PCM_FORMAT_S16_LE: break; - case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ + case SNDRV_PCM_FORMAT_S16_BE: word &= ~(AC97C_CMR_CEM_LITTLE); break; default: @@ -356,14 +356,14 @@ atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) camr = ac97c_readl(chip, CAMR); switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ - case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: ptcr = ATMEL_PDC_TXTEN; camr |= AC97C_CMR_CENA | AC97C_CSR_ENDTX; break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ - case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: ptcr |= ATMEL_PDC_TXTDIS; if (chip->opened <= 1) @@ -388,14 +388,14 @@ atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) ptcr = readl(chip->regs + ATMEL_PDC_PTSR); switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ - case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: ptcr = ATMEL_PDC_RXTEN; camr |= AC97C_CMR_CENA | AC97C_CSR_ENDRX; break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ - case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: ptcr |= ATMEL_PDC_RXTDIS; if (chip->opened <= 1) diff --git a/sound/core/init.c b/sound/core/init.c index b02a99766351d7d8d684f073629427593d503395..0478847ba2b8f6e758cc1b3673248a2033bbb222 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -203,7 +203,10 @@ int snd_card_new(struct device *parent, int idx, const char *xid, mutex_unlock(&snd_card_mutex); card->dev = parent; card->number = idx; +#ifdef MODULE + WARN_ON(!module); card->module = module; +#endif INIT_LIST_HEAD(&card->devices); init_rwsem(&card->controls_rwsem); rwlock_init(&card->ctl_files_rwlock); diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index bea46ed157a6d008d8b3bc41fb314fa7f88f9297..ad74ea9cbff5475a6162d85f977d03c2341c8c21 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -135,16 +135,17 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, dmab->dev.type = type; dmab->dev.dev = device; dmab->bytes = 0; + dmab->area = NULL; + dmab->addr = 0; + dmab->private_data = NULL; switch (type) { case SNDRV_DMA_TYPE_CONTINUOUS: gfp = snd_mem_get_gfp_flags(device, GFP_KERNEL); dmab->area = alloc_pages_exact(size, gfp); - dmab->addr = 0; break; case SNDRV_DMA_TYPE_VMALLOC: gfp = snd_mem_get_gfp_flags(device, GFP_KERNEL | __GFP_HIGHMEM); dmab->area = __vmalloc(size, gfp); - dmab->addr = 0; break; #ifdef CONFIG_HAS_DMA #ifdef CONFIG_GENERIC_ALLOCATOR @@ -157,7 +158,7 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, */ dmab->dev.type = SNDRV_DMA_TYPE_DEV; #endif /* CONFIG_GENERIC_ALLOCATOR */ - /* fall through */ + fallthrough; case SNDRV_DMA_TYPE_DEV: case SNDRV_DMA_TYPE_DEV_UC: snd_malloc_dev_pages(dmab, size); @@ -171,8 +172,6 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, #endif default: pr_err("snd-malloc: invalid device type %d\n", type); - dmab->area = NULL; - dmab->addr = 0; return -ENXIO; } if (! dmab->area) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 68630244b00ff21bf85f94b2c5330355e16dd04e..327ec42a36b0986b380b7c4aa3e0bb065223d52e 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2851,7 +2851,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream) break; - /* Fall through */ + fallthrough; case VM_READ: substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; break; diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 1545f8fdb4db6c4c7420151b7014ad8830132622..d5ca161d588c504fa79257a300a958313b98c74d 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -357,7 +357,7 @@ snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, if (snd_mask_test(format_mask, (__force int)format1)) return format1; } - /* fall through */ + fallthrough; default: return (__force snd_pcm_format_t)-EINVAL; } diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c index 073540f73b2f20cdb3010334b9b086ea696f8f95..f9a211cc1f2c7c818b8207a11a46d2e5f9f3512e 100644 --- a/sound/core/pcm_iec958.c +++ b/sound/core/pcm_iec958.c @@ -103,7 +103,7 @@ EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); /** * snd_pcm_create_iec958_consumer_hw_params - create IEC958 channel status - * @hw_params: the hw_params instance for extracting rate and sample format + * @params: the hw_params instance for extracting rate and sample format * @cs: channel status buffer, at least four bytes * @len: length of channel status buffer * diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index 860935e3aea492010c78e6274082dc32c5203e63..1bf6a3d9e0c2c868cde0d170bf5e53f5a9c7a574 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -39,6 +39,7 @@ static int do_alloc_pages(struct snd_card *card, int type, struct device *dev, if (max_alloc_per_card && card->total_pcm_alloc_bytes + size > max_alloc_per_card) return -ENOMEM; + err = snd_dma_alloc_pages(type, dev, size, dmab); if (!err) { mutex_lock(&card->memory_mutex); diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 9630d252394805bb5c223f0f080a86164a33e101..9e0b2d73faf6bfb066bb0c980b0311a4083fdedd 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1903,7 +1903,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream, switch (substream->runtime->status->state) { case SNDRV_PCM_STATE_PAUSED: snd_pcm_pause(substream, false); - /* fallthru */ + fallthrough; case SNDRV_PCM_STATE_SUSPENDED: snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); break; @@ -2811,7 +2811,7 @@ static int do_pcm_hwsync(struct snd_pcm_substream *substream) case SNDRV_PCM_STATE_DRAINING: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) return -EBADFD; - /* Fall through */ + fallthrough; case SNDRV_PCM_STATE_RUNNING: return snd_pcm_update_hw_ptr(substream); case SNDRV_PCM_STATE_PREPARED: @@ -3713,7 +3713,6 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, area->vm_end - area->vm_start, area->vm_page_prot); } #endif /* CONFIG_GENERIC_ALLOCATOR */ -#ifndef CONFIG_X86 /* for avoiding warnings arch/x86/mm/pat.c */ if (IS_ENABLED(CONFIG_HAS_DMA) && !substream->ops->page && (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV || substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_UC)) @@ -3722,7 +3721,6 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, substream->runtime->dma_area, substream->runtime->dma_addr, substream->runtime->dma_bytes); -#endif /* CONFIG_X86 */ /* mmap with fault handler */ area->vm_ops = &snd_pcm_vm_ops_data_fault; return 0; @@ -3816,7 +3814,7 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) case SNDRV_PCM_MMAP_OFFSET_STATUS_OLD: if (pcm_file->no_compat_mmap || !IS_ENABLED(CONFIG_64BIT)) return -ENXIO; - /* fallthrough */ + fallthrough; case SNDRV_PCM_MMAP_OFFSET_STATUS_NEW: if (!pcm_status_mmap_allowed(pcm_file)) return -ENXIO; @@ -3824,7 +3822,7 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) case SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD: if (pcm_file->no_compat_mmap || !IS_ENABLED(CONFIG_64BIT)) return -ENXIO; - /* fallthrough */ + fallthrough; case SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW: if (!pcm_control_mmap_allowed(pcm_file)) return -ENXIO; diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index 17f913657304399fa3775fe377d93082833cb4fb..c8b9c0b315d8f5a931677df2d59671953caf4448 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c @@ -168,10 +168,16 @@ static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct seq_oss_devinfo *dp; + long rc; + dp = file->private_data; if (snd_BUG_ON(!dp)) return -ENXIO; - return snd_seq_oss_ioctl(dp, cmd, arg); + + mutex_lock(®ister_mutex); + rc = snd_seq_oss_ioctl(dp, cmd, arg); + mutex_unlock(®ister_mutex); + return rc; } #ifdef CONFIG_COMPAT diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c index a35d429e4c27c15bac223221242413abc85f9c47..f9f57232a83f9c8e4f06b87c354d15f3452b8ca3 100644 --- a/sound/core/seq/oss/seq_oss_timer.c +++ b/sound/core/seq/oss/seq_oss_timer.c @@ -79,7 +79,7 @@ snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *ev) case TMR_WAIT_REL: parm += rec->cur_tick; rec->realtime = 0; - /* fall through */ + fallthrough; case TMR_WAIT_ABS: if (parm == 0) { rec->realtime = 1; diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index 198f285594e3104ad0a82f736b470ac82449ca58..81d2ef5e58116d5cfe7039ba86382329cad6c4b4 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c @@ -309,7 +309,7 @@ do_control(const struct snd_midi_op *ops, void *drv, break; case MIDI_CTL_MSB_DATA_ENTRY: chan->control[MIDI_CTL_LSB_DATA_ENTRY] = 0; - /* fall through */ + fallthrough; case MIDI_CTL_LSB_DATA_ENTRY: if (chan->param_type == SNDRV_MIDI_PARAM_TYPE_REGISTERED) rpn(ops, drv, chan, chset); diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index c42217e2dd195182a1ec0f7dc4bf640c5650457e..29ddb76187e57d4a85b5a6e980edaf3b515f882a 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -142,6 +142,9 @@ unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, struct snd_sg_buf *sg = dmab->private_data; unsigned int start, end, pg; + if (!sg) + return size; + start = ofs >> PAGE_SHIFT; end = (ofs + size - 1) >> PAGE_SHIFT; /* check page continuity */ diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index ab54d79654c95ccb3373d9b77b4a42639e238605..ab36f9898711a60aba8798a7eea1f88d86bab993 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Virtual master and slave controls + * Virtual master and follower controls * * Copyright (c) 2008 by Takashi Iwai */ @@ -21,15 +21,15 @@ struct link_ctl_info { }; /* - * link master - this contains a list of slave controls that are + * link master - this contains a list of follower controls that are * identical types, i.e. info returns the same value type and value * ranges, but may have different number of counts. * * The master control is so far only mono volume/switch for simplicity. - * The same value will be applied to all slaves. + * The same value will be applied to all followers. */ struct link_master { - struct list_head slaves; + struct list_head followers; struct link_ctl_info info; int val; /* the master value */ unsigned int tlv[4]; @@ -38,23 +38,23 @@ struct link_master { }; /* - * link slave - this contains a slave control element + * link follower - this contains a follower control element * - * It fakes the control callbacsk with additional attenuation by the - * master control. A slave may have either one or two channels. + * It fakes the control callbacks with additional attenuation by the + * master control. A follower may have either one or two channels. */ -struct link_slave { +struct link_follower { struct list_head list; struct link_master *master; struct link_ctl_info info; int vals[2]; /* current values */ unsigned int flags; struct snd_kcontrol *kctl; /* original kcontrol pointer */ - struct snd_kcontrol slave; /* the copy of original control entry */ + struct snd_kcontrol follower; /* the copy of original control entry */ }; -static int slave_update(struct link_slave *slave) +static int follower_update(struct link_follower *follower) { struct snd_ctl_elem_value *uctl; int err, ch; @@ -62,68 +62,68 @@ static int slave_update(struct link_slave *slave) uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (!uctl) return -ENOMEM; - uctl->id = slave->slave.id; - err = slave->slave.get(&slave->slave, uctl); + uctl->id = follower->follower.id; + err = follower->follower.get(&follower->follower, uctl); if (err < 0) goto error; - for (ch = 0; ch < slave->info.count; ch++) - slave->vals[ch] = uctl->value.integer.value[ch]; + for (ch = 0; ch < follower->info.count; ch++) + follower->vals[ch] = uctl->value.integer.value[ch]; error: kfree(uctl); return err < 0 ? err : 0; } -/* get the slave ctl info and save the initial values */ -static int slave_init(struct link_slave *slave) +/* get the follower ctl info and save the initial values */ +static int follower_init(struct link_follower *follower) { struct snd_ctl_elem_info *uinfo; int err; - if (slave->info.count) { + if (follower->info.count) { /* already initialized */ - if (slave->flags & SND_CTL_SLAVE_NEED_UPDATE) - return slave_update(slave); + if (follower->flags & SND_CTL_FOLLOWER_NEED_UPDATE) + return follower_update(follower); return 0; } uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL); if (!uinfo) return -ENOMEM; - uinfo->id = slave->slave.id; - err = slave->slave.info(&slave->slave, uinfo); + uinfo->id = follower->follower.id; + err = follower->follower.info(&follower->follower, uinfo); if (err < 0) { kfree(uinfo); return err; } - slave->info.type = uinfo->type; - slave->info.count = uinfo->count; - if (slave->info.count > 2 || - (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER && - slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) { - pr_err("ALSA: vmaster: invalid slave element\n"); + follower->info.type = uinfo->type; + follower->info.count = uinfo->count; + if (follower->info.count > 2 || + (follower->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER && + follower->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) { + pr_err("ALSA: vmaster: invalid follower element\n"); kfree(uinfo); return -EINVAL; } - slave->info.min_val = uinfo->value.integer.min; - slave->info.max_val = uinfo->value.integer.max; + follower->info.min_val = uinfo->value.integer.min; + follower->info.max_val = uinfo->value.integer.max; kfree(uinfo); - return slave_update(slave); + return follower_update(follower); } /* initialize master volume */ static int master_init(struct link_master *master) { - struct link_slave *slave; + struct link_follower *follower; if (master->info.count) return 0; /* already initialized */ - list_for_each_entry(slave, &master->slaves, list) { - int err = slave_init(slave); + list_for_each_entry(follower, &master->followers, list) { + int err = follower_init(follower); if (err < 0) return err; - master->info = slave->info; + master->info = follower->info; master->info.count = 1; /* always mono */ /* set full volume as default (= no attenuation) */ master->val = master->info.max_val; @@ -134,113 +134,113 @@ static int master_init(struct link_master *master) return -ENOENT; } -static int slave_get_val(struct link_slave *slave, - struct snd_ctl_elem_value *ucontrol) +static int follower_get_val(struct link_follower *follower, + struct snd_ctl_elem_value *ucontrol) { int err, ch; - err = slave_init(slave); + err = follower_init(follower); if (err < 0) return err; - for (ch = 0; ch < slave->info.count; ch++) - ucontrol->value.integer.value[ch] = slave->vals[ch]; + for (ch = 0; ch < follower->info.count; ch++) + ucontrol->value.integer.value[ch] = follower->vals[ch]; return 0; } -static int slave_put_val(struct link_slave *slave, - struct snd_ctl_elem_value *ucontrol) +static int follower_put_val(struct link_follower *follower, + struct snd_ctl_elem_value *ucontrol) { int err, ch, vol; - err = master_init(slave->master); + err = master_init(follower->master); if (err < 0) return err; - switch (slave->info.type) { + switch (follower->info.type) { case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - for (ch = 0; ch < slave->info.count; ch++) + for (ch = 0; ch < follower->info.count; ch++) ucontrol->value.integer.value[ch] &= - !!slave->master->val; + !!follower->master->val; break; case SNDRV_CTL_ELEM_TYPE_INTEGER: - for (ch = 0; ch < slave->info.count; ch++) { + for (ch = 0; ch < follower->info.count; ch++) { /* max master volume is supposed to be 0 dB */ vol = ucontrol->value.integer.value[ch]; - vol += slave->master->val - slave->master->info.max_val; - if (vol < slave->info.min_val) - vol = slave->info.min_val; - else if (vol > slave->info.max_val) - vol = slave->info.max_val; + vol += follower->master->val - follower->master->info.max_val; + if (vol < follower->info.min_val) + vol = follower->info.min_val; + else if (vol > follower->info.max_val) + vol = follower->info.max_val; ucontrol->value.integer.value[ch] = vol; } break; } - return slave->slave.put(&slave->slave, ucontrol); + return follower->follower.put(&follower->follower, ucontrol); } /* - * ctl callbacks for slaves + * ctl callbacks for followers */ -static int slave_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) +static int follower_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { - struct link_slave *slave = snd_kcontrol_chip(kcontrol); - return slave->slave.info(&slave->slave, uinfo); + struct link_follower *follower = snd_kcontrol_chip(kcontrol); + return follower->follower.info(&follower->follower, uinfo); } -static int slave_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int follower_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - struct link_slave *slave = snd_kcontrol_chip(kcontrol); - return slave_get_val(slave, ucontrol); + struct link_follower *follower = snd_kcontrol_chip(kcontrol); + return follower_get_val(follower, ucontrol); } -static int slave_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int follower_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - struct link_slave *slave = snd_kcontrol_chip(kcontrol); + struct link_follower *follower = snd_kcontrol_chip(kcontrol); int err, ch, changed = 0; - err = slave_init(slave); + err = follower_init(follower); if (err < 0) return err; - for (ch = 0; ch < slave->info.count; ch++) { - if (slave->vals[ch] != ucontrol->value.integer.value[ch]) { + for (ch = 0; ch < follower->info.count; ch++) { + if (follower->vals[ch] != ucontrol->value.integer.value[ch]) { changed = 1; - slave->vals[ch] = ucontrol->value.integer.value[ch]; + follower->vals[ch] = ucontrol->value.integer.value[ch]; } } if (!changed) return 0; - err = slave_put_val(slave, ucontrol); + err = follower_put_val(follower, ucontrol); if (err < 0) return err; return 1; } -static int slave_tlv_cmd(struct snd_kcontrol *kcontrol, - int op_flag, unsigned int size, - unsigned int __user *tlv) +static int follower_tlv_cmd(struct snd_kcontrol *kcontrol, + int op_flag, unsigned int size, + unsigned int __user *tlv) { - struct link_slave *slave = snd_kcontrol_chip(kcontrol); + struct link_follower *follower = snd_kcontrol_chip(kcontrol); /* FIXME: this assumes that the max volume is 0 dB */ - return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv); + return follower->follower.tlv.c(&follower->follower, op_flag, size, tlv); } -static void slave_free(struct snd_kcontrol *kcontrol) +static void follower_free(struct snd_kcontrol *kcontrol) { - struct link_slave *slave = snd_kcontrol_chip(kcontrol); - if (slave->slave.private_free) - slave->slave.private_free(&slave->slave); - if (slave->master) - list_del(&slave->list); - kfree(slave); + struct link_follower *follower = snd_kcontrol_chip(kcontrol); + if (follower->follower.private_free) + follower->follower.private_free(&follower->follower); + if (follower->master) + list_del(&follower->list); + kfree(follower); } /* - * Add a slave control to the group with the given master control + * Add a follower control to the group with the given master control * - * All slaves must be the same type (returning the same information + * All followers must be the same type (returning the same information * via info callback). The function doesn't check it, so it's your * responsibility. * @@ -249,35 +249,36 @@ static void slave_free(struct snd_kcontrol *kcontrol) * - logarithmic volume control (dB level), no linear volume * - master can only attenuate the volume, no gain */ -int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, - unsigned int flags) +int _snd_ctl_add_follower(struct snd_kcontrol *master, + struct snd_kcontrol *follower, + unsigned int flags) { struct link_master *master_link = snd_kcontrol_chip(master); - struct link_slave *srec; + struct link_follower *srec; - srec = kzalloc(struct_size(srec, slave.vd, slave->count), + srec = kzalloc(struct_size(srec, follower.vd, follower->count), GFP_KERNEL); if (!srec) return -ENOMEM; - srec->kctl = slave; - srec->slave = *slave; - memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); + srec->kctl = follower; + srec->follower = *follower; + memcpy(srec->follower.vd, follower->vd, follower->count * sizeof(*follower->vd)); srec->master = master_link; srec->flags = flags; /* override callbacks */ - slave->info = slave_info; - slave->get = slave_get; - slave->put = slave_put; - if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) - slave->tlv.c = slave_tlv_cmd; - slave->private_data = srec; - slave->private_free = slave_free; - - list_add_tail(&srec->list, &master_link->slaves); + follower->info = follower_info; + follower->get = follower_get; + follower->put = follower_put; + if (follower->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) + follower->tlv.c = follower_tlv_cmd; + follower->private_data = srec; + follower->private_free = follower_free; + + list_add_tail(&srec->list, &master_link->followers); return 0; } -EXPORT_SYMBOL(_snd_ctl_add_slave); +EXPORT_SYMBOL(_snd_ctl_add_follower); /* * ctl callbacks for master controls @@ -309,20 +310,20 @@ static int master_get(struct snd_kcontrol *kcontrol, return 0; } -static int sync_slaves(struct link_master *master, int old_val, int new_val) +static int sync_followers(struct link_master *master, int old_val, int new_val) { - struct link_slave *slave; + struct link_follower *follower; struct snd_ctl_elem_value *uval; uval = kmalloc(sizeof(*uval), GFP_KERNEL); if (!uval) return -ENOMEM; - list_for_each_entry(slave, &master->slaves, list) { + list_for_each_entry(follower, &master->followers, list) { master->val = old_val; - uval->id = slave->slave.id; - slave_get_val(slave, uval); + uval->id = follower->follower.id; + follower_get_val(follower, uval); master->val = new_val; - slave_put_val(slave, uval); + follower_put_val(follower, uval); } kfree(uval); return 0; @@ -344,7 +345,7 @@ static int master_put(struct snd_kcontrol *kcontrol, if (new_val == old_val) return 0; - err = sync_slaves(master, old_val, new_val); + err = sync_followers(master, old_val, new_val); if (err < 0) return err; if (master->hook && !first_init) @@ -355,17 +356,17 @@ static int master_put(struct snd_kcontrol *kcontrol, static void master_free(struct snd_kcontrol *kcontrol) { struct link_master *master = snd_kcontrol_chip(kcontrol); - struct link_slave *slave, *n; + struct link_follower *follower, *n; - /* free all slave links and retore the original slave kctls */ - list_for_each_entry_safe(slave, n, &master->slaves, list) { - struct snd_kcontrol *sctl = slave->kctl; + /* free all follower links and retore the original follower kctls */ + list_for_each_entry_safe(follower, n, &master->followers, list) { + struct snd_kcontrol *sctl = follower->kctl; struct list_head olist = sctl->list; - memcpy(sctl, &slave->slave, sizeof(*sctl)); - memcpy(sctl->vd, slave->slave.vd, + memcpy(sctl, &follower->follower, sizeof(*sctl)); + memcpy(sctl->vd, follower->follower.vd, sctl->count * sizeof(*sctl->vd)); sctl->list = olist; /* keep the current linked-list */ - kfree(slave); + kfree(follower); } kfree(master); } @@ -378,8 +379,8 @@ static void master_free(struct snd_kcontrol *kcontrol) * * Creates a virtual master control with the given name string. * - * After creating a vmaster element, you can add the slave controls - * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached(). + * After creating a vmaster element, you can add the follower controls + * via snd_ctl_add_follower() or snd_ctl_add_follower_uncached(). * * The optional argument @tlv can be used to specify the TLV information * for dB scale of the master control. It should be a single element @@ -403,7 +404,7 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, master = kzalloc(sizeof(*master), GFP_KERNEL); if (!master) return NULL; - INIT_LIST_HEAD(&master->slaves); + INIT_LIST_HEAD(&master->followers); kctl = snd_ctl_new1(&knew, master); if (!kctl) { @@ -455,11 +456,11 @@ int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook); /** - * snd_ctl_sync_vmaster - Sync the vmaster slaves and hook + * snd_ctl_sync_vmaster - Sync the vmaster followers and hook * @kcontrol: vmaster kctl element * @hook_only: sync only the hook * - * Forcibly call the put callback of each slave and call the hook function + * Forcibly call the put callback of each follower and call the hook function * to synchronize with the current value of the given vmaster element. * NOP when NULL is passed to @kcontrol. */ @@ -476,7 +477,7 @@ void snd_ctl_sync_vmaster(struct snd_kcontrol *kcontrol, bool hook_only) if (err < 0) return; first_init = err; - err = sync_slaves(master, master->val, master->val); + err = sync_followers(master, master->val, master->val); if (err < 0) return; } @@ -487,34 +488,34 @@ void snd_ctl_sync_vmaster(struct snd_kcontrol *kcontrol, bool hook_only) EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster); /** - * snd_ctl_apply_vmaster_slaves - Apply function to each vmaster slave + * snd_ctl_apply_vmaster_followers - Apply function to each vmaster follower * @kctl: vmaster kctl element * @func: function to apply * @arg: optional function argument * - * Apply the function @func to each slave kctl of the given vmaster kctl. + * Apply the function @func to each follower kctl of the given vmaster kctl. * Returns 0 if successful, or a negative error code. */ -int snd_ctl_apply_vmaster_slaves(struct snd_kcontrol *kctl, - int (*func)(struct snd_kcontrol *vslave, - struct snd_kcontrol *slave, - void *arg), - void *arg) +int snd_ctl_apply_vmaster_followers(struct snd_kcontrol *kctl, + int (*func)(struct snd_kcontrol *vfollower, + struct snd_kcontrol *follower, + void *arg), + void *arg) { struct link_master *master; - struct link_slave *slave; + struct link_follower *follower; int err; master = snd_kcontrol_chip(kctl); err = master_init(master); if (err < 0) return err; - list_for_each_entry(slave, &master->slaves, list) { - err = func(slave->kctl, &slave->slave, arg); + list_for_each_entry(follower, &master->followers, list) { + err = func(follower->kctl, &follower->follower, arg); if (err < 0) return err; } return 0; } -EXPORT_SYMBOL_GPL(snd_ctl_apply_vmaster_slaves); +EXPORT_SYMBOL_GPL(snd_ctl_apply_vmaster_followers); diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index 2f6e8023e05cd19c4f6b4099a89e1f91642825e5..eb23c55323ae1d5166d8093ef5d967088b4929db 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c @@ -354,7 +354,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) instr_4op = 1; break; } - /* fall through */ + fallthrough; default: spin_unlock_irqrestore(&opl3->voice_lock, flags); return; @@ -443,7 +443,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) switch (connection) { case 0x03: snd_opl3_calc_volume(&vol_op[2], vel, chan); - /* fallthru */ + fallthrough; case 0x02: snd_opl3_calc_volume(&vol_op[0], vel, chan); break; diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index ffab0400d7fbed908e4ce7522f023d9362789e0a..26d591fe6a6bff30155e53791a1963d3130601c2 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -511,8 +511,9 @@ irqreturn_t snd_vx_threaded_irq_handler(int irq, void *dev) /* The start on time code conditions are filled (ie the time code * received by the board is equal to one of those given to it). */ - if (events & TIME_CODE_EVENT_PENDING) + if (events & TIME_CODE_EVENT_PENDING) { ; /* so far, nothing to do yet */ + } /* The frequency has changed on the board (UER mode). */ if (events & FREQUENCY_CHANGE_EVENT_PENDING) diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c index 14abbe7175b69b0400c33c327ae8c04c106ca110..b596bec19774c8dfe49fa73370ac94bdd1876cb4 100644 --- a/sound/firewire/cmp.c +++ b/sound/firewire/cmp.c @@ -293,7 +293,6 @@ static int pcr_set_check(struct cmp_connection *c, __be32 pcr) /** * cmp_connection_establish - establish a connection to the target * @c: the connection manager - * @max_payload_bytes: the amount of data (including CIP headers) per packet * * This function establishes a point-to-point connection from the local * computer to the target by allocating isochronous resources (channel and diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index 01a47ac7bb2da69c3f918e3725df67a3139ff9dd..4e6b0e449ee45ecb94605c81ec312cfbd77226b0 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -24,6 +24,9 @@ #define V3_NO_ADAT_OPT_OUT_IFACE_A 0x00040000 #define V3_NO_ADAT_OPT_OUT_IFACE_B 0x00400000 +#define V3_MSG_FLAG_CLK_CHANGED 0x00000002 +#define V3_CLK_WAIT_MSEC 4000 + int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu, unsigned int *rate) { @@ -79,9 +82,16 @@ int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu, return err; if (need_to_wait) { - /* Cost expensive. */ - if (msleep_interruptible(4000) > 0) - return -EINTR; + int result; + + motu->msg = 0; + result = wait_event_interruptible_timeout(motu->hwdep_wait, + motu->msg & V3_MSG_FLAG_CLK_CHANGED, + msecs_to_jiffies(V3_CLK_WAIT_MSEC)); + if (result < 0) + return result; + if (result == 0) + return -ETIMEDOUT; } return 0; diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index a38a2af1654f72a0bf50b5c8e07b3d108980c856..abe7a1b16fe1eacbc5a312232a2818eebf848ef5 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -150,9 +150,12 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev) { unsigned char val; int timeout; + int dma_run_state; snd_hdac_stream_clear(azx_dev); + dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START; + snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET); udelay(3); timeout = 300; @@ -162,6 +165,10 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev) if (val) break; } while (--timeout); + + if (azx_dev->bus->dma_stop_delay && dma_run_state) + udelay(azx_dev->bus->dma_stop_delay); + val &= ~SD_CTL_STREAM_RESET; snd_hdac_stream_writeb(azx_dev, SD_CTL, val); udelay(3); diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 4a028f42bb74047308043b1b9def666ee00c634d..52f05adb18704f0627dff399701c6d8b647b6efa 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -39,7 +39,7 @@ * D7: consumer serial port enable (CS4237B,CS4238B) * D6: channels status block reset (CS4237B,CS4238B) * D5: user bit in sub-frame of digital audio data (CS4237B,CS4238B) - * D4: validity bit bit in sub-frame of digital audio data (CS4237B,CS4238B) + * D4: validity bit in sub-frame of digital audio data (CS4237B,CS4238B) * * C5 lower channel status (digital serial data description) (CS4237B,CS4238B) * D7-D6: first two bits of category code diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index d1135f6ae1045f3941096d5ae3dea6392ee9933b..5f8d7e8a54775f768f58075aa3b3633935d361ba 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -955,7 +955,7 @@ static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele case 0x1887: case 0x1888: return snd_ctl_enum_info(uinfo, 1, 5, texts5Source); - case 0x1869: /* DS somewhat contradictory for 1869: could be be 5 or 8 */ + case 0x1869: /* DS somewhat contradictory for 1869: could be 5 or 8 */ case 0x1879: return snd_ctl_enum_info(uinfo, 1, 8, texts8Source); default: @@ -998,7 +998,7 @@ static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem val = 3; } else retVal = snd_es18xx_mixer_bits(chip, 0x7a, 0x08, 0x00) != 0x00; - /* fall through */ + fallthrough; /* 4 source chips */ case 0x1868: case 0x1878: diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c index ce409e75ae51ffc7d5518a7427f8b33db2dfb125..65f9f46c9f583a480c4cbd162365f4752b192c5d 100644 --- a/sound/isa/galaxy/galaxy.c +++ b/sound/isa/galaxy/galaxy.c @@ -247,7 +247,7 @@ static int snd_galaxy_match(struct device *dev, unsigned int n) break; case 2: irq[n] = 9; - /* Fall through */ + fallthrough; case 9: wss_config[n] |= WSS_CONFIG_IRQ_9; break; @@ -292,7 +292,7 @@ static int snd_galaxy_match(struct device *dev, unsigned int n) case 1: if (dma1[n] == 0) break; - /* Fall through */ + fallthrough; default: dev_err(dev, "invalid capture DMA %d\n", dma2[n]); return 0; @@ -322,7 +322,7 @@ mpu: break; case 2: mpu_irq[n] = 9; - /* Fall through */ + fallthrough; case 9: config[n] |= GALAXY_CONFIG_MPUIRQ_2; break; diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c index 07bfcda43827384dc5e756f9205d44569e4f3f69..9a1ab5872c4fabf7cf1b037338cf4af28ed38aae 100644 --- a/sound/isa/gus/gus_reset.c +++ b/sound/isa/gus/gus_reset.c @@ -9,8 +9,6 @@ #include #include -extern void snd_gf1_timers_init(struct snd_gus_card * gus); -extern void snd_gf1_timers_done(struct snd_gus_card * gus); extern int snd_gf1_synth_init(struct snd_gus_card * gus); extern void snd_gf1_synth_done(struct snd_gus_card * gus); diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c index 7586619770b30e64c4cb8605fc8cd53ed67d4672..4fb4ed79e262c0a0ca73eda57e737a10bc03c7e9 100644 --- a/sound/isa/gus/gus_uart.c +++ b/sound/isa/gus/gus_uart.c @@ -13,7 +13,8 @@ static void snd_gf1_interrupt_midi_in(struct snd_gus_card * gus) { int count; - unsigned char stat, data, byte; + unsigned char stat, byte; + __always_unused unsigned char data; unsigned long flags; count = 10; diff --git a/sound/isa/msnd/msnd_pinnacle_mixer.c b/sound/isa/msnd/msnd_pinnacle_mixer.c index 02c566fca9e5671aa57712a8dd2d5a49eb129f29..63633bd41e5b6ccc85168fad989f0e09711e8ab1 100644 --- a/sound/isa/msnd/msnd_pinnacle_mixer.c +++ b/sound/isa/msnd/msnd_pinnacle_mixer.c @@ -219,11 +219,9 @@ static int snd_msndmix_set(struct snd_msnd *dev, int d, int left, int right) case MSND_MIXER_VOLUME: /* master volume */ writew(wLeft, dev->SMA + SMA_wCurrMastVolLeft); writew(wRight, dev->SMA + SMA_wCurrMastVolRight); - /* fall through */ - + fallthrough; case MSND_MIXER_AUX: /* aux pot control */ /* scaled by master volume */ - /* fall through */ /* digital controls */ case MSND_MIXER_SYNTH: /* synth vol (dsp mix) */ diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index b039429e687171c5cf40fe942383f53acd3f82fa..44ed1b65f6ce80b26e11ad8602618570a3e967c8 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -163,13 +163,13 @@ static int aci_busy_wait(struct snd_miro_aci *aci) switch (timeout-ACI_MINTIME) { case 0 ... 9: out /= 10; - /* fall through */ + fallthrough; case 10 ... 19: out /= 10; - /* fall through */ + fallthrough; case 20 ... 30: out /= 10; - /* fall through */ + fallthrough; default: set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(out); @@ -824,7 +824,7 @@ static unsigned char snd_miro_read(struct snd_miro *chip, retval = inb(chip->mc_base + 9); break; } - /* fall through */ + fallthrough; case OPTi9XX_HW_82C929: retval = inb(chip->mc_base + reg); @@ -854,7 +854,7 @@ static void snd_miro_write(struct snd_miro *chip, unsigned char reg, outb(value, chip->mc_base + 9); break; } - /* fall through */ + fallthrough; case OPTi9XX_HW_82C929: outb(value, chip->mc_base + reg); diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 0e6d20e4915854f99517c7cc47dbe5a5dafe0773..881d3b5711d273c8f92563131fb460f920668e16 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -249,7 +249,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, retval = inb(chip->mc_base + 9); break; } - /* Fall through */ + fallthrough; case OPTi9XX_HW_82C928: case OPTi9XX_HW_82C929: @@ -292,7 +292,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, outb(value, chip->mc_base + 9); break; } - /* Fall through */ + fallthrough; case OPTi9XX_HW_82C928: case OPTi9XX_HW_82C929: @@ -343,7 +343,7 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc); /* enable wave audio */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); - /* Fall through */ + fallthrough; case OPTi9XX_HW_82C925: /* enable WSS mode */ @@ -380,7 +380,8 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, case OPTi9XX_HW_82C931: /* disable 3D sound (set GPIO1 as output, low) */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(20), 0x04, 0x0c); - /* fall through */ + fallthrough; + case OPTi9XX_HW_82C933: /* * The BTC 1817DW has QS1000 wavetable which is connected @@ -392,7 +393,8 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, * or digital input signal. */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01); - /* fall through */ + fallthrough; + case OPTi9XX_HW_82C930: snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03); snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff); diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index e33dfe165276bf44f45e34fc0c99b202fe1a4536..86d0d2fdf48a868f6df3183672267640bc8d3358 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c @@ -116,13 +116,13 @@ static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream) chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; break; } - /* fall through */ + fallthrough; case SB_HW_201: if (rate > 23000) { chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; break; } - /* fall through */ + fallthrough; case SB_HW_20: chip->playback_format = SB_DSP_LO_OUTPUT_AUTO; break; @@ -261,7 +261,7 @@ static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream) chip->capture_format = SB_DSP_HI_INPUT_AUTO; break; } - /* fall through */ + fallthrough; case SB_HW_20: chip->capture_format = SB_DSP_LO_INPUT_AUTO; break; @@ -361,7 +361,7 @@ irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip) case SB_MODE_PLAYBACK_16: /* ok.. playback is active */ if (chip->hardware != SB_HW_JAZZ16) break; - /* fall through */ + fallthrough; case SB_MODE_PLAYBACK_8: substream = chip->playback_substream; if (chip->playback_format == SB_DSP_OUTPUT) @@ -371,7 +371,7 @@ irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip) case SB_MODE_CAPTURE_16: if (chip->hardware != SB_HW_JAZZ16) break; - /* fall through */ + fallthrough; case SB_MODE_CAPTURE_8: substream = chip->capture_substream; if (chip->capture_format == SB_DSP_INPUT) diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c index 823ccfa089b27d3f1d22f4a2cdf7166e3d7169db..81c6a98307273e24ce53d31d3f68a8d6c9c53d10 100644 --- a/sound/oss/dmasound/dmasound_atari.c +++ b/sound/oss/dmasound/dmasound_atari.c @@ -1449,7 +1449,7 @@ static int FalconMixerIoctl(u_int cmd, u_long arg) tt_dmasnd.input_gain = RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 | RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff); - /* fall through - return set value */ + fallthrough; /* return set value */ case SOUND_MIXER_READ_MIC: return IOCTL_OUT(arg, RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) | diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index f802ea331e244d86a665b1fb2b8ad0b17e8beca5..38f25e97538fa8468a1bdecbae8147abb1168b4e 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -1478,13 +1478,13 @@ static int dmasound_setup(char *str) printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius); else catchRadius = ints[3]; - /* fall through */ + fallthrough; case 2: if (ints[1] < MIN_BUFFERS) printk("dmasound_setup: invalid number of buffers, using default = %d\n", numWriteBufs); else numWriteBufs = ints[1]; - /* fall through */ + fallthrough; case 1: if ((size = ints[2]) < 256) /* check for small buffer specs */ size <<= 10 ; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 6758c072000e67db865fa69a59eac8e1fd3a3c2c..012a7ee849e8aad424e82752c73250b5d0a0d845 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -218,11 +218,11 @@ static int snd_ac97_valid_reg(struct snd_ac97 *ac97, unsigned short reg) case AC97_ID_ST_AC97_ID4: if (reg == 0x08) return 0; - /* fall through */ + fallthrough; case AC97_ID_ST7597: if (reg == 0x22 || reg == 0x7a) return 1; - /* fall through */ + fallthrough; case AC97_ID_AK4540: case AC97_ID_AK4542: if (reg <= 0x1c || reg == 0x20 || reg == 0x26 || reg >= 0x7c) diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 45ef0f52ec55b803e496d5a7045a1039d8f322f5..1627a74baf3c5878d4e6dedde745e194f64d1e28 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -19,7 +19,7 @@ static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97, const char *name); static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name, const unsigned int *tlv, - const char * const *slaves); + const char * const *followers); /* * Chip specific initialization @@ -1791,10 +1791,10 @@ static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = { AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0), }; -/* black list to avoid HP/Line jack-sense controls +/* deny list to avoid HP/Line jack-sense controls * (SS vendor << 16 | device) */ -static const unsigned int ad1981_jacks_blacklist[] = { +static const unsigned int ad1981_jacks_denylist[] = { 0x10140523, /* Thinkpad R40 */ 0x10140534, /* Thinkpad X31 */ 0x10140537, /* Thinkpad T41p */ @@ -1821,7 +1821,7 @@ static int check_list(struct snd_ac97 *ac97, const unsigned int *list) static int patch_ad1981a_specific(struct snd_ac97 * ac97) { - if (check_list(ac97, ad1981_jacks_blacklist)) + if (check_list(ac97, ad1981_jacks_denylist)) return 0; return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense, ARRAY_SIZE(snd_ac97_ad1981x_jack_sense)); @@ -1835,10 +1835,10 @@ static const struct snd_ac97_build_ops patch_ad1981a_build_ops = { #endif }; -/* white list to enable HP jack-sense bits +/* allow list to enable HP jack-sense bits * (SS vendor << 16 | device) */ -static const unsigned int ad1981_jacks_whitelist[] = { +static const unsigned int ad1981_jacks_allowlist[] = { 0x0e11005a, /* HP nc4000/4010 */ 0x103c0890, /* HP nc6000 */ 0x103c0938, /* HP nc4220 */ @@ -1853,7 +1853,7 @@ static const unsigned int ad1981_jacks_whitelist[] = { static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97) { - if (check_list(ac97, ad1981_jacks_whitelist)) + if (check_list(ac97, ad1981_jacks_allowlist)) /* enable headphone jack sense */ snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11); } @@ -1877,7 +1877,7 @@ static int patch_ad1981b_specific(struct snd_ac97 *ac97) if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0) return err; - if (check_list(ac97, ad1981_jacks_blacklist)) + if (check_list(ac97, ad1981_jacks_denylist)) return 0; return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense, ARRAY_SIZE(snd_ac97_ad1981x_jack_sense)); @@ -3373,7 +3373,7 @@ AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0), AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0), }; -static const char * const slave_vols_vt1616[] = { +static const char * const follower_vols_vt1616[] = { "Front Playback Volume", "Surround Playback Volume", "Center Playback Volume", @@ -3381,7 +3381,7 @@ static const char * const slave_vols_vt1616[] = { NULL }; -static const char * const slave_sws_vt1616[] = { +static const char * const follower_sws_vt1616[] = { "Front Playback Switch", "Surround Playback Switch", "Center Playback Switch", @@ -3400,10 +3400,10 @@ static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97, return snd_ctl_find_id(ac97->bus->card, &id); } -/* create a virtual master control and add slaves */ +/* create a virtual master control and add followers */ static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name, const unsigned int *tlv, - const char * const *slaves) + const char * const *followers) { struct snd_kcontrol *kctl; const char * const *s; @@ -3416,16 +3416,16 @@ static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name, if (err < 0) return err; - for (s = slaves; *s; s++) { + for (s = followers; *s; s++) { struct snd_kcontrol *sctl; sctl = snd_ac97_find_mixer_ctl(ac97, *s); if (!sctl) { dev_dbg(ac97->bus->card->dev, - "Cannot find slave %s, skipped\n", *s); + "Cannot find follower %s, skipped\n", *s); continue; } - err = snd_ctl_add_slave(kctl, sctl); + err = snd_ctl_add_follower(kctl, sctl); if (err < 0) return err; } @@ -3451,12 +3451,12 @@ static int patch_vt1616_specific(struct snd_ac97 * ac97) snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Front Playback"); err = snd_ac97_add_vmaster(ac97, "Master Playback Volume", - kctl->tlv.p, slave_vols_vt1616); + kctl->tlv.p, follower_vols_vt1616); if (err < 0) return err; err = snd_ac97_add_vmaster(ac97, "Master Playback Switch", - NULL, slave_sws_vt1616); + NULL, follower_sws_vt1616); if (err < 0) return err; diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index a9540c2c4a1a9e7da8c4a48b6f353b92289a331d..023c35a2a95139eed93c633b41b2c61934880d99 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -1904,7 +1904,7 @@ static int snd_asihpi_tuner_band_get(struct snd_kcontrol *kcontrol, */ u16 band, idx; u16 tuner_bands[HPI_TUNER_BAND_LAST]; - u32 num_bands = 0; + __always_unused u32 num_bands; num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, HPI_TUNER_BAND_LAST); @@ -1931,7 +1931,7 @@ static int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol, unsigned int idx; u16 band; u16 tuner_bands[HPI_TUNER_BAND_LAST]; - u32 num_bands = 0; + __always_unused u32 num_bands; num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, HPI_TUNER_BAND_LAST); @@ -2161,7 +2161,6 @@ static int snd_card_asihpi_mux_count_sources(struct snd_kcontrol *snd_control) static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - int err; u16 src_node_type, src_node_index; u32 h_control = kcontrol->private_value; @@ -2174,10 +2173,9 @@ static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol, uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - err = - hpi_multiplexer_query_source(h_control, - uinfo->value.enumerated.item, - &src_node_type, &src_node_index); + hpi_multiplexer_query_source(h_control, + uinfo->value.enumerated.item, + &src_node_type, &src_node_index); sprintf(uinfo->value.enumerated.name, "%s %d", asihpi_src_names[src_node_type - HPI_SOURCENODE_NONE], diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h index ad912f9dac7e44a50bc4a1e1d8f0151c82220252..6859d51389f5dade7c9bbb21654fe7fb9c1ce5e7 100644 --- a/sound/pci/asihpi/hpi_internal.h +++ b/sound/pci/asihpi/hpi_internal.h @@ -53,7 +53,7 @@ If handle is invalid *pPhysicalAddr is set to zero and return 1 u16 hpios_locked_mem_get_phys_addr(struct consistent_dma_area *locked_mem_handle, u32 *p_physical_addr); -/** Get the CPU address of of memory represented by LockedMemHandle. +/** Get the CPU address of memory represented by LockedMemHandle. If handle is NULL *ppvVirtualAddr is set to NULL and return 1 */ diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c index 968510bc2552a122ed2a360eefd5ab39a27fdb1d..7d1abaedb46acc37fb7c47dbfb7c7749b7b2c36e 100644 --- a/sound/pci/asihpi/hpicmn.c +++ b/sound/pci/asihpi/hpicmn.c @@ -28,10 +28,12 @@ struct hpi_adapters_list { static struct hpi_adapters_list adapters; /** -* Given an HPI Message that was sent out and a response that was received, -* validate that the response has the correct fields filled in, -* i.e ObjectType, Function etc -**/ + * hpi_validate_response - Given an HPI Message that was sent out and + * a response that was received, validate that the response has the + * correct fields filled in, i.e ObjectType, Function etc + * @phm: message + * @phr: response + */ u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr) { if (phr->type != HPI_TYPE_RESPONSE) { @@ -106,10 +108,11 @@ void hpi_delete_adapter(struct hpi_adapter_obj *pao) } /** -* FindAdapter returns a pointer to the struct hpi_adapter_obj with -* index wAdapterIndex in an HPI_ADAPTERS_LIST structure. -* -*/ + * hpi_find_adapter - FindAdapter returns a pointer to the struct + * hpi_adapter_obj with index wAdapterIndex in an HPI_ADAPTERS_LIST + * structure. + * @adapter_index: value in [0, HPI_MAX_ADAPTERS[ + */ struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index) { struct hpi_adapter_obj *pao = NULL; @@ -137,10 +140,9 @@ struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index) } /** -* -* wipe an HPI_ADAPTERS_LIST structure. -* -**/ + * wipe_adapter_list - wipe an HPI_ADAPTERS_LIST structure. + * + */ static void wipe_adapter_list(void) { memset(&adapters, 0, sizeof(adapters)); diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 85d3b4e954898b68c84e1c0d0f0944e416c208d0..a25d754558028aa0cf4ee18f2c5d6430b660b5f5 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -896,15 +896,15 @@ static int snd_atiixp_playback_prepare(struct snd_pcm_substream *substream) case 8: data |= ATI_REG_OUT_DMA_SLOT_BIT(10) | ATI_REG_OUT_DMA_SLOT_BIT(11); - /* fall through */ + fallthrough; case 6: data |= ATI_REG_OUT_DMA_SLOT_BIT(7) | ATI_REG_OUT_DMA_SLOT_BIT(8); - /* fall through */ + fallthrough; case 4: data |= ATI_REG_OUT_DMA_SLOT_BIT(6) | ATI_REG_OUT_DMA_SLOT_BIT(9); - /* fall through */ + fallthrough; default: data |= ATI_REG_OUT_DMA_SLOT_BIT(3) | ATI_REG_OUT_DMA_SLOT_BIT(4); diff --git a/sound/pci/au88x0/au88x0_a3ddata.c b/sound/pci/au88x0/au88x0_a3ddata.c index 18623cb6bc523de9983a7487eb81a223c4ef3e7b..a5da3b3a546a2e8358f72ee3aa71c72955d910d0 100644 --- a/sound/pci/au88x0/au88x0_a3ddata.c +++ b/sound/pci/au88x0/au88x0_a3ddata.c @@ -21,7 +21,7 @@ static const a3d_Hrtf_t A3dHrirZeros = { 0, 0, 0 }; -static const a3d_Hrtf_t A3dHrirImpulse = { +static __maybe_unused const a3d_Hrtf_t A3dHrirImpulse = { 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -30,7 +30,7 @@ static const a3d_Hrtf_t A3dHrirImpulse = { 0, 0, 0 }; -static const a3d_Hrtf_t A3dHrirOnes = { +static __maybe_unused const a3d_Hrtf_t A3dHrirOnes = { 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, @@ -47,7 +47,7 @@ static const a3d_Hrtf_t A3dHrirOnes = { 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff }; -static const a3d_Hrtf_t A3dHrirSatTest = { +static __maybe_unused const a3d_Hrtf_t A3dHrirSatTest = { 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, @@ -59,7 +59,7 @@ static const a3d_Hrtf_t A3dHrirSatTest = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static const a3d_Hrtf_t A3dHrirDImpulse = { +static __maybe_unused const a3d_Hrtf_t A3dHrirDImpulse = { 0, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index f5512b72b3e0df6f075932d84b38507f62f98524..5180f1bd1326c32b699d0c6ab4b3d4e2b24ea575 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -1103,7 +1103,7 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0xc, snd_pcm_sgbuf_get_addr(dma->substream, psize * 3)); - /* fall through */ + fallthrough; /* 3 pages */ case 3: dma->cfg0 |= 0x12000000; @@ -1111,14 +1111,14 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x8, snd_pcm_sgbuf_get_addr(dma->substream, psize * 2)); - /* fall through */ + fallthrough; /* 2 pages */ case 2: dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize - 1); hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x4, snd_pcm_sgbuf_get_addr(dma->substream, psize)); - /* fall through */ + fallthrough; /* 1 page */ case 1: dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize - 1) << 0xc); @@ -1381,20 +1381,20 @@ vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma, dma->cfg1 |= 0x88000000 | 0x44000000 | 0x30000000 | (psize-1); hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0xc, snd_pcm_sgbuf_get_addr(dma->substream, psize * 3)); - /* fall through */ + fallthrough; /* 3 pages */ case 3: dma->cfg0 |= 0x12000000; dma->cfg1 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc); hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x8, snd_pcm_sgbuf_get_addr(dma->substream, psize * 2)); - /* fall through */ + fallthrough; /* 2 pages */ case 2: dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize-1); hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x4, snd_pcm_sgbuf_get_addr(dma->substream, psize)); - /* fall through */ + fallthrough; /* 1 page */ case 1: dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc); diff --git a/sound/pci/au88x0/au88x0_xtalk.c b/sound/pci/au88x0/au88x0_xtalk.c index 084fcbf8ae804e645f072879da6163e0c2cbfc86..27859536d7c021bbdae82e07b43637f496a4124c 100644 --- a/sound/pci/au88x0/au88x0_xtalk.c +++ b/sound/pci/au88x0/au88x0_xtalk.c @@ -17,35 +17,35 @@ static short const sXtalkWideKLeftEq = 0x269C; static short const sXtalkWideKRightEq = 0x269C; static short const sXtalkWideKLeftXt = 0xF25E; -static short const sXtalkWideKRightXt = 0xF25E; +static __maybe_unused short const sXtalkWideKRightXt = 0xF25E; static short const sXtalkWideShiftLeftEq = 1; static short const sXtalkWideShiftRightEq = 1; static short const sXtalkWideShiftLeftXt = 0; -static short const sXtalkWideShiftRightXt = 0; +static __maybe_unused short const sXtalkWideShiftRightXt = 0; static unsigned short const wXtalkWideLeftDelay = 0xd; static unsigned short const wXtalkWideRightDelay = 0xd; static short const sXtalkNarrowKLeftEq = 0x468D; static short const sXtalkNarrowKRightEq = 0x468D; static short const sXtalkNarrowKLeftXt = 0xF82E; -static short const sXtalkNarrowKRightXt = 0xF82E; +static __maybe_unused short const sXtalkNarrowKRightXt = 0xF82E; static short const sXtalkNarrowShiftLeftEq = 0x3; static short const sXtalkNarrowShiftRightEq = 0x3; static short const sXtalkNarrowShiftLeftXt = 0; -static short const sXtalkNarrowShiftRightXt = 0; +static __maybe_unused short const sXtalkNarrowShiftRightXt = 0; static unsigned short const wXtalkNarrowLeftDelay = 0x7; static unsigned short const wXtalkNarrowRightDelay = 0x7; -static xtalk_gains_t const asXtalkGainsDefault = { +static __maybe_unused xtalk_gains_t const asXtalkGainsDefault = { 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000 }; -static xtalk_gains_t const asXtalkGainsTest = { +static __maybe_unused xtalk_gains_t const asXtalkGainsTest = { 0x7fff, 0x8000, 0x0000, 0x0000, 0x0001, 0xffff, 0x4000, 0xc000, 0x0002, 0xfffe }; -static xtalk_gains_t const asXtalkGains1Chan = { +static __maybe_unused xtalk_gains_t const asXtalkGains1Chan = { 0x7FFF, 0, 0, 0, 0, 0x7FFF, 0, 0, 0, 0, }; @@ -64,7 +64,7 @@ static xtalk_dline_t const alXtalkDlineZeros = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static xtalk_dline_t const alXtalkDlineTest = { +static __maybe_unused xtalk_dline_t const alXtalkDlineTest = { 0x0000fc18, 0xfff03e8, 0x000186a0, 0xfffe7960, 1, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -74,7 +74,7 @@ static xtalk_instate_t const asXtalkInStateZeros = { 0, 0, 0, 0 }; -static xtalk_instate_t const asXtalkInStateTest = { +static __maybe_unused xtalk_instate_t const asXtalkInStateTest = { 0x0080, 0xff80, 0x0001, 0xffff }; @@ -89,11 +89,11 @@ static xtalk_state_t const asXtalkOutStateZeros = { static short const sDiamondKLeftEq = 0x401d; static short const sDiamondKRightEq = 0x401d; static short const sDiamondKLeftXt = 0xF90E; -static short const sDiamondKRightXt = 0xF90E; +static __maybe_unused short const sDiamondKRightXt = 0xF90E; static short const sDiamondShiftLeftEq = 1; static short const sDiamondShiftRightEq = 1; static short const sDiamondShiftLeftXt = 0; -static short const sDiamondShiftRightXt = 0; +static __maybe_unused short const sDiamondShiftRightXt = 0; static unsigned short const wDiamondLeftDelay = 0xb; static unsigned short const wDiamondRightDelay = 0xb; @@ -118,7 +118,7 @@ static xtalk_coefs_t const asXtalkWideCoefsLeftXt = { {0x77dc, 0xc79e, 0xffb8, 0x000a, 0}, {0, 0, 0, 0, 0} }; -static xtalk_coefs_t const asXtalkWideCoefsRightXt = { +static __maybe_unused xtalk_coefs_t const asXtalkWideCoefsRightXt = { {0x55c6, 0xc97b, 0x005b, 0x0047, 0}, {0x6a60, 0xca20, 0xffc6, 0x0040, 0}, {0x6411, 0xd711, 0xfca1, 0x0190, 0}, @@ -149,7 +149,7 @@ static xtalk_coefs_t const asXtalkNarrowCoefsLeftXt = { {0, 0, 0, 0, 0} }; -static xtalk_coefs_t const asXtalkNarrowCoefsRightXt = { +static __maybe_unused xtalk_coefs_t const asXtalkNarrowCoefsRightXt = { {0x3CB2, 0xDF49, 0xF6EA, 0x095B, 0}, {0x6777, 0xC915, 0xFEAF, 0x00B1, 0}, {0x7762, 0xC7D9, 0x025B, 0xFDA6, 0}, @@ -172,7 +172,7 @@ static xtalk_coefs_t const asXtalkCoefsPipe = { {0, 0, 0x0FA0, 0, 0}, {0, 0, 0x1180, 0, 0}, }; -static xtalk_coefs_t const asXtalkCoefsNegPipe = { +static __maybe_unused xtalk_coefs_t const asXtalkCoefsNegPipe = { {0, 0, 0xF380, 0, 0}, {0, 0, 0xF380, 0, 0}, {0, 0, 0xF380, 0, 0}, @@ -180,7 +180,7 @@ static xtalk_coefs_t const asXtalkCoefsNegPipe = { {0, 0, 0xF200, 0, 0} }; -static xtalk_coefs_t const asXtalkCoefsNumTest = { +static __maybe_unused xtalk_coefs_t const asXtalkCoefsNumTest = { {0, 0, 0xF380, 0x8000, 0x6D60}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, @@ -188,7 +188,7 @@ static xtalk_coefs_t const asXtalkCoefsNumTest = { {0, 0, 0, 0, 0} }; -static xtalk_coefs_t const asXtalkCoefsDenTest = { +static __maybe_unused xtalk_coefs_t const asXtalkCoefsDenTest = { {0xC000, 0x2000, 0x4000, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, @@ -196,7 +196,7 @@ static xtalk_coefs_t const asXtalkCoefsDenTest = { {0, 0, 0, 0, 0} }; -static xtalk_state_t const asXtalkOutStateTest = { +static __maybe_unused xtalk_state_t const asXtalkOutStateTest = { {0x7FFF, 0x0004, 0xFFFC, 0}, {0xFE00, 0x0008, 0xFFF8, 0x4000}, {0x0200, 0x0010, 0xFFF0, 0xC000}, @@ -228,7 +228,7 @@ static xtalk_coefs_t const asDiamondCoefsLeftXt = { {0, 0, 0, 0, 0} }; -static xtalk_coefs_t const asDiamondCoefsRightXt = { +static __maybe_unused xtalk_coefs_t const asDiamondCoefsRightXt = { {0x3B50, 0xFE08, 0xF959, 0x0060, 0}, {0x9FCB, 0xD8F1, 0x00A2, 0x003A, 0}, {0, 0, 0, 0, 0}, diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c index 4e64eb5d8f64c7782eaf036c8473f0df35d4923d..c84f1a45194f17a789cb085127c2722f6b9b705c 100644 --- a/sound/pci/aw2/aw2-saa7146.c +++ b/sound/pci/aw2/aw2-saa7146.c @@ -330,7 +330,7 @@ void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 *chip, irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id) { unsigned int isr; - unsigned int iicsta; + __always_unused unsigned int iicsta; struct snd_aw2_saa7146 *chip = dev_id; isr = READREG(ISR); diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 58167d8469e1baca6c6afd8a052d95502b638855..77c7030ebbfa9e224b1f25e3fcef3df25d871d86 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1232,7 +1232,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec, case AZF_FREQ_32000: freq = SOUNDFORMAT_FREQ_32000; break; default: snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate); - /* fall-through */ + fallthrough; case AZF_FREQ_44100: freq = SOUNDFORMAT_FREQ_44100; break; case AZF_FREQ_48000: freq = SOUNDFORMAT_FREQ_48000; break; case AZF_FREQ_66200: freq = SOUNDFORMAT_FREQ_SUSPECTED_66200; break; diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 6567504665b9bc44160e0630ae265148a6b55a04..54cb223caa2f6be8ae5e41223d30309ebe69a087 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -30,7 +30,7 @@ static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int digital_rate[SNDRV_CARDS]; /* digital input rate */ -static bool load_all; /* allow to load the non-whitelisted cards */ +static bool load_all; /* allow to load cards not the allowlist */ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Bt87x soundcard"); @@ -41,7 +41,7 @@ MODULE_PARM_DESC(enable, "Enable Bt87x soundcard"); module_param_array(digital_rate, int, NULL, 0444); MODULE_PARM_DESC(digital_rate, "Digital input rate for Bt87x soundcard"); module_param(load_all, bool, 0444); -MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards"); +MODULE_PARM_DESC(load_all, "Allow to load cards not on the allowlist"); /* register offsets */ @@ -801,7 +801,7 @@ MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); * (DVB cards use the audio function to transfer MPEG data) */ static struct { unsigned short subvendor, subdevice; -} blacklist[] = { +} denylist[] = { {0x0071, 0x0101}, /* Nebula Electronics DigiTV */ {0x11bd, 0x001c}, /* Pinnacle PCTV Sat */ {0x11bd, 0x0026}, /* Pinnacle PCTV SAT CI */ @@ -817,7 +817,7 @@ static struct { static struct pci_driver driver; -/* return the id of the card, or a negative value if it's blacklisted */ +/* return the id of the card, or a negative value if it's on the denylist */ static int snd_bt87x_detect_card(struct pci_dev *pci) { int i; @@ -827,9 +827,9 @@ static int snd_bt87x_detect_card(struct pci_dev *pci) if (supported && supported->driver_data > 0) return supported->driver_data; - for (i = 0; i < ARRAY_SIZE(blacklist); ++i) - if (blacklist[i].subvendor == pci->subsystem_vendor && - blacklist[i].subdevice == pci->subsystem_device) { + for (i = 0; i < ARRAY_SIZE(denylist); ++i) + if (denylist[i].subvendor == pci->subsystem_vendor && + denylist[i].subdevice == pci->subsystem_device) { dev_dbg(&pci->dev, "card %#04x-%#04x:%#04x has no audio\n", pci->device, pci->subsystem_vendor, pci->subsystem_device); diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 3b8ec673dc0a88d7c5effa48f13ea220f1befd9f..c852c6a75b917399889e123176e1d0068431deba 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -739,7 +739,7 @@ static int rename_ctl(struct snd_card *card, const char *src, const char *dst) static DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1); -static const char * const slave_vols[] = { +static const char * const follower_vols[] = { "Analog Front Playback Volume", "Analog Rear Playback Volume", "Analog Center/LFE Playback Volume", @@ -752,7 +752,7 @@ static const char * const slave_vols[] = { NULL }; -static const char * const slave_sws[] = { +static const char * const follower_sws[] = { "Analog Front Playback Switch", "Analog Rear Playback Switch", "Analog Center/LFE Playback Switch", @@ -761,13 +761,13 @@ static const char * const slave_sws[] = { NULL }; -static void add_slaves(struct snd_card *card, - struct snd_kcontrol *master, const char * const *list) +static void add_followers(struct snd_card *card, + struct snd_kcontrol *master, const char * const *list) { for (; *list; list++) { - struct snd_kcontrol *slave = ctl_find(card, *list); - if (slave) - snd_ctl_add_slave(master, slave); + struct snd_kcontrol *follower = ctl_find(card, *list); + if (follower) + snd_ctl_add_follower(master, follower); } } @@ -852,7 +852,7 @@ int snd_ca0106_mixer(struct snd_ca0106 *emu) err = snd_ctl_add(card, vmaster); if (err < 0) return err; - add_slaves(card, vmaster, slave_vols); + add_followers(card, vmaster, follower_vols); if (emu->details->spi_dac) { vmaster = snd_ctl_make_virtual_master("Master Playback Switch", @@ -862,7 +862,7 @@ int snd_ca0106_mixer(struct snd_ca0106 *emu) err = snd_ctl_add(card, vmaster); if (err < 0) return err; - add_slaves(card, vmaster, slave_sws); + add_followers(card, vmaster, follower_sws); } strcpy(card->mixername, "CA0106"); diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index a080d63a9b4560248eada7a3ae9bc6adadf6a4b8..4490dd7469d996a9f398e571bd35fd0eb9b9afb9 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -766,7 +766,7 @@ static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned rate = 48000 / 9; /* - * We can not capture at at rate greater than the Input Rate (48000). + * We can not capture at a rate greater than the Input Rate (48000). * Return an error if an attempt is made to stray outside that limit. */ if (rate > 48000) diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 6b536fc23ca62abb58afc4495641483a8b3c24ca..1f90ca723f4df72006b072c6416f84e3c3344a46 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -1716,7 +1716,7 @@ int cs46xx_iec958_pre_open (struct snd_cs46xx *chip) struct dsp_spos_instance * ins = chip->dsp_spos_instance; if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) { - /* remove AsynchFGTxSCB and and PCMSerialInput_II */ + /* remove AsynchFGTxSCB and PCMSerialInput_II */ cs46xx_dsp_disable_spdif_out (chip); /* save state */ diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index e56a230f6a9c239cd73b2ff8eadc756f2e729d27..f8ac96cf38a430781f01992c5179929c451ae475 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -1282,7 +1282,7 @@ static int atc_identify_card(struct ct_atc *atc, unsigned int ssid) if (p) { if (p->value < 0) { dev_err(atc->card->dev, - "Device %04x:%04x is black-listed\n", + "Device %04x:%04x is on the denylist\n", vendor_id, device_id); return -ENOENT; } @@ -1655,6 +1655,10 @@ static const struct ct_atc atc_preset = { * ct_atc_create - create and initialize a hardware manager * @card: corresponding alsa card object * @pci: corresponding kernel pci device object + * @rsr: reference sampling rate + * @msr: master sampling rate + * @chip_type: CHIPTYP enum values + * @ssid: vendor ID (upper 16 bits) and device ID (lower 16 bits) * @ratc: return created object address in it * * Creates and initializes a hardware manager. diff --git a/sound/pci/ctxfi/cthardware.c b/sound/pci/ctxfi/cthardware.c index 9b7e63f4a3a7f3a044548b53b3dd2dea038c1fd0..1d506448621785c7c48d6dc0644ddcb2c3c1315c 100644 --- a/sound/pci/ctxfi/cthardware.c +++ b/sound/pci/ctxfi/cthardware.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. * * @File cthardware.c diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index 015c0d676897a48b8e02bc29e88557d8c9b1afb0..108ab449c968d86b0402b89d715a18a268f689a1 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. * * @File cthw20k1.c diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index ce44cbe6459f24c3f9701b8b7c10e3ca89c40c39..fc1bc18caee989ca3cf1ef15d7d915f187a427f3 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. * * @File cthw20k2.c diff --git a/sound/pci/ctxfi/ctimap.c b/sound/pci/ctxfi/ctimap.c index eb1825e13fc5c287d439e9349c3dcf2027471cfc..d5a53d2f5f15ac67fed5d3e4d26ac0709f77dfad 100644 --- a/sound/pci/ctxfi/ctimap.c +++ b/sound/pci/ctxfi/ctimap.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. * * @File ctimap.c diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index 84514dc90d87adcadcee7292ff346c59738d2082..6797fde3d78897acc9d3ae0197f551d1e61d8283 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. * * @File ctmixer.c diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index 6ee6a9675ca518ce605b4010b58ffc9f5ff59638..3f48ad0e27e7f6e6c6d2f96d36dbe33b9b2e8f4f 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. * * @File ctpcm.c diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 0941a7a17623a49e987488e58327ad2488d6a788..6aeb99aa241459fac47a02b9c8ec65f927be215b 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -2,6 +2,7 @@ /* * ALSA driver for Echoaudio soundcards. * Copyright (C) 2003-2004 Giuliano Pochini + * Copyright (C) 2020 Mark Hills */ #include @@ -245,13 +246,20 @@ static int hw_rule_sample_rate(struct snd_pcm_hw_params *params, SNDRV_PCM_HW_PARAM_RATE); struct echoaudio *chip = rule->private; struct snd_interval fixed; + int err; + + mutex_lock(&chip->mode_mutex); - if (!chip->can_set_rate) { + if (chip->can_set_rate) { + err = 0; + } else { snd_interval_any(&fixed); fixed.min = fixed.max = chip->sample_rate; - return snd_interval_refine(rate, &fixed); + err = snd_interval_refine(rate, &fixed); } - return 0; + + mutex_unlock(&chip->mode_mutex); + return err; } @@ -322,7 +330,7 @@ static int pcm_open(struct snd_pcm_substream *substream, SNDRV_PCM_HW_PARAM_RATE, -1)) < 0) return err; - /* Finally allocate a page for the scatter-gather list */ + /* Allocate a page for the scatter-gather list */ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev, PAGE_SIZE, &pipe->sgpage)) < 0) { @@ -330,6 +338,17 @@ static int pcm_open(struct snd_pcm_substream *substream, return err; } + /* + * Sole ownership required to set the rate + */ + + dev_dbg(chip->card->dev, "pcm_open opencount=%d can_set_rate=%d, rate_set=%d", + chip->opencount, chip->can_set_rate, chip->rate_set); + + chip->opencount++; + if (chip->opencount > 1 && chip->rate_set) + chip->can_set_rate = 0; + return 0; } @@ -353,12 +372,7 @@ static int pcm_analog_in_open(struct snd_pcm_substream *substream) hw_rule_capture_format_by_channels, NULL, SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) return err; - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; - dev_dbg(chip->card->dev, "pcm_analog_in_open cs=%d oc=%d r=%d\n", - chip->can_set_rate, atomic_read(&chip->opencount), - chip->sample_rate); + return 0; } @@ -388,12 +402,7 @@ static int pcm_analog_out_open(struct snd_pcm_substream *substream) NULL, SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) return err; - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; - dev_dbg(chip->card->dev, "pcm_analog_out_open cs=%d oc=%d r=%d\n", - chip->can_set_rate, atomic_read(&chip->opencount), - chip->sample_rate); + return 0; } @@ -429,10 +438,6 @@ static int pcm_digital_in_open(struct snd_pcm_substream *substream) SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) goto din_exit; - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; - din_exit: mutex_unlock(&chip->mode_mutex); return err; @@ -471,9 +476,7 @@ static int pcm_digital_out_open(struct snd_pcm_substream *substream) NULL, SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) goto dout_exit; - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; + dout_exit: mutex_unlock(&chip->mode_mutex); return err; @@ -488,23 +491,29 @@ dout_exit: static int pcm_close(struct snd_pcm_substream *substream) { struct echoaudio *chip = snd_pcm_substream_chip(substream); - int oc; /* Nothing to do here. Audio is already off and pipe will be * freed by its callback */ - atomic_dec(&chip->opencount); - oc = atomic_read(&chip->opencount); - dev_dbg(chip->card->dev, "pcm_close oc=%d cs=%d rs=%d\n", oc, - chip->can_set_rate, chip->rate_set); - if (oc < 2) + mutex_lock(&chip->mode_mutex); + + dev_dbg(chip->card->dev, "pcm_open opencount=%d can_set_rate=%d, rate_set=%d", + chip->opencount, chip->can_set_rate, chip->rate_set); + + chip->opencount--; + + switch (chip->opencount) { + case 1: chip->can_set_rate = 1; - if (oc == 0) + break; + + case 0: chip->rate_set = 0; - dev_dbg(chip->card->dev, "pcm_close2 oc=%d cs=%d rs=%d\n", oc, - chip->can_set_rate, chip->rate_set); + break; + } + mutex_unlock(&chip->mode_mutex); return 0; } @@ -582,7 +591,7 @@ static int init_engine(struct snd_pcm_substream *substream, /* This stuff is used by the irq handler, so it must be * initialized before chip->substream */ - chip->last_period[pipe_index] = 0; + pipe->last_period = 0; pipe->last_counter = 0; pipe->position = 0; smp_wmb(); @@ -690,7 +699,7 @@ static int pcm_prepare(struct snd_pcm_substream *substream) break; case SNDRV_PCM_FORMAT_S32_BE: format.data_are_bigendian = 1; - /* fall through */ + fallthrough; case SNDRV_PCM_FORMAT_S32_LE: format.bits_per_sample = 32; break; @@ -703,9 +712,22 @@ static int pcm_prepare(struct snd_pcm_substream *substream) if (snd_BUG_ON(pipe_index >= px_num(chip))) return -EINVAL; - if (snd_BUG_ON(!is_pipe_allocated(chip, pipe_index))) + + /* + * We passed checks we can do independently; now take + * exclusive control + */ + + spin_lock_irq(&chip->lock); + + if (snd_BUG_ON(!is_pipe_allocated(chip, pipe_index))) { + spin_unlock_irq(&chip->lock); return -EINVAL; + } + set_audio_format(chip, pipe_index, &format); + spin_unlock_irq(&chip->lock); + return 0; } @@ -738,11 +760,11 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) pipe = chip->substream[i]->runtime->private_data; switch (pipe->state) { case PIPE_STATE_STOPPED: - chip->last_period[i] = 0; + pipe->last_period = 0; pipe->last_counter = 0; pipe->position = 0; *pipe->dma_counter = 0; - /* fall through */ + fallthrough; case PIPE_STATE_PAUSED: pipe->state = PIPE_STATE_STARTED; break; @@ -786,19 +808,26 @@ static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct audiopipe *pipe = runtime->private_data; - size_t cnt, bufsize, pos; + u32 counter, step; - cnt = le32_to_cpu(*pipe->dma_counter); - pipe->position += cnt - pipe->last_counter; - pipe->last_counter = cnt; - bufsize = substream->runtime->buffer_size; - pos = bytes_to_frames(substream->runtime, pipe->position); + /* + * IRQ handling runs concurrently. Do not share tracking of + * counter with it, which would race or require locking + */ - while (pos >= bufsize) { - pipe->position -= frames_to_bytes(substream->runtime, bufsize); - pos -= bufsize; - } - return pos; + counter = le32_to_cpu(*pipe->dma_counter); /* presumed atomic */ + + step = counter - pipe->last_counter; /* handles wrapping */ + pipe->last_counter = counter; + + /* counter doesn't neccessarily wrap on a multiple of + * buffer_size, so can't derive the position; must + * accumulate */ + + pipe->position += step; + pipe->position %= frames_to_bytes(runtime, runtime->buffer_size); /* wrap */ + + return bytes_to_frames(runtime, pipe->position); } @@ -1409,7 +1438,7 @@ static int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol, /* Do not allow the user to change the digital mode when a pcm device is open because it also changes the number of channels and the allowed sample rates */ - if (atomic_read(&chip->opencount)) { + if (chip->opencount) { changed = -EAGAIN; } else { changed = set_digital_mode(chip, dmode); @@ -1761,14 +1790,43 @@ static const struct snd_kcontrol_new snd_echo_channels_info = { /****************************************************************************** - IRQ Handler + IRQ Handling ******************************************************************************/ +/* Check if a period has elapsed since last interrupt + * + * Don't make any updates to state; PCM core handles this with the + * correct locks. + * + * \return true if a period has elapsed, otherwise false + */ +static bool period_has_elapsed(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct audiopipe *pipe = runtime->private_data; + u32 counter, step; + size_t period_bytes; + + if (pipe->state != PIPE_STATE_STARTED) + return false; + + period_bytes = frames_to_bytes(runtime, runtime->period_size); + + counter = le32_to_cpu(*pipe->dma_counter); /* presumed atomic */ + + step = counter - pipe->last_period; /* handles wrapping */ + step -= step % period_bytes; /* acknowledge whole periods only */ + + if (step == 0) + return false; /* haven't advanced a whole period yet */ + + pipe->last_period += step; /* used exclusively by us */ + return true; +} static irqreturn_t snd_echo_interrupt(int irq, void *dev_id) { struct echoaudio *chip = dev_id; - struct snd_pcm_substream *substream; - int period, ss, st; + int ss, st; spin_lock(&chip->lock); st = service_irq(chip); @@ -1779,17 +1837,13 @@ static irqreturn_t snd_echo_interrupt(int irq, void *dev_id) /* The hardware doesn't tell us which substream caused the irq, thus we have to check all running substreams. */ for (ss = 0; ss < DSP_MAXPIPES; ss++) { + struct snd_pcm_substream *substream; + substream = chip->substream[ss]; - if (substream && ((struct audiopipe *)substream->runtime-> - private_data)->state == PIPE_STATE_STARTED) { - period = pcm_pointer(substream) / - substream->runtime->period_size; - if (period != chip->last_period[ss]) { - chip->last_period[ss] = period; - spin_unlock(&chip->lock); - snd_pcm_period_elapsed(substream); - spin_lock(&chip->lock); - } + if (substream && period_has_elapsed(substream)) { + spin_unlock(&chip->lock); + snd_pcm_period_elapsed(substream); + spin_lock(&chip->lock); } } spin_unlock(&chip->lock); @@ -1874,7 +1928,7 @@ static int snd_echo_create(struct snd_card *card, chip->card = card; chip->pci = pci; chip->irq = -1; - atomic_set(&chip->opencount, 0); + chip->opencount = 0; mutex_init(&chip->mode_mutex); chip->can_set_rate = 1; } else { @@ -1955,7 +2009,8 @@ static int snd_echo_probe(struct pci_dev *pci, struct snd_card *card; struct echoaudio *chip; char *dsp; - int i, err; + __maybe_unused int i; + int err; if (dev >= SNDRV_CARDS) return -ENODEV; diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h index be4d0489394a2d810e134d18e385820da7c737ef..30c640931f1e3676bfad44b340c0023e9fd13dca 100644 --- a/sound/pci/echoaudio/echoaudio.h +++ b/sound/pci/echoaudio/echoaudio.h @@ -298,7 +298,12 @@ struct audiopipe { * the current dma position * (lower 32 bits only) */ - u32 last_counter; /* The last position, which is used + u32 last_period; /* Counter position last time a + * period elapsed + */ + u32 last_counter; /* Used exclusively by pcm_pointer + * under PCM core locks. + * The last position, which is used * to compute... */ u32 position; /* ...the number of bytes tranferred @@ -332,11 +337,10 @@ struct audioformat { struct echoaudio { spinlock_t lock; struct snd_pcm_substream *substream[DSP_MAXPIPES]; - int last_period[DSP_MAXPIPES]; struct mutex mode_mutex; u16 num_digital_modes, digital_mode_list[6]; u16 num_clock_sources, clock_source_list[10]; - atomic_t opencount; + unsigned int opencount; /* protected by mode_mutex */ struct snd_kcontrol *clock_src_ctl; struct snd_pcm *analog_pcm, *digital_pcm; struct snd_card *card; @@ -353,8 +357,8 @@ struct echoaudio { struct timer_list timer; char tinuse; /* Timer in use */ char midi_full; /* MIDI output buffer is full */ - char can_set_rate; - char rate_set; + char can_set_rate; /* protected by mode_mutex */ + char rate_set; /* protected by mode_mutex */ /* This stuff is used mainly by the lowlevel code */ struct comm_page *comm_page; /* Virtual address of the memory diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c index f02f5b1568dee6f5e083e11417f9b67e7d355073..d10d0e460f0bd9f2558f0c724da47f5bad5c8842 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.c +++ b/sound/pci/echoaudio/echoaudio_dsp.c @@ -898,7 +898,7 @@ static int pause_transport(struct echoaudio *chip, u32 channel_mask) return 0; } - dev_warn(chip->card->dev, "pause_transport: No pipes to stop!\n"); + dev_dbg(chip->card->dev, "pause_transport: No pipes to stop!\n"); return 0; } @@ -924,7 +924,7 @@ static int stop_transport(struct echoaudio *chip, u32 channel_mask) return 0; } - dev_warn(chip->card->dev, "stop_transport: No pipes to stop!\n"); + dev_dbg(chip->card->dev, "stop_transport: No pipes to stop!\n"); return 0; } diff --git a/sound/pci/echoaudio/mona_dsp.c b/sound/pci/echoaudio/mona_dsp.c index dce9e57d01c4a98749ce8b3eb96554628486681f..f77db83dd73dbc2a321e19dda21999c39b0985bc 100644 --- a/sound/pci/echoaudio/mona_dsp.c +++ b/sound/pci/echoaudio/mona_dsp.c @@ -300,11 +300,6 @@ static int set_input_clock(struct echoaudio *chip, u16 clock) u32 control_reg, clocks_from_dsp; int err; - - /* Prevent two simultaneous calls to switch_asic() */ - if (atomic_read(&chip->opencount)) - return -EAGAIN; - /* Mask off the clock select bits */ control_reg = le32_to_cpu(chip->comm_page->control_register) & GML_CLOCK_CLEAR_MASK; diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 6ff581733a199cb944ac3abdacd4753c3826f3a5..bd70e112ffd7aff31c925d067bf96c6a86b1383e 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -623,7 +623,7 @@ static int snd_emu10k1_ecard_init(struct snd_emu10k1 *emu) static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu) { unsigned long special_port; - unsigned int value; + __always_unused unsigned int value; /* Special initialisation routine * before the rest of the IO-Ports become active. @@ -653,7 +653,7 @@ static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, int n, i; int reg; int value; - unsigned int write_post; + __always_unused unsigned int write_post; unsigned long flags; if (!fw_entry) diff --git a/sound/pci/emu10k1/emu10k1_patch.c b/sound/pci/emu10k1/emu10k1_patch.c index b3aa7bbe1067413aae0b4ed273c2a8ac54661af5..89890f24509f0312183e445782070f56ea81c01a 100644 --- a/sound/pci/emu10k1/emu10k1_patch.c +++ b/sound/pci/emu10k1/emu10k1_patch.c @@ -27,7 +27,8 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, const void __user *data, long count) { int offset; - int truesize, size, loopsize, blocksize; + int truesize, size, blocksize; + __maybe_unused int loopsize; int loopend, sampleend; unsigned int start_addr; struct snd_emu10k1 *emu; diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index b934c6ac52dd4a810539ffab55b20ee823d0d6ab..b2ddabb99438138185fd8ee89475b877f5ea2bc3 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -753,7 +753,7 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_START: snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); /* do we need this? */ snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[0]); - /* fall through */ + fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) @@ -902,8 +902,7 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream, snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]); } snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); - - /* fall through */ + fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL); diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index b4a0adf7451cc7f454ad4dfa4ba47d0530d3ba51..09704a78d799eb0a541d5d4bf89f230948b0e29a 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -1619,7 +1619,8 @@ static int snd_es1938_create(struct snd_card *card, static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id) { struct es1938 *chip = dev_id; - unsigned char status, audiostatus; + unsigned char status; + __always_unused unsigned char audiostatus; int handled = 0; status = inb(SLIO_REG(chip, IRQCONTROL)); diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index d26004b35a81aed490849f1cea824143689271b0..34332d008b27d0a68be11ff0fa6e004ef34e4d33 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2631,7 +2631,7 @@ struct ess_device_list { unsigned short vendor; /* subsystem vendor id */ }; -static const struct ess_device_list pm_whitelist[] = { +static const struct ess_device_list pm_allowlist[] = { { TYPE_MAESTRO2E, 0x0e11 }, /* Compaq Armada */ { TYPE_MAESTRO2E, 0x1028 }, { TYPE_MAESTRO2E, 0x103c }, @@ -2642,7 +2642,7 @@ static const struct ess_device_list pm_whitelist[] = { { TYPE_MAESTRO2, 0x125d }, /* a PCI card, e.g. SF64-PCE2 */ }; -static const struct ess_device_list mpu_blacklist[] = { +static const struct ess_device_list mpu_denylist[] = { { TYPE_MAESTRO2, 0x125d }, }; @@ -2724,12 +2724,12 @@ static int snd_es1968_create(struct snd_card *card, pci_set_master(pci); if (do_pm > 1) { - /* disable power-management if not on the whitelist */ + /* disable power-management if not on the allowlist */ unsigned short vend; pci_read_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend); - for (i = 0; i < (int)ARRAY_SIZE(pm_whitelist); i++) { - if (chip->type == pm_whitelist[i].type && - vend == pm_whitelist[i].vendor) { + for (i = 0; i < (int)ARRAY_SIZE(pm_allowlist); i++) { + if (chip->type == pm_allowlist[i].type && + vend == pm_allowlist[i].vendor) { do_pm = 1; break; } @@ -2848,12 +2848,12 @@ static int snd_es1968_probe(struct pci_dev *pci, } if (enable_mpu[dev] == 2) { - /* check the black list */ + /* check the deny list */ unsigned short vend; pci_read_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend); - for (i = 0; i < ARRAY_SIZE(mpu_blacklist); i++) { - if (chip->type == mpu_blacklist[i].type && - vend == mpu_blacklist[i].vendor) { + for (i = 0; i < ARRAY_SIZE(mpu_denylist); i++) { + if (chip->type == mpu_denylist[i].type && + vend == mpu_denylist[i].vendor) { enable_mpu[dev] = 0; break; } diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 181ebafa550a215801cf5374def35ef6693f429e..0a95032fd297fa7710b3332f1eeba7026c6e2c42 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -144,6 +144,8 @@ MODULE_PARM_DESC(radio_nr, "Radio device numbers"); /** * struct fm801 - describes FM801 chip + * @dev: device for this chio + * @irq: irq number * @port: I/O port number * @multichannel: multichannel support * @secondary: secondary codec @@ -151,6 +153,31 @@ MODULE_PARM_DESC(radio_nr, "Radio device numbers"); * @tea575x_tuner: tuner access method & flags * @ply_ctrl: playback control * @cap_ctrl: capture control + * @ply_buffer: playback buffer + * @ply_buf: playback buffer index + * @ply_count: playback buffer count + * @ply_size: playback buffer size + * @ply_pos: playback position + * @cap_buffer: capture buffer + * @cap_buf: capture buffer index + * @cap_count: capture buffer count + * @cap_size: capture buffer size + * @cap_pos: capture position + * @ac97_bus: ac97 bus handle + * @ac97: ac97 handle + * @ac97_sec: ac97 secondary handle + * @card: ALSA card + * @pcm: PCM devices + * @rmidi: rmidi device + * @playback_substream: substream for playback + * @capture_substream: substream for capture + * @p_dma_size: playback DMA size + * @c_dma_size: capture DMA size + * @reg_lock: lock + * @proc_entry: /proc entry + * @v4l2_dev: v4l2 device + * @tea: tea575a structure + * @saved_regs: context saved during suspend */ struct fm801 { struct device *dev; diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 7ba542e45a3d7f88e5e8ca4a4dc9ea6cf56dcfef..90759391cbac826b81bf5d5242b92dc0a3aaeeb5 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -8,6 +8,9 @@ config SND_HDA select SND_JACK select SND_HDA_CORE +config SND_HDA_GENERIC_LEDS + bool + config SND_HDA_INTEL tristate "HD Audio PCI" depends on SND_PCI @@ -91,6 +94,7 @@ config SND_HDA_PATCH_LOADER config SND_HDA_CODEC_REALTEK tristate "Build Realtek HD-audio codec support" select SND_HDA_GENERIC + select SND_HDA_GENERIC_LEDS help Say Y or M here to include Realtek HD-audio codec support in snd-hda-intel driver, such as ALC880. @@ -111,6 +115,7 @@ comment "Set to Y if you want auto-loading the codec driver" config SND_HDA_CODEC_SIGMATEL tristate "Build IDT/Sigmatel HD-audio codec support" select SND_HDA_GENERIC + select SND_HDA_GENERIC_LEDS help Say Y or M here to include IDT (Sigmatel) HD-audio codec support in snd-hda-intel driver, such as STAC9200. @@ -155,6 +160,7 @@ comment "Set to Y if you want auto-loading the codec driver" config SND_HDA_CODEC_CONEXANT tristate "Build Conexant HD-audio codec support" select SND_HDA_GENERIC + select SND_HDA_GENERIC_LEDS help Say Y or M here to include Conexant HD-audio codec support in snd-hda-intel driver, such as CX20549. @@ -215,6 +221,10 @@ comment "Set to Y if you want auto-loading the codec driver" config SND_HDA_GENERIC tristate "Enable generic HD-audio codec parser" + select NEW_LEDS if SND_HDA_GENERIC_LEDS + select LEDS_CLASS if SND_HDA_GENERIC_LEDS + select LEDS_TRIGGERS if SND_HDA_GENERIC_LEDS + select LEDS_TRIGGER_AUDIO if SND_HDA_GENERIC_LEDS help Say Y or M here to enable the generic HD-audio codec parser in snd-hda-intel driver. @@ -230,6 +240,20 @@ config SND_HDA_POWER_SAVE_DEFAULT The default time-out value in seconds for HD-audio automatic power-save mode. 0 means to disable the power-save mode. +config SND_HDA_INTEL_HDMI_SILENT_STREAM + bool "Enable Silent Stream always for HDMI" + depends on SND_HDA_INTEL + help + Intel hardware has a feature called 'silent stream', that + keeps external HDMI receiver's analog circuitry powered on + avoiding 2-3 sec silence during playback start. This mechanism + relies on setting channel_id as 0xf, sending info packet and + preventing codec D3 entry (increasing platform static power + consumption when HDMI receiver is plugged-in). 2-3 sec silence + at the playback start is expected whenever there is format change. + (default is 2 channel format). + Say Y to enable Silent Stream feature. + endif endmenu diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 841523f6b88de62267268b3414977174e657b777..53a2b89f8983ce4f1e2733d62836f68f09668429 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -102,7 +102,7 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, case SND_BELL: if (hz) hz = 1000; - /* fallthru */ + fallthrough; case SND_TONE: if (beep->linear_tone) beep->tone = beep_linear_tone(beep, hz); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 803978d69e3c4d283bfbe1b63512296bfcf43402..e96a87f1b611ffe9a02ff3b0a2ed832e20355194 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -785,13 +785,14 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec) snd_array_free(&codec->spdif_out); snd_array_free(&codec->verbs); codec->preset = NULL; - codec->slave_dig_outs = NULL; + codec->follower_dig_outs = NULL; codec->spdif_status_reset = 0; snd_array_free(&codec->mixers); snd_array_free(&codec->nids); remove_conn_list(codec); snd_hdac_regmap_exit(&codec->core); } +EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup_for_unbind); static unsigned int hda_set_power_state(struct hda_codec *codec, unsigned int power_state); @@ -1806,11 +1807,11 @@ int snd_hda_codec_reset(struct hda_codec *codec) return 0; } -typedef int (*map_slave_func_t)(struct hda_codec *, void *, struct snd_kcontrol *); +typedef int (*map_follower_func_t)(struct hda_codec *, void *, struct snd_kcontrol *); -/* apply the function to all matching slave ctls in the mixer list */ -static int map_slaves(struct hda_codec *codec, const char * const *slaves, - const char *suffix, map_slave_func_t func, void *data) +/* apply the function to all matching follower ctls in the mixer list */ +static int map_followers(struct hda_codec *codec, const char * const *followers, + const char *suffix, map_follower_func_t func, void *data) { struct hda_nid_item *items; const char * const *s; @@ -1821,7 +1822,7 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, struct snd_kcontrol *sctl = items[i].kctl; if (!sctl || sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER) continue; - for (s = slaves; *s; s++) { + for (s = followers; *s; s++) { char tmpname[sizeof(sctl->id.name)]; const char *name = *s; if (suffix) { @@ -1840,8 +1841,8 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, return 0; } -static int check_slave_present(struct hda_codec *codec, - void *data, struct snd_kcontrol *sctl) +static int check_follower_present(struct hda_codec *codec, + void *data, struct snd_kcontrol *sctl) { return 1; } @@ -1860,17 +1861,17 @@ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) return 0; } -struct slave_init_arg { +struct follower_init_arg { struct hda_codec *codec; int step; }; -/* initialize the slave volume with 0dB via snd_ctl_apply_vmaster_slaves() */ -static int init_slave_0dB(struct snd_kcontrol *slave, - struct snd_kcontrol *kctl, - void *_arg) +/* initialize the follower volume with 0dB via snd_ctl_apply_vmaster_followers() */ +static int init_follower_0dB(struct snd_kcontrol *follower, + struct snd_kcontrol *kctl, + void *_arg) { - struct slave_init_arg *arg = _arg; + struct follower_init_arg *arg = _arg; int _tlv[4]; const int *tlv = NULL; int step; @@ -1879,7 +1880,7 @@ static int init_slave_0dB(struct snd_kcontrol *slave, if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { if (kctl->tlv.c != snd_hda_mixer_amp_tlv) { codec_err(arg->codec, - "Unexpected TLV callback for slave %s:%d\n", + "Unexpected TLV callback for follower %s:%d\n", kctl->id.name, kctl->id.index); return 0; /* ignore */ } @@ -1897,7 +1898,7 @@ static int init_slave_0dB(struct snd_kcontrol *slave, return 0; if (arg->step && arg->step != step) { codec_err(arg->codec, - "Mismatching dB step for vmaster slave (%d!=%d)\n", + "Mismatching dB step for vmaster follower (%d!=%d)\n", arg->step, step); return 0; } @@ -1905,49 +1906,49 @@ static int init_slave_0dB(struct snd_kcontrol *slave, arg->step = step; val = -tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] / step; if (val > 0) { - put_kctl_with_value(slave, val); + put_kctl_with_value(follower, val); return val; } return 0; } -/* unmute the slave via snd_ctl_apply_vmaster_slaves() */ -static int init_slave_unmute(struct snd_kcontrol *slave, - struct snd_kcontrol *kctl, - void *_arg) +/* unmute the follower via snd_ctl_apply_vmaster_followers() */ +static int init_follower_unmute(struct snd_kcontrol *follower, + struct snd_kcontrol *kctl, + void *_arg) { - return put_kctl_with_value(slave, 1); + return put_kctl_with_value(follower, 1); } -static int add_slave(struct hda_codec *codec, - void *data, struct snd_kcontrol *slave) +static int add_follower(struct hda_codec *codec, + void *data, struct snd_kcontrol *follower) { - return snd_ctl_add_slave(data, slave); + return snd_ctl_add_follower(data, follower); } /** - * __snd_hda_add_vmaster - create a virtual master control and add slaves + * __snd_hda_add_vmaster - create a virtual master control and add followers * @codec: HD-audio codec * @name: vmaster control name * @tlv: TLV data (optional) - * @slaves: slave control names (optional) - * @suffix: suffix string to each slave name (optional) - * @init_slave_vol: initialize slaves to unmute/0dB + * @followers: follower control names (optional) + * @suffix: suffix string to each follower name (optional) + * @init_follower_vol: initialize followers to unmute/0dB * @ctl_ret: store the vmaster kcontrol in return * * Create a virtual master control with the given name. The TLV data * must be either NULL or a valid data. * - * @slaves is a NULL-terminated array of strings, each of which is a - * slave control name. All controls with these names are assigned to + * @followers is a NULL-terminated array of strings, each of which is a + * follower control name. All controls with these names are assigned to * the new virtual master control. * * This function returns zero if successful or a negative error code. */ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, - unsigned int *tlv, const char * const *slaves, - const char *suffix, bool init_slave_vol, + unsigned int *tlv, const char * const *followers, + const char *suffix, bool init_follower_vol, struct snd_kcontrol **ctl_ret) { struct snd_kcontrol *kctl; @@ -1956,9 +1957,9 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, if (ctl_ret) *ctl_ret = NULL; - err = map_slaves(codec, slaves, suffix, check_slave_present, NULL); + err = map_followers(codec, followers, suffix, check_follower_present, NULL); if (err != 1) { - codec_dbg(codec, "No slave found for %s\n", name); + codec_dbg(codec, "No follower found for %s\n", name); return 0; } kctl = snd_ctl_make_virtual_master(name, tlv); @@ -1968,20 +1969,20 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, if (err < 0) return err; - err = map_slaves(codec, slaves, suffix, add_slave, kctl); + err = map_followers(codec, followers, suffix, add_follower, kctl); if (err < 0) return err; /* init with master mute & zero volume */ put_kctl_with_value(kctl, 0); - if (init_slave_vol) { - struct slave_init_arg arg = { + if (init_follower_vol) { + struct follower_init_arg arg = { .codec = codec, .step = 0, }; - snd_ctl_apply_vmaster_slaves(kctl, - tlv ? init_slave_0dB : init_slave_unmute, - &arg); + snd_ctl_apply_vmaster_followers(kctl, + tlv ? init_follower_0dB : init_follower_unmute, + &arg); } if (ctl_ret) @@ -2284,7 +2285,7 @@ static unsigned int convert_to_spdif_status(unsigned short val) return sbits; } -/* set digital convert verbs both for the given NID and its slaves */ +/* set digital convert verbs both for the given NID and its followers */ static void set_dig_out(struct hda_codec *codec, hda_nid_t nid, int mask, int val) { @@ -2292,7 +2293,7 @@ static void set_dig_out(struct hda_codec *codec, hda_nid_t nid, snd_hdac_regmap_update(&codec->core, nid, AC_VERB_SET_DIGI_CONVERT_1, mask, val); - d = codec->slave_dig_outs; + d = codec->follower_dig_outs; if (!d) return; for (; *d; d++) @@ -3186,7 +3187,7 @@ int snd_hda_codec_prepare(struct hda_codec *codec, EXPORT_SYMBOL_GPL(snd_hda_codec_prepare); /** - * snd_hda_codec_cleanup - Prepare a stream + * snd_hda_codec_cleanup - Clean up stream resources * @codec: the HDA codec * @hinfo: PCM information * @substream: PCM substream @@ -3427,7 +3428,7 @@ EXPORT_SYMBOL_GPL(snd_hda_set_power_save); * @nid: NID to check / update * * Check whether the given NID is in the amp list. If it's in the list, - * check the current AMP status, and update the the power-status according + * check the current AMP status, and update the power-status according * to the mute status. * * This function is supposed to be set or called from the check_power_status @@ -3588,9 +3589,9 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, spdif->ctls & ~AC_DIG1_ENABLE & 0xff, -1); snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); - if (codec->slave_dig_outs) { + if (codec->follower_dig_outs) { const hda_nid_t *d; - for (d = codec->slave_dig_outs; *d; d++) + for (d = codec->follower_dig_outs; *d; d++) snd_hda_codec_setup_stream(codec, *d, stream_tag, 0, format); } @@ -3603,9 +3604,9 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid) { snd_hda_codec_cleanup_stream(codec, nid); - if (codec->slave_dig_outs) { + if (codec->follower_dig_outs) { const hda_nid_t *d; - for (d = codec->slave_dig_outs; *d; d++) + for (d = codec->follower_dig_outs; *d; d++) snd_hda_codec_cleanup_stream(codec, *d); } } @@ -3687,7 +3688,7 @@ EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_close); * @hinfo: PCM information to assign * * Open analog outputs and set up the hw-constraints. - * If the digital outputs can be opened as slave, open the digital + * If the digital outputs can be opened as follower, open the digital * outputs, too. */ int snd_hda_multi_out_analog_open(struct hda_codec *codec, diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 9765652a73d74033af179947c4aa55da813cefcb..80016b7b6849e987c9de3f53152fa809d64d3c09 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -1202,15 +1202,8 @@ int azx_bus_init(struct azx *chip, const char *model) if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) bus->core.align_bdle_4k = true; - /* AMD chipsets often cause the communication stalls upon certain - * sequence like the pin-detection. It seems that forcing the synced - * access works around the stall. Grrr... - */ - if (chip->driver_caps & AZX_DCAPS_SYNC_WRITE) { - dev_dbg(chip->card->dev, "Enable sync_write for stable communication\n"); - bus->core.sync_write = 1; - bus->allow_bus_reset = 1; - } + /* enable sync_write flag for stable communication as default */ + bus->core.sync_write = 1; return 0; } diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index a356fb0e57738c7558e72127c44cc5afafb2b8c0..be63ead8161f80e49c85023094eeff8e0e5148f7 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -33,7 +33,7 @@ #define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ #define AZX_DCAPS_AMD_WORKAROUND (1 << 17) /* AMD-specific workaround */ #define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */ -#define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ +/* 19 unused */ #define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ #define AZX_DCAPS_NO_ALIGN_BUFSIZE (1 << 21) /* no buffer size alignment */ /* 22 unused */ diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index f4e9d9445e18f69b4cad9c02df879458bc44c7f8..bbb17481159e0dcf568a2975fd6593722011b45f 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -813,7 +813,7 @@ static void activate_amp_in(struct hda_codec *codec, struct nid_path *path, } } -/* sync power of each widget in the the given path */ +/* sync power of each widget in the given path */ static hda_nid_t path_power_update(struct hda_codec *codec, struct nid_path *path, bool allow_powerdown) @@ -3887,6 +3887,66 @@ static int parse_mic_boost(struct hda_codec *codec) return 0; } +#ifdef CONFIG_SND_HDA_GENERIC_LEDS +/* + * vmaster mute LED hook helpers + */ + +static int create_mute_led_cdev(struct hda_codec *codec, + int (*callback)(struct led_classdev *, + enum led_brightness), + bool micmute) +{ + struct led_classdev *cdev; + + cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL); + if (!cdev) + return -ENOMEM; + + cdev->name = micmute ? "hda::micmute" : "hda::mute"; + cdev->max_brightness = 1; + cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute"; + cdev->brightness_set_blocking = callback; + cdev->brightness = ledtrig_audio_get(micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE); + cdev->flags = LED_CORE_SUSPENDRESUME; + + return devm_led_classdev_register(&codec->core.dev, cdev); +} + +static void vmaster_update_mute_led(void *private_data, int enabled) +{ + ledtrig_audio_set(LED_AUDIO_MUTE, enabled ? LED_OFF : LED_ON); +} + +/** + * snd_dha_gen_add_mute_led_cdev - Create a LED classdev and enable as vmaster mute LED + * @codec: the HDA codec + * @callback: the callback for LED classdev brightness_set_blocking + */ +int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec, + int (*callback)(struct led_classdev *, + enum led_brightness)) +{ + struct hda_gen_spec *spec = codec->spec; + int err; + + if (callback) { + err = create_mute_led_cdev(codec, callback, false); + if (err) { + codec_warn(codec, "failed to create a mute LED cdev\n"); + return err; + } + } + + if (spec->vmaster_mute.hook) + codec_err(codec, "vmaster hook already present before cdev!\n"); + + spec->vmaster_mute.hook = vmaster_update_mute_led; + spec->vmaster_mute_enum = 1; + return 0; +} +EXPORT_SYMBOL_GPL(snd_hda_gen_add_mute_led_cdev); + /* * mic mute LED hook helpers */ @@ -3921,8 +3981,8 @@ static void call_micmute_led_update(struct hda_codec *codec) if (val == spec->micmute_led.led_value) return; spec->micmute_led.led_value = val; - if (spec->micmute_led.update) - spec->micmute_led.update(codec); + ledtrig_audio_set(LED_AUDIO_MICMUTE, + spec->micmute_led.led_value ? LED_ON : LED_OFF); } static void update_micmute_led(struct hda_codec *codec, @@ -3994,20 +4054,8 @@ static const struct snd_kcontrol_new micmute_led_mode_ctl = { .put = micmute_led_mode_put, }; -/** - * snd_hda_gen_add_micmute_led - helper for setting up mic mute LED hook - * @codec: the HDA codec - * @hook: the callback for updating LED - * - * Called from the codec drivers for offering the mic mute LED controls. - * When established, it sets up cap_sync_hook and triggers the callback at - * each time when the capture mixer switch changes. The callback is supposed - * to update the LED accordingly. - * - * Returns 0 if the hook is established or a negative error code. - */ -int snd_hda_gen_add_micmute_led(struct hda_codec *codec, - void (*hook)(struct hda_codec *)) +/* Set up the capture sync hook for controlling the mic-mute LED */ +static int add_micmute_led_hook(struct hda_codec *codec) { struct hda_gen_spec *spec = codec->spec; @@ -4015,48 +4063,44 @@ int snd_hda_gen_add_micmute_led(struct hda_codec *codec, spec->micmute_led.capture = 0; spec->micmute_led.led_value = 0; spec->micmute_led.old_hook = spec->cap_sync_hook; - spec->micmute_led.update = hook; spec->cap_sync_hook = update_micmute_led; if (!snd_hda_gen_add_kctl(spec, NULL, &micmute_led_mode_ctl)) return -ENOMEM; return 0; } -EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led); - -#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) -static void call_ledtrig_micmute(struct hda_codec *codec) -{ - struct hda_gen_spec *spec = codec->spec; - - ledtrig_audio_set(LED_AUDIO_MICMUTE, - spec->micmute_led.led_value ? LED_ON : LED_OFF); -} -#endif /** - * snd_hda_gen_fixup_micmute_led - A fixup for mic-mute LED trigger - * - * Pass this function to the quirk entry if another driver supports the - * audio mic-mute LED trigger. Then this will bind the mixer capture switch - * change with the LED. + * snd_dha_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED + * @codec: the HDA codec + * @callback: the callback for LED classdev brightness_set_blocking * - * Note that this fixup has to be called after other fixup that sets - * cap_sync_hook. Otherwise the chaining wouldn't work. + * Called from the codec drivers for offering the mic mute LED controls. + * This creates a LED classdev and sets up the cap_sync_hook that is called at + * each time when the capture mixer switch changes. * - * @codec: the HDA codec - * @fix: fixup pointer - * @action: only supports HDA_FIXUP_ACT_PROBE value + * When NULL is passed to @callback, no classdev is created but only the + * LED-trigger is set up. * + * Returns 0 or a negative error. */ -void snd_hda_gen_fixup_micmute_led(struct hda_codec *codec, - const struct hda_fixup *fix, int action) +int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec, + int (*callback)(struct led_classdev *, + enum led_brightness)) { -#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) - if (action == HDA_FIXUP_ACT_PROBE) - snd_hda_gen_add_micmute_led(codec, call_ledtrig_micmute); -#endif + int err; + + if (callback) { + err = create_mute_led_cdev(codec, callback, true); + if (err) { + codec_warn(codec, "failed to create a mic-mute LED cdev\n"); + return err; + } + } + + return add_micmute_led_hook(codec); } -EXPORT_SYMBOL_GPL(snd_hda_gen_fixup_micmute_led); +EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev); +#endif /* CONFIG_SND_HDA_GENERIC_LEDS */ /* * parse digital I/Os and set up NIDs in BIOS auto-parse mode @@ -4068,7 +4112,7 @@ static void parse_digital(struct hda_codec *codec) int i, nums; hda_nid_t dig_nid, pin; - /* support multiple SPDIFs; the secondary is set up as a slave */ + /* support multiple SPDIFs; the secondary is set up as a follower */ nums = 0; for (i = 0; i < spec->autocfg.dig_outs; i++) { pin = spec->autocfg.dig_out_pins[i]; @@ -4087,10 +4131,10 @@ static void parse_digital(struct hda_codec *codec) spec->multiout.dig_out_nid = dig_nid; spec->dig_out_type = spec->autocfg.dig_out_type[0]; } else { - spec->multiout.slave_dig_outs = spec->slave_dig_outs; - if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1) + spec->multiout.follower_dig_outs = spec->follower_dig_outs; + if (nums >= ARRAY_SIZE(spec->follower_dig_outs) - 1) break; - spec->slave_dig_outs[nums - 1] = dig_nid; + spec->follower_dig_outs[nums - 1] = dig_nid; } nums++; } @@ -4545,7 +4589,7 @@ static void call_update_outputs(struct hda_codec *codec) else snd_hda_gen_update_outputs(codec); - /* sync the whole vmaster slaves to reflect the new auto-mute status */ + /* sync the whole vmaster followers to reflect the new auto-mute status */ if (spec->auto_mute_via_amp && !codec->bus->shutdown) snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false); } @@ -5189,8 +5233,8 @@ EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config); * Build control elements */ -/* slave controls for virtual master */ -static const char * const slave_pfxs[] = { +/* follower controls for virtual master */ +static const char * const follower_pfxs[] = { "Front", "Surround", "Center", "LFE", "Side", "Headphone", "Speaker", "Mono", "Line Out", "CLFE", "Bass Speaker", "PCM", @@ -5242,7 +5286,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec) if (!spec->no_analog && !spec->suppress_vmaster && !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { err = snd_hda_add_vmaster(codec, "Master Playback Volume", - spec->vmaster_tlv, slave_pfxs, + spec->vmaster_tlv, follower_pfxs, "Playback Volume"); if (err < 0) return err; @@ -5250,7 +5294,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec) if (!spec->no_analog && !spec->suppress_vmaster && !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { err = __snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, slave_pfxs, + NULL, follower_pfxs, "Playback Switch", true, &spec->vmaster_mute.sw_kctl); if (err < 0) @@ -5765,7 +5809,7 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec) spec->stream_name_digital); if (!info) return -ENOMEM; - codec->slave_dig_outs = spec->multiout.slave_dig_outs; + codec->follower_dig_outs = spec->multiout.follower_dig_outs; spec->pcm_rec[1] = info; if (spec->dig_out_type) info->pcm_type = spec->dig_out_type; diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index fb9f1a90238bfb67d2a8079bf11b3dc012f86294..a43f0bb77dae78c12e14b62c62867678ae4fec48 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -8,6 +8,8 @@ #ifndef __SOUND_HDA_GENERIC_H #define __SOUND_HDA_GENERIC_H +#include + /* table entry for multi-io paths */ struct hda_multi_io { hda_nid_t pin; /* multi-io widget pin NID */ @@ -86,7 +88,6 @@ struct hda_micmute_hook { unsigned int led_mode; unsigned int capture; unsigned int led_value; - void (*update)(struct hda_codec *codec); void (*old_hook)(struct hda_codec *codec, struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); @@ -115,7 +116,7 @@ struct hda_gen_spec { * dig_out_nid and hp_nid are optional */ hda_nid_t alt_dac_nid; - hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */ + hda_nid_t follower_dig_outs[3]; /* optional - for auto-parsing */ int dig_out_type; /* capture */ @@ -353,9 +354,11 @@ unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec, void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on); int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin); -int snd_hda_gen_add_micmute_led(struct hda_codec *codec, - void (*hook)(struct hda_codec *)); -void snd_hda_gen_fixup_micmute_led(struct hda_codec *codec, - const struct hda_fixup *fix, int action); +int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec, + int (*callback)(struct led_classdev *, + enum led_brightness)); +int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec, + int (*callback)(struct led_classdev *, + enum led_brightness)); #endif /* __SOUND_HDA_GENERIC_H */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 3fbba2e51e36daf8ff39012c8ed0af042f056509..e34a4d5d047c18e5eeea9968e0f9915ed7476dc1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -180,7 +180,7 @@ MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " static bool pm_blacklist = true; module_param(pm_blacklist, bool, 0644); -MODULE_PARM_DESC(pm_blacklist, "Enable power-management blacklist"); +MODULE_PARM_DESC(pm_blacklist, "Enable power-management denylist"); /* reset the HD-audio controller in power save mode. * this may give more power-saving, but will take longer time to @@ -283,13 +283,12 @@ enum { /* quirks for old Intel chipsets */ #define AZX_DCAPS_INTEL_ICH \ - (AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_NO_ALIGN_BUFSIZE |\ - AZX_DCAPS_SYNC_WRITE) + (AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_NO_ALIGN_BUFSIZE) /* quirks for Intel PCH */ #define AZX_DCAPS_INTEL_PCH_BASE \ (AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\ - AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE) + AZX_DCAPS_SNOOP_TYPE(SCH)) /* PCH up to IVB; no runtime PM; bind with i915 gfx */ #define AZX_DCAPS_INTEL_PCH_NOPM \ @@ -305,13 +304,13 @@ enum { #define AZX_DCAPS_INTEL_HASWELL \ (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_COUNT_LPIB_DELAY |\ AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\ - AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE) + AZX_DCAPS_SNOOP_TYPE(SCH)) /* Broadwell HDMI can't use position buffer reliably, force to use LPIB */ #define AZX_DCAPS_INTEL_BROADWELL \ (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_POSFIX_LPIB |\ AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\ - AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE) + AZX_DCAPS_SNOOP_TYPE(SCH)) #define AZX_DCAPS_INTEL_BAYTRAIL \ (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT) @@ -322,19 +321,18 @@ enum { #define AZX_DCAPS_INTEL_SKYLAKE \ (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ - AZX_DCAPS_SYNC_WRITE |\ AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT) #define AZX_DCAPS_INTEL_BROXTON AZX_DCAPS_INTEL_SKYLAKE /* quirks for ATI SB / AMD Hudson */ #define AZX_DCAPS_PRESET_ATI_SB \ - (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB |\ + (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_POSFIX_LPIB |\ AZX_DCAPS_SNOOP_TYPE(ATI)) /* quirks for ATI/AMD HDMI */ #define AZX_DCAPS_PRESET_ATI_HDMI \ - (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB|\ + (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_POSFIX_LPIB|\ AZX_DCAPS_NO_MSI64) /* quirks for ATI HDMI with snoop off */ @@ -343,7 +341,7 @@ enum { /* quirks for AMD SB */ #define AZX_DCAPS_PRESET_AMD_SB \ - (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_AMD_WORKAROUND |\ + (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_AMD_WORKAROUND |\ AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME) /* quirks for Nvidia */ @@ -1519,7 +1517,7 @@ static bool check_hdmi_disabled(struct pci_dev *pci) #endif /* SUPPORT_VGA_SWITCHEROO */ /* - * white/black-listing for position_fix + * allow/deny-listing for position_fix */ static const struct snd_pci_quirk position_fix_list[] = { SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), @@ -1612,7 +1610,7 @@ static void assign_position_fix(struct azx *chip, int fix) } /* - * black-lists for probe_mask + * deny-lists for probe_mask */ static const struct snd_pci_quirk probe_mask_list[] = { /* Thinkpad often breaks the controller communication when accessing @@ -1660,9 +1658,9 @@ static void check_probe_mask(struct azx *chip, int dev) } /* - * white/black-list for enable_msi + * allow/deny-list for enable_msi */ -static const struct snd_pci_quirk msi_black_list[] = { +static const struct snd_pci_quirk msi_deny_list[] = { SND_PCI_QUIRK(0x103c, 0x2191, "HP", 0), /* AMD Hudson */ SND_PCI_QUIRK(0x103c, 0x2192, "HP", 0), /* AMD Hudson */ SND_PCI_QUIRK(0x103c, 0x21f7, "HP", 0), /* AMD Hudson */ @@ -1685,7 +1683,7 @@ static void check_msi(struct azx *chip) return; } chip->msi = 1; /* enable MSI as default */ - q = snd_pci_quirk_lookup(chip->pci, msi_black_list); + q = snd_pci_quirk_lookup(chip->pci, msi_deny_list); if (q) { dev_info(chip->card->dev, "msi for device %04x:%04x set to %d\n", @@ -2085,11 +2083,11 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream, #endif } -/* Blacklist for skipping the whole probe: +/* Denylist for skipping the whole probe: * some HD-audio PCI entries are exposed without any codecs, and such devices * should be ignored from the beginning. */ -static const struct pci_device_id driver_blacklist[] = { +static const struct pci_device_id driver_denylist[] = { { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1043, 0x874f) }, /* ASUS ROG Zenith II / Strix */ { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1462, 0xcb59) }, /* MSI TRX40 Creator */ { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1462, 0xcb60) }, /* MSI TRX40 */ @@ -2112,8 +2110,8 @@ static int azx_probe(struct pci_dev *pci, bool schedule_probe; int err; - if (pci_match_id(driver_blacklist, pci)) { - dev_info(&pci->dev, "Skipping the blacklisted device\n"); + if (pci_match_id(driver_denylist, pci)) { + dev_info(&pci->dev, "Skipping the device on the denylist\n"); return -ENODEV; } @@ -2203,7 +2201,7 @@ out_free: * So we keep a list of devices where we disable powersaving as its known * to causes problems on these devices. */ -static const struct snd_pci_quirk power_save_blacklist[] = { +static const struct snd_pci_quirk power_save_denylist[] = { /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ SND_PCI_QUIRK(0x1849, 0xc892, "Asrock B85M-ITX", 0), /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ @@ -2249,9 +2247,9 @@ static void set_default_power_save(struct azx *chip) if (pm_blacklist) { const struct snd_pci_quirk *q; - q = snd_pci_quirk_lookup(chip->pci, power_save_blacklist); + q = snd_pci_quirk_lookup(chip->pci, power_save_denylist); if (q && val) { - dev_info(chip->card->dev, "device %04x:%04x is on the power_save blacklist, forcing power_save to 0\n", + dev_info(chip->card->dev, "device %04x:%04x is on the power_save denylist, forcing power_save to 0\n", q->subvendor, q->subdevice); val = 0; } @@ -2354,7 +2352,6 @@ static int azx_probe_continue(struct azx *chip) if (azx_has_pm_runtime(chip)) { pm_runtime_use_autosuspend(&pci->dev); - pm_runtime_allow(&pci->dev); pm_runtime_put_autosuspend(&pci->dev); } @@ -2748,6 +2745,8 @@ static const struct pci_device_id azx_ids[] = { .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI }, /* Zhaoxin */ { PCI_DEVICE(0x1d17, 0x3288), .driver_data = AZX_DRIVER_ZHAOXIN }, + /* Loongson */ + { PCI_DEVICE(0x0014, 0x7a07), .driver_data = AZX_DRIVER_GENERIC }, { 0, } }; MODULE_DEVICE_TABLE(pci, azx_ids); diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 3dca65d79b029c7bdfb50c4678a8e09cb4c7be80..8c28b1022f4909b64f81141735316a1d90b9a3d4 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -129,11 +129,11 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, const char *name); int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, - unsigned int *tlv, const char * const *slaves, - const char *suffix, bool init_slave_vol, + unsigned int *tlv, const char * const *followers, + const char *suffix, bool init_follower_vol, struct snd_kcontrol **ctl_ret); -#define snd_hda_add_vmaster(codec, name, tlv, slaves, suffix) \ - __snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true, NULL) +#define snd_hda_add_vmaster(codec, name, tlv, followers, suffix) \ + __snd_hda_add_vmaster(codec, name, tlv, followers, suffix, true, NULL) int snd_hda_codec_reset(struct hda_codec *codec); void snd_hda_codec_register(struct hda_codec *codec); void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec); @@ -216,7 +216,7 @@ struct hda_multi_out { hda_nid_t hp_out_nid[HDA_MAX_OUTS]; /* DACs for multiple HPs */ hda_nid_t extra_out_nid[HDA_MAX_OUTS]; /* other (e.g. speaker) DACs */ hda_nid_t dig_out_nid; /* digital out audio widget */ - const hda_nid_t *slave_dig_outs; + const hda_nid_t *follower_dig_outs; int max_channels; /* currently supported analog channels */ int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ int no_share_stream; /* don't share a stream with multiple pins */ diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 0cc5fad1af8a90a71e32563317e440bf3b5198e3..c94553bcca888fd445acbe0916299925adaf97d2 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -308,6 +308,7 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) return err; } bus->irq = irq_id; + bus->dma_stop_delay = 100; card->sync_irq = bus->irq; /* @@ -333,6 +334,8 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) gcap = azx_readw(chip, GCAP); dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); + chip->align_buffer_size = 1; + /* read number of streams from GCAP register instead of using * hardcoded value */ @@ -443,6 +446,7 @@ static int hda_tegra_create(struct snd_card *card, if (err < 0) return err; + chip->bus.core.sync_write = 0; chip->bus.core.needs_damn_long_delay = 1; chip->bus.core.aligned_mmio = 1; diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 34fe753a46fba00ef08e83e2216c0e6e13a3c91e..b7dbf2e7f77afcf7bde1fd53f4303f36af4a3ee4 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -1182,6 +1182,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI), SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI), SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D), + SND_PCI_QUIRK(0x1102, 0x0018, "Recon3D", QUIRK_R3D), SND_PCI_QUIRK(0x1102, 0x0051, "Sound Blaster AE-5", QUIRK_AE5), {} }; @@ -4671,7 +4672,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) tmp = FLOAT_ONE; break; case QUIRK_AE5: - ca0113_mmio_command_set(codec, 0x48, 0x28, 0x00); + ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00); tmp = FLOAT_THREE; break; default: @@ -4717,7 +4718,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) r3di_gpio_mic_set(codec, R3DI_REAR_MIC); break; case QUIRK_AE5: - ca0113_mmio_command_set(codec, 0x48, 0x28, 0x00); + ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00); break; default: break; @@ -4756,7 +4757,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) tmp = FLOAT_ONE; break; case QUIRK_AE5: - ca0113_mmio_command_set(codec, 0x48, 0x28, 0x3f); + ca0113_mmio_command_set(codec, 0x30, 0x28, 0x3f); tmp = FLOAT_THREE; break; default: @@ -5748,6 +5749,11 @@ static int ca0132_switch_get(struct snd_kcontrol *kcontrol, return 0; } + if (nid == ZXR_HEADPHONE_GAIN) { + *valp = spec->zxr_gain_set; + return 0; + } + return 0; } @@ -6245,10 +6251,10 @@ static int zxr_add_headphone_gain_switch(struct hda_codec *codec) } /* - * Need to create slave controls for the alternate codecs that have surround + * Need to create follower controls for the alternate codecs that have surround * capabilities. */ -static const char * const ca0132_alt_slave_pfxs[] = { +static const char * const ca0132_alt_follower_pfxs[] = { "Front", "Surround", "Center", "LFE", NULL, }; @@ -6376,15 +6382,15 @@ static int ca0132_build_controls(struct hda_codec *codec) if (err < 0) return err; } - /* Setup vmaster with surround slaves for desktop ca0132 devices */ + /* Setup vmaster with surround followers for desktop ca0132 devices */ if (ca0132_use_alt_functions(spec)) { snd_hda_set_vmaster_tlv(codec, spec->dacs[0], HDA_OUTPUT, spec->tlv); snd_hda_add_vmaster(codec, "Master Playback Volume", - spec->tlv, ca0132_alt_slave_pfxs, + spec->tlv, ca0132_alt_follower_pfxs, "Playback Volume"); err = __snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, ca0132_alt_slave_pfxs, + NULL, ca0132_alt_follower_pfxs, "Playback Switch", true, &spec->vmaster_mute.sw_kctl); if (err < 0) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 396b5503038adaef456e910a9ba59cf868aa3252..be5000dd158532bbecf342fc7f823153e62cd8b7 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -137,14 +137,16 @@ static void cx_auto_vmaster_hook(void *private_data, int enabled) } /* turn on/off EAPD according to Master switch (inversely!) for mute LED */ -static void cx_auto_vmaster_hook_mute_led(void *private_data, int enabled) +static int cx_auto_vmaster_mute_led(struct led_classdev *led_cdev, + enum led_brightness brightness) { - struct hda_codec *codec = private_data; + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); struct conexant_spec *spec = codec->spec; snd_hda_codec_write(codec, spec->mute_led_eapd, 0, AC_VERB_SET_EAPD_BTLENABLE, - enabled ? 0x00 : 0x02); + brightness ? 0x02 : 0x00); + return 0; } static int cx_auto_init(struct hda_codec *codec) @@ -566,7 +568,7 @@ static void cxt_fixup_mute_led_eapd(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->mute_led_eapd = 0x1b; spec->dynamic_eapd = 1; - spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook_mute_led; + snd_hda_gen_add_mute_led_cdev(codec, cx_auto_vmaster_mute_led); } } @@ -631,21 +633,25 @@ static void cxt_update_gpio_led(struct hda_codec *codec, unsigned int mask, } /* turn on/off mute LED via GPIO per vmaster hook */ -static void cxt_fixup_gpio_mute_hook(void *private_data, int enabled) +static int cxt_gpio_mute_update(struct led_classdev *led_cdev, + enum led_brightness brightness) { - struct hda_codec *codec = private_data; + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); struct conexant_spec *spec = codec->spec; - /* muted -> LED on */ - cxt_update_gpio_led(codec, spec->gpio_mute_led_mask, !enabled); + + cxt_update_gpio_led(codec, spec->gpio_mute_led_mask, brightness); + return 0; } /* turn on/off mic-mute LED via GPIO per capture hook */ -static void cxt_gpio_micmute_update(struct hda_codec *codec) +static int cxt_gpio_micmute_update(struct led_classdev *led_cdev, + enum led_brightness brightness) { + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); struct conexant_spec *spec = codec->spec; - cxt_update_gpio_led(codec, spec->gpio_mic_led_mask, - spec->gen.micmute_led.led_value); + cxt_update_gpio_led(codec, spec->gpio_mic_led_mask, brightness); + return 0; } @@ -660,12 +666,12 @@ static void cxt_fixup_mute_led_gpio(struct hda_codec *codec, }; if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->gen.vmaster_mute.hook = cxt_fixup_gpio_mute_hook; + snd_hda_gen_add_mute_led_cdev(codec, cxt_gpio_mute_update); spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x01; spec->gpio_mic_led_mask = 0x02; - snd_hda_gen_add_micmute_led(codec, cxt_gpio_micmute_update); + snd_hda_gen_add_micmute_led_cdev(codec, cxt_gpio_micmute_update); } snd_hda_add_verbs(codec, gpio_init); if (spec->gpio_led) @@ -988,8 +994,6 @@ static int patch_conexant_auto(struct hda_codec *codec) cx_auto_parse_eapd(codec); spec->gen.own_eapd_ctl = 1; - if (spec->dynamic_eapd) - spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook; switch (codec->core.vendor_id) { case 0x14f15045: @@ -1014,7 +1018,7 @@ static int patch_conexant_auto(struct hda_codec *codec) break; case 0x14f150f2: codec->power_save_node = 1; - /* Fall through */ + fallthrough; default: codec->pin_amp_workaround = 1; snd_hda_pick_fixup(codec, cxt5066_fixup_models, @@ -1022,17 +1026,8 @@ static int patch_conexant_auto(struct hda_codec *codec) break; } - /* Show mute-led control only on HP laptops - * This is a sort of white-list: on HP laptops, EAPD corresponds - * only to the mute-LED without actualy amp function. Meanwhile, - * others may use EAPD really as an amp switch, so it might be - * not good to expose it blindly. - */ - switch (codec->core.subsystem_id >> 16) { - case 0x103c: - spec->gen.vmaster_mute_enum = 1; - break; - } + if (!spec->gen.vmaster_mute.hook && spec->dynamic_eapd) + spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook; snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index cd46247988e4d38b2ff68b232874d398efacd9db..4bbd12d3b1b59919e9917a62c2c8686fc03e6cdf 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -42,6 +42,11 @@ static bool enable_acomp = true; module_param(enable_acomp, bool, 0444); MODULE_PARM_DESC(enable_acomp, "Enable audio component binding (default=yes)"); +static bool enable_silent_stream = +IS_ENABLED(CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM); +module_param(enable_silent_stream, bool, 0644); +MODULE_PARM_DESC(enable_silent_stream, "Enable Silent Stream for HDMI devices"); + struct hdmi_spec_per_cvt { hda_nid_t cvt_nid; int assigned; @@ -160,6 +165,7 @@ struct hdmi_spec { bool use_acomp_notifier; /* use eld_notify callback for hotplug */ bool acomp_registered; /* audio component registered in this driver */ + bool force_connect; /* force connectivity */ struct drm_audio_component_audio_ops drm_audio_ops; int (*port2pin)(struct hda_codec *, int); /* reverse port/pin mapping */ @@ -167,6 +173,7 @@ struct hdmi_spec { hda_nid_t vendor_nid; const int *port_map; int port_num; + bool send_silent_stream; /* Flag to enable silent stream feature */ }; #ifdef CONFIG_SND_HDA_COMPONENT @@ -1635,21 +1642,72 @@ static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, snd_hda_power_down_pm(codec); } +static void silent_stream_enable(struct hda_codec *codec, + struct hdmi_spec_per_pin *per_pin) +{ + unsigned int newval, oldval; + + codec_dbg(codec, "hdmi: enabling silent stream for NID %d\n", + per_pin->pin_nid); + + mutex_lock(&per_pin->lock); + + if (!per_pin->channels) + per_pin->channels = 2; + + oldval = snd_hda_codec_read(codec, per_pin->pin_nid, 0, + AC_VERB_GET_CONV, 0); + newval = (oldval & 0xF0) | 0xF; + snd_hda_codec_write(codec, per_pin->pin_nid, 0, + AC_VERB_SET_CHANNEL_STREAMID, newval); + + hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); + + mutex_unlock(&per_pin->lock); +} + /* update ELD and jack state via audio component */ static void sync_eld_via_acomp(struct hda_codec *codec, struct hdmi_spec_per_pin *per_pin) { struct hdmi_spec *spec = codec->spec; struct hdmi_eld *eld = &spec->temp_eld; + bool monitor_prev, monitor_next; mutex_lock(&per_pin->lock); eld->monitor_present = false; + monitor_prev = per_pin->sink_eld.monitor_present; eld->eld_size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, per_pin->dev_id, &eld->monitor_present, eld->eld_buffer, ELD_MAX_SIZE); eld->eld_valid = (eld->eld_size > 0); update_eld(codec, per_pin, eld, 0); + monitor_next = per_pin->sink_eld.monitor_present; mutex_unlock(&per_pin->lock); + + /* + * Power-up will call hdmi_present_sense, so the PM calls + * have to be done without mutex held. + */ + + if (spec->send_silent_stream) { + int pm_ret; + + if (!monitor_prev && monitor_next) { + pm_ret = snd_hda_power_up_pm(codec); + if (pm_ret < 0) + codec_err(codec, + "Monitor plugged-in, Failed to power up codec ret=[%d]\n", + pm_ret); + silent_stream_enable(codec, per_pin); + } else if (monitor_prev && !monitor_next) { + pm_ret = snd_hda_power_down_pm(codec); + if (pm_ret < 0) + codec_err(codec, + "Monitor plugged-out, Failed to power down codec ret=[%d]\n", + pm_ret); + } + } } static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) @@ -1701,7 +1759,8 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) * all device entries on the same pin */ config = snd_hda_codec_get_pincfg(codec, pin_nid); - if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) + if (get_defcfg_connect(config) == AC_JACK_PORT_NONE && + !spec->force_connect) return 0; /* @@ -1803,11 +1862,18 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) return 0; } +static const struct snd_pci_quirk force_connect_list[] = { + SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1), + {} +}; + static int hdmi_parse_codec(struct hda_codec *codec) { + struct hdmi_spec *spec = codec->spec; hda_nid_t start_nid; unsigned int caps; int i, nodes; + const struct snd_pci_quirk *q; nodes = snd_hda_get_sub_nodes(codec, codec->core.afg, &start_nid); if (!start_nid || nodes < 0) { @@ -1815,6 +1881,11 @@ static int hdmi_parse_codec(struct hda_codec *codec) return -EINVAL; } + q = snd_pci_quirk_lookup(codec->bus->pci, force_connect_list); + + if (q && q->value) + spec->force_connect = true; + /* * hdmi_add_pin() assumes total amount of converters to * be known, so first discover all converters @@ -2802,6 +2873,13 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, spec->ops.setup_stream = i915_hsw_setup_stream; spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; + /* + * Enable silent stream feature, if it is enabled via + * module param or Kconfig option + */ + if (enable_silent_stream) + spec->send_silent_stream = true; + return parse_intel_hdmi(codec); } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 29f5878f0c501119712b70e5be0240c9e3890633..2477f3ed7237353ddcbcfc109b44bed76d71959e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -67,6 +67,13 @@ struct alc_customize_define { unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */ }; +struct alc_coef_led { + unsigned int idx; + unsigned int mask; + unsigned int on; + unsigned int off; +}; + struct alc_spec { struct hda_gen_spec gen; /* must be at head */ @@ -80,7 +87,7 @@ struct alc_spec { unsigned int gpio_data; bool gpio_write_delay; /* add a delay before writing gpio_data */ - /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ + /* mute LED for HP laptops, see vref_mute_led_set() */ int mute_led_polarity; int micmute_led_polarity; hda_nid_t mute_led_nid; @@ -88,14 +95,8 @@ struct alc_spec { unsigned int gpio_mute_led_mask; unsigned int gpio_mic_led_mask; - unsigned int mute_led_coef_idx; - unsigned int mute_led_coefbit_mask; - unsigned int mute_led_coefbit_on; - unsigned int mute_led_coefbit_off; - unsigned int mic_led_coef_idx; - unsigned int mic_led_coefbit_mask; - unsigned int mic_led_coefbit_on; - unsigned int mic_led_coefbit_off; + struct alc_coef_led mute_led_coef; + struct alc_coef_led mic_led_coef; hda_nid_t headset_mic_pin; hda_nid_t headphone_mic_pin; @@ -287,6 +288,13 @@ static void alc_fixup_gpio4(struct hda_codec *codec, alc_fixup_gpio(codec, action, 0x04); } +static void alc_fixup_micmute_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + if (action == HDA_FIXUP_ACT_PROBE) + snd_hda_gen_add_micmute_led_cdev(codec, NULL); +} + /* * Fix hardware PLL issue * On some codecs, the analog PLL gating control must be off while @@ -374,7 +382,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) case 0x10ec0295: case 0x10ec0299: alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000); - /* fallthrough */ + fallthrough; case 0x10ec0215: case 0x10ec0233: case 0x10ec0235: @@ -1070,7 +1078,7 @@ static int set_beep_amp(struct alc_spec *spec, hda_nid_t nid, return 0; } -static const struct snd_pci_quirk beep_white_list[] = { +static const struct snd_pci_quirk beep_allow_list[] = { SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x115d, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), @@ -1080,7 +1088,7 @@ static const struct snd_pci_quirk beep_white_list[] = { SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1), SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1), SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), - /* blacklist -- no beep available */ + /* denylist -- no beep available */ SND_PCI_QUIRK(0x17aa, 0x309e, "Lenovo ThinkCentre M73", 0), SND_PCI_QUIRK(0x17aa, 0x30a3, "Lenovo ThinkCentre M93", 0), {} @@ -1090,7 +1098,7 @@ static inline int has_cdefine_beep(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; const struct snd_pci_quirk *q; - q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list); + q = snd_pci_quirk_lookup(codec->bus->pci, beep_allow_list); if (q) return q->value; return spec->cdefine.enable_pcbeep; @@ -3982,25 +3990,34 @@ static void alc269_fixup_x101_headset_mic(struct hda_codec *codec, } } +static void alc_update_vref_led(struct hda_codec *codec, hda_nid_t pin, + bool polarity, bool on) +{ + unsigned int pinval; + + if (!pin) + return; + if (polarity) + on = !on; + pinval = snd_hda_codec_get_pin_target(codec, pin); + pinval &= ~AC_PINCTL_VREFEN; + pinval |= on ? AC_PINCTL_VREF_80 : AC_PINCTL_VREF_HIZ; + /* temporarily power up/down for setting VREF */ + snd_hda_power_up_pm(codec); + snd_hda_set_pin_ctl_cache(codec, pin, pinval); + snd_hda_power_down_pm(codec); +} /* update mute-LED according to the speaker mute state via mic VREF pin */ -static void alc269_fixup_mic_mute_hook(void *private_data, int enabled) +static int vref_mute_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) { - struct hda_codec *codec = private_data; + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); struct alc_spec *spec = codec->spec; - unsigned int pinval; - if (spec->mute_led_polarity) - enabled = !enabled; - pinval = snd_hda_codec_get_pin_target(codec, spec->mute_led_nid); - pinval &= ~AC_PINCTL_VREFEN; - pinval |= enabled ? AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80; - if (spec->mute_led_nid) { - /* temporarily power up/down for setting VREF */ - snd_hda_power_up_pm(codec); - snd_hda_set_pin_ctl_cache(codec, spec->mute_led_nid, pinval); - snd_hda_power_down_pm(codec); - } + alc_update_vref_led(codec, spec->mute_led_nid, + spec->mute_led_polarity, brightness); + return 0; } /* Make sure the led works even in runtime suspend */ @@ -4038,8 +4055,7 @@ static void alc269_fixup_hp_mute_led(struct hda_codec *codec, break; spec->mute_led_polarity = pol; spec->mute_led_nid = pin - 0x0a + 0x18; - spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook; - spec->gen.vmaster_mute_enum = 1; + snd_hda_gen_add_mute_led_cdev(codec, vref_mute_led_set); codec->power_filter = led_power_filter; codec_dbg(codec, "Detected mute LED for %x:%d\n", spec->mute_led_nid, @@ -4057,8 +4073,7 @@ static void alc269_fixup_hp_mute_led_micx(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->mute_led_polarity = 0; spec->mute_led_nid = pin; - spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook; - spec->gen.vmaster_mute_enum = 1; + snd_hda_gen_add_mute_led_cdev(codec, vref_mute_led_set); codec->power_filter = led_power_filter; } } @@ -4091,26 +4106,18 @@ static void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask, } /* turn on/off mute LED via GPIO per vmaster hook */ -static void alc_fixup_gpio_mute_hook(void *private_data, int enabled) +static int gpio_mute_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) { - struct hda_codec *codec = private_data; + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); struct alc_spec *spec = codec->spec; alc_update_gpio_led(codec, spec->gpio_mute_led_mask, - spec->mute_led_polarity, enabled); + spec->mute_led_polarity, !brightness); + return 0; } /* turn on/off mic-mute LED via GPIO per capture hook */ -static void alc_gpio_micmute_update(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - alc_update_gpio_led(codec, spec->gpio_mic_led_mask, - spec->micmute_led_polarity, - spec->gen.micmute_led.led_value); -} - -#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) static int micmute_led_set(struct led_classdev *led_cdev, enum led_brightness brightness) { @@ -4122,14 +4129,6 @@ static int micmute_led_set(struct led_classdev *led_cdev, return 0; } -static struct led_classdev micmute_led_cdev = { - .name = "hda::micmute", - .max_brightness = 1, - .brightness_set_blocking = micmute_led_set, - .default_trigger = "audio-micmute", -}; -#endif - /* setup mute and mic-mute GPIO bits, add hooks appropriately */ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, int action, @@ -4137,9 +4136,6 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, unsigned int micmute_mask) { struct alc_spec *spec = codec->spec; -#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) - int err; -#endif alc_fixup_gpio(codec, action, mute_mask | micmute_mask); @@ -4147,18 +4143,11 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, return; if (mute_mask) { spec->gpio_mute_led_mask = mute_mask; - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; + snd_hda_gen_add_mute_led_cdev(codec, gpio_mute_led_set); } if (micmute_mask) { spec->gpio_mic_led_mask = micmute_mask; - snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); - -#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) - micmute_led_cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE); - err = devm_led_classdev_register(&codec->core.dev, &micmute_led_cdev); - if (err) - codec_warn(codec, "failed to register micmute LED\n"); -#endif + snd_hda_gen_add_micmute_led_cdev(codec, micmute_led_set); } } @@ -4184,21 +4173,16 @@ static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, alc_fixup_hp_gpio_led(codec, action, 0x02, 0x20); } -/* turn on/off mic-mute LED per capture hook */ -static void alc_cap_micmute_update(struct hda_codec *codec) +/* turn on/off mic-mute LED per capture hook via VREF change */ +static int vref_micmute_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) { + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); struct alc_spec *spec = codec->spec; - unsigned int pinval; - if (!spec->cap_mute_led_nid) - return; - pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid); - pinval &= ~AC_PINCTL_VREFEN; - if (spec->gen.micmute_led.led_value) - pinval |= AC_PINCTL_VREF_80; - else - pinval |= AC_PINCTL_VREF_HIZ; - snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval); + alc_update_vref_led(codec, spec->cap_mute_led_nid, + spec->micmute_led_polarity, brightness); + return 0; } static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, @@ -4214,7 +4198,7 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, spec->gpio_mask |= 0x10; spec->gpio_dir |= 0x10; spec->cap_mute_led_nid = 0x18; - snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update); + snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set); codec->power_filter = led_power_filter; } } @@ -4227,25 +4211,32 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec, alc_fixup_hp_gpio_led(codec, action, 0x08, 0); if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->cap_mute_led_nid = 0x18; - snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update); + snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set); codec->power_filter = led_power_filter; } } +static void alc_update_coef_led(struct hda_codec *codec, + struct alc_coef_led *led, + bool polarity, bool on) +{ + if (polarity) + on = !on; + /* temporarily power up/down for setting COEF bit */ + alc_update_coef_idx(codec, led->idx, led->mask, + on ? led->on : led->off); +} + /* update mute-LED according to the speaker mute state via COEF bit */ -static void alc_fixup_mute_led_coefbit_hook(void *private_data, int enabled) +static int coef_mute_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) { - struct hda_codec *codec = private_data; + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); struct alc_spec *spec = codec->spec; - if (spec->mute_led_polarity) - enabled = !enabled; - - /* temporarily power up/down for setting COEF bit */ - enabled ? alc_update_coef_idx(codec, spec->mute_led_coef_idx, - spec->mute_led_coefbit_mask, spec->mute_led_coefbit_off) : - alc_update_coef_idx(codec, spec->mute_led_coef_idx, - spec->mute_led_coefbit_mask, spec->mute_led_coefbit_on); + alc_update_coef_led(codec, &spec->mute_led_coef, + spec->mute_led_polarity, brightness); + return 0; } static void alc285_fixup_hp_mute_led_coefbit(struct hda_codec *codec, @@ -4256,12 +4247,11 @@ static void alc285_fixup_hp_mute_led_coefbit(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->mute_led_polarity = 0; - spec->mute_led_coef_idx = 0x0b; - spec->mute_led_coefbit_mask = 1<<3; - spec->mute_led_coefbit_on = 1<<3; - spec->mute_led_coefbit_off = 0; - spec->gen.vmaster_mute.hook = alc_fixup_mute_led_coefbit_hook; - spec->gen.vmaster_mute_enum = 1; + spec->mute_led_coef.idx = 0x0b; + spec->mute_led_coef.mask = 1 << 3; + spec->mute_led_coef.on = 1 << 3; + spec->mute_led_coef.off = 0; + snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set); } } @@ -4273,26 +4263,24 @@ static void alc236_fixup_hp_mute_led_coefbit(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->mute_led_polarity = 0; - spec->mute_led_coef_idx = 0x34; - spec->mute_led_coefbit_mask = 1<<5; - spec->mute_led_coefbit_on = 0; - spec->mute_led_coefbit_off = 1<<5; - spec->gen.vmaster_mute.hook = alc_fixup_mute_led_coefbit_hook; - spec->gen.vmaster_mute_enum = 1; + spec->mute_led_coef.idx = 0x34; + spec->mute_led_coef.mask = 1 << 5; + spec->mute_led_coef.on = 0; + spec->mute_led_coef.off = 1 << 5; + snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set); } } /* turn on/off mic-mute LED per capture hook by coef bit */ -static void alc_hp_cap_micmute_update(struct hda_codec *codec) +static int coef_micmute_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) { + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); struct alc_spec *spec = codec->spec; - if (spec->gen.micmute_led.led_value) - alc_update_coef_idx(codec, spec->mic_led_coef_idx, - spec->mic_led_coefbit_mask, spec->mic_led_coefbit_on); - else - alc_update_coef_idx(codec, spec->mic_led_coef_idx, - spec->mic_led_coefbit_mask, spec->mic_led_coefbit_off); + alc_update_coef_led(codec, &spec->mic_led_coef, + spec->micmute_led_polarity, brightness); + return 0; } static void alc285_fixup_hp_coef_micmute_led(struct hda_codec *codec, @@ -4301,11 +4289,11 @@ static void alc285_fixup_hp_coef_micmute_led(struct hda_codec *codec, struct alc_spec *spec = codec->spec; if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->mic_led_coef_idx = 0x19; - spec->mic_led_coefbit_mask = 1<<13; - spec->mic_led_coefbit_on = 1<<13; - spec->mic_led_coefbit_off = 0; - snd_hda_gen_add_micmute_led(codec, alc_hp_cap_micmute_update); + spec->mic_led_coef.idx = 0x19; + spec->mic_led_coef.mask = 1 << 13; + spec->mic_led_coef.on = 1 << 13; + spec->mic_led_coef.off = 0; + snd_hda_gen_add_micmute_led_cdev(codec, coef_micmute_led_set); } } @@ -4315,11 +4303,11 @@ static void alc236_fixup_hp_coef_micmute_led(struct hda_codec *codec, struct alc_spec *spec = codec->spec; if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->mic_led_coef_idx = 0x35; - spec->mic_led_coefbit_mask = 3<<2; - spec->mic_led_coefbit_on = 2<<2; - spec->mic_led_coefbit_off = 1<<2; - snd_hda_gen_add_micmute_led(codec, alc_hp_cap_micmute_update); + spec->mic_led_coef.idx = 0x35; + spec->mic_led_coef.mask = 3 << 2; + spec->mic_led_coef.on = 2 << 2; + spec->mic_led_coef.off = 1 << 2; + snd_hda_gen_add_micmute_led_cdev(codec, coef_micmute_led_set); } } @@ -4459,7 +4447,7 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x1a); if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->cap_mute_led_nid = 0x18; - snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update); + snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set); } } @@ -4710,7 +4698,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, break; case 0x10ec0867: alc_update_coefex_idx(codec, 0x57, 0x5, 0, 1<<14); - /* fallthru */ + fallthrough; case 0x10ec0221: case 0x10ec0662: snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); @@ -6166,6 +6154,11 @@ enum { ALC289_FIXUP_ASUS_GA502, ALC256_FIXUP_ACER_MIC_NO_PRESENCE, ALC285_FIXUP_HP_GPIO_AMP_INIT, + ALC269_FIXUP_CZC_B20, + ALC269_FIXUP_CZC_TMI, + ALC269_FIXUP_CZC_L101, + ALC269_FIXUP_LEMOTE_A1802, + ALC269_FIXUP_LEMOTE_A190X, }; static const struct hda_fixup alc269_fixups[] = { @@ -6706,7 +6699,7 @@ static const struct hda_fixup alc269_fixups[] = { }, [ALC255_FIXUP_MIC_MUTE_LED] = { .type = HDA_FIXUP_FUNC, - .v.func = snd_hda_gen_fixup_micmute_led, + .v.func = alc_fixup_micmute_led, }, [ALC282_FIXUP_ASPIRE_V5_PINS] = { .type = HDA_FIXUP_PINS, @@ -6809,7 +6802,7 @@ static const struct hda_fixup alc269_fixups[] = { }, [ALC292_FIXUP_DELL_E7X] = { .type = HDA_FIXUP_FUNC, - .v.func = snd_hda_gen_fixup_micmute_led, + .v.func = alc_fixup_micmute_led, /* micmute fixup must be applied at last */ .chained_before = true, .chain_id = ALC292_FIXUP_DELL_E7X_AAMIX, @@ -7404,6 +7397,89 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC285_FIXUP_HP_GPIO_LED }, + [ALC269_FIXUP_CZC_B20] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x12, 0x411111f0 }, + { 0x14, 0x90170110 }, /* speaker */ + { 0x15, 0x032f1020 }, /* HP out */ + { 0x17, 0x411111f0 }, + { 0x18, 0x03ab1040 }, /* mic */ + { 0x19, 0xb7a7013f }, + { 0x1a, 0x0181305f }, + { 0x1b, 0x411111f0 }, + { 0x1d, 0x411111f0 }, + { 0x1e, 0x411111f0 }, + { } + }, + .chain_id = ALC269_FIXUP_DMIC, + }, + [ALC269_FIXUP_CZC_TMI] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x12, 0x4000c000 }, + { 0x14, 0x90170110 }, /* speaker */ + { 0x15, 0x0421401f }, /* HP out */ + { 0x17, 0x411111f0 }, + { 0x18, 0x04a19020 }, /* mic */ + { 0x19, 0x411111f0 }, + { 0x1a, 0x411111f0 }, + { 0x1b, 0x411111f0 }, + { 0x1d, 0x40448505 }, + { 0x1e, 0x411111f0 }, + { 0x20, 0x8000ffff }, + { } + }, + .chain_id = ALC269_FIXUP_DMIC, + }, + [ALC269_FIXUP_CZC_L101] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x12, 0x40000000 }, + { 0x14, 0x01014010 }, /* speaker */ + { 0x15, 0x411111f0 }, /* HP out */ + { 0x16, 0x411111f0 }, + { 0x18, 0x01a19020 }, /* mic */ + { 0x19, 0x02a19021 }, + { 0x1a, 0x0181302f }, + { 0x1b, 0x0221401f }, + { 0x1c, 0x411111f0 }, + { 0x1d, 0x4044c601 }, + { 0x1e, 0x411111f0 }, + { } + }, + .chain_id = ALC269_FIXUP_DMIC, + }, + [ALC269_FIXUP_LEMOTE_A1802] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x12, 0x40000000 }, + { 0x14, 0x90170110 }, /* speaker */ + { 0x17, 0x411111f0 }, + { 0x18, 0x03a19040 }, /* mic1 */ + { 0x19, 0x90a70130 }, /* mic2 */ + { 0x1a, 0x411111f0 }, + { 0x1b, 0x411111f0 }, + { 0x1d, 0x40489d2d }, + { 0x1e, 0x411111f0 }, + { 0x20, 0x0003ffff }, + { 0x21, 0x03214020 }, + { } + }, + .chain_id = ALC269_FIXUP_DMIC, + }, + [ALC269_FIXUP_LEMOTE_A190X] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x14, 0x99130110 }, /* speaker */ + { 0x15, 0x0121401f }, /* HP out */ + { 0x18, 0x01a19c20 }, /* rear mic */ + { 0x19, 0x99a3092f }, /* front mic */ + { 0x1b, 0x0201401f }, /* front lineout */ + { } + }, + .chain_id = ALC269_FIXUP_DMIC, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -7693,9 +7769,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS), + SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20), + SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI), + SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101), SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE), + SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802), + SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X), #if 0 /* Below is a quirk table taken from the old code. @@ -8951,6 +9032,7 @@ enum { ALC662_FIXUP_LED_GPIO1, ALC662_FIXUP_IDEAPAD, ALC272_FIXUP_MARIO, + ALC662_FIXUP_CZC_ET26, ALC662_FIXUP_CZC_P10T, ALC662_FIXUP_SKU_IGNORE, ALC662_FIXUP_HP_RP5800, @@ -9020,6 +9102,25 @@ static const struct hda_fixup alc662_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc272_fixup_mario, }, + [ALC662_FIXUP_CZC_ET26] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + {0x12, 0x403cc000}, + {0x14, 0x90170110}, /* speaker */ + {0x15, 0x411111f0}, + {0x16, 0x411111f0}, + {0x18, 0x01a19030}, /* mic */ + {0x19, 0x90a7013f}, /* int-mic */ + {0x1a, 0x01014020}, + {0x1b, 0x0121401f}, + {0x1c, 0x411111f0}, + {0x1d, 0x411111f0}, + {0x1e, 0x40478e35}, + {} + }, + .chained = true, + .chain_id = ALC662_FIXUP_SKU_IGNORE + }, [ALC662_FIXUP_CZC_P10T] = { .type = HDA_FIXUP_VERBS, .v.verbs = (const struct hda_verb[]) { @@ -9403,6 +9504,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO), SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68), SND_PCI_QUIRK(0x1b0a, 0x01b8, "ACER Veriton", ALC662_FIXUP_ACER_VERITON), + SND_PCI_QUIRK(0x1b35, 0x1234, "CZC ET26", ALC662_FIXUP_CZC_ET26), SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T), SND_PCI_QUIRK(0x1025, 0x0566, "Acer Aspire Ethos 8951G", ALC669_FIXUP_ACER_ASPIRE_ETHOS), diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index a608d0486ae49be77c4fdd55e99b68ed4ac35494..c662431bf13a51b6514af8c8fe5a141513041c14 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -320,15 +320,18 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, } /* hook for controlling mic-mute LED GPIO */ -static void stac_capture_led_update(struct hda_codec *codec) +static int stac_capture_led_update(struct led_classdev *led_cdev, + enum led_brightness brightness) { + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); struct sigmatel_spec *spec = codec->spec; - if (spec->gen.micmute_led.led_value) + if (brightness) spec->gpio_data |= spec->mic_mute_led_gpio; else spec->gpio_data &= ~spec->mic_mute_led_gpio; stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); + return 0; } static int stac_vrefout_set(struct hda_codec *codec, @@ -366,10 +369,9 @@ static unsigned int stac_vref_led_power_filter(struct hda_codec *codec, } /* update mute-LED accoring to the master switch */ -static void stac_update_led_status(struct hda_codec *codec, int enabled) +static void stac_update_led_status(struct hda_codec *codec, bool muted) { struct sigmatel_spec *spec = codec->spec; - int muted = !enabled; if (!spec->gpio_led) return; @@ -393,9 +395,13 @@ static void stac_update_led_status(struct hda_codec *codec, int enabled) } /* vmaster hook to update mute LED */ -static void stac_vmaster_hook(void *private_data, int val) +static int stac_vmaster_hook(struct led_classdev *led_cdev, + enum led_brightness brightness) { - stac_update_led_status(private_data, val); + struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent); + + stac_update_led_status(codec, brightness); + return 0; } /* automute hook to handle GPIO mute and EAPD updates */ @@ -832,7 +838,7 @@ static int stac_auto_create_beep_ctls(struct hda_codec *codec, static const struct snd_kcontrol_new beep_vol_ctl = HDA_CODEC_VOLUME(NULL, 0, 0, 0); - /* check for mute support for the the amp */ + /* check for mute support for the amp */ if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) { const struct snd_kcontrol_new *temp; if (spec->anabeep_nid == nid) @@ -3129,7 +3135,7 @@ static void fixup_hp_headphone(struct hda_codec *codec, hda_nid_t pin) unsigned int pin_cfg = snd_hda_codec_get_pincfg(codec, pin); /* It was changed in the BIOS to just satisfy MS DTM. - * Lets turn it back into slaved HP + * Lets turn it back into follower HP */ pin_cfg = (pin_cfg & (~AC_DEFCFG_DEVICE)) | (AC_JACK_HP_OUT << AC_DEFCFG_DEVICE_SHIFT); @@ -4313,7 +4319,7 @@ static int stac_parse_auto_config(struct hda_codec *codec) #endif if (spec->gpio_led) - spec->gen.vmaster_mute.hook = stac_vmaster_hook; + snd_hda_gen_add_mute_led_cdev(codec, stac_vmaster_hook); if (spec->aloopback_ctl && snd_hda_get_bool_hint(codec, "loopback") == 1) { @@ -4636,7 +4642,7 @@ static void stac_setup_gpio(struct hda_codec *codec) spec->gpio_dir |= spec->mic_mute_led_gpio; spec->mic_enabled = 0; spec->gpio_data |= spec->mic_mute_led_gpio; - snd_hda_gen_add_micmute_led(codec, stac_capture_led_update); + snd_hda_gen_add_micmute_led_cdev(codec, stac_capture_led_update); } } diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c index 4089feb8c68e339fc33bbbb26591a13b909daf0f..6698ae241efcb9c810d9c0834a32f7830ab7abc3 100644 --- a/sound/pci/hda/thinkpad_helper.c +++ b/sound/pci/hda/thinkpad_helper.c @@ -3,13 +3,11 @@ * to be included from codec driver */ -#if IS_ENABLED(CONFIG_THINKPAD_ACPI) && IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) +#if IS_ENABLED(CONFIG_THINKPAD_ACPI) #include #include -static void (*old_vmaster_hook)(void *, int); - static bool is_thinkpad(struct hda_codec *codec) { return (codec->core.subsystem_id >> 16 == 0x17aa) && @@ -17,25 +15,14 @@ static bool is_thinkpad(struct hda_codec *codec) acpi_dev_found("IBM0068")); } -static void update_tpacpi_mute_led(void *private_data, int enabled) -{ - if (old_vmaster_hook) - old_vmaster_hook(private_data, enabled); - - ledtrig_audio_set(LED_AUDIO_MUTE, enabled ? LED_OFF : LED_ON); -} - static void hda_fixup_thinkpad_acpi(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - struct hda_gen_spec *spec = codec->spec; - if (action == HDA_FIXUP_ACT_PROBE) { if (!is_thinkpad(codec)) return; - old_vmaster_hook = spec->vmaster_mute.hook; - spec->vmaster_mute.hook = update_tpacpi_mute_led; - snd_hda_gen_fixup_micmute_led(codec, fix, action); + snd_hda_gen_add_mute_led_cdev(codec, NULL); + snd_hda_gen_add_micmute_led_cdev(codec, NULL); } } diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 81929063b2fad4040934b8ec35960270ea11c0cc..1d2a0287284b5058bc603b6dbdfe27d61353d4aa 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c @@ -691,7 +691,7 @@ static int snd_ice1712_delta_init(struct snd_ice1712 *ice) break; case ICE1712_SUBDEVICE_DELTADIO2496: ice->gpio.set_pro_rate = delta_1010_set_rate_val; - /* fall thru */ + fallthrough; case ICE1712_SUBDEVICE_DELTA66: ice->spdif.ops.open = delta_open_spdif; ice->spdif.ops.setup_rate = delta_setup_spdif; diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index 7be4eb42f05ebaae464bb1f8217b4c1cf15efc1b..e57a55cebc5a3181fec289cb63d4b6c81d5afadb 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c @@ -397,7 +397,7 @@ static const struct snd_kcontrol_new juli_mute_controls[] = { }, }; -static const char * const slave_vols[] = { +static const char * const follower_vols[] = { PCM_VOLUME, MONITOR_AN_IN_VOLUME, MONITOR_DIG_IN_VOLUME, @@ -418,16 +418,16 @@ static struct snd_kcontrol *ctl_find(struct snd_card *card, return snd_ctl_find_id(card, &sid); } -static void add_slaves(struct snd_card *card, - struct snd_kcontrol *master, - const char * const *list) +static void add_followers(struct snd_card *card, + struct snd_kcontrol *master, + const char * const *list) { for (; *list; list++) { - struct snd_kcontrol *slave = ctl_find(card, *list); - /* dev_dbg(card->dev, "add_slaves - %s\n", *list); */ - if (slave) { - /* dev_dbg(card->dev, "slave %s found\n", *list); */ - snd_ctl_add_slave(master, slave); + struct snd_kcontrol *follower = ctl_find(card, *list); + /* dev_dbg(card->dev, "add_followers - %s\n", *list); */ + if (follower) { + /* dev_dbg(card->dev, "follower %s found\n", *list); */ + snd_ctl_add_follower(master, follower); } } } @@ -454,7 +454,7 @@ static int juli_add_controls(struct snd_ice1712 *ice) juli_master_db_scale); if (!vmaster) return -ENOMEM; - add_slaves(ice->card, vmaster, slave_vols); + add_followers(ice->card, vmaster, follower_vols); err = snd_ctl_add(ice->card, vmaster); if (err < 0) return err; diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index 8df14f63b10df66e96436ff5780d101d49da4d4b..096ec76f5304672ba838a9ddd45d5e282ae3b294 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c @@ -32,7 +32,7 @@ * Experimentally I found out that only a combination of * OCKS0=1, OCKS1=1 (128fs, 64fs output) and ice1724 - * VT1724_MT_I2S_MCLK_128X=0 (256fs input) yields correct - * sampling rate. That means the the FPGA doubles the + * sampling rate. That means that the FPGA doubles the * MCK01 rate. * * Copyright (c) 2003 Takashi Iwai diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c index 86659620571006f8eefcaa9efd07f44d096a932f..0e3e04aa9faf615189a2b76af5f90c163e209c78 100644 --- a/sound/pci/ice1712/quartet.c +++ b/sound/pci/ice1712/quartet.c @@ -757,7 +757,7 @@ static const struct snd_kcontrol_new qtet_controls[] = { QTET_CONTROL("Output 3/4 to Monitor 1/2", sw, OUT34_MON12), }; -static const char * const slave_vols[] = { +static const char * const follower_vols[] = { PCM_12_PLAYBACK_VOLUME, PCM_34_PLAYBACK_VOLUME, NULL @@ -776,13 +776,13 @@ static struct snd_kcontrol *ctl_find(struct snd_card *card, return snd_ctl_find_id(card, &sid); } -static void add_slaves(struct snd_card *card, - struct snd_kcontrol *master, const char * const *list) +static void add_followers(struct snd_card *card, + struct snd_kcontrol *master, const char * const *list) { for (; *list; list++) { - struct snd_kcontrol *slave = ctl_find(card, *list); - if (slave) - snd_ctl_add_slave(master, slave); + struct snd_kcontrol *follower = ctl_find(card, *list); + if (follower) + snd_ctl_add_follower(master, follower); } } @@ -806,7 +806,7 @@ static int qtet_add_controls(struct snd_ice1712 *ice) qtet_master_db_scale); if (!vmaster) return -ENOMEM; - add_slaves(ice->card, vmaster, slave_vols); + add_followers(ice->card, vmaster, follower_vols); err = snd_ctl_add(ice->card, vmaster); if (err < 0) return err; diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 1781a1c081c3d4f986facbc3063eedb2f680692a..3349e455a871ad2a5bc2e6e44f6518001edb709f 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -66,7 +66,7 @@ MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard."); module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard."); module_param(ac97_clock, int, 0444); -MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = whitelist + auto-detect, 1 = force autodetect)."); +MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = allowlist + auto-detect, 1 = force autodetect)."); module_param(ac97_quirk, charp, 0444); MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); module_param(buggy_semaphore, bool, 0444); @@ -810,7 +810,7 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: ichdev->suspended = 0; - /* fall through */ + fallthrough; case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: val = ICH_IOCE | ICH_STARTBM; @@ -818,7 +818,7 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd break; case SNDRV_PCM_TRIGGER_SUSPEND: ichdev->suspended = 1; - /* fall through */ + fallthrough; case SNDRV_PCM_TRIGGER_STOP: val = 0; break; @@ -852,7 +852,7 @@ static int snd_intel8x0_ali_trigger(struct snd_pcm_substream *substream, int cmd switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: ichdev->suspended = 0; - /* fall through */ + fallthrough; case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -869,7 +869,7 @@ static int snd_intel8x0_ali_trigger(struct snd_pcm_substream *substream, int cmd break; case SNDRV_PCM_TRIGGER_SUSPEND: ichdev->suspended = 1; - /* fall through */ + fallthrough; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* pause */ @@ -2792,7 +2792,7 @@ static int intel8x0_in_clock_list(struct intel8x0 *chip) wl = snd_pci_quirk_lookup(pci, intel8x0_clock_list); if (!wl) return 0; - dev_info(chip->card->dev, "white list rate for %04x:%04x is %i\n", + dev_info(chip->card->dev, "allow list rate for %04x:%04x is %i\n", pci->subsystem_vendor, pci->subsystem_device, wl->value); chip->ac97_bus->clock = wl->value; return 1; @@ -3138,7 +3138,7 @@ static const struct snd_pci_quirk spdif_aclink_defaults[] = { { } /* end */ }; -/* look up white/black list for SPDIF over ac-link */ +/* look up allow/deny list for SPDIF over ac-link */ static int check_default_spdif_aclink(struct pci_dev *pci) { const struct snd_pci_quirk *w; diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 65a887b217ee503833ee0eb502d72a56b2151f19..2eddd9de9e6daaacdfdaafe11b4b07dab127f4b7 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -2149,7 +2149,9 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci, { int err, rc; unsigned int i; - unsigned ioport_size, iomem_size, iomem2_size; + unsigned iomem_size; + __maybe_unused unsigned ioport_size; + __maybe_unused unsigned iomem2_size; struct snd_korg1212 * korg1212; const struct firmware *dsp_code; diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 7ba487443c7f7b62dfb202ff1c5a2d3c2c6d6db5..efff220b26ea7cf27f11cfe9b8e4b251e778c3de 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -169,7 +169,7 @@ static int mixart_set_clock(struct mixart_mgr *mgr, case PIPE_RUNNING: if(rate != 0) break; - /* fall through */ + fallthrough; default: if(rate == 0) return 0; /* nothing to do */ diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 048a2660d18d4df27aaa8e2bdaf0dfd79e9ebf1f..0bdd33b0af654b87999ef5b37038f8fcdf307802 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c @@ -527,7 +527,7 @@ irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id) dev_err(&mgr->pci->dev, "canceled notification %x !\n", msg); } - /* fall through */ + fallthrough; case MSG_TYPE_ANSWER: /* answer or notification to a message we are waiting for*/ mutex_lock(&mgr->msg_lock); diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index ebce4d259e06937adf9500f7990cc7122f7966f7..975994623c2ceb9d5480bb6665a7989c54a3fbbe 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -560,7 +560,7 @@ snd_nm256_playback_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: s->suspended = 0; - /* fallthru */ + fallthrough; case SNDRV_PCM_TRIGGER_START: if (! s->running) { snd_nm256_playback_start(chip, s, substream); @@ -569,7 +569,7 @@ snd_nm256_playback_trigger(struct snd_pcm_substream *substream, int cmd) break; case SNDRV_PCM_TRIGGER_SUSPEND: s->suspended = 1; - /* fallthru */ + fallthrough; case SNDRV_PCM_TRIGGER_STOP: if (s->running) { snd_nm256_playback_stop(chip); @@ -1632,11 +1632,11 @@ __error: } -enum { NM_BLACKLISTED, NM_RESET_WORKAROUND, NM_RESET_WORKAROUND_2 }; +enum { NM_IGNORED, NM_RESET_WORKAROUND, NM_RESET_WORKAROUND_2 }; static const struct snd_pci_quirk nm256_quirks[] = { /* HP omnibook 4150 has cs4232 codec internally */ - SND_PCI_QUIRK(0x103c, 0x0007, "HP omnibook 4150", NM_BLACKLISTED), + SND_PCI_QUIRK(0x103c, 0x0007, "HP omnibook 4150", NM_IGNORED), /* Reset workarounds to avoid lock-ups */ SND_PCI_QUIRK(0x104d, 0x8041, "Sony PCG-F305", NM_RESET_WORKAROUND), SND_PCI_QUIRK(0x1028, 0x0080, "Dell Latitude LS", NM_RESET_WORKAROUND), @@ -1658,13 +1658,13 @@ static int snd_nm256_probe(struct pci_dev *pci, dev_dbg(&pci->dev, "Enabled quirk for %s.\n", snd_pci_quirk_name(q)); switch (q->value) { - case NM_BLACKLISTED: + case NM_IGNORED: dev_info(&pci->dev, - "The device is blacklisted. Loading stopped\n"); + "The device is on the denylist. Loading stopped\n"); return -ENODEV; case NM_RESET_WORKAROUND_2: reset_workaround_2 = 1; - /* Fall-through */ + fallthrough; case NM_RESET_WORKAROUND: reset_workaround = 1; break; diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index 75b25ecf83a9ce7e8f8afdc264180b118c89ee08..b2a3fcfe31d4435258aeffc3e6da7d3ea34e8ef7 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c @@ -137,7 +137,7 @@ static int oxygen_open(struct snd_pcm_substream *substream, SNDRV_PCM_RATE_64000); runtime->hw.rate_min = 44100; } - /* fall through */ + fallthrough; case PCM_A: case PCM_B: runtime->hw.fifo_size = 0; diff --git a/sound/pci/oxygen/xonar_dg.c b/sound/pci/oxygen/xonar_dg.c index c3f8721624cd4ac63941e1d0259cdd831ff0c16f..b90421a1d909ac8fb7a4afce5d31d0c210284cfd 100644 --- a/sound/pci/oxygen/xonar_dg.c +++ b/sound/pci/oxygen/xonar_dg.c @@ -29,7 +29,7 @@ * GPIO 4 <- headphone detect * GPIO 5 -> enable ADC analog circuit for the left channel * GPIO 6 -> enable ADC analog circuit for the right channel - * GPIO 7 -> switch green rear output jack between CS4245 and and the first + * GPIO 7 -> switch green rear output jack between CS4245 and the first * channel of CS4361 (mechanical relay) * GPIO 8 -> enable output to speakers * diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index 0767276582cafa4acb0b8c0b2aeed8661c474109..8aa92f3e5ee88848d62bdf55ae1b064d41535b7a 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c @@ -116,7 +116,8 @@ static void wm8776_write(struct oxygen *chip, else wm8776_write_i2c(chip, reg, value); if (reg < ARRAY_SIZE(data->wm8776_regs)) { - if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER) + /* reg >= WM8776_HPLVOL is always true */ + if (reg <= WM8776_DACMASTER) value &= ~WM8776_UPDATE; data->wm8776_regs[reg] = value; } @@ -144,7 +145,8 @@ static void wm8766_write(struct oxygen *chip, OXYGEN_SPI_CEN_LATCH_CLOCK_LO, (reg << 9) | value); if (reg < ARRAY_SIZE(data->wm8766_regs)) { - if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) || + /* reg >= WM8766_LDA1 is always true */ + if (reg <= WM8766_RDA1 || (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA)) value &= ~WM8766_UPDATE; data->wm8766_regs[reg] = value; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index f7cda906208895c19fe592aa114b32f6f6067781..0fa49f4d15cff7a2a2f27f7f3db97e25eb1c1a36 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -3027,8 +3027,8 @@ static int hdspm_autosync_ref(struct hdspm *hdspm) unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF; - if ((syncref >= HDSPM_AES32_AUTOSYNC_FROM_WORD) && - (syncref <= HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN)) { + /* syncref >= HDSPM_AES32_AUTOSYNC_FROM_WORD is always true */ + if (syncref <= HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN) { return syncref; } return HDSPM_AES32_AUTOSYNC_FROM_NONE; diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 8b03e2dc503f0176a9873616ea460e7ae348429a..154d88ce88131c96863360cf7dcdb926a56984c2 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -544,7 +544,7 @@ static int snd_via82xx_codec_valid(struct via82xx *chip, int secondary) static void snd_via82xx_codec_wait(struct snd_ac97 *ac97) { struct via82xx *chip = ac97->private_data; - int err; + __always_unused int err; err = snd_via82xx_codec_ready(chip, ac97->num); /* here we need to wait fairly for long time.. */ if (!nodelay) @@ -2419,7 +2419,7 @@ static const struct via823x_info via823x_cards[] = { * auto detection of DXS channel supports. */ -static const struct snd_pci_quirk dxs_whitelist[] = { +static const struct snd_pci_quirk dxs_allowlist[] = { SND_PCI_QUIRK(0x1005, 0x4710, "Avance Logic Mobo", VIA_DXS_ENABLE), SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K), SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA), @@ -2467,9 +2467,9 @@ static int check_dxs_list(struct pci_dev *pci, int revision) { const struct snd_pci_quirk *w; - w = snd_pci_quirk_lookup(pci, dxs_whitelist); + w = snd_pci_quirk_lookup(pci, dxs_allowlist); if (w) { - dev_dbg(&pci->dev, "DXS white list for %s found\n", + dev_dbg(&pci->dev, "DXS allow list for %s found\n", snd_pci_quirk_name(w)); return w->value; } diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 607b7100db1cfee08f088a93c25cd4617789b553..addfa196df21da577dfcb28b74d014236b9b01b4 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -398,7 +398,7 @@ static int snd_via82xx_codec_valid(struct via82xx_modem *chip, int secondary) static void snd_via82xx_codec_wait(struct snd_ac97 *ac97) { struct via82xx_modem *chip = ac97->private_data; - int err; + __always_unused int err; err = snd_via82xx_codec_ready(chip, ac97->num); /* here we need to wait fairly for long time.. */ msleep(500); diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index db7d76a3cfeb75aa2879bb4e96d6f263e1305fa2..cacc6a9d14c8b685b073bdeff5cb8529a5305e73 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -400,7 +400,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, kctl = chip->pcm_mixer[substream->number].ctl; kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; } - /* fall through */ + fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 6c33ea91cc0513fbd3f37b98cc32c07584818a31..27d9da6d61e83b31a644e47065b9f15e7c38e54f 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -139,6 +139,7 @@ static int snd_pdacf_probe(struct pcmcia_device *link) /** * snd_pdacf_assign_resources - initialize the hardware and card instance. + * @pdacf: context * @port: i/o port for the card * @irq: irq number for the card * diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 6cbe5cb3435828c9489bac72b9981975ec568ed8..dfc4295b69c413a5164a932d98f9f38313aa8126 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -45,7 +45,7 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd) case SNDRV_PCM_TRIGGER_START: chip->pcm_hwptr = 0; chip->pcm_tdone = 0; - /* fall thru */ + fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: mask = 0; @@ -132,7 +132,7 @@ static int pdacf_pcm_prepare(struct snd_pcm_substream *subs) case SNDRV_PCM_FORMAT_S24_3LE: case SNDRV_PCM_FORMAT_S24_3BE: chip->pcm_sample = 3; - /* fall through */ + fallthrough; default: /* 24-bit */ aval = AK4117_DIF_24R; chip->pcm_frame = 3; diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index 73c0fd7277e6284173a218d45d77fda983dd901a..53d558b2806c89df438e5bc2c6416d12f7f052c4 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c @@ -1063,12 +1063,12 @@ snd_pmac_awacs_init(struct snd_pmac *chip) if (pm5500 || imac || lombard) { vmaster_sw = snd_ctl_make_virtual_master( "Master Playback Switch", (unsigned int *) NULL); - err = snd_ctl_add_slave_uncached(vmaster_sw, - chip->master_sw_ctl); + err = snd_ctl_add_follower_uncached(vmaster_sw, + chip->master_sw_ctl); if (err < 0) return err; - err = snd_ctl_add_slave_uncached(vmaster_sw, - chip->speaker_sw_ctl); + err = snd_ctl_add_follower_uncached(vmaster_sw, + chip->speaker_sw_ctl); if (err < 0) return err; err = snd_ctl_add(chip->card, vmaster_sw); @@ -1076,10 +1076,10 @@ snd_pmac_awacs_init(struct snd_pmac *chip) return err; vmaster_vol = snd_ctl_make_virtual_master( "Master Playback Volume", (unsigned int *) NULL); - err = snd_ctl_add_slave(vmaster_vol, master_vol); + err = snd_ctl_add_follower(vmaster_vol, master_vol); if (err < 0) return err; - err = snd_ctl_add_slave(vmaster_vol, speaker_vol); + err = snd_ctl_add_follower(vmaster_vol, speaker_vol); if (err < 0) return err; err = snd_ctl_add(chip->card, vmaster_vol); diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 7f1747518e794ef644b413bb2e927748da79bdf5..ddbac3a2169f293386e84ba16c0584a4c0779720 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o -snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o soc-link.o soc-card.o +snd-soc-core-objs += soc-pcm.o soc-devres.o soc-ops.o soc-link.o soc-card.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o ifneq ($(CONFIG_SND_SOC_TOPOLOGY),) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index e37cf72f2babfbf1da29c7fdbe0e1e793f590448..a6ce000fac3f229bd67041ec9f96e64bd6b47e7f 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -33,6 +33,7 @@ config SND_SOC_AMD_RV_RT5682_MACH select SND_SOC_MAX98357A select SND_SOC_CROS_EC_CODEC select I2C_CROS_EC_TUNNEL + select SND_SOC_RT1015 depends on SND_SOC_AMD_ACP3x && I2C && CROS_EC help This option enables machine driver for RT5682 and MAX9835. diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index 9414d7269c4f58f280f90d3217fc2b8480856d86..a7702e64ec512d4e2f926229c154e2cca018d65d 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -99,7 +99,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) static int da7219_clk_enable(struct snd_pcm_substream *substream) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* * Set wclk to 48000 because the rate constraint of this driver is @@ -146,7 +146,7 @@ static const struct snd_pcm_hw_constraint_list constraints_channels = { static int cz_da7219_play_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -167,7 +167,7 @@ static int cz_da7219_play_startup(struct snd_pcm_substream *substream) static int cz_da7219_cap_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -189,7 +189,7 @@ static int cz_da7219_cap_startup(struct snd_pcm_substream *substream) static int cz_max_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -210,7 +210,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream) static int cz_dmic0_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -231,7 +231,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream *substream) static int cz_dmic1_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -450,11 +450,13 @@ static int cz_probe(struct platform_device *pdev) return 0; } +#ifdef CONFIG_ACPI static const struct acpi_device_id cz_audio_acpi_match[] = { { "AMD7219", 0 }, {}, }; MODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match); +#endif static struct platform_driver cz_pcm_driver = { .driver = { diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index f54beb7f39a82e504ac91aafde6f39f288b75807..143155a840aca797b2a54b28829e026c85adae14 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -840,7 +840,7 @@ static int acp_dma_hw_params(struct snd_soc_component *component, u32 val = 0; struct snd_pcm_runtime *runtime; struct audio_substream_data *rtd; - struct snd_soc_pcm_runtime *prtd = substream->private_data; + struct snd_soc_pcm_runtime *prtd = asoc_substream_to_rtd(substream); struct audio_drv_data *adata = dev_get_drvdata(component->dev); struct snd_soc_card *card = prtd->card; struct acp_platform_info *pinfo = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/amd/acp-rt5645.c b/sound/soc/amd/acp-rt5645.c index 73b31f88a6b5660bf1d3a2767a2d47c2b6351f21..d6ba94677ac2629783f5246fe0723b684b1649a1 100644 --- a/sound/soc/amd/acp-rt5645.c +++ b/sound/soc/amd/acp-rt5645.c @@ -47,7 +47,7 @@ static int cz_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); ret = snd_soc_dai_set_pll(codec_dai, 0, RT5645_PLL1_S_MCLK, @@ -182,11 +182,13 @@ static int cz_probe(struct platform_device *pdev) return 0; } +#ifdef CONFIG_ACPI static const struct acpi_device_id cz_audio_acpi_match[] = { { "AMDI1002", 0 }, {}, }; MODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match); +#endif static struct platform_driver cz_pcm_driver = { .driver = { diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index e499c00e0c66a036acea52018756a11d1aaa6bee..55815fdaa1aafeffb3813869529e8f0a128bcf21 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -21,6 +21,7 @@ #include "raven/acp3x.h" #include "../codecs/rt5682.h" +#include "../codecs/rt1015.h" #define PCO_PLAT_CLK 48000000 #define RT5682_PLL_FREQ (48000 * 512) @@ -30,6 +31,13 @@ static struct snd_soc_jack pco_jack; static struct clk *rt5682_dai_wclk; static struct clk *rt5682_dai_bclk; static struct gpio_desc *dmic_sel; +void *soc_is_rltk_max(struct device *dev); + +enum { + RT5682 = 0, + MAX, + EC, +}; static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd) { @@ -105,7 +113,7 @@ static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd) static int rt5682_clk_enable(struct snd_pcm_substream *substream) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* RT5682 will support only 48K output with 48M mclk */ clk_set_rate(rt5682_dai_wclk, 48000); @@ -119,6 +127,34 @@ static int rt5682_clk_enable(struct snd_pcm_substream *substream) return ret; } +static int acp3x_1015_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai; + int srate, i, ret; + + ret = 0; + srate = params_rate(params); + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + if (strcmp(codec_dai->component->name, "rt1015-aif")) + continue; + ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (ret < 0) + return ret; + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, + 64 * srate, 256 * srate); + if (ret < 0) + return ret; + ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL, + 256 * srate, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + } + return ret; +} + static void rt5682_clk_disable(void) { clk_disable_unprepare(rt5682_dai_wclk); @@ -147,7 +183,7 @@ static const struct snd_pcm_hw_constraint_list constraints_channels = { static int acp3x_5682_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -165,7 +201,7 @@ static int acp3x_5682_startup(struct snd_pcm_substream *substream) static int acp3x_max_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); @@ -181,32 +217,34 @@ static int acp3x_max_startup(struct snd_pcm_substream *substream) static int acp3x_ec_dmic0_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); machine->cap_i2s_instance = I2S_BT_INSTANCE; snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (dmic_sel) - gpiod_set_value(dmic_sel, 0); return rt5682_clk_enable(substream); } -static int acp3x_ec_dmic1_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card); +static int dmic_switch; - machine->cap_i2s_instance = I2S_BT_INSTANCE; - snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (dmic_sel) - gpiod_set_value(dmic_sel, 1); +static int dmic_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = dmic_switch; + return 0; +} - return rt5682_clk_enable(substream); +static int dmic_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + if (dmic_sel) { + dmic_switch = ucontrol->value.integer.value[0]; + gpiod_set_value(dmic_sel, dmic_switch); + } + return 0; } static void rt5682_shutdown(struct snd_pcm_substream *substream) @@ -222,6 +260,7 @@ static const struct snd_soc_ops acp3x_5682_ops = { static const struct snd_soc_ops acp3x_max_play_ops = { .startup = acp3x_max_startup, .shutdown = rt5682_shutdown, + .hw_params = acp3x_1015_hw_params, }; static const struct snd_soc_ops acp3x_ec_cap0_ops = { @@ -229,11 +268,6 @@ static const struct snd_soc_ops acp3x_ec_cap0_ops = { .shutdown = rt5682_shutdown, }; -static const struct snd_soc_ops acp3x_ec_cap1_ops = { - .startup = acp3x_ec_dmic1_startup, - .shutdown = rt5682_shutdown, -}; - SND_SOC_DAILINK_DEF(acp3x_i2s, DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0"))); SND_SOC_DAILINK_DEF(acp3x_bt, @@ -243,14 +277,28 @@ SND_SOC_DAILINK_DEF(rt5682, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1"))); SND_SOC_DAILINK_DEF(max, DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi"))); +SND_SOC_DAILINK_DEF(rt1015, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1015:00", "rt1015-aif"), + COMP_CODEC("i2c-10EC1015:01", "rt1015-aif"))); SND_SOC_DAILINK_DEF(cros_ec, DAILINK_COMP_ARRAY(COMP_CODEC("GOOG0013:00", "EC Codec I2S RX"))); SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("acp3x_rv_i2s_dma.0"))); -static struct snd_soc_dai_link acp3x_dai_5682_98357[] = { +static struct snd_soc_codec_conf rt1015_conf[] = { + { + .dlc = COMP_CODEC_CONF("i2c-10EC1015:00"), + .name_prefix = "Left", + }, { + .dlc = COMP_CODEC_CONF("i2c-10EC1015:01"), + .name_prefix = "Right", + }, +}; + +static struct snd_soc_dai_link acp3x_dai[] = { + [RT5682] = { .name = "acp3x-5682-play", .stream_name = "Playback", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF @@ -261,16 +309,19 @@ static struct snd_soc_dai_link acp3x_dai_5682_98357[] = { .ops = &acp3x_5682_ops, SND_SOC_DAILINK_REG(acp3x_i2s, rt5682, platform), }, - { + [MAX] = { .name = "acp3x-max98357-play", .stream_name = "HiFi Playback", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBS_CFS, .dpcm_playback = 1, .ops = &acp3x_max_play_ops, - SND_SOC_DAILINK_REG(acp3x_bt, max, platform), + .cpus = acp3x_bt, + .num_cpus = ARRAY_SIZE(acp3x_bt), + .platforms = platform, + .num_platforms = ARRAY_SIZE(platform), }, - { + [EC] = { .name = "acp3x-ec-dmic0-capture", .stream_name = "Capture DMIC0", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF @@ -279,61 +330,136 @@ static struct snd_soc_dai_link acp3x_dai_5682_98357[] = { .ops = &acp3x_ec_cap0_ops, SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform), }, - { - .name = "acp3x-ec-dmic1-capture", - .stream_name = "Capture DMIC1", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBS_CFS, - .dpcm_capture = 1, - .ops = &acp3x_ec_cap1_ops, - SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform), - }, }; -static const struct snd_soc_dapm_widget acp3x_widgets[] = { +static const char * const dmic_mux_text[] = { + "Front Mic", + "Rear Mic", +}; + +static SOC_ENUM_SINGLE_DECL( + acp3x_dmic_enum, SND_SOC_NOPM, 0, dmic_mux_text); + +static const struct snd_kcontrol_new acp3x_dmic_mux_control = + SOC_DAPM_ENUM_EXT("DMIC Select Mux", acp3x_dmic_enum, + dmic_get, dmic_set); + +static const struct snd_soc_dapm_widget acp3x_5682_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_SPK("Spk", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, + &acp3x_dmic_mux_control), }; -static const struct snd_soc_dapm_route acp3x_audio_route[] = { +static const struct snd_soc_dapm_route acp3x_5682_audio_route[] = { {"Headphone Jack", NULL, "HPOL"}, {"Headphone Jack", NULL, "HPOR"}, {"IN1P", NULL, "Headset Mic"}, {"Spk", NULL, "Speaker"}, + {"Dmic Mux", "Front Mic", "DMIC"}, + {"Dmic Mux", "Rear Mic", "DMIC"}, }; -static const struct snd_kcontrol_new acp3x_mc_controls[] = { +static const struct snd_kcontrol_new acp3x_5682_mc_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Spk"), SOC_DAPM_PIN_SWITCH("Headset Mic"), }; -static struct snd_soc_card acp3x_card = { +static struct snd_soc_card acp3x_5682 = { .name = "acp3xalc5682m98357", .owner = THIS_MODULE, - .dai_link = acp3x_dai_5682_98357, - .num_links = ARRAY_SIZE(acp3x_dai_5682_98357), - .dapm_widgets = acp3x_widgets, - .num_dapm_widgets = ARRAY_SIZE(acp3x_widgets), - .dapm_routes = acp3x_audio_route, - .num_dapm_routes = ARRAY_SIZE(acp3x_audio_route), - .controls = acp3x_mc_controls, - .num_controls = ARRAY_SIZE(acp3x_mc_controls), + .dai_link = acp3x_dai, + .num_links = ARRAY_SIZE(acp3x_dai), + .dapm_widgets = acp3x_5682_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp3x_5682_widgets), + .dapm_routes = acp3x_5682_audio_route, + .num_dapm_routes = ARRAY_SIZE(acp3x_5682_audio_route), + .controls = acp3x_5682_mc_controls, + .num_controls = ARRAY_SIZE(acp3x_5682_mc_controls), +}; + +static const struct snd_soc_dapm_widget acp3x_1015_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, + &acp3x_dmic_mux_control), + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_soc_dapm_route acp3x_1015_route[] = { + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, + {"IN1P", NULL, "Headset Mic"}, + {"Dmic Mux", "Front Mic", "DMIC"}, + {"Dmic Mux", "Rear Mic", "DMIC"}, + {"Left Spk", NULL, "Left SPO"}, + {"Right Spk", NULL, "Right SPO"}, +}; + +static const struct snd_kcontrol_new acp3x_mc_1015_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 struct snd_soc_card acp3x_1015 = { + .name = "acp3xalc56821015", + .owner = THIS_MODULE, + .dai_link = acp3x_dai, + .num_links = ARRAY_SIZE(acp3x_dai), + .dapm_widgets = acp3x_1015_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp3x_1015_widgets), + .dapm_routes = acp3x_1015_route, + .num_dapm_routes = ARRAY_SIZE(acp3x_1015_route), + .codec_conf = rt1015_conf, + .num_configs = ARRAY_SIZE(rt1015_conf), + .controls = acp3x_mc_1015_controls, + .num_controls = ARRAY_SIZE(acp3x_mc_1015_controls), }; +void *soc_is_rltk_max(struct device *dev) +{ + const struct acpi_device_id *match; + + match = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!match) + return NULL; + return (void *)match->driver_data; +} + +static void card_spk_dai_link_present(struct snd_soc_dai_link *links, + const char *card_name) +{ + if (!strcmp(card_name, "acp3xalc56821015")) { + links[1].codecs = rt1015; + links[1].num_codecs = ARRAY_SIZE(rt1015); + } else { + links[1].codecs = max; + links[1].num_codecs = ARRAY_SIZE(max); + } +} + static int acp3x_probe(struct platform_device *pdev) { int ret; struct snd_soc_card *card; struct acp3x_platform_info *machine; + struct device *dev = &pdev->dev; + + card = (struct snd_soc_card *)soc_is_rltk_max(dev); + if (!card) + return -ENODEV; machine = devm_kzalloc(&pdev->dev, sizeof(*machine), GFP_KERNEL); if (!machine) return -ENOMEM; - card = &acp3x_card; - acp3x_card.dev = &pdev->dev; + card_spk_dai_link_present(card->dai_link, card->name); + card->dev = &pdev->dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, machine); @@ -344,18 +470,19 @@ static int acp3x_probe(struct platform_device *pdev) return PTR_ERR(dmic_sel); } - ret = devm_snd_soc_register_card(&pdev->dev, &acp3x_card); + ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { dev_err(&pdev->dev, "devm_snd_soc_register_card(%s) failed: %d\n", - acp3x_card.name, ret); + card->name, ret); return ret; } return 0; } static const struct acpi_device_id acp3x_audio_acpi_match[] = { - { "AMDI5682", 0 }, + { "AMDI5682", (unsigned long)&acp3x_5682}, + { "AMDI1015", (unsigned long)&acp3x_1015}, {}, }; MODULE_DEVICE_TABLE(acpi, acp3x_audio_acpi_match); @@ -372,5 +499,6 @@ static struct platform_driver acp3x_audio = { module_platform_driver(acp3x_audio); MODULE_AUTHOR("akshu.agrawal@amd.com"); -MODULE_DESCRIPTION("ALC5682 & MAX98357 audio support"); +MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com"); +MODULE_DESCRIPTION("ALC5682 ALC1015 & MAX98357 audio support"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c index a532e01a2622e02620bf642da8e8a105f424b089..5bc028692fcf84067a2e29678bf52d60b3fe2ce2 100644 --- a/sound/soc/amd/raven/acp3x-i2s.c +++ b/sound/soc/amd/raven/acp3x-i2s.c @@ -80,7 +80,7 @@ static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream, u32 val; u32 reg_val, frmt_reg; - prtd = substream->private_data; + prtd = asoc_substream_to_rtd(substream); rtd = substream->runtime->private_data; card = prtd->card; adata = snd_soc_dai_get_drvdata(dai); @@ -149,22 +149,10 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct i2s_stream_instance *rtd; - struct snd_soc_pcm_runtime *prtd; - struct snd_soc_card *card; - struct acp3x_platform_info *pinfo; u32 ret, val, period_bytes, reg_val, ier_val, water_val; u32 buf_size, buf_reg; - prtd = substream->private_data; rtd = substream->runtime->private_data; - card = prtd->card; - pinfo = snd_soc_card_get_drvdata(card); - if (pinfo) { - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - rtd->i2s_instance = pinfo->play_i2s_instance; - else - rtd->i2s_instance = pinfo->cap_i2s_instance; - } period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size); buf_size = frames_to_bytes(substream->runtime, diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index e6386de20ac7fc24bad79422e83788676bc17afc..417cda24030cd22469f6bd4abef73529920c6009 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -217,7 +217,7 @@ static int acp3x_dma_open(struct snd_soc_component *component, int ret; runtime = substream->runtime; - prtd = substream->private_data; + prtd = asoc_substream_to_rtd(substream); component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); adata = dev_get_drvdata(component->dev); i2s_data = kzalloc(sizeof(*i2s_data), GFP_KERNEL); @@ -238,7 +238,7 @@ static int acp3x_dma_open(struct snd_soc_component *component, } if (!adata->play_stream && !adata->capture_stream && - adata->i2ssp_play_stream && !adata->i2ssp_capture_stream) + !adata->i2ssp_play_stream && !adata->i2ssp_capture_stream) rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); i2s_data->acp3x_base = adata->acp3x_base; @@ -258,7 +258,7 @@ static int acp3x_dma_hw_params(struct snd_soc_component *component, struct i2s_dev_data *adata; u64 size; - prtd = substream->private_data; + prtd = asoc_substream_to_rtd(substream); card = prtd->card; pinfo = snd_soc_card_get_drvdata(card); adata = dev_get_drvdata(component->dev); @@ -301,15 +301,11 @@ static int acp3x_dma_hw_params(struct snd_soc_component *component, static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *prtd; - struct snd_soc_card *card; struct i2s_stream_instance *rtd; u32 pos; u32 buffersize; u64 bytescount; - prtd = substream->private_data; - card = prtd->card; rtd = substream->runtime->private_data; buffersize = frames_to_bytes(substream->runtime, @@ -344,7 +340,7 @@ static int acp3x_dma_close(struct snd_soc_component *component, struct i2s_dev_data *adata; struct i2s_stream_instance *ins; - prtd = substream->private_data; + prtd = asoc_substream_to_rtd(substream); component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); adata = dev_get_drvdata(component->dev); ins = substream->runtime->private_data; diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c index ebf4388b626215ffb0bc76ea22fb63624dbcea98..31b797c8bfe6444ab6d05ccde297e0642762580c 100644 --- a/sound/soc/amd/raven/pci-acp3x.c +++ b/sound/soc/amd/raven/pci-acp3x.c @@ -19,10 +19,12 @@ struct acp3x_dev_data { bool acp3x_audio_mode; struct resource *res; struct platform_device *pdev[ACP3x_DEVS]; + u32 pme_en; }; -static int acp3x_power_on(void __iomem *acp3x_base) +static int acp3x_power_on(struct acp3x_dev_data *adata) { + void __iomem *acp3x_base = adata->acp3x_base; u32 val; int timeout; @@ -39,10 +41,10 @@ static int acp3x_power_on(void __iomem *acp3x_base) while (++timeout < 500) { val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS); if (!val) { - /* Set PME_EN as after ACP power On, - * PME_EN gets cleared + /* ACP power On clears PME_EN. + * Restore the value to its prior state */ - rv_writel(0x1, acp3x_base + mmACP_PME_EN); + rv_writel(adata->pme_en, acp3x_base + mmACP_PME_EN); return 0; } udelay(1); @@ -74,12 +76,13 @@ static int acp3x_reset(void __iomem *acp3x_base) return -ETIMEDOUT; } -static int acp3x_init(void __iomem *acp3x_base) +static int acp3x_init(struct acp3x_dev_data *adata) { + void __iomem *acp3x_base = adata->acp3x_base; int ret; /* power on */ - ret = acp3x_power_on(acp3x_base); + ret = acp3x_power_on(adata); if (ret) { pr_err("ACP3x power on failed\n"); return ret; @@ -151,7 +154,9 @@ static int snd_acp3x_probe(struct pci_dev *pci, } pci_set_master(pci); pci_set_drvdata(pci, adata); - ret = acp3x_init(adata->acp3x_base); + /* Save ACP_PME_EN state */ + adata->pme_en = rv_readl(adata->acp3x_base + mmACP_PME_EN); + ret = acp3x_init(adata); if (ret) goto disable_msi; @@ -274,7 +279,7 @@ static int snd_acp3x_resume(struct device *dev) struct acp3x_dev_data *adata; adata = dev_get_drvdata(dev); - ret = acp3x_init(adata->acp3x_base); + ret = acp3x_init(adata); if (ret) { dev_err(dev, "ACP init failed\n"); return ret; diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c index 859ed67b93cfff1199fcd60a54d98cb5574da08e..b943e59fc302437580b14f45febe569819892d44 100644 --- a/sound/soc/amd/renoir/rn-pci-acp3x.c +++ b/sound/soc/amd/renoir/rn-pci-acp3x.c @@ -5,6 +5,7 @@ //Copyright 2020 Advanced Micro Devices, Inc. #include +#include #include #include #include @@ -18,6 +19,16 @@ static int acp_power_gating; module_param(acp_power_gating, int, 0644); MODULE_PARM_DESC(acp_power_gating, "Enable acp power gating"); +/** + * dmic_acpi_check = -1 - Checks ACPI method to know DMIC hardware status runtime + * = 0 - Skips the DMIC device creation and returns probe failure + * = 1 - Assumes that platform has DMIC support and skips ACPI + * method check + */ +static int dmic_acpi_check = ACP_DMIC_AUTO; +module_param(dmic_acpi_check, bint, 0644); +MODULE_PARM_DESC(dmic_acpi_check, "checks Dmic hardware runtime"); + struct acp_dev_data { void __iomem *acp_base; struct resource *res; @@ -157,6 +168,10 @@ static int snd_rn_acp_probe(struct pci_dev *pci, { struct acp_dev_data *adata; struct platform_device_info pdevinfo[ACP_DEVS]; +#if defined(CONFIG_ACPI) + acpi_handle handle; + acpi_integer dmic_status; +#endif unsigned int irqflags; int ret, index; u32 addr; @@ -201,6 +216,24 @@ static int snd_rn_acp_probe(struct pci_dev *pci, if (ret) goto disable_msi; + if (!dmic_acpi_check) { + ret = -ENODEV; + goto de_init; + } else if (dmic_acpi_check == ACP_DMIC_AUTO) { +#if defined(CONFIG_ACPI) + handle = ACPI_HANDLE(&pci->dev); + ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status); + if (ACPI_FAILURE(ret)) { + ret = -EINVAL; + goto de_init; + } + if (!dmic_status) { + ret = -ENODEV; + goto de_init; + } +#endif + } + adata->res = devm_kzalloc(&pci->dev, sizeof(struct resource) * 2, GFP_KERNEL); diff --git a/sound/soc/amd/renoir/rn_acp3x.h b/sound/soc/amd/renoir/rn_acp3x.h index 75228e306e0b4693f87dbd3f6a1b24114d636861..14620399d766c43f4a5c3d54dfe2e45abbf67653 100644 --- a/sound/soc/amd/renoir/rn_acp3x.h +++ b/sound/soc/amd/renoir/rn_acp3x.h @@ -55,6 +55,8 @@ #define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS) #define MIN_BUFFER MAX_BUFFER +#define ACP_DMIC_AUTO -1 + struct pdm_dev_data { u32 pdm_irq; void __iomem *acp_base; diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index e98601eccfa337fdd3da7873a0120fbb66fa3415..b1a28a9382fbccda65d3a72c834b5be8b14ebecd 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -118,48 +118,30 @@ static const struct snd_pcm_hardware atmel_classd_hw = { static int atmel_classd_cpu_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); + int err; regmap_write(dd->regmap, CLASSD_THR, 0x0); - return clk_prepare_enable(dd->pclk); -} - -static void atmel_classd_cpu_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); - - clk_disable_unprepare(dd->pclk); + err = clk_prepare_enable(dd->pclk); + if (err) + return err; + err = clk_prepare_enable(dd->gclk); + if (err) { + clk_disable_unprepare(dd->pclk); + return err; + } + return 0; } -static const struct snd_soc_dai_ops atmel_classd_cpu_dai_ops = { - .startup = atmel_classd_cpu_dai_startup, - .shutdown = atmel_classd_cpu_dai_shutdown, -}; - -static struct snd_soc_dai_driver atmel_classd_cpu_dai = { - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = ATMEL_CLASSD_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &atmel_classd_cpu_dai_ops, -}; - -static const struct snd_soc_component_driver atmel_classd_cpu_dai_component = { - .name = "atmel-classd", -}; - /* platform */ static int atmel_classd_platform_configure_dma(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); if (params_physical_width(params) != 16) { @@ -306,31 +288,10 @@ static int atmel_classd_component_resume(struct snd_soc_component *component) return regcache_sync(dd->regmap); } -static struct snd_soc_component_driver soc_component_dev_classd = { - .probe = atmel_classd_component_probe, - .resume = atmel_classd_component_resume, - .controls = atmel_classd_snd_controls, - .num_controls = ARRAY_SIZE(atmel_classd_snd_controls), - .idle_bias_on = 1, - .use_pmdown_time = 1, - .endianness = 1, - .non_legacy_dai_naming = 1, -}; - -/* codec dai component */ -static int atmel_classd_codec_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *codec_dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); - - return clk_prepare_enable(dd->gclk); -} - -static int atmel_classd_codec_dai_digital_mute(struct snd_soc_dai *codec_dai, - int mute) +static int atmel_classd_cpu_dai_mute_stream(struct snd_soc_dai *cpu_dai, + int mute, int direction) { - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; u32 mask, val; mask = CLASSD_MR_LMUTE_MASK | CLASSD_MR_RMUTE_MASK; @@ -373,13 +334,13 @@ static struct { }; static int -atmel_classd_codec_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *codec_dai) +atmel_classd_cpu_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; int fs; int i, best, best_val, cur_val, ret; u32 mask, val; @@ -417,19 +378,19 @@ atmel_classd_codec_dai_hw_params(struct snd_pcm_substream *substream, } static void -atmel_classd_codec_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *codec_dai) +atmel_classd_cpu_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); clk_disable_unprepare(dd->gclk); } -static int atmel_classd_codec_dai_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *codec_dai) +static int atmel_classd_cpu_dai_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) { - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; snd_soc_component_update_bits(component, CLASSD_MR, CLASSD_MR_LEN_MASK | CLASSD_MR_REN_MASK, @@ -439,10 +400,10 @@ static int atmel_classd_codec_dai_prepare(struct snd_pcm_substream *substream, return 0; } -static int atmel_classd_codec_dai_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *codec_dai) +static int atmel_classd_cpu_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *cpu_dai) { - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; u32 mask, val; mask = CLASSD_MR_LEN_MASK | CLASSD_MR_REN_MASK; @@ -468,19 +429,17 @@ static int atmel_classd_codec_dai_trigger(struct snd_pcm_substream *substream, return 0; } -static const struct snd_soc_dai_ops atmel_classd_codec_dai_ops = { - .digital_mute = atmel_classd_codec_dai_digital_mute, - .startup = atmel_classd_codec_dai_startup, - .shutdown = atmel_classd_codec_dai_shutdown, - .hw_params = atmel_classd_codec_dai_hw_params, - .prepare = atmel_classd_codec_dai_prepare, - .trigger = atmel_classd_codec_dai_trigger, +static const struct snd_soc_dai_ops atmel_classd_cpu_dai_ops = { + .startup = atmel_classd_cpu_dai_startup, + .shutdown = atmel_classd_cpu_dai_shutdown, + .mute_stream = atmel_classd_cpu_dai_mute_stream, + .hw_params = atmel_classd_cpu_dai_hw_params, + .prepare = atmel_classd_cpu_dai_prepare, + .trigger = atmel_classd_cpu_dai_trigger, + .no_capture_mute = 1, }; -#define ATMEL_CLASSD_CODEC_DAI_NAME "atmel-classd-hifi" - -static struct snd_soc_dai_driver atmel_classd_codec_dai = { - .name = ATMEL_CLASSD_CODEC_DAI_NAME, +static struct snd_soc_dai_driver atmel_classd_cpu_dai = { .playback = { .stream_name = "Playback", .channels_min = 1, @@ -488,7 +447,18 @@ static struct snd_soc_dai_driver atmel_classd_codec_dai = { .rates = ATMEL_CLASSD_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .ops = &atmel_classd_codec_dai_ops, + .ops = &atmel_classd_cpu_dai_ops, +}; + +static const struct snd_soc_component_driver atmel_classd_cpu_dai_component = { + .name = "atmel-classd", + .probe = atmel_classd_component_probe, + .resume = atmel_classd_component_resume, + .controls = atmel_classd_snd_controls, + .num_controls = ARRAY_SIZE(atmel_classd_snd_controls), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, }; /* ASoC sound card */ @@ -517,9 +487,9 @@ static int atmel_classd_asoc_card_init(struct device *dev, dai_link->name = "CLASSD"; dai_link->stream_name = "CLASSD PCM"; - dai_link->codecs->dai_name = ATMEL_CLASSD_CODEC_DAI_NAME; + dai_link->codecs->dai_name = "snd-soc-dummy-dai"; dai_link->cpus->dai_name = dev_name(dev); - dai_link->codecs->name = dev_name(dev); + dai_link->codecs->name = "snd-soc-dummy"; dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; @@ -620,13 +590,6 @@ static int atmel_classd_probe(struct platform_device *pdev) return ret; } - ret = devm_snd_soc_register_component(dev, &soc_component_dev_classd, - &atmel_classd_codec_dai, 1); - if (ret) { - dev_err(dev, "could not register component: %d\n", ret); - return ret; - } - /* register sound card */ card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) { diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c index cb03c4f7324c9c49b85a5952c0722f5dd535e6e3..e597e35459ce47d32df962175c2d8f10952f4990 100644 --- a/sound/soc/atmel/atmel-pcm-dma.c +++ b/sound/soc/atmel/atmel-pcm-dma.c @@ -44,7 +44,7 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = { .buffer_bytes_max = 512 * 1024, }; -/** +/* * atmel_pcm_dma_irq: SSC interrupt handler for DMAENGINE enabled SSC * * We use DMAENGINE to send/receive data to/from SSC so this ISR is only to @@ -53,7 +53,7 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = { static void atmel_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pcm_dma_params *prtd; prtd = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); @@ -78,7 +78,7 @@ static void atmel_pcm_dma_irq(u32 ssc_sr, static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pcm_dma_params *prtd; struct ssc_device *ssc; int ret; diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c index a8daebcbf6c818183071c619f542268fab010030..704f700013d3e3e20f83b52c8d5449d4d6c741df 100644 --- a/sound/soc/atmel/atmel-pcm-pdc.c +++ b/sound/soc/atmel/atmel-pcm-pdc.c @@ -205,7 +205,7 @@ static int atmel_pcm_hw_params(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = substream->runtime; struct atmel_runtime_data *prtd = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* this may get called several times by oss emulation * with different params */ diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index 04ec6f0af17987851a456d0b82a13aa434767e67..8e1d8230b180f2b8c4dd6378db4b7a3bf401f44d 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -104,7 +104,7 @@ static struct atmel_pdmic_pdata *atmel_pdmic_dt_init(struct device *dev) static int atmel_pdmic_cpu_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card); int ret; @@ -132,7 +132,7 @@ static int atmel_pdmic_cpu_dai_startup(struct snd_pcm_substream *substream, static void atmel_pdmic_cpu_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card); /* Disable the overrun error interrupt */ @@ -145,34 +145,28 @@ static void atmel_pdmic_cpu_dai_shutdown(struct snd_pcm_substream *substream, static int atmel_pdmic_cpu_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_component *component = cpu_dai->component; u32 val; + int ret; /* Clean the PDMIC Converted Data Register */ - return regmap_read(dd->regmap, PDMIC_CDR, &val); -} - -static const struct snd_soc_dai_ops atmel_pdmic_cpu_dai_ops = { - .startup = atmel_pdmic_cpu_dai_startup, - .shutdown = atmel_pdmic_cpu_dai_shutdown, - .prepare = atmel_pdmic_cpu_dai_prepare, -}; + ret = regmap_read(dd->regmap, PDMIC_CDR, &val); + if (ret < 0) + return 0; -#define ATMEL_PDMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) + ret = snd_soc_component_update_bits(component, PDMIC_CR, + PDMIC_CR_ENPDM_MASK, + PDMIC_CR_ENPDM_DIS << + PDMIC_CR_ENPDM_SHIFT); + if (ret < 0) + return ret; -static struct snd_soc_dai_driver atmel_pdmic_cpu_dai = { - .capture = { - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_KNOT, - .formats = ATMEL_PDMIC_FORMATS,}, - .ops = &atmel_pdmic_cpu_dai_ops, -}; + return 0; +} -static const struct snd_soc_component_driver atmel_pdmic_cpu_dai_component = { - .name = "atmel-pdmic", -}; +#define ATMEL_PDMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) /* platform */ #define ATMEL_PDMIC_MAX_BUF_SIZE (64 * 1024) @@ -197,7 +191,7 @@ atmel_pdmic_platform_configure_dma(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card); int ret; @@ -290,10 +284,10 @@ static int pdmic_get_mic_volsw(struct snd_kcontrol *kcontrol, unsigned int dgain_val, scale_val; int i; - dgain_val = (snd_soc_component_read32(component, PDMIC_DSPR1) & PDMIC_DSPR1_DGAIN_MASK) + dgain_val = (snd_soc_component_read(component, PDMIC_DSPR1) & PDMIC_DSPR1_DGAIN_MASK) >> PDMIC_DSPR1_DGAIN_SHIFT; - scale_val = (snd_soc_component_read32(component, PDMIC_DSPR0) & PDMIC_DSPR0_SCALE_MASK) + scale_val = (snd_soc_component_read(component, PDMIC_DSPR0) & PDMIC_DSPR0_SCALE_MASK) >> PDMIC_DSPR0_SCALE_SHIFT; for (i = 0; i < ARRAY_SIZE(mic_gain_table); i++) { @@ -355,27 +349,16 @@ static int atmel_pdmic_component_probe(struct snd_soc_component *component) return 0; } -static struct snd_soc_component_driver soc_component_dev_pdmic = { - .probe = atmel_pdmic_component_probe, - .controls = atmel_pdmic_snd_controls, - .num_controls = ARRAY_SIZE(atmel_pdmic_snd_controls), - .idle_bias_on = 1, - .use_pmdown_time = 1, - .endianness = 1, - .non_legacy_dai_naming = 1, -}; - -/* codec dai component */ #define PDMIC_MR_PRESCAL_MAX_VAL 127 static int -atmel_pdmic_codec_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *codec_dai) +atmel_pdmic_cpu_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; unsigned int rate_min = substream->runtime->hw.rate_min; unsigned int rate_max = substream->runtime->hw.rate_max; int fs = params_rate(params); @@ -445,21 +428,10 @@ atmel_pdmic_codec_dai_hw_params(struct snd_pcm_substream *substream, return 0; } -static int atmel_pdmic_codec_dai_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *codec_dai) -{ - struct snd_soc_component *component = codec_dai->component; - - snd_soc_component_update_bits(component, PDMIC_CR, PDMIC_CR_ENPDM_MASK, - PDMIC_CR_ENPDM_DIS << PDMIC_CR_ENPDM_SHIFT); - - return 0; -} - -static int atmel_pdmic_codec_dai_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *codec_dai) +static int atmel_pdmic_cpu_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *cpu_dai) { - struct snd_soc_component *component = codec_dai->component; + struct snd_soc_component *component = cpu_dai->component; u32 val; switch (cmd) { @@ -482,16 +454,16 @@ static int atmel_pdmic_codec_dai_trigger(struct snd_pcm_substream *substream, return 0; } -static const struct snd_soc_dai_ops atmel_pdmic_codec_dai_ops = { - .hw_params = atmel_pdmic_codec_dai_hw_params, - .prepare = atmel_pdmic_codec_dai_prepare, - .trigger = atmel_pdmic_codec_dai_trigger, +static const struct snd_soc_dai_ops atmel_pdmic_cpu_dai_ops = { + .startup = atmel_pdmic_cpu_dai_startup, + .shutdown = atmel_pdmic_cpu_dai_shutdown, + .prepare = atmel_pdmic_cpu_dai_prepare, + .hw_params = atmel_pdmic_cpu_dai_hw_params, + .trigger = atmel_pdmic_cpu_dai_trigger, }; -#define ATMEL_PDMIC_CODEC_DAI_NAME "atmel-pdmic-hifi" -static struct snd_soc_dai_driver atmel_pdmic_codec_dai = { - .name = ATMEL_PDMIC_CODEC_DAI_NAME, +static struct snd_soc_dai_driver atmel_pdmic_cpu_dai = { .capture = { .stream_name = "Capture", .channels_min = 1, @@ -499,7 +471,17 @@ static struct snd_soc_dai_driver atmel_pdmic_codec_dai = { .rates = SNDRV_PCM_RATE_KNOT, .formats = ATMEL_PDMIC_FORMATS, }, - .ops = &atmel_pdmic_codec_dai_ops, + .ops = &atmel_pdmic_cpu_dai_ops, +}; + +static const struct snd_soc_component_driver atmel_pdmic_cpu_dai_component = { + .name = "atmel-pdmic", + .probe = atmel_pdmic_component_probe, + .controls = atmel_pdmic_snd_controls, + .num_controls = ARRAY_SIZE(atmel_pdmic_snd_controls), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, }; /* ASoC sound card */ @@ -528,9 +510,9 @@ static int atmel_pdmic_asoc_card_init(struct device *dev, dai_link->name = "PDMIC"; dai_link->stream_name = "PDMIC PCM"; - dai_link->codecs->dai_name = ATMEL_PDMIC_CODEC_DAI_NAME; + dai_link->codecs->dai_name = "snd-soc-dummy-dai"; dai_link->cpus->dai_name = dev_name(dev); - dai_link->codecs->name = dev_name(dev); + dai_link->codecs->name = "snd-soc-dummy"; dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; @@ -684,16 +666,6 @@ static int atmel_pdmic_probe(struct platform_device *pdev) return ret; } - /* register codec and codec dai */ - atmel_pdmic_codec_dai.capture.rate_min = rate_min; - atmel_pdmic_codec_dai.capture.rate_max = rate_max; - ret = devm_snd_soc_register_component(dev, &soc_component_dev_pdmic, - &atmel_pdmic_codec_dai, 1); - if (ret) { - dev_err(dev, "could not register component: %d\n", ret); - return ret; - } - /* register sound card */ card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) { diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 0f18dfb85bfeda0d7687606c7d84c81eaa0fc80b..6a63e8797a0b6b5ecd58076dd1cd751dd81a1afd 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -887,6 +887,7 @@ static int asoc_ssc_init(struct device *dev) /** * atmel_ssc_set_audio - Allocate the specified SSC for audio use. + * @ssc_id: SSD ID in [0, NUM_SSC_DEVICES[ */ int atmel_ssc_set_audio(int ssc_id) { diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c index 148c943cb5384373a479097276e897d2e5d64aaf..9e237580afa9fca3088d0ca742054cedcb436f12 100644 --- a/sound/soc/atmel/atmel_wm8904.c +++ b/sound/soc/atmel/atmel_wm8904.c @@ -26,7 +26,7 @@ static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = { static int atmel_asoc_wm8904_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index d649037bda9b8e3da6c7046a576f1af3b72c9bfa..5f8baad37a4016db012b796cc261c83bbf3722e9 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c @@ -94,7 +94,7 @@ static struct snd_soc_card db1550_ac97_machine = { static int db1200_i2s_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); /* WM8731 has its own 12MHz crystal */ diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index e82bbf2d1eea78701f09f7aeb0086139f06f0c06..3d67e27fada9e795c1699b16741db2f111f0ab82 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -278,7 +278,7 @@ static int au1xpsc_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream, component); - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int stype = substream->stream, *dmaids; dmaids = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c index 4e246c7e78f247c6af56374351752db3ce104e70..7f5be90c9ed10d078589eccaa352f9cfc6e4cdb3 100644 --- a/sound/soc/au1x/dma.c +++ b/sound/soc/au1x/dma.c @@ -191,7 +191,7 @@ static int alchemy_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream, component); - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int *dmaids, s = substream->stream; char *name; diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index d80b570e950ea7059bff5b37a7c5980d958dd453..dc34fe1559c6b916f008c4e66683a45534db9ecd 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -841,9 +841,12 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) dev->clk_prepared = false; dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) { - dev_err(&pdev->dev, "could not get clk: %ld\n", - PTR_ERR(dev->clk)); - return PTR_ERR(dev->clk); + ret = PTR_ERR(dev->clk); + if (ret == -EPROBE_DEFER) + dev_dbg(&pdev->dev, "could not get clk: %d\n", ret); + else + dev_err(&pdev->dev, "could not get clk: %d\n", ret); + return ret; } /* Request ioarea */ diff --git a/sound/soc/bcm/bcm63xx-pcm-whistler.c b/sound/soc/bcm/bcm63xx-pcm-whistler.c index b7a1efc7406e41d3d7ca9375a5287f44676e8635..7ec8559d53a2fd68450c729570610486ba13566b 100644 --- a/sound/soc/bcm/bcm63xx-pcm-whistler.c +++ b/sound/soc/bcm/bcm63xx-pcm-whistler.c @@ -45,7 +45,7 @@ static int bcm63xx_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_hw_params *params) { struct i2s_dma_desc *dma_desc; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); @@ -64,7 +64,7 @@ static int bcm63xx_pcm_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct i2s_dma_desc *dma_desc; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); dma_desc = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); kfree(dma_desc); @@ -81,7 +81,7 @@ static int bcm63xx_pcm_trigger(struct snd_soc_component *component, struct bcm_i2s_priv *i2s_priv; struct regmap *regmap_i2s; - rtd = substream->private_data; + rtd = asoc_substream_to_rtd(substream); i2s_priv = dev_get_drvdata(asoc_rtd_to_cpu(rtd, 0)->dev); regmap_i2s = i2s_priv->regmap_i2s; @@ -148,7 +148,7 @@ static int bcm63xx_pcm_prepare(struct snd_soc_component *component, struct i2s_dma_desc *dma_desc; struct regmap *regmap_i2s; struct bcm_i2s_priv *i2s_priv; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; uint32_t regaddr_desclen, regaddr_descaddr; @@ -267,7 +267,7 @@ static irqreturn_t i2s_dma_isr(int irq, void *bcm_i2s_priv) if (int_status & I2S_RX_DESC_OFF_INTR_EN_MSK) { substream = i2s_priv->capture_substream; runtime = substream->runtime; - rtd = substream->private_data; + rtd = asoc_substream_to_rtd(substream); prtd = runtime->private_data; dma_desc = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); @@ -315,7 +315,7 @@ static irqreturn_t i2s_dma_isr(int irq, void *bcm_i2s_priv) if (int_status & I2S_TX_DESC_OFF_INTR_EN_MSK) { substream = i2s_priv->play_substream; runtime = substream->runtime; - rtd = substream->private_data; + rtd = asoc_substream_to_rtd(substream); prtd = runtime->private_data; dma_desc = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c index f96d27c8b3018295bcfc78b60700cb37b8ebbc9e..7ad07239f99c4909bc5c117173560ea7d882727e 100644 --- a/sound/soc/bcm/cygnus-pcm.c +++ b/sound/soc/bcm/cygnus-pcm.c @@ -207,7 +207,7 @@ static u64 cygnus_dma_dmamask = DMA_BIT_MASK(32); static struct cygnus_aio_port *cygnus_dai_get_dma_data( struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); return snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(soc_runtime, 0), substream); } @@ -353,7 +353,7 @@ static void enable_intr(struct snd_pcm_substream *substream) static void disable_intr(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct cygnus_aio_port *aio; u32 set_mask; @@ -581,7 +581,7 @@ static irqreturn_t cygnus_dma_irq(int irq, void *data) static int cygnus_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; int ret; @@ -618,7 +618,7 @@ static int cygnus_pcm_open(struct snd_soc_component *component, static int cygnus_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct cygnus_aio_port *aio; aio = cygnus_dai_get_dma_data(substream); @@ -640,7 +640,7 @@ static int cygnus_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; @@ -656,7 +656,7 @@ static int cygnus_pcm_hw_params(struct snd_soc_component *component, static int cygnus_pcm_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct cygnus_aio_port *aio; aio = cygnus_dai_get_dma_data(substream); @@ -669,7 +669,7 @@ static int cygnus_pcm_hw_free(struct snd_soc_component *component, static int cygnus_pcm_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct cygnus_aio_port *aio; unsigned long bufsize, periodsize; @@ -733,7 +733,7 @@ static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_soc_component *component, static int cygnus_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) { struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_dma_buffer *buf = &substream->dma_buffer; size_t size; diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c index ccf65f087ea61876c4c306ea47b98f70bd692035..7b6cdc9c8a238238b74580ed9e2f78d031ba9764 100644 --- a/sound/soc/cirrus/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c @@ -22,7 +22,7 @@ static int edb93xx_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int err; diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index 1c45fb9ff9908607139300a6707ec99e373bce0a..16f9bb283b5cb2800c0ef5e7dd5c8342251df8f6 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c @@ -285,7 +285,7 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, /* * As per Cirrus EP93xx errata described below: * - * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf + * https://www.cirrus.com/en/pubs/errata/ER667E2B.pdf * * we will wait for the TX FIFO to be empty before * clearing the TEN bit. diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c index cb133e80b7c34ac04513f41d3fa7f01affd78caa..c4b11292166163ad1320bb4b8e559ca7fa0d8c86 100644 --- a/sound/soc/cirrus/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c @@ -22,7 +22,7 @@ static int snappercl15_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int err; diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 00b2c43d28a1e3ec629c60df510780ccbcf50bc1..cac7e557edc80085aa9e0563d290bb316f438ef0 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -274,10 +274,10 @@ static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol, unsigned int reg2 = mc->rreg; int val[2], val2[2], i; - val[0] = snd_soc_component_read32(component, reg) & 0x3f; - val[1] = (snd_soc_component_read32(component, PM860X_SIDETONE_SHIFT) >> 4) & 0xf; - val2[0] = snd_soc_component_read32(component, reg2) & 0x3f; - val2[1] = (snd_soc_component_read32(component, PM860X_SIDETONE_SHIFT)) & 0xf; + val[0] = snd_soc_component_read(component, reg) & 0x3f; + val[1] = (snd_soc_component_read(component, PM860X_SIDETONE_SHIFT) >> 4) & 0xf; + val2[0] = snd_soc_component_read(component, reg2) & 0x3f; + val2[1] = (snd_soc_component_read(component, PM860X_SIDETONE_SHIFT)) & 0xf; for (i = 0; i < ARRAY_SIZE(st_table); i++) { if ((st_table[i].m == val[0]) && (st_table[i].n == val[1])) @@ -333,8 +333,8 @@ static int snd_soc_get_volsw_2r_out(struct snd_kcontrol *kcontrol, int max = mc->max, val, val2; unsigned int mask = (1 << fls(max)) - 1; - val = snd_soc_component_read32(component, reg) >> shift; - val2 = snd_soc_component_read32(component, reg2) >> shift; + val = snd_soc_component_read(component, reg) >> shift; + val2 = snd_soc_component_read(component, reg2) >> shift; ucontrol->value.integer.value[0] = (max - val) & mask; ucontrol->value.integer.value[1] = (max - val2) & mask; @@ -426,7 +426,7 @@ static int pm860x_dac_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, PM860X_EAR_CTRL_2, RSYNC_CHANGE, RSYNC_CHANGE); /* update dac */ - data = snd_soc_component_read32(component, PM860X_DAC_EN_2); + data = snd_soc_component_read(component, PM860X_DAC_EN_2); data &= ~dac; if (!(data & (DAC_LEFT | DAC_RIGHT))) data &= ~MODULATOR; @@ -902,7 +902,7 @@ static const struct snd_soc_dapm_route pm860x_dapm_routes[] = { * Use MUTE_LEFT & MUTE_RIGHT to implement digital mute. * These bits can also be used to mute. */ -static int pm860x_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int pm860x_mute_stream(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; int data = 0, mask = MUTE_LEFT | MUTE_RIGHT; @@ -1136,17 +1136,19 @@ static int pm860x_set_bias_level(struct snd_soc_component *component, } static const struct snd_soc_dai_ops pm860x_pcm_dai_ops = { - .digital_mute = pm860x_digital_mute, + .mute_stream = pm860x_mute_stream, .hw_params = pm860x_pcm_hw_params, .set_fmt = pm860x_pcm_set_dai_fmt, .set_sysclk = pm860x_set_dai_sysclk, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops pm860x_i2s_dai_ops = { - .digital_mute = pm860x_digital_mute, + .mute_stream = pm860x_mute_stream, .hw_params = pm860x_i2s_hw_params, .set_fmt = pm860x_i2s_set_dai_fmt, .set_sysclk = pm860x_set_dai_sysclk, + .no_capture_mute = 1, }; #define PM860X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 986a6308818b2e7ad19c5026aab09d04872c6f25..946a70210f492a53633df90077089182ea2f8b80 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -115,7 +115,8 @@ config SND_SOC_ALL_CODECS imply SND_SOC_MAX98925 imply SND_SOC_MAX98926 imply SND_SOC_MAX98927 - imply SND_SOC_MAX98373 + imply SND_SOC_MAX98373_I2C + imply SND_SOC_MAX98373_SDW imply SND_SOC_MAX98390 imply SND_SOC_MAX9850 imply SND_SOC_MAX9860 @@ -868,8 +869,25 @@ config SND_SOC_MAX98927 depends on I2C config SND_SOC_MAX98373 + tristate + +config SND_SOC_MAX98373_I2C tristate "Maxim Integrated MAX98373 Speaker Amplifier" depends on I2C + select SND_SOC_MAX98373 + +config SND_SOC_MAX98373_SDW + tristate "Maxim Integrated MAX98373 Speaker Amplifier - SDW" + depends on SOUNDWIRE + select SND_SOC_MAX98373 + select REGMAP_SOUNDWIRE + help + Enable support for Maxim Integrated MAX98373 Soundwire + amplifier. MAX98373 supports either the MIPI SoundWire + compatible interface for audio and control data, or + the PCM interface for audio data and a standard I2C + interface for control data. Select this if MAX98373 is + connected via soundwire. config SND_SOC_MAX98390 tristate "Maxim Integrated MAX98390 Speaker Amplifier" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 47ae3cebb61ea298aad04f4b5d1d7572915d04e8..0140c60db695d0a3c4f186a0a55c46da96b18b97 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -115,6 +115,8 @@ snd-soc-max98925-objs := max98925.o snd-soc-max98926-objs := max98926.o snd-soc-max98927-objs := max98927.o snd-soc-max98373-objs := max98373.o +snd-soc-max98373-i2c-objs := max98373-i2c.o +snd-soc-max98373-sdw-objs := max98373-sdw.o snd-soc-max98390-objs := max98390.o snd-soc-max9850-objs := max9850.o snd-soc-max9860-objs := max9860.o @@ -418,6 +420,8 @@ obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o obj-$(CONFIG_SND_SOC_MAX98373) += snd-soc-max98373.o +obj-$(CONFIG_SND_SOC_MAX98373_I2C) += snd-soc-max98373-i2c.o +obj-$(CONFIG_SND_SOC_MAX98373_SDW) += snd-soc-max98373-sdw.o obj-$(CONFIG_SND_SOC_MAX98390) += snd-soc-max98390.o obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 98e25d93440c6b1810bccc6e3a1cc72bc05c2b9c..31a8c4162d209cdc10d2c520c9eb1b5311835f4a 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -1100,7 +1100,7 @@ static void anc_configure(struct snd_soc_component *component, if (apply_fir) for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++) for (par = 0; par < AB8500_ANC_FIR_COEFFS; par++) { - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, drvdata->anc_fir_values[par]); anc_fir(component, bnk, par, val); } @@ -1108,7 +1108,7 @@ static void anc_configure(struct snd_soc_component *component, if (apply_iir) for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++) for (par = 0; par < AB8500_ANC_IIR_COEFFS; par++) { - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, drvdata->anc_iir_values[par]); anc_iir(component, bnk, par, val); } @@ -1153,7 +1153,7 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol, mutex_lock(&drvdata->ctrl_lock); - sidconf = snd_soc_component_read32(component, AB8500_SIDFIRCONF); + sidconf = snd_soc_component_read(component, AB8500_SIDFIRCONF); if (((sidconf & BIT(AB8500_SIDFIRCONF_FIRSIDBUSY)) != 0)) { if ((sidconf & BIT(AB8500_SIDFIRCONF_ENFIRSIDS)) == 0) { dev_err(component->dev, "%s: Sidetone busy while off!\n", @@ -1168,7 +1168,7 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol, snd_soc_component_write(component, AB8500_SIDFIRADR, 0); for (param = 0; param < AB8500_SID_FIR_COEFFS; param++) { - val = snd_soc_component_read32(component, drvdata->sid_fir_values[param]); + val = snd_soc_component_read(component, drvdata->sid_fir_values[param]); snd_soc_component_write(component, AB8500_SIDFIRCOEF1, val >> 8 & 0xff); snd_soc_component_write(component, AB8500_SIDFIRCOEF2, val & 0xff); } @@ -2126,7 +2126,7 @@ static int ab8500_codec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) dev_err(dai->component->dev, "%s: ERROR: The device is either a master or a slave.\n", __func__); - /* fall through */ + fallthrough; default: dev_err(dai->component->dev, "%s: ERROR: Unsupporter master mask 0x%x\n", diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 980e024a5720d19fbed54202d17df0f516c2e5ad..f37ab7eda615533fcf5570d0b4f1af6c479d4cab 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -143,7 +143,7 @@ static inline bool ad193x_has_adc(const struct ad193x_priv *ad193x) * DAI ops entries */ -static int ad193x_mute(struct snd_soc_dai *dai, int mute) +static int ad193x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(dai->component); @@ -371,10 +371,11 @@ static int ad193x_startup(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops ad193x_dai_ops = { .startup = ad193x_startup, .hw_params = ad193x_hw_params, - .digital_mute = ad193x_mute, + .mute_stream = ad193x_mute, .set_tdm_slot = ad193x_set_tdm_slot, .set_sysclk = ad193x_set_dai_sysclk, .set_fmt = ad193x_set_dai_fmt, + .no_capture_mute = 1, }; /* codec DAI instance */ diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 43b1337bac37f70f98ab937e6f225b96704f188e..9fd2023da218f69623762f29d3dc1142cc97e064 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -256,7 +256,7 @@ static int ad1980_soc_probe(struct snd_soc_component *component) if (ret < 0) goto reset_err; - vendor_id2 = snd_soc_component_read32(component, AC97_VENDOR_ID2); + vendor_id2 = snd_soc_component_read(component, AC97_VENDOR_ID2); if (vendor_id2 == 0x5374) { dev_warn(component->dev, "Found AD1981 - only 2/2 IN/OUT Channels supported\n"); @@ -270,7 +270,7 @@ static int ad1980_soc_probe(struct snd_soc_component *component) snd_soc_component_write(component, AC97_SURROUND_MASTER, 0x0000); /*power on LFE/CENTER/Surround DACs*/ - ext_status = snd_soc_component_read32(component, AC97_EXTENDED_STATUS); + ext_status = snd_soc_component_read(component, AC97_EXTENDED_STATUS); snd_soc_component_write(component, AC97_EXTENDED_STATUS, ext_status&~0x3800); return 0; diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 115e296b2ad63931217508a40d7529d44b45b216..68130eaa64a404509f0aca81c854fcf0cb389b8e 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c @@ -573,7 +573,7 @@ static int adau1701_set_bias_level(struct snd_soc_component *component, return 0; } -static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute) +static int adau1701_mute_stream(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; unsigned int mask = ADAU1701_DSPCTRL_DAM; @@ -631,8 +631,9 @@ static int adau1701_startup(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops adau1701_dai_ops = { .set_fmt = adau1701_set_dai_fmt, .hw_params = adau1701_hw_params, - .digital_mute = adau1701_digital_mute, + .mute_stream = adau1701_mute_stream, .startup = adau1701_startup, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver adau1701_dai = { diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index 5ca9b744b7d849271ef941af7c391f4dd3987a9e..fb006fc81653a6166378c47629267dc4d0758ae0 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c @@ -642,7 +642,7 @@ static int adau1761_setup_digmic_jackdetect(struct snd_soc_component *component) ARRAY_SIZE(adau1761_jack_detect_controls)); if (ret) return ret; - /* fall through */ + fallthrough; case ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: ret = snd_soc_dapm_add_routes(dapm, adau1761_no_dmic_routes, ARRAY_SIZE(adau1761_no_dmic_routes)); @@ -693,7 +693,7 @@ static int adau1761_setup_headphone_mode(struct snd_soc_component *component) ADAU1761_PLAY_MONO_OUTPUT_VOL_UNMUTE, ADAU1761_PLAY_MONO_OUTPUT_VOL_MODE_HP | ADAU1761_PLAY_MONO_OUTPUT_VOL_UNMUTE); - /* fallthrough */ + fallthrough; case ADAU1761_OUTPUT_MODE_HEADPHONE: regmap_update_bits(adau->regmap, ADAU1761_PLAY_HP_RIGHT_VOL, ADAU1761_PLAY_HP_RIGHT_VOL_MODE_HP, diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index b6352de077b52386301d34b10ddab7bffd179cd7..30e072c80ac179f2b08263a20b2ac93c9995495a 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -385,7 +385,7 @@ static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai, case ADAU17X1_CLK_SRC_PLL_AUTO: if (!adau->mclk) return -EINVAL; - /* Fall-through */ + fallthrough; case ADAU17X1_CLK_SRC_PLL: is_pll = true; break; @@ -469,7 +469,7 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream, ret = adau17x1_auto_pll(dai, params); if (ret) return ret; - /* Fall-through */ + fallthrough; case ADAU17X1_CLK_SRC_PLL: freq = adau->pll_freq; break; diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index c4b9722c3d8f5f92b5d705a94214ece37547232f..4fd99280d7dbb9a921437ac431509a14d07a8200 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -647,7 +647,7 @@ static int adav80x_set_pll(struct snd_soc_component *component, int pll_id, pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV; break; } - /* fall through */ + fallthrough; default: return -EINVAL; } diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index 71562154c0b1e6e38873cfa76d8ab9e03721767d..cbe3c782e0ca897163bc9b3f3ef8f571a3804308 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -401,29 +401,29 @@ static int ak4458_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) static const int att_speed[] = { 4080, 2040, 510, 255 }; -static int ak4458_set_dai_mute(struct snd_soc_dai *dai, int mute) +static int ak4458_set_dai_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component); - int nfs, ndt, ret, reg; + int nfs, ndt, reg; int ats; nfs = ak4458->fs; - reg = snd_soc_component_read32(component, AK4458_0B_CONTROL7); + reg = snd_soc_component_read(component, AK4458_0B_CONTROL7); ats = (reg & AK4458_ATS_MASK) >> AK4458_ATS_SHIFT; ndt = att_speed[ats] / (nfs / 1000); if (mute) { - ret = snd_soc_component_update_bits(component, AK4458_01_CONTROL2, 0x01, 1); + snd_soc_component_update_bits(component, AK4458_01_CONTROL2, 0x01, 1); mdelay(ndt); if (ak4458->mute_gpiod) gpiod_set_value_cansleep(ak4458->mute_gpiod, 1); } else { if (ak4458->mute_gpiod) gpiod_set_value_cansleep(ak4458->mute_gpiod, 0); - ret = snd_soc_component_update_bits(component, AK4458_01_CONTROL2, 0x01, 0); + snd_soc_component_update_bits(component, AK4458_01_CONTROL2, 0x01, 0); mdelay(ndt); } @@ -495,8 +495,9 @@ static const struct snd_soc_dai_ops ak4458_dai_ops = { .startup = ak4458_startup, .hw_params = ak4458_hw_params, .set_fmt = ak4458_set_dai_fmt, - .digital_mute = ak4458_set_dai_mute, + .mute_stream = ak4458_set_dai_mute, .set_tdm_slot = ak4458_set_tdm_slot, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ak4458_dai = { diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index b2635f3b11cac6afcaa0ea2ca19797d610fdb6a7..91e7a57c43da98d5309d32f10e25844b474ebaca 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -261,7 +261,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct ak4535_priv *ak4535 = snd_soc_component_get_drvdata(component); - u8 mode2 = snd_soc_component_read32(component, AK4535_MODE2) & ~(0x3 << 5); + u8 mode2 = snd_soc_component_read(component, AK4535_MODE2) & ~(0x3 << 5); int rate = params_rate(params), fs = 256; if (rate) @@ -309,10 +309,11 @@ static int ak4535_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int ak4535_mute(struct snd_soc_dai *dai, int mute) +static int ak4535_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, AK4535_DAC); + u16 mute_reg = snd_soc_component_read(component, AK4535_DAC); + if (!mute) snd_soc_component_write(component, AK4535_DAC, mute_reg & ~0x20); else @@ -348,8 +349,9 @@ static int ak4535_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops ak4535_dai_ops = { .hw_params = ak4535_hw_params, .set_fmt = ak4535_set_dai_fmt, - .digital_mute = ak4535_mute, + .mute_stream = ak4535_mute, .set_sysclk = ak4535_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ak4535_dai = { diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index c1181a20714ddeaa8c634fa8cff119c1d52079d0..8d663e8d64c49814763e97bf2dfceb3726e0ff63 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -451,13 +451,13 @@ static int ak4613_set_bias_level(struct snd_soc_component *component, switch (level) { case SND_SOC_BIAS_ON: mgmt1 |= RSTN; - /* fall through */ + fallthrough; case SND_SOC_BIAS_PREPARE: mgmt1 |= PMADC | PMDAC; - /* fall through */ + fallthrough; case SND_SOC_BIAS_STANDBY: mgmt1 |= PMVR; - /* fall through */ + fallthrough; case SND_SOC_BIAS_OFF: default: break; @@ -490,8 +490,8 @@ static void ak4613_dummy_write(struct work_struct *work) */ udelay(5000000 / priv->rate); - snd_soc_component_read(component, PW_MGMT1, &mgmt1); - snd_soc_component_read(component, PW_MGMT3, &mgmt3); + mgmt1 = snd_soc_component_read(component, PW_MGMT1); + mgmt3 = snd_soc_component_read(component, PW_MGMT3); snd_soc_component_write(component, PW_MGMT1, mgmt1); snd_soc_component_write(component, PW_MGMT3, mgmt3); diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 2d5b640aab5811dfb4f56dbd55a8acf954c7db1c..77004cd7caa3ec8db578f6af47f14336e0a30343 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -405,7 +405,7 @@ static int ak4641_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, return snd_soc_component_write(component, AK4641_MODE1, mode1); } -static int ak4641_mute(struct snd_soc_dai *dai, int mute) +static int ak4641_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -467,15 +467,17 @@ static int ak4641_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops ak4641_i2s_dai_ops = { .hw_params = ak4641_i2s_hw_params, .set_fmt = ak4641_i2s_set_dai_fmt, - .digital_mute = ak4641_mute, + .mute_stream = ak4641_mute, .set_sysclk = ak4641_set_dai_sysclk, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops ak4641_pcm_dai_ops = { .hw_params = NULL, /* rates are controlled by BT chip */ .set_fmt = ak4641_pcm_set_dai_fmt, - .digital_mute = ak4641_mute, + .mute_stream = ak4641_mute, .set_sysclk = ak4641_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ak4641_dai[] = { diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 67564798f303d9fb4256f19d5fd98e13e529d420..eb435235b5a31adfb579a97ae10cefd524fc41e5 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -425,7 +425,7 @@ static int ak4671_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; u8 fs; - fs = snd_soc_component_read32(component, AK4671_PLL_MODE_SELECT0); + fs = snd_soc_component_read(component, AK4671_PLL_MODE_SELECT0); fs &= ~AK4671_FS; switch (params_rate(params)) { @@ -471,7 +471,7 @@ static int ak4671_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, struct snd_soc_component *component = dai->component; u8 pll; - pll = snd_soc_component_read32(component, AK4671_PLL_MODE_SELECT0); + pll = snd_soc_component_read(component, AK4671_PLL_MODE_SELECT0); pll &= ~AK4671_PLL; switch (freq) { @@ -518,7 +518,7 @@ static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) u8 format; /* set master/slave audio interface */ - mode = snd_soc_component_read32(component, AK4671_PLL_MODE_SELECT1); + mode = snd_soc_component_read(component, AK4671_PLL_MODE_SELECT1); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: @@ -532,7 +532,7 @@ static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) } /* interface format */ - format = snd_soc_component_read32(component, AK4671_FORMAT_SELECT); + format = snd_soc_component_read(component, AK4671_FORMAT_SELECT); format &= ~AK4671_DIF; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index 6added8f28da32972b9a5361e69bff0342236ea5..3d1761a531f58cfd9b00e765a161629f53a775c7 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -534,7 +534,7 @@ static int alc5623_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, 0); /* pll is not used in slave mode */ - reg = snd_soc_component_read32(component, ALC5623_DAI_CONTROL); + reg = snd_soc_component_read(component, ALC5623_DAI_CONTROL); if (reg & ALC5623_DAI_SDP_SLAVE_MODE) return 0; @@ -701,7 +701,7 @@ static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream, int coeff, rate; u16 iface; - iface = snd_soc_component_read32(component, ALC5623_DAI_CONTROL); + iface = snd_soc_component_read(component, ALC5623_DAI_CONTROL); iface &= ~ALC5623_DAI_I2S_DL_MASK; /* bit size */ @@ -737,11 +737,11 @@ static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int alc5623_mute(struct snd_soc_dai *dai, int mute) +static int alc5623_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u16 hp_mute = ALC5623_MISC_M_DAC_L_INPUT | ALC5623_MISC_M_DAC_R_INPUT; - u16 mute_reg = snd_soc_component_read32(component, ALC5623_MISC_CTRL) & ~hp_mute; + u16 mute_reg = snd_soc_component_read(component, ALC5623_MISC_CTRL) & ~hp_mute; if (mute) mute_reg |= hp_mute; @@ -829,10 +829,11 @@ static int alc5623_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops alc5623_dai_ops = { .hw_params = alc5623_pcm_hw_params, - .digital_mute = alc5623_mute, + .mute_stream = alc5623_mute, .set_fmt = alc5623_set_dai_fmt, .set_sysclk = alc5623_set_dai_sysclk, .set_pll = alc5623_set_dai_pll, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver alc5623_dai = { diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index e4ca87cccfc6dff1194f788f293a5b67a037c52a..9d6dcd3ffa573004ac78bdf763bdbbd19c585dbf 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -694,7 +694,7 @@ static int alc5632_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, 0); /* pll is not used in slave mode */ - reg = snd_soc_component_read32(component, ALC5632_DAI_CONTROL); + reg = snd_soc_component_read(component, ALC5632_DAI_CONTROL); if (reg & ALC5632_DAI_SDP_SLAVE_MODE) return 0; @@ -871,7 +871,7 @@ static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream, int coeff, rate; u16 iface; - iface = snd_soc_component_read32(component, ALC5632_DAI_CONTROL); + iface = snd_soc_component_read(component, ALC5632_DAI_CONTROL); iface &= ~ALC5632_DAI_I2S_DL_MASK; /* bit size */ @@ -902,12 +902,12 @@ static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int alc5632_mute(struct snd_soc_dai *dai, int mute) +static int alc5632_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u16 hp_mute = ALC5632_MISC_HP_DEPOP_MUTE_L |ALC5632_MISC_HP_DEPOP_MUTE_R; - u16 mute_reg = snd_soc_component_read32(component, ALC5632_MISC_CTRL) & ~hp_mute; + u16 mute_reg = snd_soc_component_read(component, ALC5632_MISC_CTRL) & ~hp_mute; if (mute) mute_reg |= hp_mute; @@ -1005,10 +1005,11 @@ static int alc5632_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops alc5632_dai_ops = { .hw_params = alc5632_pcm_hw_params, - .digital_mute = alc5632_mute, + .mute_stream = alc5632_mute, .set_fmt = alc5632_set_dai_fmt, .set_sysclk = alc5632_set_dai_sysclk, .set_pll = alc5632_set_dai_pll, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver alc5632_dai = { diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 9716c9624a8912e9c83197e34872a11f3029a0e3..1228f2de02975cadb757c3c92c94119c1b612572 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -87,7 +87,7 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, ARIZONA_INTERRUPT_RAW_STATUS_3); if (val & ARIZONA_SPK_OVERHEAT_STS) { dev_crit(arizona->dev, @@ -897,7 +897,7 @@ static void arizona_in_set_vu(struct snd_soc_component *component, int ena) bool arizona_input_analog(struct snd_soc_component *component, int shift) { unsigned int reg = ARIZONA_IN1L_CONTROL + ((shift / 2) * 8); - unsigned int val = snd_soc_component_read32(component, reg); + unsigned int val = snd_soc_component_read(component, reg); return !(val & ARIZONA_IN1_MODE_MASK); } @@ -937,7 +937,7 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, break; case SND_SOC_DAPM_POST_PMD: /* Disable volume updates if no inputs are enabled */ - reg = snd_soc_component_read32(component, ARIZONA_INPUT_ENABLES); + reg = snd_soc_component_read(component, ARIZONA_INPUT_ENABLES); if (reg == 0) arizona_in_set_vu(component, 0); break; @@ -1755,15 +1755,15 @@ static bool arizona_aif_cfg_changed(struct snd_soc_component *component, { int val; - val = snd_soc_component_read32(component, base + ARIZONA_AIF_BCLK_CTRL); + val = snd_soc_component_read(component, base + ARIZONA_AIF_BCLK_CTRL); if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK)) return true; - val = snd_soc_component_read32(component, base + ARIZONA_AIF_TX_BCLK_RATE); + val = snd_soc_component_read(component, base + ARIZONA_AIF_TX_BCLK_RATE); if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK)) return true; - val = snd_soc_component_read32(component, base + ARIZONA_AIF_FRAME_CTRL_1); + val = snd_soc_component_read(component, base + ARIZONA_AIF_FRAME_CTRL_1); if (frame != (val & (ARIZONA_AIF1TX_WL_MASK | ARIZONA_AIF1TX_SLOT_LEN_MASK))) return true; @@ -1813,7 +1813,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, } /* Force multiple of 2 channels for I2S mode */ - val = snd_soc_component_read32(component, base + ARIZONA_AIF_FORMAT); + val = snd_soc_component_read(component, base + ARIZONA_AIF_FORMAT); val &= ARIZONA_AIF1_FMT_MASK; if ((channels & 1) && (val == ARIZONA_FMT_I2S_MODE)) { arizona_aif_dbg(dai, "Forcing stereo mode\n"); @@ -1845,9 +1845,9 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, if (reconfig) { /* Save AIF TX/RX state */ - aif_tx_state = snd_soc_component_read32(component, + aif_tx_state = snd_soc_component_read(component, base + ARIZONA_AIF_TX_ENABLES); - aif_rx_state = snd_soc_component_read32(component, + aif_rx_state = snd_soc_component_read(component, base + ARIZONA_AIF_RX_ENABLES); /* Disable AIF TX/RX before reconfiguring it */ regmap_update_bits_async(arizona->regmap, diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c index d7f05b384f1fbb83b944cf072f34c3efd238b601..f046987ee4cdb3f44febe980ba3c1c6517c73c13 100644 --- a/sound/soc/codecs/cpcap.c +++ b/sound/soc/codecs/cpcap.c @@ -1216,7 +1216,7 @@ static int cpcap_hifi_set_dai_fmt(struct snd_soc_dai *codec_dai, return regmap_update_bits(cpcap->regmap, reg, mask, val); } -static int cpcap_hifi_set_mute(struct snd_soc_dai *dai, int mute) +static int cpcap_hifi_set_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component); @@ -1237,7 +1237,8 @@ static const struct snd_soc_dai_ops cpcap_dai_hifi_ops = { .hw_params = cpcap_hifi_hw_params, .set_sysclk = cpcap_hifi_set_dai_sysclk, .set_fmt = cpcap_hifi_set_dai_fmt, - .digital_mute = cpcap_hifi_set_mute, + .mute_stream = cpcap_hifi_set_mute, + .no_capture_mute = 1, }; static int cpcap_voice_hw_params(struct snd_pcm_substream *substream, @@ -1370,7 +1371,8 @@ static int cpcap_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int cpcap_voice_set_mute(struct snd_soc_dai *dai, int mute) +static int cpcap_voice_set_mute(struct snd_soc_dai *dai, + int mute, int direction) { struct snd_soc_component *component = dai->component; struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component); @@ -1391,7 +1393,8 @@ static const struct snd_soc_dai_ops cpcap_dai_voice_ops = { .hw_params = cpcap_voice_hw_params, .set_sysclk = cpcap_voice_set_dai_sysclk, .set_fmt = cpcap_voice_set_dai_fmt, - .digital_mute = cpcap_voice_set_mute, + .mute_stream = cpcap_voice_set_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cpcap_dai[] = { diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index b0cc61178a41615bfd4ecb1ca0e477cb7bcf0863..0aae5790222aef28b905ac83c86b584a356d70f3 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c @@ -30,7 +30,7 @@ static const struct snd_kcontrol_new cq93vc_snd_controls[] = { SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09, 0, 0x3f, 0), }; -static int cq93vc_mute(struct snd_soc_dai *dai, int mute) +static int cq93vc_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u8 reg; @@ -87,8 +87,9 @@ static int cq93vc_set_bias_level(struct snd_soc_component *component, #define CQ93VC_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE) static const struct snd_soc_dai_ops cq93vc_dai_ops = { - .digital_mute = cq93vc_mute, + .mute_stream = cq93vc_mute, .set_sysclk = cq93vc_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cq93vc_dai = { diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index ab009c7dfdf453f353f37a672bb4052d85201351..28f039adfa1388d884a069d3d02e74f9ba88bd5d 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -1030,11 +1030,13 @@ static const struct of_device_id cros_ec_codec_of_match[] = { MODULE_DEVICE_TABLE(of, cros_ec_codec_of_match); #endif +#ifdef CONFIG_ACPI static const struct acpi_device_id cros_ec_codec_acpi_id[] = { { "GOOG0013", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, cros_ec_codec_acpi_id); +#endif static struct platform_driver cros_ec_codec_platform_driver = { .driver = { diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 2fb65f246b0cfa0ad7115be40e8e304844f75f96..d76be44f46b406df325c9cda1d6384a99642dbce 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c @@ -378,7 +378,7 @@ static int cs4265_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static int cs4265_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs4265_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -498,9 +498,10 @@ static int cs4265_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops cs4265_ops = { .hw_params = cs4265_pcm_hw_params, - .digital_mute = cs4265_digital_mute, + .mute_stream = cs4265_mute, .set_fmt = cs4265_set_fmt, .set_sysclk = cs4265_set_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs4265_dai[] = { diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 8a02791e44ad68b5f8fe563782717dd67b0b1645..ddd95c8269edfaf635645e23ef3e9e4aefccd036 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -355,7 +355,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, /* Set the sample rate */ - reg = snd_soc_component_read32(component, CS4270_MODE); + reg = snd_soc_component_read(component, CS4270_MODE); reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK); reg |= cs4270_mode_ratios[i].mclk; @@ -372,7 +372,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, /* Set the DAI format */ - reg = snd_soc_component_read32(component, CS4270_FORMAT); + reg = snd_soc_component_read(component, CS4270_FORMAT); reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK); switch (cs4270->mode) { @@ -406,13 +406,13 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, * board does not have the MUTEA or MUTEB pins connected to such circuitry, * then this function will do nothing. */ -static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute) +static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct cs4270_private *cs4270 = snd_soc_component_get_drvdata(component); int reg6; - reg6 = snd_soc_component_read32(component, CS4270_MUTE); + reg6 = snd_soc_component_read(component, CS4270_MUTE); if (mute) reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; @@ -471,7 +471,8 @@ static const struct snd_soc_dai_ops cs4270_dai_ops = { .hw_params = cs4270_hw_params, .set_sysclk = cs4270_set_dai_sysclk, .set_fmt = cs4270_set_dai_fmt, - .digital_mute = cs4270_dai_mute, + .mute_stream = cs4270_dai_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs4270_dai = { @@ -499,7 +500,7 @@ static struct snd_soc_dai_driver cs4270_dai = { /** * cs4270_probe - ASoC probe function - * @pdev: platform device + * @component: ASoC component * * This function is called when ASoC has all the pieces it needs to * instantiate a sound driver. @@ -540,7 +541,7 @@ static int cs4270_probe(struct snd_soc_component *component) /** * cs4270_remove - ASoC remove function - * @pdev: platform device + * @component: ASoC component * * This function is the counterpart to cs4270_probe(). */ @@ -567,7 +568,7 @@ static int cs4270_soc_suspend(struct snd_soc_component *component) struct cs4270_private *cs4270 = snd_soc_component_get_drvdata(component); int reg, ret; - reg = snd_soc_component_read32(component, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; + reg = snd_soc_component_read(component, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; if (reg < 0) return reg; @@ -599,7 +600,7 @@ static int cs4270_soc_resume(struct snd_soc_component *component) regcache_sync(cs4270->regmap); /* ... then disable the power-down bits */ - reg = snd_soc_component_read32(component, CS4270_PWRCTL); + reg = snd_soc_component_read(component, CS4270_PWRCTL); reg &= ~CS4270_PWRCTL_PDN_ALL; return snd_soc_component_write(component, CS4270_PWRCTL, reg); diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 5125bb9b37b5513864127c512e8df5a4f37d6fc8..210fcbedf2413b41464e1c42759cab2433081ab6 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -849,7 +849,7 @@ static int cs42l42_set_sysclk(struct snd_soc_dai *dai, return 0; } -static int cs42l42_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs42l42_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; unsigned int regval; @@ -877,7 +877,7 @@ static int cs42l42_digital_mute(struct snd_soc_dai *dai, int mute) CS42L42_PLL_START_MASK, 1 << CS42L42_PLL_START_SHIFT); /* Read the headphone load */ - regval = snd_soc_component_read32(component, CS42L42_LOAD_DET_RCSTAT); + regval = snd_soc_component_read(component, CS42L42_LOAD_DET_RCSTAT); if (((regval & CS42L42_RLA_STAT_MASK) >> CS42L42_RLA_STAT_SHIFT) == CS42L42_RLA_STAT_15_OHM) { fullScaleVol = CS42L42_HP_FULL_SCALE_VOL_MASK; @@ -909,7 +909,8 @@ static const struct snd_soc_dai_ops cs42l42_ops = { .hw_params = cs42l42_pcm_hw_params, .set_fmt = cs42l42_set_dai_fmt, .set_sysclk = cs42l42_set_sysclk, - .digital_mute = cs42l42_digital_mute + .mute_stream = cs42l42_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs42l42_dai = { @@ -1658,8 +1659,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client, ret = of_property_read_u32(np, "cirrus,btn-det-init-dbnce", &val); if (!ret) { - if ((val >= CS42L42_BTN_DET_INIT_DBNCE_MIN) && - (val <= CS42L42_BTN_DET_INIT_DBNCE_MAX)) + if (val <= CS42L42_BTN_DET_INIT_DBNCE_MAX) cs42l42->btn_det_init_dbnce = val; else { dev_err(&i2c_client->dev, @@ -1676,8 +1676,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client, ret = of_property_read_u32(np, "cirrus,btn-det-event-dbnce", &val); if (!ret) { - if ((val >= CS42L42_BTN_DET_EVENT_DBNCE_MIN) && - (val <= CS42L42_BTN_DET_EVENT_DBNCE_MAX)) + if (val <= CS42L42_BTN_DET_EVENT_DBNCE_MAX) cs42l42->btn_det_event_dbnce = val; else { dev_err(&i2c_client->dev, @@ -1695,8 +1694,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client, if (!ret) { for (i = 0; i < CS42L42_NUM_BIASES; i++) { - if ((thresholds[i] >= CS42L42_HS_DET_LEVEL_MIN) && - (thresholds[i] <= CS42L42_HS_DET_LEVEL_MAX)) + if (thresholds[i] <= CS42L42_HS_DET_LEVEL_MAX) cs42l42->bias_thresholds[i] = thresholds[i]; else { dev_err(&i2c_client->dev, diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index e47758e4fb3600df2cb9975b3c18221323c52a9a..764f2ef8f59df6f26fd8f2f9c3b085d800069179 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -61,7 +61,7 @@ static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - unsigned long value = snd_soc_component_read32(component, CS42L51_PCM_MIXER)&3; + unsigned long value = snd_soc_component_read(component, CS42L51_PCM_MIXER)&3; switch (value) { default: @@ -407,8 +407,8 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - intf_ctl = snd_soc_component_read32(component, CS42L51_INTF_CTL); - power_ctl = snd_soc_component_read32(component, CS42L51_MIC_POWER_CTL); + intf_ctl = snd_soc_component_read(component, CS42L51_INTF_CTL); + power_ctl = snd_soc_component_read(component, CS42L51_MIC_POWER_CTL); intf_ctl &= ~(CS42L51_INTF_CTL_MASTER | CS42L51_INTF_CTL_ADC_I2S | CS42L51_INTF_CTL_DAC_FORMAT(7)); @@ -484,13 +484,13 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream, return 0; } -static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute) +static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int reg; int mask = CS42L51_DAC_OUT_CTL_DACA_MUTE|CS42L51_DAC_OUT_CTL_DACB_MUTE; - reg = snd_soc_component_read32(component, CS42L51_DAC_OUT_CTL); + reg = snd_soc_component_read(component, CS42L51_DAC_OUT_CTL); if (mute) reg |= mask; @@ -511,7 +511,8 @@ static const struct snd_soc_dai_ops cs42l51_dai_ops = { .hw_params = cs42l51_hw_params, .set_sysclk = cs42l51_set_dai_sysclk, .set_fmt = cs42l51_set_dai_fmt, - .digital_mute = cs42l51_dai_mute, + .mute_stream = cs42l51_dai_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs42l51_dai = { diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 2ea4cba3be2ad4a3020142dcd47fc1aca7d1be44..f772628f233ef5b5596d0e06ef805a80dacc68d9 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -784,7 +784,7 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static int cs42l52_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs42l52_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -865,9 +865,10 @@ static int cs42l52_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops cs42l52_ops = { .hw_params = cs42l52_pcm_hw_params, - .digital_mute = cs42l52_digital_mute, + .mute_stream = cs42l52_mute, .set_fmt = cs42l52_set_fmt, .set_sysclk = cs42l52_set_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs42l52_dai = { diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index ac569ab3d30f4576726d1cbcbbc3ea7318c1ec1c..97024a6ac96d78450c11eb1683c428e141d7fba2 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -800,7 +800,7 @@ static int cs42l56_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static int cs42l56_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs42l56_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -929,9 +929,10 @@ static int cs42l56_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops cs42l56_ops = { .hw_params = cs42l56_pcm_hw_params, - .digital_mute = cs42l56_digital_mute, + .mute_stream = cs42l56_mute, .set_fmt = cs42l56_set_dai_fmt, .set_sysclk = cs42l56_set_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs42l56_dai = { diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 36089f8bcf0a63dd092bb6d5501acc65998cba5b..988ca7e19821ea6dc6c72fc1c205875082e4a702 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -938,8 +938,8 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) unsigned int inv, format; u8 spc, mmcc; - spc = snd_soc_component_read32(component, CS42L73_SPC(id)); - mmcc = snd_soc_component_read32(component, CS42L73_MMCC(id)); + spc = snd_soc_component_read(component, CS42L73_SPC(id)); + mmcc = snd_soc_component_read(component, CS42L73_MMCC(id)); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 94b1adb088fde0ecf639b7712fcc021cc9989253..5d6ef660f851f8f4dc20385a2b3b059f415f0672 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -362,7 +362,7 @@ static int cs42xx8_hw_free(struct snd_pcm_substream *substream, return 0; } -static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs42xx8_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); @@ -380,7 +380,8 @@ static const struct snd_soc_dai_ops cs42xx8_dai_ops = { .set_sysclk = cs42xx8_set_dai_sysclk, .hw_params = cs42xx8_hw_params, .hw_free = cs42xx8_hw_free, - .digital_mute = cs42xx8_digital_mute, + .mute_stream = cs42xx8_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs42xx8_dai = { diff --git a/sound/soc/codecs/cs4341.c b/sound/soc/codecs/cs4341.c index ade7477d04f11e0e50061713b39c16065f33dfc2..f566604de78cfe2d9ef1c4a91a08c9077d2aee72 100644 --- a/sound/soc/codecs/cs4341.c +++ b/sound/soc/codecs/cs4341.c @@ -116,7 +116,7 @@ static int cs4341_hw_params(struct snd_pcm_substream *substream, CS4341_MODE2_DIF, mode); } -static int cs4341_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs4341_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int ret; @@ -174,7 +174,8 @@ static const struct snd_kcontrol_new cs4341_controls[] = { static const struct snd_soc_dai_ops cs4341_dai_ops = { .set_fmt = cs4341_set_fmt, .hw_params = cs4341_hw_params, - .digital_mute = cs4341_digital_mute, + .mute_stream = cs4341_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs4341_dai = { diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index 3381209a882d61c9e8d4cf97d99229e9ea372bda..fd55263197798a462c7683167e204d7b8d68cecd 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -131,7 +131,7 @@ static int cs4349_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int cs4349_digital_mute(struct snd_soc_dai *dai, int mute) +static int cs4349_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int reg; @@ -236,7 +236,8 @@ static const struct snd_soc_dapm_route cs4349_routes[] = { static const struct snd_soc_dai_ops cs4349_dai_ops = { .hw_params = cs4349_pcm_hw_params, .set_fmt = cs4349_set_dai_fmt, - .digital_mute = cs4349_digital_mute, + .mute_stream = cs4349_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver cs4349_dai = { diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c index 402c6b7c7014757f7e9e86c12a06019fab91ca7c..a591e7457d11f4a8e58c25457e8be534577fd81d 100644 --- a/sound/soc/codecs/cs47l15.c +++ b/sound/soc/codecs/cs47l15.c @@ -540,29 +540,29 @@ SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 2, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 3, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, @@ -631,29 +631,29 @@ SND_SOC_DAPM_PGA_E("IN2R", MADERA_INPUT_ENABLES, MADERA_IN2R_ENA_SHIFT, SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 2, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 3, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index d7538d50bbd385043568692b43a9a65dafceb7b4..7f5dd01f40c9d8fbe2b22fed0b045a58073725b3 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -129,19 +129,11 @@ static void cs47l35_hp_post_enable(struct snd_soc_dapm_widget *w) struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); unsigned int val; - int ret; switch (w->shift) { case MADERA_OUT1L_ENA_SHIFT: case MADERA_OUT1R_ENA_SHIFT: - ret = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1, - &val); - if (ret) { - dev_err(component->dev, - "Failed to check output enables: %d\n", ret); - return; - } - + val = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1); val &= (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA); if (val != (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA)) @@ -642,43 +634,43 @@ SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 1, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 2, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 3, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 4, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 5, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX6_ENA_SHIFT, 0), @@ -749,43 +741,43 @@ SND_SOC_DAPM_PGA_E("IN2R", MADERA_INPUT_ENABLES, MADERA_IN2R_ENA_SHIFT, SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 1, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 2, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 3, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 4, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 5, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX6_ENA_SHIFT, 0), diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c index 9de991adad74daffed0d5facb6bf123f8d27589c..47b16466b6c17a370f4eac9296b94cd37358d92e 100644 --- a/sound/soc/codecs/cs47l85.c +++ b/sound/soc/codecs/cs47l85.c @@ -191,19 +191,11 @@ static void cs47l85_hp_post_enable(struct snd_soc_dapm_widget *w) struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); unsigned int val; - int ret; switch (w->shift) { case MADERA_OUT1L_ENA_SHIFT: case MADERA_OUT1R_ENA_SHIFT: - ret = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1, - &val); - if (ret) { - dev_err(component->dev, - "Failed to check output enables: %d\n", ret); - return; - } - + val = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1); val &= (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA); if (val != (MADERA_OUT1L_ENA | MADERA_OUT1R_ENA)) @@ -1024,71 +1016,71 @@ SND_SOC_DAPM_MUX("SPKDAT2R ANC Source", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 6, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 7, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 2, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 3, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 4, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 5, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 6, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 7, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 1, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 2, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 3, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 4, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 5, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 6, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 7, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF4TX1", NULL, 0, MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF4TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF4TX2", NULL, 1, MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX2_ENA_SHIFT, 0), SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, @@ -1213,70 +1205,70 @@ SND_SOC_DAPM_PGA_E("IN6R", MADERA_INPUT_ENABLES, MADERA_IN6R_ENA_SHIFT, SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 6, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 7, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 2, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 3, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 4, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 5, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 6, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 7, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF4RX1", NULL, 0, MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF4RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF4RX2", NULL, 1, MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 1, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 2, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 3, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 4, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 5, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 6, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 7, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX8_ENA_SHIFT, 0), diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index 2715b5da04159474cf2e8a34cfa54616ef475133..8838dd557321a66f28e2e5b7f42010ce2d0a1ae0 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c @@ -977,71 +977,71 @@ SND_SOC_DAPM_MUX("SPKDAT1R ANC Source", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 6, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 7, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 2, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 3, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 4, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 5, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 6, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 7, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 1, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 2, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 3, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 4, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 5, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 6, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 7, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF4TX1", NULL, 0, MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF4TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF4TX2", NULL, 1, MADERA_AIF4_TX_ENABLES, MADERA_AIF4TX2_ENA_SHIFT, 0), SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, @@ -1147,63 +1147,63 @@ SND_SOC_DAPM_PGA_E("IN5R", MADERA_INPUT_ENABLES, MADERA_IN5R_ENA_SHIFT, SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 6, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 7, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 2, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 3, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 4, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 5, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 6, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 7, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF4RX1", NULL, 0, MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF4RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF4RX2", NULL, 1, MADERA_AIF4_RX_ENABLES, MADERA_AIF4RX2_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 1, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 2, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 3, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 4, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 5, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 6, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 7, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX8_ENA_SHIFT, 0), SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c index 108d28007185e82c9bbcce3d0aac2bd9dbb42373..6e34106c268f5d7bc7092005c6a6d4da5d661de3 100644 --- a/sound/soc/codecs/cs47l92.c +++ b/sound/soc/codecs/cs47l92.c @@ -790,70 +790,70 @@ SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 6, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 7, MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 2, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 3, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 4, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 5, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 6, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 7, MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 1, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 2, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 3, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 4, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 5, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 6, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, +SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 7, MADERA_SLIMBUS_TX_CHANNEL_ENABLE, MADERA_SLIMTX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX3", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX3", NULL, 2, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX4", NULL, 0, +SND_SOC_DAPM_AIF_OUT("AIF3TX4", NULL, 3, MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX4_ENA_SHIFT, 0), SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, @@ -948,62 +948,62 @@ SND_SOC_DAPM_PGA_E("IN4R", MADERA_INPUT_ENABLES, MADERA_IN4R_ENA_SHIFT, SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 6, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 7, MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 2, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 3, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 4, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 5, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 6, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 7, MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX8_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX3", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX3", NULL, 2, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX4", NULL, 0, +SND_SOC_DAPM_AIF_IN("AIF3RX4", NULL, 3, MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX4_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 1, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 2, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 3, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 4, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 5, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 6, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, +SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 7, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, MADERA_SLIMRX8_ENA_SHIFT, 0), SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index e172913d04a4a2b7d86aaafa046d30011a5e4539..3d05c37f676ebe7999d86c753ea797ef5e007e22 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -330,7 +330,7 @@ static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0]) { /* Check if noise suppression is enabled */ - if (snd_soc_component_read32(component, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) { + if (snd_soc_component_read(component, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) { dev_dbg(component->dev, "Disable noise suppression to enable ALC\n"); return -EINVAL; @@ -354,27 +354,27 @@ static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0]) { /* Check if ALC is enabled */ - if (snd_soc_component_read32(component, DA7210_ADC) & DA7210_ADC_ALC_EN) + if (snd_soc_component_read(component, DA7210_ADC) & DA7210_ADC_ALC_EN) goto err; /* Check ZC for HP and AUX1 PGA */ - if ((snd_soc_component_read32(component, DA7210_ZERO_CROSS) & + if ((snd_soc_component_read(component, DA7210_ZERO_CROSS) & (DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | DA7210_HP_R_ZC)) != (DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | DA7210_HP_R_ZC)) goto err; /* Check INPGA_L_VOL and INPGA_R_VOL */ - val = snd_soc_component_read32(component, DA7210_IN_GAIN); + val = snd_soc_component_read(component, DA7210_IN_GAIN); if (((val & DA7210_INPGA_L_VOL) < DA7210_INPGA_MIN_VOL_NS) || (((val & DA7210_INPGA_R_VOL) >> 4) < DA7210_INPGA_MIN_VOL_NS)) goto err; /* Check AUX1_L_VOL and AUX1_R_VOL */ - if (((snd_soc_component_read32(component, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) < + if (((snd_soc_component_read(component, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) < DA7210_AUX1_MIN_VOL_NS) || - ((snd_soc_component_read32(component, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) < + ((snd_soc_component_read(component, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) < DA7210_AUX1_MIN_VOL_NS)) goto err; } @@ -767,7 +767,7 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, /* Enable DAI */ snd_soc_component_write(component, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN); - dai_cfg1 = 0xFC & snd_soc_component_read32(component, DA7210_DAI_CFG1); + dai_cfg1 = 0xFC & snd_soc_component_read(component, DA7210_DAI_CFG1); switch (params_width(params)) { case 16: @@ -874,11 +874,11 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) u32 dai_cfg1; u32 dai_cfg3; - dai_cfg1 = 0x7f & snd_soc_component_read32(component, DA7210_DAI_CFG1); - dai_cfg3 = 0xfc & snd_soc_component_read32(component, DA7210_DAI_CFG3); + dai_cfg1 = 0x7f & snd_soc_component_read(component, DA7210_DAI_CFG1); + dai_cfg3 = 0xfc & snd_soc_component_read(component, DA7210_DAI_CFG3); - if ((snd_soc_component_read32(component, DA7210_PLL) & DA7210_PLL_EN) && - (!(snd_soc_component_read32(component, DA7210_PLL_DIV3) & DA7210_PLL_BYP))) + if ((snd_soc_component_read(component, DA7210_PLL) & DA7210_PLL_EN) && + (!(snd_soc_component_read(component, DA7210_PLL_DIV3) & DA7210_PLL_BYP))) return -EINVAL; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -924,10 +924,10 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) return 0; } -static int da7210_mute(struct snd_soc_dai *dai, int mute) +static int da7210_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u8 mute_reg = snd_soc_component_read32(component, DA7210_DAC_HPF) & 0xFB; + u8 mute_reg = snd_soc_component_read(component, DA7210_DAC_HPF) & 0xFB; if (mute) snd_soc_component_write(component, DA7210_DAC_HPF, mute_reg | 0x4); @@ -971,14 +971,16 @@ static int da7210_set_dai_sysclk(struct snd_soc_dai *codec_dai, /** * da7210_set_dai_pll :Configure the codec PLL - * @param codec_dai : pointer to codec DAI - * @param pll_id : da7210 has only one pll, so pll_id is always zero - * @param fref : MCLK frequency, should be < 20MHz - * @param fout : FsDM value, Refer page 44 & 45 of datasheet - * @return int : Zero for success, negative error code for error + * @codec_dai: pointer to codec DAI + * @pll_id: da7210 has only one pll, so pll_id is always zero + * @source: clock source + * @fref: MCLK frequency, should be < 20MHz + * @fout: FsDM value, Refer page 44 & 45 of datasheet * * Note: Supported PLL input frequencies are 12MHz, 13MHz, 13.5MHz, 14.4MHz, * 19.2MHz, 19.6MHz and 19.8MHz + * + * Return: Zero for success, negative error code for error */ static int da7210_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, int source, unsigned int fref, unsigned int fout) @@ -1034,7 +1036,8 @@ static const struct snd_soc_dai_ops da7210_dai_ops = { .set_fmt = da7210_set_dai_fmt, .set_sysclk = da7210_set_dai_sysclk, .set_pll = da7210_set_dai_pll, - .digital_mute = da7210_mute, + .mute_stream = da7210_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver da7210_dai = { diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 3e6ad996741bed9e6e7478bd27b4046a93ea6da3..72402467adcc629a8b1da53211c00c45e6ec68ae 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -205,12 +205,12 @@ static int da7213_get_alc_data(struct snd_soc_component *component, u8 reg_val) /* Select middle 8 bits for read back from data register */ snd_soc_component_write(component, DA7213_ALC_CIC_OP_LVL_CTRL, reg_val | DA7213_ALC_DATA_MIDDLE); - mid_data = snd_soc_component_read32(component, DA7213_ALC_CIC_OP_LVL_DATA); + mid_data = snd_soc_component_read(component, DA7213_ALC_CIC_OP_LVL_DATA); /* Select top 8 bits for read back from data register */ snd_soc_component_write(component, DA7213_ALC_CIC_OP_LVL_CTRL, reg_val | DA7213_ALC_DATA_TOP); - top_data = snd_soc_component_read32(component, DA7213_ALC_CIC_OP_LVL_DATA); + top_data = snd_soc_component_read(component, DA7213_ALC_CIC_OP_LVL_DATA); sum += ((mid_data << 8) | (top_data << 16)); } @@ -259,7 +259,7 @@ static void da7213_alc_calib_auto(struct snd_soc_component *component) snd_soc_component_update_bits(component, DA7213_ALC_CTRL1, DA7213_ALC_AUTO_CALIB_EN, DA7213_ALC_AUTO_CALIB_EN); do { - alc_ctrl1 = snd_soc_component_read32(component, DA7213_ALC_CTRL1); + alc_ctrl1 = snd_soc_component_read(component, DA7213_ALC_CTRL1); } while (alc_ctrl1 & DA7213_ALC_AUTO_CALIB_EN); /* If auto calibration fails, fall back to digital gain only mode */ @@ -286,16 +286,16 @@ static void da7213_alc_calib(struct snd_soc_component *component) u8 mic_1_ctrl, mic_2_ctrl; /* Save current values from ADC control registers */ - adc_l_ctrl = snd_soc_component_read32(component, DA7213_ADC_L_CTRL); - adc_r_ctrl = snd_soc_component_read32(component, DA7213_ADC_R_CTRL); + adc_l_ctrl = snd_soc_component_read(component, DA7213_ADC_L_CTRL); + adc_r_ctrl = snd_soc_component_read(component, DA7213_ADC_R_CTRL); /* Save current values from MIXIN_L/R_SELECT registers */ - mixin_l_sel = snd_soc_component_read32(component, DA7213_MIXIN_L_SELECT); - mixin_r_sel = snd_soc_component_read32(component, DA7213_MIXIN_R_SELECT); + mixin_l_sel = snd_soc_component_read(component, DA7213_MIXIN_L_SELECT); + mixin_r_sel = snd_soc_component_read(component, DA7213_MIXIN_R_SELECT); /* Save current values from MIC control registers */ - mic_1_ctrl = snd_soc_component_read32(component, DA7213_MIC_1_CTRL); - mic_2_ctrl = snd_soc_component_read32(component, DA7213_MIC_2_CTRL); + mic_1_ctrl = snd_soc_component_read(component, DA7213_MIC_1_CTRL); + mic_2_ctrl = snd_soc_component_read(component, DA7213_MIC_2_CTRL); /* Enable ADC Left and Right */ snd_soc_component_update_bits(component, DA7213_ADC_L_CTRL, DA7213_ADC_EN, @@ -751,7 +751,7 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, DA7213_PC_FREERUN_MASK, 0); /* If SRM not enabled then nothing more to do */ - pll_ctrl = snd_soc_component_read32(component, DA7213_PLL_CTRL); + pll_ctrl = snd_soc_component_read(component, DA7213_PLL_CTRL); if (!(pll_ctrl & DA7213_PLL_SRM_EN)) return 0; @@ -764,7 +764,7 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, /* Check SRM has locked */ do { - pll_status = snd_soc_component_read32(component, DA7213_PLL_STATUS); + pll_status = snd_soc_component_read(component, DA7213_PLL_STATUS); if (pll_status & DA7219_PLL_SRM_LOCK) { srm_lock = true; } else { @@ -779,7 +779,7 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, return 0; case SND_SOC_DAPM_POST_PMD: /* Revert 32KHz PLL lock udpates if applied previously */ - pll_ctrl = snd_soc_component_read32(component, DA7213_PLL_CTRL); + pll_ctrl = snd_soc_component_read(component, DA7213_PLL_CTRL); if (pll_ctrl & DA7213_PLL_32K_MODE) { snd_soc_component_write(component, 0xF0, 0x8B); snd_soc_component_write(component, 0xF2, 0x01); @@ -1156,6 +1156,7 @@ static int da7213_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; + struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); u8 dai_ctrl = 0; u8 fs; @@ -1181,33 +1182,43 @@ static int da7213_hw_params(struct snd_pcm_substream *substream, switch (params_rate(params)) { case 8000: fs = DA7213_SR_8000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; case 11025: fs = DA7213_SR_11025; + da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800; break; case 12000: fs = DA7213_SR_12000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; case 16000: fs = DA7213_SR_16000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; case 22050: fs = DA7213_SR_22050; + da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800; break; case 32000: fs = DA7213_SR_32000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; case 44100: fs = DA7213_SR_44100; + da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800; break; case 48000: fs = DA7213_SR_48000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; case 88200: fs = DA7213_SR_88200; + da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800; break; case 96000: fs = DA7213_SR_96000; + da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000; break; default: return -EINVAL; @@ -1321,7 +1332,7 @@ static int da7213_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static int da7213_mute(struct snd_soc_dai *dai, int mute) +static int da7213_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -1392,9 +1403,9 @@ static int da7213_set_component_sysclk(struct snd_soc_component *component, } /* Supported PLL input frequencies are 32KHz, 5MHz - 54MHz. */ -static int da7213_set_component_pll(struct snd_soc_component *component, - int pll_id, int source, - unsigned int fref, unsigned int fout) +static int _da7213_set_component_pll(struct snd_soc_component *component, + int pll_id, int source, + unsigned int fref, unsigned int fout) { struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); @@ -1503,11 +1514,22 @@ static int da7213_set_component_pll(struct snd_soc_component *component, return 0; } +static int da7213_set_component_pll(struct snd_soc_component *component, + int pll_id, int source, + unsigned int fref, unsigned int fout) +{ + struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); + da7213->fixed_clk_auto_pll = false; + + return _da7213_set_component_pll(component, pll_id, source, fref, fout); +} + /* DAI operations */ static const struct snd_soc_dai_ops da7213_dai_ops = { .hw_params = da7213_hw_params, .set_fmt = da7213_set_dai_fmt, - .digital_mute = da7213_mute, + .mute_stream = da7213_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver da7213_dai = { @@ -1532,6 +1554,50 @@ static struct snd_soc_dai_driver da7213_dai = { .symmetric_rates = 1, }; +static int da7213_set_auto_pll(struct snd_soc_component *component, bool enable) +{ + struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); + int mode; + + if (!da7213->fixed_clk_auto_pll) + return 0; + + da7213->mclk_rate = clk_get_rate(da7213->mclk); + + if (enable) { + /* Slave mode needs SRM for non-harmonic frequencies */ + if (da7213->master) + mode = DA7213_SYSCLK_PLL; + else + mode = DA7213_SYSCLK_PLL_SRM; + + /* PLL is not required for harmonic frequencies */ + switch (da7213->out_rate) { + case DA7213_PLL_FREQ_OUT_90316800: + if (da7213->mclk_rate == 11289600 || + da7213->mclk_rate == 22579200 || + da7213->mclk_rate == 45158400) + mode = DA7213_SYSCLK_MCLK; + break; + case DA7213_PLL_FREQ_OUT_98304000: + if (da7213->mclk_rate == 12288000 || + da7213->mclk_rate == 24576000 || + da7213->mclk_rate == 49152000) + mode = DA7213_SYSCLK_MCLK; + + break; + default: + return -1; + } + } else { + /* Disable PLL in standby */ + mode = DA7213_SYSCLK_MCLK; + } + + return _da7213_set_component_pll(component, 0, mode, + da7213->mclk_rate, da7213->out_rate); +} + static int da7213_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { @@ -1551,6 +1617,8 @@ static int da7213_set_bias_level(struct snd_soc_component *component, "Failed to enable mclk\n"); return ret; } + + da7213_set_auto_pll(component, true); } } break; @@ -1562,8 +1630,10 @@ static int da7213_set_bias_level(struct snd_soc_component *component, DA7213_VMID_EN | DA7213_BIAS_EN); } else { /* Remove MCLK */ - if (da7213->mclk) + if (da7213->mclk) { + da7213_set_auto_pll(component, false); clk_disable_unprepare(da7213->mclk); + } } break; case SND_SOC_BIAS_OFF: @@ -1693,7 +1763,6 @@ static struct da7213_platform_data return pdata; } - static int da7213_probe(struct snd_soc_component *component) { struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component); @@ -1829,6 +1898,11 @@ static int da7213_probe(struct snd_soc_component *component) return PTR_ERR(da7213->mclk); else da7213->mclk = NULL; + } else { + /* Do automatic PLL handling assuming fixed clock until + * set_pll() has been called. This makes the codec usable + * with the simple-audio-card driver. */ + da7213->fixed_clk_auto_pll = true; } return 0; diff --git a/sound/soc/codecs/da7213.h b/sound/soc/codecs/da7213.h index 3890829dfb6e1f0a73b12bf0084ebb7eb52ef09d..97ccf0ddd2be200d870dc1079e58bde02b583f3a 100644 --- a/sound/soc/codecs/da7213.h +++ b/sound/soc/codecs/da7213.h @@ -535,10 +535,12 @@ struct da7213_priv { struct regulator_bulk_data supplies[DA7213_NUM_SUPPLIES]; struct clk *mclk; unsigned int mclk_rate; + unsigned int out_rate; int clk_src; bool master; bool alc_calib_auto; bool alc_en; + bool fixed_clk_auto_pll; struct da7213_platform_data *pdata; }; diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index a3003f2998682f0e0704278cd19a5267d2d438b0..6d78bccb55c3588e6c5a8a0920dd21cb547a6df5 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -298,22 +298,22 @@ static void da7218_alc_calib(struct snd_soc_component *component) bool calibrated = false; /* Save current state of MIC control registers */ - mic_1_ctrl = snd_soc_component_read32(component, DA7218_MIC_1_CTRL); - mic_2_ctrl = snd_soc_component_read32(component, DA7218_MIC_2_CTRL); + mic_1_ctrl = snd_soc_component_read(component, DA7218_MIC_1_CTRL); + mic_2_ctrl = snd_soc_component_read(component, DA7218_MIC_2_CTRL); /* Save current state of input mixer control registers */ - mixin_1_ctrl = snd_soc_component_read32(component, DA7218_MIXIN_1_CTRL); - mixin_2_ctrl = snd_soc_component_read32(component, DA7218_MIXIN_2_CTRL); + mixin_1_ctrl = snd_soc_component_read(component, DA7218_MIXIN_1_CTRL); + mixin_2_ctrl = snd_soc_component_read(component, DA7218_MIXIN_2_CTRL); /* Save current state of input filter control registers */ - in_1l_filt_ctrl = snd_soc_component_read32(component, DA7218_IN_1L_FILTER_CTRL); - in_1r_filt_ctrl = snd_soc_component_read32(component, DA7218_IN_1R_FILTER_CTRL); - in_2l_filt_ctrl = snd_soc_component_read32(component, DA7218_IN_2L_FILTER_CTRL); - in_2r_filt_ctrl = snd_soc_component_read32(component, DA7218_IN_2R_FILTER_CTRL); + in_1l_filt_ctrl = snd_soc_component_read(component, DA7218_IN_1L_FILTER_CTRL); + in_1r_filt_ctrl = snd_soc_component_read(component, DA7218_IN_1R_FILTER_CTRL); + in_2l_filt_ctrl = snd_soc_component_read(component, DA7218_IN_2L_FILTER_CTRL); + in_2r_filt_ctrl = snd_soc_component_read(component, DA7218_IN_2R_FILTER_CTRL); /* Save current state of input HPF control registers */ - in_1_hpf_ctrl = snd_soc_component_read32(component, DA7218_IN_1_HPF_FILTER_CTRL); - in_2_hpf_ctrl = snd_soc_component_read32(component, DA7218_IN_2_HPF_FILTER_CTRL); + in_1_hpf_ctrl = snd_soc_component_read(component, DA7218_IN_1_HPF_FILTER_CTRL); + in_2_hpf_ctrl = snd_soc_component_read(component, DA7218_IN_2_HPF_FILTER_CTRL); /* Enable then Mute MIC PGAs */ snd_soc_component_update_bits(component, DA7218_MIC_1_CTRL, DA7218_MIC_1_AMP_EN_MASK, @@ -369,7 +369,7 @@ static void da7218_alc_calib(struct snd_soc_component *component) snd_soc_component_update_bits(component, DA7218_CALIB_CTRL, DA7218_CALIB_AUTO_EN_MASK, DA7218_CALIB_AUTO_EN_MASK); do { - calib_ctrl = snd_soc_component_read32(component, DA7218_CALIB_CTRL); + calib_ctrl = snd_soc_component_read(component, DA7218_CALIB_CTRL); if (calib_ctrl & DA7218_CALIB_AUTO_EN_MASK) { ++i; usleep_range(DA7218_ALC_CALIB_DELAY_MIN, @@ -613,7 +613,7 @@ static int da7218_biquad_coeff_put(struct snd_kcontrol *kcontrol, } /* Make sure at least out filter1 enabled to allow programming */ - out_filt1l = snd_soc_component_read32(component, DA7218_OUT_1L_FILTER_CTRL); + out_filt1l = snd_soc_component_read(component, DA7218_OUT_1L_FILTER_CTRL); snd_soc_component_write(component, DA7218_OUT_1L_FILTER_CTRL, out_filt1l | DA7218_OUT_1L_FILTER_EN_MASK); @@ -1419,7 +1419,7 @@ static int da7218_dai_event(struct snd_soc_dapm_widget *w, i = 0; success = false; do { - refosc_cal = snd_soc_component_read32(component, DA7218_PLL_REFOSC_CAL); + refosc_cal = snd_soc_component_read(component, DA7218_PLL_REFOSC_CAL); if (!(refosc_cal & DA7218_PLL_REFOSC_CAL_START_MASK)) { success = true; } else { @@ -1438,7 +1438,7 @@ static int da7218_dai_event(struct snd_soc_dapm_widget *w, DA7218_PC_RESYNC_AUTO_MASK); /* If SRM not enabled, we don't need to check status */ - pll_ctrl = snd_soc_component_read32(component, DA7218_PLL_CTRL); + pll_ctrl = snd_soc_component_read(component, DA7218_PLL_CTRL); if ((pll_ctrl & DA7218_PLL_MODE_MASK) != DA7218_PLL_MODE_SRM) return 0; @@ -1446,7 +1446,7 @@ static int da7218_dai_event(struct snd_soc_dapm_widget *w, i = 0; success = false; do { - pll_status = snd_soc_component_read32(component, DA7218_PLL_STATUS); + pll_status = snd_soc_component_read(component, DA7218_PLL_STATUS); if (pll_status & DA7218_PLL_SRM_STATUS_SRM_LOCK) { success = true; } else { @@ -2236,7 +2236,7 @@ static void da7218_hpldet_irq(struct snd_soc_component *component) u8 jack_status; int report; - jack_status = snd_soc_component_read32(component, DA7218_EVENT_STATUS); + jack_status = snd_soc_component_read(component, DA7218_EVENT_STATUS); if (jack_status & DA7218_HPLDET_JACK_STS_MASK) report = SND_JACK_HEADPHONE; @@ -2256,7 +2256,7 @@ static irqreturn_t da7218_irq_thread(int irq, void *data) u8 status; /* Read IRQ status reg */ - status = snd_soc_component_read32(component, DA7218_EVENT); + status = snd_soc_component_read(component, DA7218_EVENT); if (!status) return IRQ_NONE; diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index 4f2a96e9fd45badade06975bd38c5a7f8472ae4b..b1dfd91609f7c3eef48f312184303e963dbe8b6d 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -73,7 +73,7 @@ static void da7219_aad_btn_det_work(struct work_struct *work) snd_soc_dapm_sync(dapm); do { - statusa = snd_soc_component_read32(component, DA7219_ACCDET_STATUS_A); + statusa = snd_soc_component_read(component, DA7219_ACCDET_STATUS_A); if (statusa & DA7219_MICBIAS_UP_STS_MASK) micbias_up = true; else if (retries++ < DA7219_AAD_MICBIAS_CHK_RETRIES) @@ -91,7 +91,7 @@ static void da7219_aad_btn_det_work(struct work_struct *work) */ if (da7219_aad->micbias_pulse_lvl && da7219_aad->micbias_pulse_time) { /* Pulse higher level voltage */ - micbias_ctrl = snd_soc_component_read32(component, DA7219_MICBIAS_CTRL); + micbias_ctrl = snd_soc_component_read(component, DA7219_MICBIAS_CTRL); snd_soc_component_update_bits(component, DA7219_MICBIAS_CTRL, DA7219_MICBIAS1_LEVEL_MASK, da7219_aad->micbias_pulse_lvl); @@ -141,11 +141,11 @@ static void da7219_aad_hptest_work(struct work_struct *work) * If MCLK is present, but PLL is not enabled then we enable it here to * ensure a consistent detection procedure. */ - pll_srm_sts = snd_soc_component_read32(component, DA7219_PLL_SRM_STS); + pll_srm_sts = snd_soc_component_read(component, DA7219_PLL_SRM_STS); if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) { tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); - pll_ctrl = snd_soc_component_read32(component, DA7219_PLL_CTRL); + pll_ctrl = snd_soc_component_read(component, DA7219_PLL_CTRL); if ((pll_ctrl & DA7219_PLL_MODE_MASK) == DA7219_PLL_MODE_BYPASS) da7219_set_pll(component, DA7219_SYSCLK_PLL, DA7219_PLL_FREQ_OUT_98304); @@ -154,7 +154,7 @@ static void da7219_aad_hptest_work(struct work_struct *work) } /* Ensure gain ramping at fastest rate */ - gain_ramp_ctrl = snd_soc_component_read32(component, DA7219_GAIN_RAMP_CTRL); + gain_ramp_ctrl = snd_soc_component_read(component, DA7219_GAIN_RAMP_CTRL); snd_soc_component_write(component, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_X8); /* Bypass cache so it saves current settings */ @@ -248,7 +248,7 @@ static void da7219_aad_hptest_work(struct work_struct *work) msleep(DA7219_AAD_HPTEST_PERIOD); /* Grab comparator reading */ - accdet_cfg8 = snd_soc_component_read32(component, DA7219_ACCDET_CONFIG_8); + accdet_cfg8 = snd_soc_component_read(component, DA7219_ACCDET_CONFIG_8); if (accdet_cfg8 & DA7219_HPTEST_COMP_MASK) report |= SND_JACK_HEADPHONE; else @@ -357,7 +357,7 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) return IRQ_NONE; /* Read status register for jack insertion & type status */ - statusa = snd_soc_component_read32(component, DA7219_ACCDET_STATUS_A); + statusa = snd_soc_component_read(component, DA7219_ACCDET_STATUS_A); /* Clear events */ regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A, @@ -847,7 +847,7 @@ void da7219_aad_suspend(struct snd_soc_component *component) * suspend then this will be dealt with through the IRQ handler. */ if (da7219_aad->jack_inserted) { - micbias_ctrl = snd_soc_component_read32(component, DA7219_MICBIAS_CTRL); + micbias_ctrl = snd_soc_component_read(component, DA7219_MICBIAS_CTRL); if (micbias_ctrl & DA7219_MICBIAS1_EN_MASK) { snd_soc_dapm_disable_pin(dapm, "Mic Bias"); snd_soc_dapm_sync(dapm); diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index f83a6eaba12cb7180dbb6dce892aa77c2560317f..153ea30b5a8f85e3726744449bc224af608ae68a 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -313,13 +313,13 @@ static void da7219_alc_calib(struct snd_soc_component *component) u8 mic_ctrl, mixin_ctrl, adc_ctrl, calib_ctrl; /* Save current state of mic control register */ - mic_ctrl = snd_soc_component_read32(component, DA7219_MIC_1_CTRL); + mic_ctrl = snd_soc_component_read(component, DA7219_MIC_1_CTRL); /* Save current state of input mixer control register */ - mixin_ctrl = snd_soc_component_read32(component, DA7219_MIXIN_L_CTRL); + mixin_ctrl = snd_soc_component_read(component, DA7219_MIXIN_L_CTRL); /* Save current state of input ADC control register */ - adc_ctrl = snd_soc_component_read32(component, DA7219_ADC_L_CTRL); + adc_ctrl = snd_soc_component_read(component, DA7219_ADC_L_CTRL); /* Enable then Mute MIC PGAs */ snd_soc_component_update_bits(component, DA7219_MIC_1_CTRL, DA7219_MIC_1_AMP_EN_MASK, @@ -344,7 +344,7 @@ static void da7219_alc_calib(struct snd_soc_component *component) DA7219_ALC_AUTO_CALIB_EN_MASK, DA7219_ALC_AUTO_CALIB_EN_MASK); do { - calib_ctrl = snd_soc_component_read32(component, DA7219_ALC_CTRL1); + calib_ctrl = snd_soc_component_read(component, DA7219_ALC_CTRL1); } while (calib_ctrl & DA7219_ALC_AUTO_CALIB_EN_MASK); /* If auto calibration fails, disable DC offset, hybrid ALC */ @@ -822,13 +822,13 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w, DA7219_PC_FREERUN_MASK, 0); /* Slave mode, if SRM not enabled no need for status checks */ - pll_ctrl = snd_soc_component_read32(component, DA7219_PLL_CTRL); + pll_ctrl = snd_soc_component_read(component, DA7219_PLL_CTRL); if ((pll_ctrl & DA7219_PLL_MODE_MASK) != DA7219_PLL_MODE_SRM) return 0; /* Check SRM has locked */ do { - pll_status = snd_soc_component_read32(component, DA7219_PLL_SRM_STS); + pll_status = snd_soc_component_read(component, DA7219_PLL_SRM_STS); if (pll_status & DA7219_PLL_SRM_STS_SRM_LOCK) { srm_lock = true; } else { @@ -928,7 +928,7 @@ static int da7219_gain_ramp_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_PRE_PMD: /* Ensure nominal gain ramping for DAPM sequence */ da7219->gain_ramp_ctrl = - snd_soc_component_read32(component, DA7219_GAIN_RAMP_CTRL); + snd_soc_component_read(component, DA7219_GAIN_RAMP_CTRL); snd_soc_component_write(component, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_NOMINAL); break; @@ -1708,11 +1708,13 @@ static const struct of_device_id da7219_of_match[] = { }; MODULE_DEVICE_TABLE(of, da7219_of_match); +#ifdef CONFIG_ACPI static const struct acpi_device_id da7219_acpi_match[] = { { .id = "DLGS7219", }, { } }; MODULE_DEVICE_TABLE(acpi, da7219_acpi_match); +#endif static enum da7219_micbias_voltage da7219_fw_micbias_lvl(struct device *dev, u32 val) @@ -1930,7 +1932,7 @@ static int da7219_wclk_is_prepared(struct clk_hw *hw) if (!da7219->master) return -EINVAL; - clk_reg = snd_soc_component_read32(component, DA7219_DAI_CLK_MODE); + clk_reg = snd_soc_component_read(component, DA7219_DAI_CLK_MODE); return !!(clk_reg & DA7219_DAI_CLK_EN_MASK); } @@ -1942,7 +1944,7 @@ static unsigned long da7219_wclk_recalc_rate(struct clk_hw *hw, container_of(hw, struct da7219_priv, dai_clks_hw[DA7219_DAI_WCLK_IDX]); struct snd_soc_component *component = da7219->component; - u8 fs = snd_soc_component_read32(component, DA7219_SR); + u8 fs = snd_soc_component_read(component, DA7219_SR); switch (fs & DA7219_SR_MASK) { case DA7219_SR_8000: @@ -2027,7 +2029,7 @@ static unsigned long da7219_bclk_recalc_rate(struct clk_hw *hw, container_of(hw, struct da7219_priv, dai_clks_hw[DA7219_DAI_BCLK_IDX]); struct snd_soc_component *component = da7219->component; - u8 bclks_per_wclk = snd_soc_component_read32(component, + u8 bclks_per_wclk = snd_soc_component_read(component, DA7219_DAI_CLK_MODE); switch (bclks_per_wclk & DA7219_DAI_BCLKS_PER_WCLK_MASK) { diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 3f60c45e1e6dd99229742fc897db5276287bd9e6..d43ee7159ae0e3706bbe16303a01a2a0f155a298 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -361,7 +361,7 @@ static int da732x_hpf_get(struct snd_kcontrol *kcontrol, unsigned int reg = enum_ctrl->reg; int val; - val = snd_soc_component_read32(component, reg) & DA732X_HPF_MASK; + val = snd_soc_component_read(component, reg) & DA732X_HPF_MASK; switch (val) { case DA732X_HPF_VOICE_EN: @@ -1287,9 +1287,9 @@ static void da732x_dac_offset_adjust(struct snd_soc_component *component) msleep(DA732X_WAIT_FOR_STABILIZATION); /* Check DAC offset sign */ - sign[DA732X_HPL_DAC] = (snd_soc_component_read32(component, DA732X_REG_HPL_DAC_OFF_CNTL) & + sign[DA732X_HPL_DAC] = (snd_soc_component_read(component, DA732X_REG_HPL_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO); - sign[DA732X_HPR_DAC] = (snd_soc_component_read32(component, DA732X_REG_HPR_DAC_OFF_CNTL) & + sign[DA732X_HPR_DAC] = (snd_soc_component_read(component, DA732X_REG_HPR_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO); /* Binary search DAC offset values (both channels at once) */ @@ -1306,10 +1306,10 @@ static void da732x_dac_offset_adjust(struct snd_soc_component *component) msleep(DA732X_WAIT_FOR_STABILIZATION); - if ((snd_soc_component_read32(component, DA732X_REG_HPL_DAC_OFF_CNTL) & + if ((snd_soc_component_read(component, DA732X_REG_HPL_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC]) offset[DA732X_HPL_DAC] &= ~step; - if ((snd_soc_component_read32(component, DA732X_REG_HPR_DAC_OFF_CNTL) & + if ((snd_soc_component_read(component, DA732X_REG_HPR_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC]) offset[DA732X_HPR_DAC] &= ~step; @@ -1350,9 +1350,9 @@ static void da732x_output_offset_adjust(struct snd_soc_component *component) msleep(DA732X_WAIT_FOR_STABILIZATION); /* Check output offset sign */ - sign[DA732X_HPL_AMP] = snd_soc_component_read32(component, DA732X_REG_HPL) & + sign[DA732X_HPL_AMP] = snd_soc_component_read(component, DA732X_REG_HPL) & DA732X_HP_OUT_COMPO; - sign[DA732X_HPR_AMP] = snd_soc_component_read32(component, DA732X_REG_HPR) & + sign[DA732X_HPR_AMP] = snd_soc_component_read(component, DA732X_REG_HPR) & DA732X_HP_OUT_COMPO; snd_soc_component_write(component, DA732X_REG_HPL, DA732X_HP_OUT_COMP | @@ -1373,10 +1373,10 @@ static void da732x_output_offset_adjust(struct snd_soc_component *component) msleep(DA732X_WAIT_FOR_STABILIZATION); - if ((snd_soc_component_read32(component, DA732X_REG_HPL) & + if ((snd_soc_component_read(component, DA732X_REG_HPL) & DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP]) offset[DA732X_HPL_AMP] &= ~step; - if ((snd_soc_component_read32(component, DA732X_REG_HPR) & + if ((snd_soc_component_read(component, DA732X_REG_HPR) & DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP]) offset[DA732X_HPR_AMP] &= ~step; diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 94800f522d3e57cbaf5532d9f566fbc707e25316..b0d9ca6de685417b5d83a5531bd309ce9c337877 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -461,12 +461,12 @@ static int da9055_get_alc_data(struct snd_soc_component *component, u8 reg_val) /* Select middle 8 bits for read back from data register */ snd_soc_component_write(component, DA9055_ALC_CIC_OP_LVL_CTRL, reg_val | DA9055_ALC_DATA_MIDDLE); - mid_data = snd_soc_component_read32(component, DA9055_ALC_CIC_OP_LVL_DATA); + mid_data = snd_soc_component_read(component, DA9055_ALC_CIC_OP_LVL_DATA); /* Select top 8 bits for read back from data register */ snd_soc_component_write(component, DA9055_ALC_CIC_OP_LVL_CTRL, reg_val | DA9055_ALC_DATA_TOP); - top_data = snd_soc_component_read32(component, DA9055_ALC_CIC_OP_LVL_DATA); + top_data = snd_soc_component_read(component, DA9055_ALC_CIC_OP_LVL_DATA); sum += ((mid_data << 8) | (top_data << 16)); } @@ -488,8 +488,8 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, */ /* Save current values from Mic control registers */ - mic_left = snd_soc_component_read32(component, DA9055_MIC_L_CTRL); - mic_right = snd_soc_component_read32(component, DA9055_MIC_R_CTRL); + mic_left = snd_soc_component_read(component, DA9055_MIC_L_CTRL); + mic_right = snd_soc_component_read(component, DA9055_MIC_R_CTRL); /* Mute Mic PGA Left and Right */ snd_soc_component_update_bits(component, DA9055_MIC_L_CTRL, @@ -498,8 +498,8 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, DA9055_MIC_R_MUTE_EN, DA9055_MIC_R_MUTE_EN); /* Save current values from ADC control registers */ - adc_left = snd_soc_component_read32(component, DA9055_ADC_L_CTRL); - adc_right = snd_soc_component_read32(component, DA9055_ADC_R_CTRL); + adc_left = snd_soc_component_read(component, DA9055_ADC_L_CTRL); + adc_right = snd_soc_component_read(component, DA9055_ADC_R_CTRL); /* Enable ADC Left and Right */ snd_soc_component_update_bits(component, DA9055_ADC_L_CTRL, @@ -1176,7 +1176,7 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) } /* Don't allow change of mode if PLL is enabled */ - if ((snd_soc_component_read32(component, DA9055_PLL_CTRL) & DA9055_PLL_EN) && + if ((snd_soc_component_read(component, DA9055_PLL_CTRL) & DA9055_PLL_EN) && (da9055->master != mode)) return -EINVAL; @@ -1211,7 +1211,7 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static int da9055_mute(struct snd_soc_dai *dai, int mute) +static int da9055_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -1324,7 +1324,8 @@ static const struct snd_soc_dai_ops da9055_dai_ops = { .set_fmt = da9055_set_dai_fmt, .set_sysclk = da9055_set_dai_sysclk, .set_pll = da9055_set_dai_pll, - .digital_mute = da9055_mute, + .mute_stream = da9055_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver da9055_dai = { diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 36eef1fb3d181e31d630cfa57b6698e55cc8a5c3..bd5d230c5df2f4bdddf14adc75e59eafc20791fb 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -507,7 +507,7 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int es8316_mute(struct snd_soc_dai *dai, int mute) +static int es8316_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, ES8316_DAC_SET1, 0x20, mute ? 0x20 : 0); @@ -522,7 +522,8 @@ static const struct snd_soc_dai_ops es8316_ops = { .hw_params = es8316_pcm_hw_params, .set_fmt = es8316_set_dai_fmt, .set_sysclk = es8316_set_dai_sysclk, - .digital_mute = es8316_mute, + .mute_stream = es8316_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver es8316_dai = { @@ -839,11 +840,13 @@ static const struct of_device_id es8316_of_match[] = { }; MODULE_DEVICE_TABLE(of, es8316_of_match); +#ifdef CONFIG_ACPI static const struct acpi_device_id es8316_acpi_match[] = { {"ESSX8316", 0}, {}, }; MODULE_DEVICE_TABLE(acpi, es8316_acpi_match); +#endif static struct i2c_driver es8316_i2c_driver = { .driver = { diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index fdf64c29f563d03139aa1f071e1b1c5d2acf2b31..7e26231a596a415f9b78d5b7121fb5ec45fcd9b4 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -449,7 +449,7 @@ static const struct snd_soc_dapm_route es8328_dapm_routes[] = { { "ROUT2", NULL, "Right Out 2" }, }; -static int es8328_mute(struct snd_soc_dai *dai, int mute) +static int es8328_mute(struct snd_soc_dai *dai, int mute, int direction) { return snd_soc_component_update_bits(dai->component, ES8328_DACCONTROL3, ES8328_DACCONTROL3_DACMUTE, @@ -562,14 +562,14 @@ static int es8328_set_sysclk(struct snd_soc_dai *codec_dai, break; case 22579200: mclkdiv2 = 1; - /* fall through */ + fallthrough; case 11289600: es8328->sysclk_constraints = &constraints_11289; es8328->mclk_ratios = ratios_11289; break; case 24576000: mclkdiv2 = 1; - /* fall through */ + fallthrough; case 12288000: es8328->sysclk_constraints = &constraints_12288; es8328->mclk_ratios = ratios_12288; @@ -692,9 +692,10 @@ static int es8328_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops es8328_dai_ops = { .startup = es8328_startup, .hw_params = es8328_hw_params, - .digital_mute = es8328_mute, + .mute_stream = es8328_mute, .set_sysclk = es8328_set_sysclk, .set_fmt = es8328_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver es8328_dai = { diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index 473efe9ef998a71de37cc47b7593fd9a6be91c52..49e6f23fc76610aaa6a1bea74ac591079aa6b074 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -289,7 +289,6 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream, struct hdac_hda_priv *hda_pvt; struct hda_pcm_stream *hda_stream; struct hda_pcm *pcm; - int ret; hda_pvt = snd_soc_component_get_drvdata(component); pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai); @@ -300,11 +299,7 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream, hda_stream = &pcm->stream[substream->stream]; - ret = hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream); - if (ret < 0) - snd_hda_codec_pcm_put(pcm); - - return ret; + return hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream); } static void hdac_hda_dai_close(struct snd_pcm_substream *substream, @@ -467,7 +462,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) ret = snd_hda_codec_parse_pcms(hcodec); if (ret < 0) { dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret); - goto error_regmap; + goto error_patch; } /* HDMI controls need to be created in machine drivers */ @@ -476,7 +471,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) if (ret < 0) { dev_err(&hdev->dev, "unable to create controls %d\n", ret); - goto error_regmap; + goto error_patch; } } @@ -496,6 +491,9 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) return 0; +error_patch: + if (hcodec->patch_ops.free) + hcodec->patch_ops.free(hcodec); error_regmap: snd_hdac_regmap_exit(hdev); error_pm: @@ -510,6 +508,7 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component) struct hdac_hda_priv *hda_pvt = snd_soc_component_get_drvdata(component); struct hdac_device *hdev = &hda_pvt->codec.core; + struct hda_codec *codec = &hda_pvt->codec; struct hdac_ext_link *hlink = NULL; hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev)); @@ -521,7 +520,10 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component) pm_runtime_disable(&hdev->dev); snd_hdac_ext_bus_link_put(hdev->bus, hlink); - snd_hdac_regmap_exit(hdev); + if (codec->patch_ops.free) + codec->patch_ops.free(codec); + + snd_hda_codec_cleanup_for_unbind(codec); } static const struct snd_soc_dapm_route hdac_hda_dapm_routes[] = { @@ -605,12 +607,10 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev) static int hdac_hda_dev_remove(struct hdac_device *hdev) { - struct hdac_hda_priv *hda_pvt; - - hda_pvt = dev_get_drvdata(&hdev->dev); - if (hda_pvt && hda_pvt->codec.registered) - cancel_delayed_work_sync(&hda_pvt->codec.jackpoll_work); - + /* + * Resources are freed in hdac_hda_codec_remove(). This + * function is kept to keep hda_codec_driver_remove() happy. + */ return 0; } diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index f005751da2ccb39abd42adb029c0f5fa0e4e3eac..8c6f540533ba408bc13c02b58ab58227376628bc 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * ALSA SoC codec for HDMI encoder drivers - * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/ * Author: Jyri Sarha */ #include @@ -558,15 +558,24 @@ static int hdmi_codec_i2s_set_fmt(struct snd_soc_dai *dai, return 0; } -static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute) +static int hdmi_codec_mute(struct snd_soc_dai *dai, int mute, int direction) { struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); - if (hcp->hcd.ops->digital_mute) - return hcp->hcd.ops->digital_mute(dai->dev->parent, - hcp->hcd.data, mute); - - return 0; + /* + * ignore if direction was CAPTURE + * and it had .no_capture_mute flag + * see + * snd_soc_dai_digital_mute() + */ + if (hcp->hcd.ops->mute_stream && + (direction == SNDRV_PCM_STREAM_PLAYBACK || + !hcp->hcd.ops->no_capture_mute)) + return hcp->hcd.ops->mute_stream(dai->dev->parent, + hcp->hcd.data, + mute, direction); + + return -ENOTSUPP; } static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = { @@ -574,14 +583,14 @@ static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = { .shutdown = hdmi_codec_shutdown, .hw_params = hdmi_codec_hw_params, .set_fmt = hdmi_codec_i2s_set_fmt, - .digital_mute = hdmi_codec_digital_mute, + .mute_stream = hdmi_codec_mute, }; static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = { .startup = hdmi_codec_startup, .shutdown = hdmi_codec_shutdown, .hw_params = hdmi_codec_hw_params, - .digital_mute = hdmi_codec_digital_mute, + .mute_stream = hdmi_codec_mute, }; #define HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c index 14d8fe1c28a4337d2c6a696bf245d72e28053d6f..d0e8f0d2fbc18193d8c6914fbc385ad69c0309c8 100644 --- a/sound/soc/codecs/inno_rk3036.c +++ b/sound/soc/codecs/inno_rk3036.c @@ -48,11 +48,9 @@ static int rk3036_codec_antipop_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - int val, ret, regval; + int val, regval; - ret = snd_soc_component_read(component, INNO_R09, ®val); - if (ret) - return ret; + regval = snd_soc_component_read(component, INNO_R09); val = ((regval >> INNO_R09_HPL_ANITPOP_SHIFT) & INNO_R09_HP_ANTIPOP_MSK) == INNO_R09_HP_ANTIPOP_ON; ucontrol->value.integer.value[0] = val; diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 3626f70f77683673771061670fcf3fc5a1ac8faf..79afced75d76cb83b4835459b86358a090c3b4de 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -860,7 +860,7 @@ static const struct snd_soc_dapm_route isabelle_intercon[] = { { "LINEOUT2", NULL, "LINEOUT2 Driver" }, }; -static int isabelle_hs_mute(struct snd_soc_dai *dai, int mute) +static int isabelle_hs_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, ISABELLE_DAC1_SOFTRAMP_REG, BIT(4), (mute ? BIT(4) : 0)); @@ -868,7 +868,7 @@ static int isabelle_hs_mute(struct snd_soc_dai *dai, int mute) return 0; } -static int isabelle_hf_mute(struct snd_soc_dai *dai, int mute) +static int isabelle_hf_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, ISABELLE_DAC2_SOFTRAMP_REG, BIT(4), (mute ? BIT(4) : 0)); @@ -876,7 +876,7 @@ static int isabelle_hf_mute(struct snd_soc_dai *dai, int mute) return 0; } -static int isabelle_line_mute(struct snd_soc_dai *dai, int mute) +static int isabelle_line_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, ISABELLE_DAC3_SOFTRAMP_REG, BIT(4), (mute ? BIT(4) : 0)); @@ -1014,19 +1014,22 @@ static int isabelle_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) static const struct snd_soc_dai_ops isabelle_hs_dai_ops = { .hw_params = isabelle_hw_params, .set_fmt = isabelle_set_dai_fmt, - .digital_mute = isabelle_hs_mute, + .mute_stream = isabelle_hs_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops isabelle_hf_dai_ops = { .hw_params = isabelle_hw_params, .set_fmt = isabelle_set_dai_fmt, - .digital_mute = isabelle_hf_mute, + .mute_stream = isabelle_hf_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops isabelle_line_dai_ops = { .hw_params = isabelle_hw_params, .set_fmt = isabelle_set_dai_fmt, - .digital_mute = isabelle_line_mute, + .mute_stream = isabelle_line_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops isabelle_ul_dai_ops = { diff --git a/sound/soc/codecs/jz4770.c b/sound/soc/codecs/jz4770.c index 34775aa624024855a8ef66e90f85c5056e37785f..c0a28f06b09a7d845d67f2f4a6018952df375113 100644 --- a/sound/soc/codecs/jz4770.c +++ b/sound/soc/codecs/jz4770.c @@ -264,7 +264,7 @@ static int jz4770_codec_pcm_trigger(struct snd_pcm_substream *substream, return ret; } -static int jz4770_codec_digital_mute(struct snd_soc_dai *dai, int mute) +static int jz4770_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *codec = dai->component; struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec); @@ -303,7 +303,6 @@ static int jz4770_codec_digital_mute(struct snd_soc_dai *dai, int mute) static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0); static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0); static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600); -static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, 0, 400, 0); static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0); /* Unconditional controls. */ @@ -753,7 +752,8 @@ static const struct snd_soc_dai_ops jz4770_codec_dai_ops = { .shutdown = jz4770_codec_shutdown, .hw_params = jz4770_codec_hw_params, .trigger = jz4770_codec_pcm_trigger, - .digital_mute = jz4770_codec_digital_mute, + .mute_stream = jz4770_codec_mute_stream, + .no_capture_mute = 1, }; #define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index f864b07cb0b829e0f2f151d7442c88a3d40704df..06ab61f6f7199ccd58ce163021c4e521ca6b0eb2 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -1218,35 +1218,35 @@ static int lm49453_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, return 0; } -static int lm49453_hp_mute(struct snd_soc_dai *dai, int mute) +static int lm49453_hp_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, LM49453_P0_DAC_DSP_REG, BIT(1)|BIT(0), (mute ? (BIT(1)|BIT(0)) : 0)); return 0; } -static int lm49453_lo_mute(struct snd_soc_dai *dai, int mute) +static int lm49453_lo_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, LM49453_P0_DAC_DSP_REG, BIT(3)|BIT(2), (mute ? (BIT(3)|BIT(2)) : 0)); return 0; } -static int lm49453_ls_mute(struct snd_soc_dai *dai, int mute) +static int lm49453_ls_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, LM49453_P0_DAC_DSP_REG, BIT(5)|BIT(4), (mute ? (BIT(5)|BIT(4)) : 0)); return 0; } -static int lm49453_ep_mute(struct snd_soc_dai *dai, int mute) +static int lm49453_ep_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, LM49453_P0_DAC_DSP_REG, BIT(4), (mute ? BIT(4) : 0)); return 0; } -static int lm49453_ha_mute(struct snd_soc_dai *dai, int mute) +static int lm49453_ha_mute(struct snd_soc_dai *dai, int mute, int direction) { snd_soc_component_update_bits(dai->component, LM49453_P0_DAC_DSP_REG, BIT(7)|BIT(6), (mute ? (BIT(7)|BIT(6)) : 0)); @@ -1288,35 +1288,40 @@ static const struct snd_soc_dai_ops lm49453_headset_dai_ops = { .hw_params = lm49453_hw_params, .set_sysclk = lm49453_set_dai_sysclk, .set_fmt = lm49453_set_dai_fmt, - .digital_mute = lm49453_hp_mute, + .mute_stream = lm49453_hp_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops lm49453_speaker_dai_ops = { .hw_params = lm49453_hw_params, .set_sysclk = lm49453_set_dai_sysclk, .set_fmt = lm49453_set_dai_fmt, - .digital_mute = lm49453_ls_mute, + .mute_stream = lm49453_ls_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops lm49453_haptic_dai_ops = { .hw_params = lm49453_hw_params, .set_sysclk = lm49453_set_dai_sysclk, .set_fmt = lm49453_set_dai_fmt, - .digital_mute = lm49453_ha_mute, + .mute_stream = lm49453_ha_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops lm49453_ep_dai_ops = { .hw_params = lm49453_hw_params, .set_sysclk = lm49453_set_dai_sysclk, .set_fmt = lm49453_set_dai_fmt, - .digital_mute = lm49453_ep_mute, + .mute_stream = lm49453_ep_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops lm49453_lineout_dai_ops = { .hw_params = lm49453_hw_params, .set_sysclk = lm49453_set_dai_sysclk, .set_fmt = lm49453_set_dai_fmt, - .digital_mute = lm49453_lo_mute, + .mute_stream = lm49453_lo_mute, + .no_capture_mute = 1, }; /* LM49453 dai structure. */ diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index ec380b0b2d4e3c2f0d9583857c0bf4fabd2ff12f..680f31a6493a29d51a63158181cf17a308325bc3 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -628,12 +628,8 @@ int madera_out1_demux_get(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); unsigned int val; - int ret; - - ret = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1, &val); - if (ret) - return ret; + val = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1); val &= MADERA_EP_SEL_MASK; val >>= MADERA_EP_SEL_SHIFT; ucontrol->value.enumerated.item[0] = val; @@ -1068,12 +1064,7 @@ int madera_rate_put(struct snd_kcontrol *kcontrol, */ mutex_lock(&priv->rate_lock); - ret = snd_soc_component_read(component, e->reg, &val); - if (ret < 0) { - dev_warn(priv->madera->dev, "Failed to read 0x%x (%d)\n", - e->reg, ret); - goto out; - } + val = snd_soc_component_read(component, e->reg); val >>= e->shift_l; val &= e->mask; if (snd_soc_enum_item_to_val(e, item) == val) { @@ -2178,10 +2169,7 @@ int madera_dfc_put(struct snd_kcontrol *kcontrol, snd_soc_dapm_mutex_lock(dapm); - ret = snd_soc_component_read(component, reg, &val); - if (ret) - goto exit; - + val = snd_soc_component_read(component, reg); if (val & MADERA_DFC1_ENA) { ret = -EBUSY; dev_err(component->dev, "Can't change mode on an active DFC\n"); @@ -2211,9 +2199,7 @@ int madera_lp_mode_put(struct snd_kcontrol *kcontrol, snd_soc_dapm_mutex_lock(dapm); /* Cannot change lp mode on an active input */ - ret = snd_soc_component_read(component, MADERA_INPUT_ENABLES, &val); - if (ret) - goto exit; + val = snd_soc_component_read(component, MADERA_INPUT_ENABLES); mask = (mc->reg - MADERA_ADC_DIGITAL_VOLUME_1L) / 4; mask ^= 0x1; /* Flip bottom bit for channel order */ @@ -2276,7 +2262,6 @@ int madera_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct madera_priv *priv = snd_soc_component_get_drvdata(component); unsigned int reg, val; - int ret; if (w->shift % 2) reg = MADERA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8); @@ -2305,9 +2290,8 @@ int madera_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, break; case SND_SOC_DAPM_POST_PMD: /* Disable volume updates if no inputs are enabled */ - ret = snd_soc_component_read(component, MADERA_INPUT_ENABLES, - &val); - if (!ret && !val) + val = snd_soc_component_read(component, MADERA_INPUT_ENABLES); + if (!val) madera_in_set_vu(priv, false); break; default: @@ -3087,26 +3071,16 @@ static int madera_aif_cfg_changed(struct snd_soc_component *component, int base, int bclk, int lrclk, int frame) { unsigned int val; - int ret; - ret = snd_soc_component_read(component, base + MADERA_AIF_BCLK_CTRL, - &val); - if (ret) - return ret; + val = snd_soc_component_read(component, base + MADERA_AIF_BCLK_CTRL); if (bclk != (val & MADERA_AIF1_BCLK_FREQ_MASK)) return 1; - ret = snd_soc_component_read(component, base + MADERA_AIF_RX_BCLK_RATE, - &val); - if (ret) - return ret; + val = snd_soc_component_read(component, base + MADERA_AIF_RX_BCLK_RATE); if (lrclk != (val & MADERA_AIF1RX_BCPF_MASK)) return 1; - ret = snd_soc_component_read(component, base + MADERA_AIF_FRAME_CTRL_1, - &val); - if (ret) - return ret; + val = snd_soc_component_read(component, base + MADERA_AIF_FRAME_CTRL_1); if (frame != (val & (MADERA_AIF1TX_WL_MASK | MADERA_AIF1TX_SLOT_LEN_MASK))) return 1; @@ -3162,10 +3136,7 @@ static int madera_hw_params(struct snd_pcm_substream *substream, } /* Force multiple of 2 channels for I2S mode */ - ret = snd_soc_component_read(component, base + MADERA_AIF_FORMAT, &val); - if (ret) - return ret; - + val = snd_soc_component_read(component, base + MADERA_AIF_FORMAT); val &= MADERA_AIF1_FMT_MASK; if ((channels & 1) && val == MADERA_FMT_I2S_MODE) { madera_aif_dbg(dai, "Forcing stereo mode\n"); diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index f031d2caa8b774d542ce4249e94a14342ee2a418..4be24e7f51c89e41a979a9ee14c4f23fc1ba1ab3 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -996,7 +996,7 @@ static int max98088_dai1_hw_params(struct snd_pcm_substream *substream, cdata->rate = rate; /* Configure NI when operating as master */ - if (snd_soc_component_read32(component, M98088_REG_14_DAI1_FORMAT) + if (snd_soc_component_read(component, M98088_REG_14_DAI1_FORMAT) & M98088_DAI_MAS) { if (max98088->sysclk == 0) { dev_err(component->dev, "Invalid system clock frequency\n"); @@ -1063,7 +1063,7 @@ static int max98088_dai2_hw_params(struct snd_pcm_substream *substream, cdata->rate = rate; /* Configure NI when operating as master */ - if (snd_soc_component_read32(component, M98088_REG_1C_DAI2_FORMAT) + if (snd_soc_component_read(component, M98088_REG_1C_DAI2_FORMAT) & M98088_DAI_MAS) { if (max98088->sysclk == 0) { dev_err(component->dev, "Invalid system clock frequency\n"); @@ -1120,7 +1120,7 @@ static int max98088_dai_set_sysclk(struct snd_soc_dai *dai, return -EINVAL; } - if (snd_soc_component_read32(component, M98088_REG_51_PWR_SYS) & M98088_SHDNRUN) { + if (snd_soc_component_read(component, M98088_REG_51_PWR_SYS) & M98088_SHDNRUN) { snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0); snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, @@ -1274,7 +1274,8 @@ static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int max98088_dai1_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int max98088_dai1_mute(struct snd_soc_dai *codec_dai, int mute, + int direction) { struct snd_soc_component *component = codec_dai->component; int reg; @@ -1289,7 +1290,8 @@ static int max98088_dai1_digital_mute(struct snd_soc_dai *codec_dai, int mute) return 0; } -static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int max98088_dai2_mute(struct snd_soc_dai *codec_dai, int mute, + int direction) { struct snd_soc_component *component = codec_dai->component; int reg; @@ -1354,14 +1356,16 @@ static const struct snd_soc_dai_ops max98088_dai1_ops = { .set_sysclk = max98088_dai_set_sysclk, .set_fmt = max98088_dai1_set_fmt, .hw_params = max98088_dai1_hw_params, - .digital_mute = max98088_dai1_digital_mute, + .mute_stream = max98088_dai1_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops max98088_dai2_ops = { .set_sysclk = max98088_dai_set_sysclk, .set_fmt = max98088_dai2_set_fmt, .hw_params = max98088_dai2_hw_params, - .digital_mute = max98088_dai2_digital_mute, + .mute_stream = max98088_dai2_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver max98088_dai[] = { @@ -1440,7 +1444,7 @@ static void max98088_setup_eq1(struct snd_soc_component *component) pdata->eq_cfg[best].rate, fs); /* Disable EQ while configuring, and save current on/off state */ - save = snd_soc_component_read32(component, M98088_REG_49_CFG_LEVEL); + save = snd_soc_component_read(component, M98088_REG_49_CFG_LEVEL); snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, 0); coef_set = &pdata->eq_cfg[sel]; @@ -1487,7 +1491,7 @@ static void max98088_setup_eq2(struct snd_soc_component *component) pdata->eq_cfg[best].rate, fs); /* Disable EQ while configuring, and save current on/off state */ - save = snd_soc_component_read32(component, M98088_REG_49_CFG_LEVEL); + save = snd_soc_component_read(component, M98088_REG_49_CFG_LEVEL); snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, 0); coef_set = &pdata->eq_cfg[sel]; @@ -1673,7 +1677,7 @@ static int max98088_probe(struct snd_soc_component *component) max98088->mic1pre = 0; max98088->mic2pre = 0; - ret = snd_soc_component_read32(component, M98088_REG_FF_REV_ID); + ret = snd_soc_component_read(component, M98088_REG_FF_REV_ID); if (ret < 0) { dev_err(component->dev, "Failed to read device revision: %d\n", ret); diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index e2cc1ad8cb0ab92c598072a83b7a77616567a70d..945a79e4f3eb461d5b5d0246cb3ca71d939d8714 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -353,7 +353,7 @@ static int max98090_get_enab_tlv(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; unsigned int mask = (1 << fls(mc->max)) - 1; - unsigned int val = snd_soc_component_read32(component, mc->reg); + unsigned int val = snd_soc_component_read(component, mc->reg); unsigned int *select; switch (mc->reg) { @@ -394,7 +394,7 @@ static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; unsigned int mask = (1 << fls(mc->max)) - 1; unsigned int sel = ucontrol->value.integer.value[0]; - unsigned int val = snd_soc_component_read32(component, mc->reg); + unsigned int val = snd_soc_component_read(component, mc->reg); unsigned int *select; switch (mc->reg) { @@ -730,7 +730,7 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component); - unsigned int val = snd_soc_component_read32(component, w->reg); + unsigned int val = snd_soc_component_read(component, w->reg); if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) val = (val & M98090_MIC_PA1EN_MASK) >> M98090_MIC_PA1EN_SHIFT; @@ -1496,7 +1496,7 @@ static void max98090_configure_bclk(struct snd_soc_component *component) } /* Skip configuration when operating as slave */ - if (!(snd_soc_component_read32(component, M98090_REG_MASTER_MODE) & + if (!(snd_soc_component_read(component, M98090_REG_MASTER_MODE) & M98090_MAS_MASK)) { return; } @@ -2017,7 +2017,8 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai, return 0; } -static int max98090_dai_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int max98090_dai_mute(struct snd_soc_dai *codec_dai, int mute, + int direction) { struct snd_soc_component *component = codec_dai->component; int regval; @@ -2132,7 +2133,7 @@ static void max98090_pll_work(struct max98090_priv *max98090) usleep_range(1000, 1200); /* Check lock status */ - pll = snd_soc_component_read32( + pll = snd_soc_component_read( component, M98090_REG_DEVICE_STATUS); if (!(pll & M98090_ULK_MASK)) break; @@ -2157,16 +2158,16 @@ static void max98090_jack_work(struct work_struct *work) msleep(50); - reg = snd_soc_component_read32(component, M98090_REG_JACK_STATUS); + reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS); /* Weak pull up allows only insertion detection */ snd_soc_component_update_bits(component, M98090_REG_JACK_DETECT, M98090_JDWK_MASK, M98090_JDWK_MASK); } else { - reg = snd_soc_component_read32(component, M98090_REG_JACK_STATUS); + reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS); } - reg = snd_soc_component_read32(component, M98090_REG_JACK_STATUS); + reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS); switch (reg & (M98090_LSNS_MASK | M98090_JKSNS_MASK)) { case M98090_LSNS_MASK | M98090_JKSNS_MASK: @@ -2347,8 +2348,9 @@ static const struct snd_soc_dai_ops max98090_dai_ops = { .set_fmt = max98090_dai_set_fmt, .set_tdm_slot = max98090_set_tdm_slot, .hw_params = max98090_dai_hw_params, - .digital_mute = max98090_dai_digital_mute, + .mute_stream = max98090_dai_mute, .trigger = max98090_dai_trigger, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver max98090_dai[] = { @@ -2406,7 +2408,7 @@ static int max98090_probe(struct snd_soc_component *component) max98090->pa1en = 0; max98090->pa2en = 0; - ret = snd_soc_component_read32(component, M98090_REG_REVISION_ID); + ret = snd_soc_component_read(component, M98090_REG_REVISION_ID); if (ret < 0) { dev_err(component->dev, "Failed to read device revision: %d\n", ret); @@ -2446,7 +2448,7 @@ static int max98090_probe(struct snd_soc_component *component) * An old interrupt ocurring prior to installing the ISR * can keep a new interrupt from generating a trigger. */ - snd_soc_component_read32(component, M98090_REG_DEVICE_STATUS); + snd_soc_component_read(component, M98090_REG_DEVICE_STATUS); /* High Performance is default */ snd_soc_component_update_bits(component, M98090_REG_DAC_CONTROL, diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index c7e0a55f3dc243d65905cd861278320bc081ab4c..9bdc6392382a6bd3f561a0ad9a037e39aa114270 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -971,7 +971,7 @@ static int max98095_dai1_hw_params(struct snd_pcm_substream *substream, cdata->rate = rate; /* Configure NI when operating as master */ - if (snd_soc_component_read32(component, M98095_02A_DAI1_FORMAT) & M98095_DAI_MAS) { + if (snd_soc_component_read(component, M98095_02A_DAI1_FORMAT) & M98095_DAI_MAS) { if (max98095->sysclk == 0) { dev_err(component->dev, "Invalid system clock frequency\n"); return -EINVAL; @@ -1032,7 +1032,7 @@ static int max98095_dai2_hw_params(struct snd_pcm_substream *substream, cdata->rate = rate; /* Configure NI when operating as master */ - if (snd_soc_component_read32(component, M98095_034_DAI2_FORMAT) & M98095_DAI_MAS) { + if (snd_soc_component_read(component, M98095_034_DAI2_FORMAT) & M98095_DAI_MAS) { if (max98095->sysclk == 0) { dev_err(component->dev, "Invalid system clock frequency\n"); return -EINVAL; @@ -1093,7 +1093,7 @@ static int max98095_dai3_hw_params(struct snd_pcm_substream *substream, cdata->rate = rate; /* Configure NI when operating as master */ - if (snd_soc_component_read32(component, M98095_03E_DAI3_FORMAT) & M98095_DAI_MAS) { + if (snd_soc_component_read(component, M98095_03E_DAI3_FORMAT) & M98095_DAI_MAS) { if (max98095->sysclk == 0) { dev_err(component->dev, "Invalid system clock frequency\n"); return -EINVAL; @@ -1534,7 +1534,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol, regmask = (channel == 0) ? M98095_EQ1EN : M98095_EQ2EN; /* Disable filter while configuring, and save current on/off state */ - regsave = snd_soc_component_read32(component, M98095_088_CFG_LEVEL); + regsave = snd_soc_component_read(component, M98095_088_CFG_LEVEL); snd_soc_component_update_bits(component, M98095_088_CFG_LEVEL, regmask, 0); mutex_lock(&max98095->lock); @@ -1685,7 +1685,7 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol, regmask = (channel == 0) ? M98095_BQ1EN : M98095_BQ2EN; /* Disable filter while configuring, and save current on/off state */ - regsave = snd_soc_component_read32(component, M98095_088_CFG_LEVEL); + regsave = snd_soc_component_read(component, M98095_088_CFG_LEVEL); snd_soc_component_update_bits(component, M98095_088_CFG_LEVEL, regmask, 0); mutex_lock(&max98095->lock); @@ -1816,7 +1816,7 @@ static irqreturn_t max98095_report_jack(int irq, void *data) int mic_report = 0; /* Read the Jack Status Register */ - value = snd_soc_component_read32(component, M98095_007_JACK_AUTO_STS); + value = snd_soc_component_read(component, M98095_007_JACK_AUTO_STS); /* If ddone is not set, then detection isn't finished yet */ if ((value & M98095_DDONE) == 0) @@ -1972,7 +1972,7 @@ static int max98095_reset(struct snd_soc_component *component) /* Reset to hardware default for registers, as there is not * a soft reset hardware control register */ for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) { - ret = snd_soc_component_write(component, i, snd_soc_component_read32(component, i)); + ret = snd_soc_component_write(component, i, snd_soc_component_read(component, i)); if (ret < 0) { dev_err(component->dev, "Failed to reset: %d\n", ret); return ret; @@ -2038,7 +2038,7 @@ static int max98095_probe(struct snd_soc_component *component) } } - ret = snd_soc_component_read32(component, M98095_0FF_REV_ID); + ret = snd_soc_component_read(component, M98095_0FF_REV_ID); if (ret < 0) { dev_err(component->dev, "Failure reading hardware revision: %d\n", ret); diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index a8bd793a78674f73423b29831ac54204f6d95359..918812763884861252d433f2094c59560f29df1c 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c @@ -23,36 +23,61 @@ struct max98357a_priv { struct gpio_desc *sdmode; unsigned int sdmode_delay; + int sdmode_switch; }; -static int max98357a_sdmode_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) +static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) { - struct snd_soc_component *component = - snd_soc_dapm_to_component(w->dapm); + struct snd_soc_component *component = dai->component; struct max98357a_priv *max98357a = snd_soc_component_get_drvdata(component); if (!max98357a->sdmode) return 0; - if (event & SND_SOC_DAPM_POST_PMU) { - msleep(max98357a->sdmode_delay); - gpiod_set_value(max98357a->sdmode, 1); - dev_dbg(component->dev, "set sdmode to 1"); - } else if (event & SND_SOC_DAPM_PRE_PMD) { + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + mdelay(max98357a->sdmode_delay); + if (max98357a->sdmode_switch) { + gpiod_set_value(max98357a->sdmode, 1); + dev_dbg(component->dev, "set sdmode to 1"); + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: gpiod_set_value(max98357a->sdmode, 0); dev_dbg(component->dev, "set sdmode to 0"); + break; } return 0; } +static int max98357a_sdmode_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct max98357a_priv *max98357a = + snd_soc_component_get_drvdata(component); + + if (event & SND_SOC_DAPM_POST_PMU) + max98357a->sdmode_switch = 1; + else if (event & SND_SOC_DAPM_POST_PMD) + max98357a->sdmode_switch = 0; + + return 0; +} + static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("Speaker"), SND_SOC_DAPM_OUT_DRV_E("SD_MODE", SND_SOC_NOPM, 0, 0, NULL, 0, max98357a_sdmode_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), }; static const struct snd_soc_dapm_route max98357a_dapm_routes[] = { @@ -71,6 +96,10 @@ static const struct snd_soc_component_driver max98357a_component_driver = { .non_legacy_dai_naming = 1, }; +static const struct snd_soc_dai_ops max98357a_dai_ops = { + .trigger = max98357a_daiops_trigger, +}; + static struct snd_soc_dai_driver max98357a_dai_driver = { .name = "HiFi", .playback = { @@ -90,6 +119,7 @@ static struct snd_soc_dai_driver max98357a_dai_driver = { .channels_min = 1, .channels_max = 2, }, + .ops = &max98357a_dai_ops, }; static int max98357a_platform_probe(struct platform_device *pdev) @@ -125,6 +155,7 @@ static int max98357a_platform_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id max98357a_device_id[] = { { .compatible = "maxim,max98357a" }, + { .compatible = "maxim,max98360a" }, {} }; MODULE_DEVICE_TABLE(of, max98357a_device_id); diff --git a/sound/soc/codecs/max98373-i2c.c b/sound/soc/codecs/max98373-i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..92921e34f9486708242b60d6dfd02828c3c8f834 --- /dev/null +++ b/sound/soc/codecs/max98373-i2c.c @@ -0,0 +1,612 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2017, Maxim Integrated + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "max98373.h" + +static struct reg_default max98373_reg[] = { + {MAX98373_R2000_SW_RESET, 0x00}, + {MAX98373_R2001_INT_RAW1, 0x00}, + {MAX98373_R2002_INT_RAW2, 0x00}, + {MAX98373_R2003_INT_RAW3, 0x00}, + {MAX98373_R2004_INT_STATE1, 0x00}, + {MAX98373_R2005_INT_STATE2, 0x00}, + {MAX98373_R2006_INT_STATE3, 0x00}, + {MAX98373_R2007_INT_FLAG1, 0x00}, + {MAX98373_R2008_INT_FLAG2, 0x00}, + {MAX98373_R2009_INT_FLAG3, 0x00}, + {MAX98373_R200A_INT_EN1, 0x00}, + {MAX98373_R200B_INT_EN2, 0x00}, + {MAX98373_R200C_INT_EN3, 0x00}, + {MAX98373_R200D_INT_FLAG_CLR1, 0x00}, + {MAX98373_R200E_INT_FLAG_CLR2, 0x00}, + {MAX98373_R200F_INT_FLAG_CLR3, 0x00}, + {MAX98373_R2010_IRQ_CTRL, 0x00}, + {MAX98373_R2014_THERM_WARN_THRESH, 0x10}, + {MAX98373_R2015_THERM_SHDN_THRESH, 0x27}, + {MAX98373_R2016_THERM_HYSTERESIS, 0x01}, + {MAX98373_R2017_THERM_FOLDBACK_SET, 0xC0}, + {MAX98373_R2018_THERM_FOLDBACK_EN, 0x00}, + {MAX98373_R201E_PIN_DRIVE_STRENGTH, 0x55}, + {MAX98373_R2020_PCM_TX_HIZ_EN_1, 0xFE}, + {MAX98373_R2021_PCM_TX_HIZ_EN_2, 0xFF}, + {MAX98373_R2022_PCM_TX_SRC_1, 0x00}, + {MAX98373_R2023_PCM_TX_SRC_2, 0x00}, + {MAX98373_R2024_PCM_DATA_FMT_CFG, 0xC0}, + {MAX98373_R2025_AUDIO_IF_MODE, 0x00}, + {MAX98373_R2026_PCM_CLOCK_RATIO, 0x04}, + {MAX98373_R2027_PCM_SR_SETUP_1, 0x08}, + {MAX98373_R2028_PCM_SR_SETUP_2, 0x88}, + {MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 0x00}, + {MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 0x00}, + {MAX98373_R202B_PCM_RX_EN, 0x00}, + {MAX98373_R202C_PCM_TX_EN, 0x00}, + {MAX98373_R202E_ICC_RX_CH_EN_1, 0x00}, + {MAX98373_R202F_ICC_RX_CH_EN_2, 0x00}, + {MAX98373_R2030_ICC_TX_HIZ_EN_1, 0xFF}, + {MAX98373_R2031_ICC_TX_HIZ_EN_2, 0xFF}, + {MAX98373_R2032_ICC_LINK_EN_CFG, 0x30}, + {MAX98373_R2034_ICC_TX_CNTL, 0x00}, + {MAX98373_R2035_ICC_TX_EN, 0x00}, + {MAX98373_R2036_SOUNDWIRE_CTRL, 0x05}, + {MAX98373_R203D_AMP_DIG_VOL_CTRL, 0x00}, + {MAX98373_R203E_AMP_PATH_GAIN, 0x08}, + {MAX98373_R203F_AMP_DSP_CFG, 0x02}, + {MAX98373_R2040_TONE_GEN_CFG, 0x00}, + {MAX98373_R2041_AMP_CFG, 0x03}, + {MAX98373_R2042_AMP_EDGE_RATE_CFG, 0x00}, + {MAX98373_R2043_AMP_EN, 0x00}, + {MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 0x04}, + {MAX98373_R2047_IV_SENSE_ADC_EN, 0x00}, + {MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0x00}, + {MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0x00}, + {MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 0x00}, + {MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0x00}, + {MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0x00}, + {MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0x00}, + {MAX98373_R2090_BDE_LVL_HOLD, 0x00}, + {MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0x00}, + {MAX98373_R2092_BDE_CLIPPER_MODE, 0x00}, + {MAX98373_R2097_BDE_L1_THRESH, 0x00}, + {MAX98373_R2098_BDE_L2_THRESH, 0x00}, + {MAX98373_R2099_BDE_L3_THRESH, 0x00}, + {MAX98373_R209A_BDE_L4_THRESH, 0x00}, + {MAX98373_R209B_BDE_THRESH_HYST, 0x00}, + {MAX98373_R20A8_BDE_L1_CFG_1, 0x00}, + {MAX98373_R20A9_BDE_L1_CFG_2, 0x00}, + {MAX98373_R20AA_BDE_L1_CFG_3, 0x00}, + {MAX98373_R20AB_BDE_L2_CFG_1, 0x00}, + {MAX98373_R20AC_BDE_L2_CFG_2, 0x00}, + {MAX98373_R20AD_BDE_L2_CFG_3, 0x00}, + {MAX98373_R20AE_BDE_L3_CFG_1, 0x00}, + {MAX98373_R20AF_BDE_L3_CFG_2, 0x00}, + {MAX98373_R20B0_BDE_L3_CFG_3, 0x00}, + {MAX98373_R20B1_BDE_L4_CFG_1, 0x00}, + {MAX98373_R20B2_BDE_L4_CFG_2, 0x00}, + {MAX98373_R20B3_BDE_L4_CFG_3, 0x00}, + {MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE, 0x00}, + {MAX98373_R20B5_BDE_EN, 0x00}, + {MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0x00}, + {MAX98373_R20D1_DHT_CFG, 0x01}, + {MAX98373_R20D2_DHT_ATTACK_CFG, 0x02}, + {MAX98373_R20D3_DHT_RELEASE_CFG, 0x03}, + {MAX98373_R20D4_DHT_EN, 0x00}, + {MAX98373_R20E0_LIMITER_THRESH_CFG, 0x00}, + {MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0x00}, + {MAX98373_R20E2_LIMITER_EN, 0x00}, + {MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, 0x00}, + {MAX98373_R20FF_GLOBAL_SHDN, 0x00}, + {MAX98373_R21FF_REV_ID, 0x42}, +}; + +static int max98373_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + struct snd_soc_component *component = codec_dai->component; + struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); + unsigned int format = 0; + unsigned int invert = 0; + + dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt); + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + invert = MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE; + break; + default: + dev_err(component->dev, "DAI invert mode unsupported\n"); + return -EINVAL; + } + + regmap_update_bits(max98373->regmap, + MAX98373_R2026_PCM_CLOCK_RATIO, + MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE, + invert); + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + format = MAX98373_PCM_FORMAT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + format = MAX98373_PCM_FORMAT_LJ; + break; + case SND_SOC_DAIFMT_DSP_A: + format = MAX98373_PCM_FORMAT_TDM_MODE1; + break; + case SND_SOC_DAIFMT_DSP_B: + format = MAX98373_PCM_FORMAT_TDM_MODE0; + break; + default: + return -EINVAL; + } + + regmap_update_bits(max98373->regmap, + MAX98373_R2024_PCM_DATA_FMT_CFG, + MAX98373_PCM_MODE_CFG_FORMAT_MASK, + format << MAX98373_PCM_MODE_CFG_FORMAT_SHIFT); + + return 0; +} + +/* BCLKs per LRCLK */ +static const int bclk_sel_table[] = { + 32, 48, 64, 96, 128, 192, 256, 384, 512, 320, +}; + +static int max98373_get_bclk_sel(int bclk) +{ + int i; + /* match BCLKs per LRCLK */ + for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { + if (bclk_sel_table[i] == bclk) + return i + 2; + } + return 0; +} + +static int max98373_set_clock(struct snd_soc_component *component, + struct snd_pcm_hw_params *params) +{ + struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); + /* BCLK/LRCLK ratio calculation */ + int blr_clk_ratio = params_channels(params) * max98373->ch_size; + int value; + + if (!max98373->tdm_mode) { + /* BCLK configuration */ + value = max98373_get_bclk_sel(blr_clk_ratio); + if (!value) { + dev_err(component->dev, "format unsupported %d\n", + params_format(params)); + return -EINVAL; + } + + regmap_update_bits(max98373->regmap, + MAX98373_R2026_PCM_CLOCK_RATIO, + MAX98373_PCM_CLK_SETUP_BSEL_MASK, + value); + } + return 0; +} + +static int max98373_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); + unsigned int sampling_rate = 0; + unsigned int chan_sz = 0; + + /* pcm mode configuration */ + switch (snd_pcm_format_width(params_format(params))) { + case 16: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; + break; + case 24: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; + break; + case 32: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; + break; + default: + dev_err(component->dev, "format unsupported %d\n", + params_format(params)); + goto err; + } + + max98373->ch_size = snd_pcm_format_width(params_format(params)); + + regmap_update_bits(max98373->regmap, + MAX98373_R2024_PCM_DATA_FMT_CFG, + MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); + + dev_dbg(component->dev, "format supported %d", + params_format(params)); + + /* sampling rate configuration */ + switch (params_rate(params)) { + case 8000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_8000; + break; + case 11025: + sampling_rate = MAX98373_PCM_SR_SET1_SR_11025; + break; + case 12000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_12000; + break; + case 16000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_16000; + break; + case 22050: + sampling_rate = MAX98373_PCM_SR_SET1_SR_22050; + break; + case 24000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_24000; + break; + case 32000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_32000; + break; + case 44100: + sampling_rate = MAX98373_PCM_SR_SET1_SR_44100; + break; + case 48000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_48000; + break; + case 88200: + sampling_rate = MAX98373_PCM_SR_SET1_SR_88200; + break; + case 96000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_96000; + break; + default: + dev_err(component->dev, "rate %d not supported\n", + params_rate(params)); + goto err; + } + + /* set DAI_SR to correct LRCLK frequency */ + regmap_update_bits(max98373->regmap, + MAX98373_R2027_PCM_SR_SETUP_1, + MAX98373_PCM_SR_SET1_SR_MASK, + sampling_rate); + regmap_update_bits(max98373->regmap, + MAX98373_R2028_PCM_SR_SETUP_2, + MAX98373_PCM_SR_SET2_SR_MASK, + sampling_rate << MAX98373_PCM_SR_SET2_SR_SHIFT); + + /* set sampling rate of IV */ + if (max98373->interleave_mode && + sampling_rate > MAX98373_PCM_SR_SET1_SR_16000) + regmap_update_bits(max98373->regmap, + MAX98373_R2028_PCM_SR_SETUP_2, + MAX98373_PCM_SR_SET2_IVADC_SR_MASK, + sampling_rate - 3); + else + regmap_update_bits(max98373->regmap, + MAX98373_R2028_PCM_SR_SETUP_2, + MAX98373_PCM_SR_SET2_IVADC_SR_MASK, + sampling_rate); + + return max98373_set_clock(component, params); +err: + return -EINVAL; +} + +static int max98373_dai_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct snd_soc_component *component = dai->component; + struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); + int bsel = 0; + unsigned int chan_sz = 0; + unsigned int mask; + int x, slot_found; + + if (!tx_mask && !rx_mask && !slots && !slot_width) + max98373->tdm_mode = false; + else + max98373->tdm_mode = true; + + /* BCLK configuration */ + bsel = max98373_get_bclk_sel(slots * slot_width); + if (bsel == 0) { + dev_err(component->dev, "BCLK %d not supported\n", + slots * slot_width); + return -EINVAL; + } + + regmap_update_bits(max98373->regmap, + MAX98373_R2026_PCM_CLOCK_RATIO, + MAX98373_PCM_CLK_SETUP_BSEL_MASK, + bsel); + + /* Channel size configuration */ + switch (slot_width) { + case 16: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; + break; + case 24: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; + break; + case 32: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; + break; + default: + dev_err(component->dev, "format unsupported %d\n", + slot_width); + return -EINVAL; + } + + regmap_update_bits(max98373->regmap, + MAX98373_R2024_PCM_DATA_FMT_CFG, + MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); + + /* Rx slot configuration */ + slot_found = 0; + mask = rx_mask; + for (x = 0 ; x < 16 ; x++, mask >>= 1) { + if (mask & 0x1) { + if (slot_found == 0) + regmap_update_bits(max98373->regmap, + MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, + MAX98373_PCM_TO_SPK_CH0_SRC_MASK, x); + else + regmap_write(max98373->regmap, + MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, + x); + slot_found++; + if (slot_found > 1) + break; + } + } + + /* Tx slot Hi-Z configuration */ + regmap_write(max98373->regmap, + MAX98373_R2020_PCM_TX_HIZ_EN_1, + ~tx_mask & 0xFF); + regmap_write(max98373->regmap, + MAX98373_R2021_PCM_TX_HIZ_EN_2, + (~tx_mask & 0xFF00) >> 8); + + return 0; +} + +#define MAX98373_RATES SNDRV_PCM_RATE_8000_96000 + +#define MAX98373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static const struct snd_soc_dai_ops max98373_dai_ops = { + .set_fmt = max98373_dai_set_fmt, + .hw_params = max98373_dai_hw_params, + .set_tdm_slot = max98373_dai_tdm_slot, +}; + +static bool max98373_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98373_R2000_SW_RESET: + case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3: + case MAX98373_R2010_IRQ_CTRL: + case MAX98373_R2014_THERM_WARN_THRESH + ... MAX98373_R2018_THERM_FOLDBACK_EN: + case MAX98373_R201E_PIN_DRIVE_STRENGTH + ... MAX98373_R2036_SOUNDWIRE_CTRL: + case MAX98373_R203D_AMP_DIG_VOL_CTRL ... MAX98373_R2043_AMP_EN: + case MAX98373_R2046_IV_SENSE_ADC_DSP_CFG + ... MAX98373_R2047_IV_SENSE_ADC_EN: + case MAX98373_R2051_MEAS_ADC_SAMPLING_RATE + ... MAX98373_R2056_MEAS_ADC_PVDD_CH_EN: + case MAX98373_R2090_BDE_LVL_HOLD ... MAX98373_R2092_BDE_CLIPPER_MODE: + case MAX98373_R2097_BDE_L1_THRESH + ... MAX98373_R209B_BDE_THRESH_HYST: + case MAX98373_R20A8_BDE_L1_CFG_1 ... MAX98373_R20B3_BDE_L4_CFG_3: + case MAX98373_R20B5_BDE_EN ... MAX98373_R20B6_BDE_CUR_STATE_READBACK: + case MAX98373_R20D1_DHT_CFG ... MAX98373_R20D4_DHT_EN: + case MAX98373_R20E0_LIMITER_THRESH_CFG ... MAX98373_R20E2_LIMITER_EN: + case MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG + ... MAX98373_R20FF_GLOBAL_SHDN: + case MAX98373_R21FF_REV_ID: + return true; + default: + return false; + } +}; + +static bool max98373_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3: + case MAX98373_R203E_AMP_PATH_GAIN: + case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK: + case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK: + case MAX98373_R20B6_BDE_CUR_STATE_READBACK: + case MAX98373_R21FF_REV_ID: + return true; + default: + return false; + } +} + +static struct snd_soc_dai_driver max98373_dai[] = { + { + .name = "max98373-aif1", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MAX98373_RATES, + .formats = MAX98373_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MAX98373_RATES, + .formats = MAX98373_FORMATS, + }, + .ops = &max98373_dai_ops, + } +}; + +#ifdef CONFIG_PM_SLEEP +static int max98373_suspend(struct device *dev) +{ + struct max98373_priv *max98373 = dev_get_drvdata(dev); + + regcache_cache_only(max98373->regmap, true); + regcache_mark_dirty(max98373->regmap); + return 0; +} + +static int max98373_resume(struct device *dev) +{ + struct max98373_priv *max98373 = dev_get_drvdata(dev); + + regcache_cache_only(max98373->regmap, false); + max98373_reset(max98373, dev); + regcache_sync(max98373->regmap); + return 0; +} +#endif + +static const struct dev_pm_ops max98373_pm = { + SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume) +}; + +static const struct regmap_config max98373_regmap = { + .reg_bits = 16, + .val_bits = 8, + .max_register = MAX98373_R21FF_REV_ID, + .reg_defaults = max98373_reg, + .num_reg_defaults = ARRAY_SIZE(max98373_reg), + .readable_reg = max98373_readable_register, + .volatile_reg = max98373_volatile_reg, + .cache_type = REGCACHE_RBTREE, +}; + +static int max98373_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + int ret = 0; + int reg = 0; + struct max98373_priv *max98373 = NULL; + + max98373 = devm_kzalloc(&i2c->dev, sizeof(*max98373), GFP_KERNEL); + + if (!max98373) { + ret = -ENOMEM; + return ret; + } + i2c_set_clientdata(i2c, max98373); + + /* update interleave mode info */ + if (device_property_read_bool(&i2c->dev, "maxim,interleave_mode")) + max98373->interleave_mode = true; + else + max98373->interleave_mode = false; + + /* regmap initialization */ + max98373->regmap = devm_regmap_init_i2c(i2c, &max98373_regmap); + if (IS_ERR(max98373->regmap)) { + ret = PTR_ERR(max98373->regmap); + dev_err(&i2c->dev, + "Failed to allocate regmap: %d\n", ret); + return ret; + } + + /* voltage/current slot & gpio configuration */ + max98373_slot_config(&i2c->dev, max98373); + + /* Power on device */ + if (gpio_is_valid(max98373->reset_gpio)) { + ret = devm_gpio_request(&i2c->dev, max98373->reset_gpio, + "MAX98373_RESET"); + if (ret) { + dev_err(&i2c->dev, "%s: Failed to request gpio %d\n", + __func__, max98373->reset_gpio); + return -EINVAL; + } + gpio_direction_output(max98373->reset_gpio, 0); + msleep(50); + gpio_direction_output(max98373->reset_gpio, 1); + msleep(20); + } + + /* Check Revision ID */ + ret = regmap_read(max98373->regmap, + MAX98373_R21FF_REV_ID, ®); + if (ret < 0) { + dev_err(&i2c->dev, + "Failed to read: 0x%02X\n", MAX98373_R21FF_REV_ID); + return ret; + } + dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg); + + /* codec registration */ + ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373, + max98373_dai, ARRAY_SIZE(max98373_dai)); + if (ret < 0) + dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); + + return ret; +} + +static const struct i2c_device_id max98373_i2c_id[] = { + { "max98373", 0}, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, max98373_i2c_id); + +#if defined(CONFIG_OF) +static const struct of_device_id max98373_of_match[] = { + { .compatible = "maxim,max98373", }, + { } +}; +MODULE_DEVICE_TABLE(of, max98373_of_match); +#endif + +#ifdef CONFIG_ACPI +static const struct acpi_device_id max98373_acpi_match[] = { + { "MX98373", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, max98373_acpi_match); +#endif + +static struct i2c_driver max98373_i2c_driver = { + .driver = { + .name = "max98373", + .of_match_table = of_match_ptr(max98373_of_match), + .acpi_match_table = ACPI_PTR(max98373_acpi_match), + .pm = &max98373_pm, + }, + .probe = max98373_i2c_probe, + .id_table = max98373_i2c_id, +}; + +module_i2c_driver(max98373_i2c_driver) + +MODULE_DESCRIPTION("ALSA SoC MAX98373 driver"); +MODULE_AUTHOR("Ryan Lee "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c new file mode 100644 index 0000000000000000000000000000000000000000..5fe724728e84e9a5746cdf6839a26bb65ced5d32 --- /dev/null +++ b/sound/soc/codecs/max98373-sdw.c @@ -0,0 +1,887 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2020, Maxim Integrated + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "max98373.h" +#include "max98373-sdw.h" + +struct sdw_stream_data { + struct sdw_stream_runtime *sdw_stream; +}; + +static struct reg_default max98373_reg[] = { + {MAX98373_R0040_SCP_INIT_STAT_1, 0x00}, + {MAX98373_R0041_SCP_INIT_MASK_1, 0x00}, + {MAX98373_R0042_SCP_INIT_STAT_2, 0x00}, + {MAX98373_R0044_SCP_CTRL, 0x00}, + {MAX98373_R0045_SCP_SYSTEM_CTRL, 0x00}, + {MAX98373_R0046_SCP_DEV_NUMBER, 0x00}, + {MAX98373_R0050_SCP_DEV_ID_0, 0x21}, + {MAX98373_R0051_SCP_DEV_ID_1, 0x01}, + {MAX98373_R0052_SCP_DEV_ID_2, 0x9F}, + {MAX98373_R0053_SCP_DEV_ID_3, 0x87}, + {MAX98373_R0054_SCP_DEV_ID_4, 0x08}, + {MAX98373_R0055_SCP_DEV_ID_5, 0x00}, + {MAX98373_R0060_SCP_FRAME_CTLR, 0x00}, + {MAX98373_R0070_SCP_FRAME_CTLR, 0x00}, + {MAX98373_R0100_DP1_INIT_STAT, 0x00}, + {MAX98373_R0101_DP1_INIT_MASK, 0x00}, + {MAX98373_R0102_DP1_PORT_CTRL, 0x00}, + {MAX98373_R0103_DP1_BLOCK_CTRL_1, 0x00}, + {MAX98373_R0104_DP1_PREPARE_STATUS, 0x00}, + {MAX98373_R0105_DP1_PREPARE_CTRL, 0x00}, + {MAX98373_R0120_DP1_CHANNEL_EN, 0x00}, + {MAX98373_R0122_DP1_SAMPLE_CTRL1, 0x00}, + {MAX98373_R0123_DP1_SAMPLE_CTRL2, 0x00}, + {MAX98373_R0124_DP1_OFFSET_CTRL1, 0x00}, + {MAX98373_R0125_DP1_OFFSET_CTRL2, 0x00}, + {MAX98373_R0126_DP1_HCTRL, 0x00}, + {MAX98373_R0127_DP1_BLOCK_CTRL3, 0x00}, + {MAX98373_R0130_DP1_CHANNEL_EN, 0x00}, + {MAX98373_R0132_DP1_SAMPLE_CTRL1, 0x00}, + {MAX98373_R0133_DP1_SAMPLE_CTRL2, 0x00}, + {MAX98373_R0134_DP1_OFFSET_CTRL1, 0x00}, + {MAX98373_R0135_DP1_OFFSET_CTRL2, 0x00}, + {MAX98373_R0136_DP1_HCTRL, 0x0136}, + {MAX98373_R0137_DP1_BLOCK_CTRL3, 0x00}, + {MAX98373_R0300_DP3_INIT_STAT, 0x00}, + {MAX98373_R0301_DP3_INIT_MASK, 0x00}, + {MAX98373_R0302_DP3_PORT_CTRL, 0x00}, + {MAX98373_R0303_DP3_BLOCK_CTRL_1, 0x00}, + {MAX98373_R0304_DP3_PREPARE_STATUS, 0x00}, + {MAX98373_R0305_DP3_PREPARE_CTRL, 0x00}, + {MAX98373_R0320_DP3_CHANNEL_EN, 0x00}, + {MAX98373_R0322_DP3_SAMPLE_CTRL1, 0x00}, + {MAX98373_R0323_DP3_SAMPLE_CTRL2, 0x00}, + {MAX98373_R0324_DP3_OFFSET_CTRL1, 0x00}, + {MAX98373_R0325_DP3_OFFSET_CTRL2, 0x00}, + {MAX98373_R0326_DP3_HCTRL, 0x00}, + {MAX98373_R0327_DP3_BLOCK_CTRL3, 0x00}, + {MAX98373_R0330_DP3_CHANNEL_EN, 0x00}, + {MAX98373_R0332_DP3_SAMPLE_CTRL1, 0x00}, + {MAX98373_R0333_DP3_SAMPLE_CTRL2, 0x00}, + {MAX98373_R0334_DP3_OFFSET_CTRL1, 0x00}, + {MAX98373_R0335_DP3_OFFSET_CTRL2, 0x00}, + {MAX98373_R0336_DP3_HCTRL, 0x00}, + {MAX98373_R0337_DP3_BLOCK_CTRL3, 0x00}, + {MAX98373_R2000_SW_RESET, 0x00}, + {MAX98373_R2001_INT_RAW1, 0x00}, + {MAX98373_R2002_INT_RAW2, 0x00}, + {MAX98373_R2003_INT_RAW3, 0x00}, + {MAX98373_R2004_INT_STATE1, 0x00}, + {MAX98373_R2005_INT_STATE2, 0x00}, + {MAX98373_R2006_INT_STATE3, 0x00}, + {MAX98373_R2007_INT_FLAG1, 0x00}, + {MAX98373_R2008_INT_FLAG2, 0x00}, + {MAX98373_R2009_INT_FLAG3, 0x00}, + {MAX98373_R200A_INT_EN1, 0x00}, + {MAX98373_R200B_INT_EN2, 0x00}, + {MAX98373_R200C_INT_EN3, 0x00}, + {MAX98373_R200D_INT_FLAG_CLR1, 0x00}, + {MAX98373_R200E_INT_FLAG_CLR2, 0x00}, + {MAX98373_R200F_INT_FLAG_CLR3, 0x00}, + {MAX98373_R2010_IRQ_CTRL, 0x00}, + {MAX98373_R2014_THERM_WARN_THRESH, 0x10}, + {MAX98373_R2015_THERM_SHDN_THRESH, 0x27}, + {MAX98373_R2016_THERM_HYSTERESIS, 0x01}, + {MAX98373_R2017_THERM_FOLDBACK_SET, 0xC0}, + {MAX98373_R2018_THERM_FOLDBACK_EN, 0x00}, + {MAX98373_R201E_PIN_DRIVE_STRENGTH, 0x55}, + {MAX98373_R2020_PCM_TX_HIZ_EN_1, 0xFE}, + {MAX98373_R2021_PCM_TX_HIZ_EN_2, 0xFF}, + {MAX98373_R2022_PCM_TX_SRC_1, 0x00}, + {MAX98373_R2023_PCM_TX_SRC_2, 0x00}, + {MAX98373_R2024_PCM_DATA_FMT_CFG, 0xC0}, + {MAX98373_R2025_AUDIO_IF_MODE, 0x00}, + {MAX98373_R2026_PCM_CLOCK_RATIO, 0x04}, + {MAX98373_R2027_PCM_SR_SETUP_1, 0x08}, + {MAX98373_R2028_PCM_SR_SETUP_2, 0x88}, + {MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 0x00}, + {MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 0x00}, + {MAX98373_R202B_PCM_RX_EN, 0x00}, + {MAX98373_R202C_PCM_TX_EN, 0x00}, + {MAX98373_R202E_ICC_RX_CH_EN_1, 0x00}, + {MAX98373_R202F_ICC_RX_CH_EN_2, 0x00}, + {MAX98373_R2030_ICC_TX_HIZ_EN_1, 0xFF}, + {MAX98373_R2031_ICC_TX_HIZ_EN_2, 0xFF}, + {MAX98373_R2032_ICC_LINK_EN_CFG, 0x30}, + {MAX98373_R2034_ICC_TX_CNTL, 0x00}, + {MAX98373_R2035_ICC_TX_EN, 0x00}, + {MAX98373_R2036_SOUNDWIRE_CTRL, 0x05}, + {MAX98373_R203D_AMP_DIG_VOL_CTRL, 0x00}, + {MAX98373_R203E_AMP_PATH_GAIN, 0x08}, + {MAX98373_R203F_AMP_DSP_CFG, 0x02}, + {MAX98373_R2040_TONE_GEN_CFG, 0x00}, + {MAX98373_R2041_AMP_CFG, 0x03}, + {MAX98373_R2042_AMP_EDGE_RATE_CFG, 0x00}, + {MAX98373_R2043_AMP_EN, 0x00}, + {MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 0x04}, + {MAX98373_R2047_IV_SENSE_ADC_EN, 0x00}, + {MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0x00}, + {MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0x00}, + {MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 0x00}, + {MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0x00}, + {MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0x00}, + {MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0x00}, + {MAX98373_R2090_BDE_LVL_HOLD, 0x00}, + {MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0x00}, + {MAX98373_R2092_BDE_CLIPPER_MODE, 0x00}, + {MAX98373_R2097_BDE_L1_THRESH, 0x00}, + {MAX98373_R2098_BDE_L2_THRESH, 0x00}, + {MAX98373_R2099_BDE_L3_THRESH, 0x00}, + {MAX98373_R209A_BDE_L4_THRESH, 0x00}, + {MAX98373_R209B_BDE_THRESH_HYST, 0x00}, + {MAX98373_R20A8_BDE_L1_CFG_1, 0x00}, + {MAX98373_R20A9_BDE_L1_CFG_2, 0x00}, + {MAX98373_R20AA_BDE_L1_CFG_3, 0x00}, + {MAX98373_R20AB_BDE_L2_CFG_1, 0x00}, + {MAX98373_R20AC_BDE_L2_CFG_2, 0x00}, + {MAX98373_R20AD_BDE_L2_CFG_3, 0x00}, + {MAX98373_R20AE_BDE_L3_CFG_1, 0x00}, + {MAX98373_R20AF_BDE_L3_CFG_2, 0x00}, + {MAX98373_R20B0_BDE_L3_CFG_3, 0x00}, + {MAX98373_R20B1_BDE_L4_CFG_1, 0x00}, + {MAX98373_R20B2_BDE_L4_CFG_2, 0x00}, + {MAX98373_R20B3_BDE_L4_CFG_3, 0x00}, + {MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE, 0x00}, + {MAX98373_R20B5_BDE_EN, 0x00}, + {MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0x00}, + {MAX98373_R20D1_DHT_CFG, 0x01}, + {MAX98373_R20D2_DHT_ATTACK_CFG, 0x02}, + {MAX98373_R20D3_DHT_RELEASE_CFG, 0x03}, + {MAX98373_R20D4_DHT_EN, 0x00}, + {MAX98373_R20E0_LIMITER_THRESH_CFG, 0x00}, + {MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0x00}, + {MAX98373_R20E2_LIMITER_EN, 0x00}, + {MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, 0x00}, + {MAX98373_R20FF_GLOBAL_SHDN, 0x00}, + {MAX98373_R21FF_REV_ID, 0x42}, +}; + +static bool max98373_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98373_R21FF_REV_ID: + case MAX98373_R2010_IRQ_CTRL: + /* SoundWire Control Port Registers */ + case MAX98373_R0040_SCP_INIT_STAT_1 ... MAX98373_R0070_SCP_FRAME_CTLR: + /* Soundwire Data Port 1 Registers */ + case MAX98373_R0100_DP1_INIT_STAT ... MAX98373_R0137_DP1_BLOCK_CTRL3: + /* Soundwire Data Port 3 Registers */ + case MAX98373_R0300_DP3_INIT_STAT ... MAX98373_R0337_DP3_BLOCK_CTRL3: + case MAX98373_R2000_SW_RESET ... MAX98373_R200C_INT_EN3: + case MAX98373_R2014_THERM_WARN_THRESH + ... MAX98373_R2018_THERM_FOLDBACK_EN: + case MAX98373_R201E_PIN_DRIVE_STRENGTH + ... MAX98373_R2036_SOUNDWIRE_CTRL: + case MAX98373_R203D_AMP_DIG_VOL_CTRL ... MAX98373_R2043_AMP_EN: + case MAX98373_R2046_IV_SENSE_ADC_DSP_CFG + ... MAX98373_R2047_IV_SENSE_ADC_EN: + case MAX98373_R2051_MEAS_ADC_SAMPLING_RATE + ... MAX98373_R2056_MEAS_ADC_PVDD_CH_EN: + case MAX98373_R2090_BDE_LVL_HOLD ... MAX98373_R2092_BDE_CLIPPER_MODE: + case MAX98373_R2097_BDE_L1_THRESH + ... MAX98373_R209B_BDE_THRESH_HYST: + case MAX98373_R20A8_BDE_L1_CFG_1 ... MAX98373_R20B3_BDE_L4_CFG_3: + case MAX98373_R20B5_BDE_EN ... MAX98373_R20B6_BDE_CUR_STATE_READBACK: + case MAX98373_R20D1_DHT_CFG ... MAX98373_R20D4_DHT_EN: + case MAX98373_R20E0_LIMITER_THRESH_CFG ... MAX98373_R20E2_LIMITER_EN: + case MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG + ... MAX98373_R20FF_GLOBAL_SHDN: + return true; + default: + return false; + } +}; + +static bool max98373_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK: + case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK: + case MAX98373_R20B6_BDE_CUR_STATE_READBACK: + case MAX98373_R21FF_REV_ID: + /* SoundWire Control Port Registers */ + case MAX98373_R0040_SCP_INIT_STAT_1 ... MAX98373_R0070_SCP_FRAME_CTLR: + /* Soundwire Data Port 1 Registers */ + case MAX98373_R0100_DP1_INIT_STAT ... MAX98373_R0137_DP1_BLOCK_CTRL3: + /* Soundwire Data Port 3 Registers */ + case MAX98373_R0300_DP3_INIT_STAT ... MAX98373_R0337_DP3_BLOCK_CTRL3: + case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3: + return true; + default: + return false; + } +} + +static const struct regmap_config max98373_sdw_regmap = { + .reg_bits = 32, + .val_bits = 8, + .max_register = MAX98373_R21FF_REV_ID, + .reg_defaults = max98373_reg, + .num_reg_defaults = ARRAY_SIZE(max98373_reg), + .readable_reg = max98373_readable_register, + .volatile_reg = max98373_volatile_reg, + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +/* Power management functions and structure */ +static __maybe_unused int max98373_suspend(struct device *dev) +{ + struct max98373_priv *max98373 = dev_get_drvdata(dev); + + regcache_cache_only(max98373->regmap, true); + regcache_mark_dirty(max98373->regmap); + return 0; +} + +static __maybe_unused int max98373_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct max98373_priv *max98373 = dev_get_drvdata(dev); + unsigned long time; + + if (!slave->unattach_request) + goto regmap_sync; + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(2000)); + if (!time) { + dev_err(dev, "Initialization not complete, timed out\n"); + return -ETIMEDOUT; + } + +regmap_sync: + slave->unattach_request = 0; + regcache_cache_only(max98373->regmap, false); + regcache_sync(max98373->regmap); + + return 0; +} + +static const struct dev_pm_ops max98373_pm = { + SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume) + SET_RUNTIME_PM_OPS(max98373_suspend, max98373_resume, NULL) +}; + +static int max98373_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval, i, num_of_ports; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + /* BITMAP: 00001000 Dataport 3 is active */ + prop->source_ports = BIT(3); + /* BITMAP: 00000010 Dataport 1 is active */ + prop->sink_ports = BIT(1); + prop->paging_support = true; + prop->clk_stop_timeout = 20; + + nval = hweight32(prop->source_ports); + num_of_ports = nval; + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), + GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* do this again for sink now */ + nval = hweight32(prop->sink_ports); + num_of_ports += nval; + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->sink_dpn_prop), + GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* Allocate port_ready based on num_of_ports */ + slave->port_ready = devm_kcalloc(&slave->dev, num_of_ports, + sizeof(*slave->port_ready), + GFP_KERNEL); + if (!slave->port_ready) + return -ENOMEM; + + /* Initialize completion */ + for (i = 0; i < num_of_ports; i++) + init_completion(&slave->port_ready[i]); + + /* set the timeout values */ + prop->clk_stop_timeout = 20; + + return 0; +} + +static int max98373_io_init(struct sdw_slave *slave) +{ + struct device *dev = &slave->dev; + struct max98373_priv *max98373 = dev_get_drvdata(dev); + + if (max98373->pm_init_once) { + regcache_cache_only(max98373->regmap, false); + regcache_cache_bypass(max98373->regmap, true); + } + + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + if (!max98373->pm_init_once) { + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(dev); + + pm_runtime_enable(dev); + } + + pm_runtime_get_noresume(dev); + + /* Software Reset */ + max98373_reset(max98373, dev); + + /* Set soundwire mode */ + regmap_write(max98373->regmap, MAX98373_R2025_AUDIO_IF_MODE, 3); + /* Enable ADC */ + regmap_write(max98373->regmap, MAX98373_R2047_IV_SENSE_ADC_EN, 3); + /* Set default Soundwire clock */ + regmap_write(max98373->regmap, MAX98373_R2036_SOUNDWIRE_CTRL, 5); + /* Set default sampling rate for speaker and IVDAC */ + regmap_write(max98373->regmap, MAX98373_R2028_PCM_SR_SETUP_2, 0x88); + /* IV default slot configuration */ + regmap_write(max98373->regmap, + MAX98373_R2020_PCM_TX_HIZ_EN_1, + 0xFF); + regmap_write(max98373->regmap, + MAX98373_R2021_PCM_TX_HIZ_EN_2, + 0xFF); + /* L/R mix configuration */ + regmap_write(max98373->regmap, + MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, + 0x80); + regmap_write(max98373->regmap, + MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, + 0x1); + /* Enable DC blocker */ + regmap_write(max98373->regmap, + MAX98373_R203F_AMP_DSP_CFG, + 0x3); + /* Enable IMON VMON DC blocker */ + regmap_write(max98373->regmap, + MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, + 0x7); + /* voltage, current slot configuration */ + regmap_write(max98373->regmap, + MAX98373_R2022_PCM_TX_SRC_1, + (max98373->i_slot << MAX98373_PCM_TX_CH_SRC_A_I_SHIFT | + max98373->v_slot) & 0xFF); + if (max98373->v_slot < 8) + regmap_update_bits(max98373->regmap, + MAX98373_R2020_PCM_TX_HIZ_EN_1, + 1 << max98373->v_slot, 0); + else + regmap_update_bits(max98373->regmap, + MAX98373_R2021_PCM_TX_HIZ_EN_2, + 1 << (max98373->v_slot - 8), 0); + + if (max98373->i_slot < 8) + regmap_update_bits(max98373->regmap, + MAX98373_R2020_PCM_TX_HIZ_EN_1, + 1 << max98373->i_slot, 0); + else + regmap_update_bits(max98373->regmap, + MAX98373_R2021_PCM_TX_HIZ_EN_2, + 1 << (max98373->i_slot - 8), 0); + + /* speaker feedback slot configuration */ + regmap_write(max98373->regmap, + MAX98373_R2023_PCM_TX_SRC_2, + max98373->spkfb_slot & 0xFF); + + /* Set interleave mode */ + if (max98373->interleave_mode) + regmap_update_bits(max98373->regmap, + MAX98373_R2024_PCM_DATA_FMT_CFG, + MAX98373_PCM_TX_CH_INTERLEAVE_MASK, + MAX98373_PCM_TX_CH_INTERLEAVE_MASK); + + /* Speaker enable */ + regmap_update_bits(max98373->regmap, + MAX98373_R2043_AMP_EN, + MAX98373_SPK_EN_MASK, 1); + + regmap_write(max98373->regmap, MAX98373_R20B5_BDE_EN, 1); + regmap_write(max98373->regmap, MAX98373_R20E2_LIMITER_EN, 1); + + if (max98373->pm_init_once) { + regcache_cache_bypass(max98373->regmap, false); + regcache_mark_dirty(max98373->regmap); + } + + max98373->pm_init_once = true; + max98373->hw_init = true; + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return 0; +} + +static int max98373_clock_calculate(struct sdw_slave *slave, + unsigned int clk_freq) +{ + int x, y; + static const int max98373_clk_family[] = { + 7680000, 8400000, 9600000, 11289600, + 12000000, 12288000, 13000000 + }; + + for (x = 0; x < 4; x++) + for (y = 0; y < ARRAY_SIZE(max98373_clk_family); y++) + if (clk_freq == (max98373_clk_family[y] >> x)) + return (x << 3) + y; + + /* Set default clock (12.288 Mhz) if the value is not in the list */ + dev_err(&slave->dev, "Requested clock not found. (clk_freq = %d)\n", + clk_freq); + return 0x5; +} + +static int max98373_clock_config(struct sdw_slave *slave, + struct sdw_bus_params *params) +{ + struct device *dev = &slave->dev; + struct max98373_priv *max98373 = dev_get_drvdata(dev); + unsigned int clk_freq, value; + + clk_freq = (params->curr_dr_freq >> 1); + + /* + * Select the proper value for the register based on the + * requested clock. If the value is not in the list, + * use reasonable default - 12.288 Mhz + */ + value = max98373_clock_calculate(slave, clk_freq); + + /* SWCLK */ + regmap_write(max98373->regmap, MAX98373_R2036_SOUNDWIRE_CTRL, value); + + /* The default Sampling Rate value for IV is 48KHz*/ + regmap_write(max98373->regmap, MAX98373_R2028_PCM_SR_SETUP_2, 0x88); + + return 0; +} + +#define MAX98373_RATES SNDRV_PCM_RATE_8000_96000 +#define MAX98373_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) + +static int max98373_sdw_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98373_priv *max98373 = + snd_soc_component_get_drvdata(component); + + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + enum sdw_data_direction direction; + struct sdw_stream_data *stream; + int ret, chan_sz, sampling_rate; + + stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!stream) + return -EINVAL; + + if (!max98373->slave) + return -EINVAL; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + direction = SDW_DATA_DIR_RX; + port_config.num = 1; + } else { + direction = SDW_DATA_DIR_TX; + port_config.num = 3; + } + + stream_config.frame_rate = params_rate(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = direction; + + if (max98373->slot && direction == SDW_DATA_DIR_RX) { + stream_config.ch_count = max98373->slot; + port_config.ch_mask = max98373->rx_mask; + } else { + /* only IV are supported by capture */ + if (direction == SDW_DATA_DIR_TX) + stream_config.ch_count = 2; + else + stream_config.ch_count = params_channels(params); + + port_config.ch_mask = GENMASK((int)stream_config.ch_count - 1, 0); + } + + ret = sdw_stream_add_slave(max98373->slave, &stream_config, + &port_config, 1, stream->sdw_stream); + if (ret) { + dev_err(dai->dev, "Unable to configure port\n"); + return ret; + } + + if (params_channels(params) > 16) { + dev_err(component->dev, "Unsupported channels %d\n", + params_channels(params)); + return -EINVAL; + } + + /* Channel size configuration */ + switch (snd_pcm_format_width(params_format(params))) { + case 16: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; + break; + case 24: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; + break; + case 32: + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; + break; + default: + dev_err(component->dev, "Channel size unsupported %d\n", + params_format(params)); + return -EINVAL; + } + + max98373->ch_size = snd_pcm_format_width(params_format(params)); + + regmap_update_bits(max98373->regmap, + MAX98373_R2024_PCM_DATA_FMT_CFG, + MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); + + dev_dbg(component->dev, "Format supported %d", params_format(params)); + + /* Sampling rate configuration */ + switch (params_rate(params)) { + case 8000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_8000; + break; + case 11025: + sampling_rate = MAX98373_PCM_SR_SET1_SR_11025; + break; + case 12000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_12000; + break; + case 16000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_16000; + break; + case 22050: + sampling_rate = MAX98373_PCM_SR_SET1_SR_22050; + break; + case 24000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_24000; + break; + case 32000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_32000; + break; + case 44100: + sampling_rate = MAX98373_PCM_SR_SET1_SR_44100; + break; + case 48000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_48000; + break; + case 88200: + sampling_rate = MAX98373_PCM_SR_SET1_SR_88200; + break; + case 96000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_96000; + break; + default: + dev_err(component->dev, "Rate %d is not supported\n", + params_rate(params)); + return -EINVAL; + } + + /* set correct sampling frequency */ + regmap_update_bits(max98373->regmap, + MAX98373_R2028_PCM_SR_SETUP_2, + MAX98373_PCM_SR_SET2_SR_MASK, + sampling_rate << MAX98373_PCM_SR_SET2_SR_SHIFT); + + /* set sampling rate of IV */ + regmap_update_bits(max98373->regmap, + MAX98373_R2028_PCM_SR_SETUP_2, + MAX98373_PCM_SR_SET2_IVADC_SR_MASK, + sampling_rate); + + return 0; +} + +static int max98373_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98373_priv *max98373 = + snd_soc_component_get_drvdata(component); + struct sdw_stream_data *stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!max98373->slave) + return -EINVAL; + + sdw_stream_remove_slave(max98373->slave, stream->sdw_stream); + return 0; +} + +static int max98373_set_sdw_stream(struct snd_soc_dai *dai, + void *sdw_stream, int direction) +{ + struct sdw_stream_data *stream; + + if (!sdw_stream) + return 0; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + + stream->sdw_stream = sdw_stream; + + /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ + if (direction == SNDRV_PCM_STREAM_PLAYBACK) + dai->playback_dma_data = stream; + else + dai->capture_dma_data = stream; + + return 0; +} + +static void max98373_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sdw_stream_data *stream; + + stream = snd_soc_dai_get_dma_data(dai, substream); + snd_soc_dai_set_dma_data(dai, substream, NULL); + kfree(stream); +} + +static int max98373_sdw_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, + unsigned int rx_mask, + int slots, int slot_width) +{ + struct snd_soc_component *component = dai->component; + struct max98373_priv *max98373 = + snd_soc_component_get_drvdata(component); + + /* tx_mask is unused since it's irrelevant for I/V feedback */ + if (tx_mask) + return -EINVAL; + + if (!rx_mask && !slots && !slot_width) + max98373->tdm_mode = false; + else + max98373->tdm_mode = true; + + max98373->rx_mask = rx_mask; + max98373->slot = slots; + + return 0; +} + +static const struct snd_soc_dai_ops max98373_dai_sdw_ops = { + .hw_params = max98373_sdw_dai_hw_params, + .hw_free = max98373_pcm_hw_free, + .set_sdw_stream = max98373_set_sdw_stream, + .shutdown = max98373_shutdown, + .set_tdm_slot = max98373_sdw_set_tdm_slot, +}; + +static struct snd_soc_dai_driver max98373_sdw_dai[] = { + { + .name = "max98373-aif1", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MAX98373_RATES, + .formats = MAX98373_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MAX98373_RATES, + .formats = MAX98373_FORMATS, + }, + .ops = &max98373_dai_sdw_ops, + } +}; + +static int max98373_init(struct sdw_slave *slave, struct regmap *regmap) +{ + struct max98373_priv *max98373; + int ret; + struct device *dev = &slave->dev; + + /* Allocate and assign private driver data structure */ + max98373 = devm_kzalloc(dev, sizeof(*max98373), GFP_KERNEL); + if (!max98373) + return -ENOMEM; + + dev_set_drvdata(dev, max98373); + max98373->regmap = regmap; + max98373->slave = slave; + + /* Read voltage and slot configuration */ + max98373_slot_config(dev, max98373); + + max98373->hw_init = false; + max98373->pm_init_once = false; + + /* codec registration */ + ret = devm_snd_soc_register_component(dev, &soc_codec_dev_max98373_sdw, + max98373_sdw_dai, + ARRAY_SIZE(max98373_sdw_dai)); + if (ret < 0) + dev_err(dev, "Failed to register codec: %d\n", ret); + + return ret; +} + +static int max98373_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct max98373_priv *max98373 = dev_get_drvdata(&slave->dev); + + if (status == SDW_SLAVE_UNATTACHED) + max98373->hw_init = false; + + /* + * Perform initialization only if slave status is SDW_SLAVE_ATTACHED + */ + if (max98373->hw_init || status != SDW_SLAVE_ATTACHED) + return 0; + + /* perform I/O transfers required for Slave initialization */ + return max98373_io_init(slave); +} + +static int max98373_bus_config(struct sdw_slave *slave, + struct sdw_bus_params *params) +{ + int ret; + + ret = max98373_clock_config(slave, params); + if (ret < 0) + dev_err(&slave->dev, "Invalid clk config"); + + return ret; +} + +/* + * slave_ops: callbacks for get_clock_stop_mode, clock_stop and + * port_prep are not defined for now + */ +static struct sdw_slave_ops max98373_slave_ops = { + .read_prop = max98373_read_prop, + .update_status = max98373_update_status, + .bus_config = max98373_bus_config, +}; + +static int max98373_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *regmap; + + /* Regmap Initialization */ + regmap = devm_regmap_init_sdw(slave, &max98373_sdw_regmap); + if (!regmap) + return -EINVAL; + + return max98373_init(slave, regmap); +} + +#if defined(CONFIG_OF) +static const struct of_device_id max98373_of_match[] = { + { .compatible = "maxim,max98373", }, + {}, +}; +MODULE_DEVICE_TABLE(of, max98373_of_match); +#endif + +#ifdef CONFIG_ACPI +static const struct acpi_device_id max98373_acpi_match[] = { + { "MX98373", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, max98373_acpi_match); +#endif + +static const struct sdw_device_id max98373_id[] = { + SDW_SLAVE_ENTRY(0x019F, 0x8373, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, max98373_id); + +static struct sdw_driver max98373_sdw_driver = { + .driver = { + .name = "max98373", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(max98373_of_match), + .acpi_match_table = ACPI_PTR(max98373_acpi_match), + .pm = &max98373_pm, + }, + .probe = max98373_sdw_probe, + .remove = NULL, + .ops = &max98373_slave_ops, + .id_table = max98373_id, +}; + +module_sdw_driver(max98373_sdw_driver); + +MODULE_DESCRIPTION("ASoC MAX98373 driver SDW"); +MODULE_AUTHOR("Oleg Sherbakov "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/max98373-sdw.h b/sound/soc/codecs/max98373-sdw.h new file mode 100644 index 0000000000000000000000000000000000000000..2d8033515d3426c092a037cb9995d300c1cd4c82 --- /dev/null +++ b/sound/soc/codecs/max98373-sdw.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2020 Maxim Integrated */ + +#ifndef _MAX98373_SDW_H +#define _MAX98373_SDW_H + +#include "max98373.h" + +/* SoundWire Slave Control Port (SCP) */ +#define MAX98373_R0040_SCP_INIT_STAT_1 0x0040 +#define MAX98373_R0041_SCP_INIT_MASK_1 0x0041 +#define MAX98373_R0042_SCP_INIT_STAT_2 0x0042 +#define MAX98373_R0044_SCP_CTRL 0x0044 +#define MAX98373_R0045_SCP_SYSTEM_CTRL 0x0045 +#define MAX98373_R0046_SCP_DEV_NUMBER 0x0046 +#define MAX98373_R0050_SCP_DEV_ID_0 0x0050 +#define MAX98373_R0051_SCP_DEV_ID_1 0x0051 +#define MAX98373_R0052_SCP_DEV_ID_2 0x0052 +#define MAX98373_R0053_SCP_DEV_ID_3 0x0053 +#define MAX98373_R0054_SCP_DEV_ID_4 0x0054 +#define MAX98373_R0055_SCP_DEV_ID_5 0x0055 +#define MAX98373_R0060_SCP_FRAME_CTLR 0x0060 +#define MAX98373_R0070_SCP_FRAME_CTLR 0x0070 + +/* SoundWire Device Data Port (DP) */ +/* Data Port 1 Registers */ +#define MAX98373_R0100_DP1_INIT_STAT 0x0100 +#define MAX98373_R0101_DP1_INIT_MASK 0x0101 +#define MAX98373_R0102_DP1_PORT_CTRL 0x0102 +#define MAX98373_R0103_DP1_BLOCK_CTRL_1 0x0103 +#define MAX98373_R0104_DP1_PREPARE_STATUS 0x0104 +#define MAX98373_R0105_DP1_PREPARE_CTRL 0x0105 +/* Data Port 1 Bank 0 Registers */ +#define MAX98373_R0120_DP1_CHANNEL_EN 0x0120 +#define MAX98373_R0122_DP1_SAMPLE_CTRL1 0x0122 +#define MAX98373_R0123_DP1_SAMPLE_CTRL2 0x0123 +#define MAX98373_R0124_DP1_OFFSET_CTRL1 0x0124 +#define MAX98373_R0125_DP1_OFFSET_CTRL2 0x0125 +#define MAX98373_R0126_DP1_HCTRL 0x0126 +#define MAX98373_R0127_DP1_BLOCK_CTRL3 0x0127 +/* Data Port 1 Bank 1 Registers */ +#define MAX98373_R0130_DP1_CHANNEL_EN 0x0130 +#define MAX98373_R0132_DP1_SAMPLE_CTRL1 0x0132 +#define MAX98373_R0133_DP1_SAMPLE_CTRL2 0x0133 +#define MAX98373_R0134_DP1_OFFSET_CTRL1 0x0134 +#define MAX98373_R0135_DP1_OFFSET_CTRL2 0x0135 +#define MAX98373_R0136_DP1_HCTRL 0x0136 +#define MAX98373_R0137_DP1_BLOCK_CTRL3 0x0137 +/* Data Port 3 Registers */ +#define MAX98373_R0300_DP3_INIT_STAT 0x0300 +#define MAX98373_R0301_DP3_INIT_MASK 0x0301 +#define MAX98373_R0302_DP3_PORT_CTRL 0x0302 +#define MAX98373_R0303_DP3_BLOCK_CTRL_1 0x0303 +#define MAX98373_R0304_DP3_PREPARE_STATUS 0x0304 +#define MAX98373_R0305_DP3_PREPARE_CTRL 0x0305 +/* Data Port 3 Bank 0 Registers */ +#define MAX98373_R0320_DP3_CHANNEL_EN 0x0320 +#define MAX98373_R0322_DP3_SAMPLE_CTRL1 0x0322 +#define MAX98373_R0323_DP3_SAMPLE_CTRL2 0x0323 +#define MAX98373_R0324_DP3_OFFSET_CTRL1 0x0324 +#define MAX98373_R0325_DP3_OFFSET_CTRL2 0x0325 +#define MAX98373_R0326_DP3_HCTRL 0x0326 +#define MAX98373_R0327_DP3_BLOCK_CTRL3 0x0327 +/* Data Port 3 Bank 1 Registers */ +#define MAX98373_R0330_DP3_CHANNEL_EN 0x0330 +#define MAX98373_R0332_DP3_SAMPLE_CTRL1 0x0332 +#define MAX98373_R0333_DP3_SAMPLE_CTRL2 0x0333 +#define MAX98373_R0334_DP3_OFFSET_CTRL1 0x0334 +#define MAX98373_R0335_DP3_OFFSET_CTRL2 0x0335 +#define MAX98373_R0336_DP3_HCTRL 0x0336 +#define MAX98373_R0337_DP3_BLOCK_CTRL3 0x0337 +#endif diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index d87402a86c88006379927fa08c1dd994d0ed4703..929bb1798c43f9a5c03af199052a9682aae8ae34 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -17,388 +17,6 @@ #include #include "max98373.h" -static struct reg_default max98373_reg[] = { - {MAX98373_R2000_SW_RESET, 0x00}, - {MAX98373_R2001_INT_RAW1, 0x00}, - {MAX98373_R2002_INT_RAW2, 0x00}, - {MAX98373_R2003_INT_RAW3, 0x00}, - {MAX98373_R2004_INT_STATE1, 0x00}, - {MAX98373_R2005_INT_STATE2, 0x00}, - {MAX98373_R2006_INT_STATE3, 0x00}, - {MAX98373_R2007_INT_FLAG1, 0x00}, - {MAX98373_R2008_INT_FLAG2, 0x00}, - {MAX98373_R2009_INT_FLAG3, 0x00}, - {MAX98373_R200A_INT_EN1, 0x00}, - {MAX98373_R200B_INT_EN2, 0x00}, - {MAX98373_R200C_INT_EN3, 0x00}, - {MAX98373_R200D_INT_FLAG_CLR1, 0x00}, - {MAX98373_R200E_INT_FLAG_CLR2, 0x00}, - {MAX98373_R200F_INT_FLAG_CLR3, 0x00}, - {MAX98373_R2010_IRQ_CTRL, 0x00}, - {MAX98373_R2014_THERM_WARN_THRESH, 0x10}, - {MAX98373_R2015_THERM_SHDN_THRESH, 0x27}, - {MAX98373_R2016_THERM_HYSTERESIS, 0x01}, - {MAX98373_R2017_THERM_FOLDBACK_SET, 0xC0}, - {MAX98373_R2018_THERM_FOLDBACK_EN, 0x00}, - {MAX98373_R201E_PIN_DRIVE_STRENGTH, 0x55}, - {MAX98373_R2020_PCM_TX_HIZ_EN_1, 0xFE}, - {MAX98373_R2021_PCM_TX_HIZ_EN_2, 0xFF}, - {MAX98373_R2022_PCM_TX_SRC_1, 0x00}, - {MAX98373_R2023_PCM_TX_SRC_2, 0x00}, - {MAX98373_R2024_PCM_DATA_FMT_CFG, 0xC0}, - {MAX98373_R2025_AUDIO_IF_MODE, 0x00}, - {MAX98373_R2026_PCM_CLOCK_RATIO, 0x04}, - {MAX98373_R2027_PCM_SR_SETUP_1, 0x08}, - {MAX98373_R2028_PCM_SR_SETUP_2, 0x88}, - {MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 0x00}, - {MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 0x00}, - {MAX98373_R202B_PCM_RX_EN, 0x00}, - {MAX98373_R202C_PCM_TX_EN, 0x00}, - {MAX98373_R202E_ICC_RX_CH_EN_1, 0x00}, - {MAX98373_R202F_ICC_RX_CH_EN_2, 0x00}, - {MAX98373_R2030_ICC_TX_HIZ_EN_1, 0xFF}, - {MAX98373_R2031_ICC_TX_HIZ_EN_2, 0xFF}, - {MAX98373_R2032_ICC_LINK_EN_CFG, 0x30}, - {MAX98373_R2034_ICC_TX_CNTL, 0x00}, - {MAX98373_R2035_ICC_TX_EN, 0x00}, - {MAX98373_R2036_SOUNDWIRE_CTRL, 0x05}, - {MAX98373_R203D_AMP_DIG_VOL_CTRL, 0x00}, - {MAX98373_R203E_AMP_PATH_GAIN, 0x08}, - {MAX98373_R203F_AMP_DSP_CFG, 0x02}, - {MAX98373_R2040_TONE_GEN_CFG, 0x00}, - {MAX98373_R2041_AMP_CFG, 0x03}, - {MAX98373_R2042_AMP_EDGE_RATE_CFG, 0x00}, - {MAX98373_R2043_AMP_EN, 0x00}, - {MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 0x04}, - {MAX98373_R2047_IV_SENSE_ADC_EN, 0x00}, - {MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0x00}, - {MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0x00}, - {MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 0x00}, - {MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0x00}, - {MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0x00}, - {MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0x00}, - {MAX98373_R2090_BDE_LVL_HOLD, 0x00}, - {MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0x00}, - {MAX98373_R2092_BDE_CLIPPER_MODE, 0x00}, - {MAX98373_R2097_BDE_L1_THRESH, 0x00}, - {MAX98373_R2098_BDE_L2_THRESH, 0x00}, - {MAX98373_R2099_BDE_L3_THRESH, 0x00}, - {MAX98373_R209A_BDE_L4_THRESH, 0x00}, - {MAX98373_R209B_BDE_THRESH_HYST, 0x00}, - {MAX98373_R20A8_BDE_L1_CFG_1, 0x00}, - {MAX98373_R20A9_BDE_L1_CFG_2, 0x00}, - {MAX98373_R20AA_BDE_L1_CFG_3, 0x00}, - {MAX98373_R20AB_BDE_L2_CFG_1, 0x00}, - {MAX98373_R20AC_BDE_L2_CFG_2, 0x00}, - {MAX98373_R20AD_BDE_L2_CFG_3, 0x00}, - {MAX98373_R20AE_BDE_L3_CFG_1, 0x00}, - {MAX98373_R20AF_BDE_L3_CFG_2, 0x00}, - {MAX98373_R20B0_BDE_L3_CFG_3, 0x00}, - {MAX98373_R20B1_BDE_L4_CFG_1, 0x00}, - {MAX98373_R20B2_BDE_L4_CFG_2, 0x00}, - {MAX98373_R20B3_BDE_L4_CFG_3, 0x00}, - {MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE, 0x00}, - {MAX98373_R20B5_BDE_EN, 0x00}, - {MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0x00}, - {MAX98373_R20D1_DHT_CFG, 0x01}, - {MAX98373_R20D2_DHT_ATTACK_CFG, 0x02}, - {MAX98373_R20D3_DHT_RELEASE_CFG, 0x03}, - {MAX98373_R20D4_DHT_EN, 0x00}, - {MAX98373_R20E0_LIMITER_THRESH_CFG, 0x00}, - {MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0x00}, - {MAX98373_R20E2_LIMITER_EN, 0x00}, - {MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, 0x00}, - {MAX98373_R20FF_GLOBAL_SHDN, 0x00}, - {MAX98373_R21FF_REV_ID, 0x42}, -}; - -static int max98373_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -{ - struct snd_soc_component *component = codec_dai->component; - struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); - unsigned int format = 0; - unsigned int invert = 0; - - dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt); - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - invert = MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE; - break; - default: - dev_err(component->dev, "DAI invert mode unsupported\n"); - return -EINVAL; - } - - regmap_update_bits(max98373->regmap, - MAX98373_R2026_PCM_CLOCK_RATIO, - MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE, - invert); - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - format = MAX98373_PCM_FORMAT_I2S; - break; - case SND_SOC_DAIFMT_LEFT_J: - format = MAX98373_PCM_FORMAT_LJ; - break; - case SND_SOC_DAIFMT_DSP_A: - format = MAX98373_PCM_FORMAT_TDM_MODE1; - break; - case SND_SOC_DAIFMT_DSP_B: - format = MAX98373_PCM_FORMAT_TDM_MODE0; - break; - default: - return -EINVAL; - } - - regmap_update_bits(max98373->regmap, - MAX98373_R2024_PCM_DATA_FMT_CFG, - MAX98373_PCM_MODE_CFG_FORMAT_MASK, - format << MAX98373_PCM_MODE_CFG_FORMAT_SHIFT); - - return 0; -} - -/* BCLKs per LRCLK */ -static const int bclk_sel_table[] = { - 32, 48, 64, 96, 128, 192, 256, 384, 512, 320, -}; - -static int max98373_get_bclk_sel(int bclk) -{ - int i; - /* match BCLKs per LRCLK */ - for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { - if (bclk_sel_table[i] == bclk) - return i + 2; - } - return 0; -} - -static int max98373_set_clock(struct snd_soc_component *component, - struct snd_pcm_hw_params *params) -{ - struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); - /* BCLK/LRCLK ratio calculation */ - int blr_clk_ratio = params_channels(params) * max98373->ch_size; - int value; - - if (!max98373->tdm_mode) { - /* BCLK configuration */ - value = max98373_get_bclk_sel(blr_clk_ratio); - if (!value) { - dev_err(component->dev, "format unsupported %d\n", - params_format(params)); - return -EINVAL; - } - - regmap_update_bits(max98373->regmap, - MAX98373_R2026_PCM_CLOCK_RATIO, - MAX98373_PCM_CLK_SETUP_BSEL_MASK, - value); - } - return 0; -} - -static int max98373_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_component *component = dai->component; - struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); - unsigned int sampling_rate = 0; - unsigned int chan_sz = 0; - - /* pcm mode configuration */ - switch (snd_pcm_format_width(params_format(params))) { - case 16: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; - break; - case 24: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; - break; - case 32: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; - break; - default: - dev_err(component->dev, "format unsupported %d\n", - params_format(params)); - goto err; - } - - max98373->ch_size = snd_pcm_format_width(params_format(params)); - - regmap_update_bits(max98373->regmap, - MAX98373_R2024_PCM_DATA_FMT_CFG, - MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); - - dev_dbg(component->dev, "format supported %d", - params_format(params)); - - /* sampling rate configuration */ - switch (params_rate(params)) { - case 8000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_8000; - break; - case 11025: - sampling_rate = MAX98373_PCM_SR_SET1_SR_11025; - break; - case 12000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_12000; - break; - case 16000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_16000; - break; - case 22050: - sampling_rate = MAX98373_PCM_SR_SET1_SR_22050; - break; - case 24000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_24000; - break; - case 32000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_32000; - break; - case 44100: - sampling_rate = MAX98373_PCM_SR_SET1_SR_44100; - break; - case 48000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_48000; - break; - case 88200: - sampling_rate = MAX98373_PCM_SR_SET1_SR_88200; - break; - case 96000: - sampling_rate = MAX98373_PCM_SR_SET1_SR_96000; - break; - default: - dev_err(component->dev, "rate %d not supported\n", - params_rate(params)); - goto err; - } - - /* set DAI_SR to correct LRCLK frequency */ - regmap_update_bits(max98373->regmap, - MAX98373_R2027_PCM_SR_SETUP_1, - MAX98373_PCM_SR_SET1_SR_MASK, - sampling_rate); - regmap_update_bits(max98373->regmap, - MAX98373_R2028_PCM_SR_SETUP_2, - MAX98373_PCM_SR_SET2_SR_MASK, - sampling_rate << MAX98373_PCM_SR_SET2_SR_SHIFT); - - /* set sampling rate of IV */ - if (max98373->interleave_mode && - sampling_rate > MAX98373_PCM_SR_SET1_SR_16000) - regmap_update_bits(max98373->regmap, - MAX98373_R2028_PCM_SR_SETUP_2, - MAX98373_PCM_SR_SET2_IVADC_SR_MASK, - sampling_rate - 3); - else - regmap_update_bits(max98373->regmap, - MAX98373_R2028_PCM_SR_SETUP_2, - MAX98373_PCM_SR_SET2_IVADC_SR_MASK, - sampling_rate); - - return max98373_set_clock(component, params); -err: - return -EINVAL; -} - -static int max98373_dai_tdm_slot(struct snd_soc_dai *dai, - unsigned int tx_mask, unsigned int rx_mask, - int slots, int slot_width) -{ - struct snd_soc_component *component = dai->component; - struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); - int bsel = 0; - unsigned int chan_sz = 0; - unsigned int mask; - int x, slot_found; - - if (!tx_mask && !rx_mask && !slots && !slot_width) - max98373->tdm_mode = false; - else - max98373->tdm_mode = true; - - /* BCLK configuration */ - bsel = max98373_get_bclk_sel(slots * slot_width); - if (bsel == 0) { - dev_err(component->dev, "BCLK %d not supported\n", - slots * slot_width); - return -EINVAL; - } - - regmap_update_bits(max98373->regmap, - MAX98373_R2026_PCM_CLOCK_RATIO, - MAX98373_PCM_CLK_SETUP_BSEL_MASK, - bsel); - - /* Channel size configuration */ - switch (slot_width) { - case 16: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; - break; - case 24: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; - break; - case 32: - chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; - break; - default: - dev_err(component->dev, "format unsupported %d\n", - slot_width); - return -EINVAL; - } - - regmap_update_bits(max98373->regmap, - MAX98373_R2024_PCM_DATA_FMT_CFG, - MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); - - /* Rx slot configuration */ - slot_found = 0; - mask = rx_mask; - for (x = 0 ; x < 16 ; x++, mask >>= 1) { - if (mask & 0x1) { - if (slot_found == 0) - regmap_update_bits(max98373->regmap, - MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, - MAX98373_PCM_TO_SPK_CH0_SRC_MASK, x); - else - regmap_write(max98373->regmap, - MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, - x); - slot_found++; - if (slot_found > 1) - break; - } - } - - /* Tx slot Hi-Z configuration */ - regmap_write(max98373->regmap, - MAX98373_R2020_PCM_TX_HIZ_EN_1, - ~tx_mask & 0xFF); - regmap_write(max98373->regmap, - MAX98373_R2021_PCM_TX_HIZ_EN_2, - (~tx_mask & 0xFF00) >> 8); - - return 0; -} - -#define MAX98373_RATES SNDRV_PCM_RATE_8000_96000 - -#define MAX98373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops max98373_dai_ops = { - .set_fmt = max98373_dai_set_fmt, - .hw_params = max98373_dai_hw_params, - .set_tdm_slot = max98373_dai_tdm_slot, -}; - static int max98373_dac_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -493,52 +111,6 @@ static const DECLARE_TLV_DB_RANGE(max98373_bde_gain_tlv, 0, 60, TLV_DB_SCALE_ITEM(-1500, 25, 0), ); -static bool max98373_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case MAX98373_R2000_SW_RESET: - case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3: - case MAX98373_R2010_IRQ_CTRL: - case MAX98373_R2014_THERM_WARN_THRESH - ... MAX98373_R2018_THERM_FOLDBACK_EN: - case MAX98373_R201E_PIN_DRIVE_STRENGTH - ... MAX98373_R2036_SOUNDWIRE_CTRL: - case MAX98373_R203D_AMP_DIG_VOL_CTRL ... MAX98373_R2043_AMP_EN: - case MAX98373_R2046_IV_SENSE_ADC_DSP_CFG - ... MAX98373_R2047_IV_SENSE_ADC_EN: - case MAX98373_R2051_MEAS_ADC_SAMPLING_RATE - ... MAX98373_R2056_MEAS_ADC_PVDD_CH_EN: - case MAX98373_R2090_BDE_LVL_HOLD ... MAX98373_R2092_BDE_CLIPPER_MODE: - case MAX98373_R2097_BDE_L1_THRESH - ... MAX98373_R209B_BDE_THRESH_HYST: - case MAX98373_R20A8_BDE_L1_CFG_1 ... MAX98373_R20B3_BDE_L4_CFG_3: - case MAX98373_R20B5_BDE_EN ... MAX98373_R20B6_BDE_CUR_STATE_READBACK: - case MAX98373_R20D1_DHT_CFG ... MAX98373_R20D4_DHT_EN: - case MAX98373_R20E0_LIMITER_THRESH_CFG ... MAX98373_R20E2_LIMITER_EN: - case MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG - ... MAX98373_R20FF_GLOBAL_SHDN: - case MAX98373_R21FF_REV_ID: - return true; - default: - return false; - } -}; - -static bool max98373_volatile_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3: - case MAX98373_R203E_AMP_PATH_GAIN: - case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK: - case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK: - case MAX98373_R20B6_BDE_CUR_STATE_READBACK: - case MAX98373_R21FF_REV_ID: - return true; - default: - return false; - } -} - static const char * const max98373_output_voltage_lvl_text[] = { "5.43V", "6.09V", "6.83V", "7.67V", "8.60V", "9.65V", "10.83V", "12.15V", "13.63V", "15.29V" @@ -710,28 +282,7 @@ static const struct snd_soc_dapm_route max98373_audio_map[] = { { "Speaker FB Sense", NULL, "SpkFB Sense" }, }; -static struct snd_soc_dai_driver max98373_dai[] = { - { - .name = "max98373-aif1", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = MAX98373_RATES, - .formats = MAX98373_FORMATS, - }, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = MAX98373_RATES, - .formats = MAX98373_FORMATS, - }, - .ops = &max98373_dai_ops, - } -}; - -static void max98373_reset(struct max98373_priv *max98373, struct device *dev) +void max98373_reset(struct max98373_priv *max98373, struct device *dev) { int ret, reg, count; @@ -757,6 +308,7 @@ static void max98373_reset(struct max98373_priv *max98373, struct device *dev) } dev_err(dev, "Reset failed. (ret:%d)\n", ret); } +EXPORT_SYMBOL_GPL(max98373_reset); static int max98373_probe(struct snd_soc_component *component) { @@ -830,31 +382,7 @@ static int max98373_probe(struct snd_soc_component *component) return 0; } -#ifdef CONFIG_PM_SLEEP -static int max98373_suspend(struct device *dev) -{ - struct max98373_priv *max98373 = dev_get_drvdata(dev); - - regcache_cache_only(max98373->regmap, true); - regcache_mark_dirty(max98373->regmap); - return 0; -} -static int max98373_resume(struct device *dev) -{ - struct max98373_priv *max98373 = dev_get_drvdata(dev); - - regcache_cache_only(max98373->regmap, false); - max98373_reset(max98373, dev); - regcache_sync(max98373->regmap); - return 0; -} -#endif - -static const struct dev_pm_ops max98373_pm = { - SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume) -}; - -static const struct snd_soc_component_driver soc_codec_dev_max98373 = { +const struct snd_soc_component_driver soc_codec_dev_max98373 = { .probe = max98373_probe, .controls = max98373_snd_controls, .num_controls = ARRAY_SIZE(max98373_snd_controls), @@ -866,23 +394,26 @@ static const struct snd_soc_component_driver soc_codec_dev_max98373 = { .endianness = 1, .non_legacy_dai_naming = 1, }; +EXPORT_SYMBOL_GPL(soc_codec_dev_max98373); -static const struct regmap_config max98373_regmap = { - .reg_bits = 16, - .val_bits = 8, - .max_register = MAX98373_R21FF_REV_ID, - .reg_defaults = max98373_reg, - .num_reg_defaults = ARRAY_SIZE(max98373_reg), - .readable_reg = max98373_readable_register, - .volatile_reg = max98373_volatile_reg, - .cache_type = REGCACHE_RBTREE, +const struct snd_soc_component_driver soc_codec_dev_max98373_sdw = { + .probe = NULL, + .controls = max98373_snd_controls, + .num_controls = ARRAY_SIZE(max98373_snd_controls), + .dapm_widgets = max98373_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98373_dapm_widgets), + .dapm_routes = max98373_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98373_audio_map), + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, }; +EXPORT_SYMBOL_GPL(soc_codec_dev_max98373_sdw); -static void max98373_slot_config(struct i2c_client *i2c, - struct max98373_priv *max98373) +void max98373_slot_config(struct device *dev, + struct max98373_priv *max98373) { int value; - struct device *dev = &i2c->dev; if (!device_property_read_u32(dev, "maxim,vmon-slot-no", &value)) max98373->v_slot = value & 0xF; @@ -914,111 +445,7 @@ static void max98373_slot_config(struct i2c_client *i2c, else max98373->spkfb_slot = 2; } - -static int max98373_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - - int ret = 0; - int reg = 0; - struct max98373_priv *max98373 = NULL; - - max98373 = devm_kzalloc(&i2c->dev, sizeof(*max98373), GFP_KERNEL); - - if (!max98373) { - ret = -ENOMEM; - return ret; - } - i2c_set_clientdata(i2c, max98373); - - /* update interleave mode info */ - if (device_property_read_bool(&i2c->dev, "maxim,interleave_mode")) - max98373->interleave_mode = true; - else - max98373->interleave_mode = false; - - /* regmap initialization */ - max98373->regmap - = devm_regmap_init_i2c(i2c, &max98373_regmap); - if (IS_ERR(max98373->regmap)) { - ret = PTR_ERR(max98373->regmap); - dev_err(&i2c->dev, - "Failed to allocate regmap: %d\n", ret); - return ret; - } - - /* voltage/current slot & gpio configuration */ - max98373_slot_config(i2c, max98373); - - /* Power on device */ - if (gpio_is_valid(max98373->reset_gpio)) { - ret = devm_gpio_request(&i2c->dev, max98373->reset_gpio, - "MAX98373_RESET"); - if (ret) { - dev_err(&i2c->dev, "%s: Failed to request gpio %d\n", - __func__, max98373->reset_gpio); - return -EINVAL; - } - gpio_direction_output(max98373->reset_gpio, 0); - msleep(50); - gpio_direction_output(max98373->reset_gpio, 1); - msleep(20); - } - - /* Check Revision ID */ - ret = regmap_read(max98373->regmap, - MAX98373_R21FF_REV_ID, ®); - if (ret < 0) { - dev_err(&i2c->dev, - "Failed to read: 0x%02X\n", MAX98373_R21FF_REV_ID); - return ret; - } - dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg); - - /* codec registeration */ - ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373, - max98373_dai, ARRAY_SIZE(max98373_dai)); - if (ret < 0) - dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); - - return ret; -} - -static const struct i2c_device_id max98373_i2c_id[] = { - { "max98373", 0}, - { }, -}; - -MODULE_DEVICE_TABLE(i2c, max98373_i2c_id); - -#if defined(CONFIG_OF) -static const struct of_device_id max98373_of_match[] = { - { .compatible = "maxim,max98373", }, - { } -}; -MODULE_DEVICE_TABLE(of, max98373_of_match); -#endif - -#ifdef CONFIG_ACPI -static const struct acpi_device_id max98373_acpi_match[] = { - { "MX98373", 0 }, - {}, -}; -MODULE_DEVICE_TABLE(acpi, max98373_acpi_match); -#endif - -static struct i2c_driver max98373_i2c_driver = { - .driver = { - .name = "max98373", - .of_match_table = of_match_ptr(max98373_of_match), - .acpi_match_table = ACPI_PTR(max98373_acpi_match), - .pm = &max98373_pm, - }, - .probe = max98373_i2c_probe, - .id_table = max98373_i2c_id, -}; - -module_i2c_driver(max98373_i2c_driver) +EXPORT_SYMBOL_GPL(max98373_slot_config); MODULE_DESCRIPTION("ALSA SoC MAX98373 driver"); MODULE_AUTHOR("Ryan Lee "); diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index 63dae8be7105b2aa5c61c509f16c5dd9bd1b402b..4ab29b9d51c74edd602d036e13c110b14ceb56f1 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2017, Maxim Integrated +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2017 Maxim Integrated */ #ifndef _MAX98373_H #define _MAX98373_H @@ -212,5 +212,18 @@ struct max98373_priv { bool interleave_mode; unsigned int ch_size; bool tdm_mode; + /* variables to support soundwire */ + struct sdw_slave *slave; + bool hw_init; + bool pm_init_once; + int slot; + unsigned int rx_mask; }; + +extern const struct snd_soc_component_driver soc_codec_dev_max98373; +extern const struct snd_soc_component_driver soc_codec_dev_max98373_sdw; + +void max98373_reset(struct max98373_priv *max98373, struct device *dev); +void max98373_slot_config(struct device *dev, + struct max98373_priv *max98373); #endif diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c index e6613b52bd78f05f26ea45c462b8c462b5f00479..ff5cc9bbec2917655cc738259f07b0ece6a9a024 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -678,7 +678,7 @@ static const struct snd_kcontrol_new max98390_dai_controls = static const struct snd_soc_dapm_widget max98390_dapm_widgets[] = { SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", - MAX98390_R203A_AMP_EN, 0, 0, max98390_dac_event, + SND_SOC_NOPM, 0, 0, max98390_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0, &max98390_dai_controls), @@ -790,7 +790,7 @@ static int max98390_dsm_init(struct snd_soc_component *component) param_start_addr = (dsm_param[0] & 0xff) | (dsm_param[1] & 0xff) << 8; param_size = (dsm_param[2] & 0xff) | (dsm_param[3] & 0xff) << 8; if (param_size > MAX98390_DSM_PARAM_MAX_SIZE || - param_start_addr < DSM_STBASS_HPF_B0_BYTE0 || + param_start_addr < MAX98390_IRQ_CTRL || fw->size < param_size + MAX98390_DSM_PAYLOAD_OFFSET) { dev_err(component->dev, "param fw is invalid.\n"); @@ -842,6 +842,20 @@ static int max98390_dsm_calibrate(struct snd_soc_component *component) return 0; } +static void max98390_init_regs(struct snd_soc_component *component) +{ + struct max98390_priv *max98390 = + snd_soc_component_get_drvdata(component); + + regmap_write(max98390->regmap, MAX98390_CLK_MON, 0x6f); + regmap_write(max98390->regmap, MAX98390_DAT_MON, 0x00); + regmap_write(max98390->regmap, MAX98390_PWR_GATE_CTL, 0x00); + regmap_write(max98390->regmap, MAX98390_PCM_RX_EN_A, 0x03); + regmap_write(max98390->regmap, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e); + regmap_write(max98390->regmap, MAX98390_BOOST_BYPASS1, 0x46); + regmap_write(max98390->regmap, MAX98390_FET_SCALING3, 0x03); +} + static int max98390_probe(struct snd_soc_component *component) { struct max98390_priv *max98390 = @@ -850,21 +864,13 @@ static int max98390_probe(struct snd_soc_component *component) regmap_write(max98390->regmap, MAX98390_SOFTWARE_RESET, 0x01); /* Sleep reset settle time */ msleep(20); + + /* Amp init setting */ + max98390_init_regs(component); /* Update dsm bin param */ max98390_dsm_init(component); - /* Amp Setting */ - regmap_write(max98390->regmap, MAX98390_CLK_MON, 0x6f); - regmap_write(max98390->regmap, MAX98390_PCM_RX_EN_A, 0x03); - regmap_write(max98390->regmap, MAX98390_PWR_GATE_CTL, 0x2d); - regmap_write(max98390->regmap, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e); - regmap_write(max98390->regmap, MAX98390_BOOST_BYPASS1, 0x46); - regmap_write(max98390->regmap, MAX98390_FET_SCALING3, 0x03); - /* Dsm Setting */ - regmap_write(max98390->regmap, DSM_VOL_CTRL, 0x94); - regmap_write(max98390->regmap, DSMIG_EN, 0x19); - regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x80); if (max98390->ref_rdc_value) { regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE0, max98390->ref_rdc_value & 0x000000ff); @@ -938,14 +944,6 @@ static const struct regmap_config max98390_regmap = { .cache_type = REGCACHE_RBTREE, }; -#ifdef CONFIG_OF -static const struct of_device_id max98390_dt_ids[] = { - { .compatible = "maxim,max98390", }, - { } -}; -MODULE_DEVICE_TABLE(of, max98390_dt_ids); -#endif - static int max98390_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { diff --git a/sound/soc/codecs/max98390.h b/sound/soc/codecs/max98390.h index 5f444e7779b0a38ae54389b563f3159b6ca284d9..dff884f68e3e9f996b6e7b1e42df16943fc11e2c 100644 --- a/sound/soc/codecs/max98390.h +++ b/sound/soc/codecs/max98390.h @@ -650,7 +650,7 @@ /* DSM register offset */ #define MAX98390_DSM_PAYLOAD_OFFSET 16 -#define MAX98390_DSM_PARAM_MAX_SIZE 770 +#define MAX98390_DSM_PARAM_MAX_SIZE 1024 #define MAX98390_DSM_PARAM_MIN_SIZE 670 struct max98390_priv { diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 6f43748f923949df39dc5be45a1fe8e40568b18a..dec51893af74f421077139ada554540126f35db4 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -7,7 +7,7 @@ * Author: Christian Glindkamp * * Initial development of this code was funded by - * MICRONIC Computer Systeme GmbH, http://www.mcsberlin.de/ + * MICRONIC Computer Systeme GmbH, https://www.mcsberlin.de/ */ #include @@ -121,7 +121,7 @@ static int max9850_hw_params(struct snd_pcm_substream *substream, return -EINVAL; /* lrclk_div = 2^22 * rate / iclk with iclk = mclk / sf */ - sf = (snd_soc_component_read32(component, MAX9850_CLOCK) >> 2) + 1; + sf = (snd_soc_component_read(component, MAX9850_CLOCK) >> 2) + 1; lrclk_div = (1 << 22); lrclk_div *= params_rate(params); lrclk_div *= sf; diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c index 8be636fe6552063d0a59cad9e215bf377eec686a..d5925c42b4b572142dee65a0b1bdc9a4def2f4ff 100644 --- a/sound/soc/codecs/max9860.c +++ b/sound/soc/codecs/max9860.c @@ -334,7 +334,7 @@ static int max9860_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } ifc1a ^= MAX9860_WCI; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_IB_NF: ifc1a ^= MAX9860_DBCI; ifc1b ^= MAX9860_ABCI; diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index c72cb2888c21664209764eccd778f6b26d12e07e..fcb31144d69ced3d79d929096985643beb21b61f 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -283,7 +283,7 @@ static int max9867_dai_hw_params(struct snd_pcm_substream *substream, return 0; } -static int max9867_mute(struct snd_soc_dai *dai, int mute) +static int max9867_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component); @@ -393,9 +393,10 @@ static int max9867_dai_set_fmt(struct snd_soc_dai *codec_dai, static const struct snd_soc_dai_ops max9867_dai_ops = { .set_sysclk = max9867_set_dai_sysclk, .set_fmt = max9867_dai_set_fmt, - .digital_mute = max9867_mute, + .mute_stream = max9867_mute, .startup = max9867_startup, .hw_params = max9867_dai_hw_params, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver max9867_dai[] = { diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index f9830bd3da18c1338ed88d6b479ec17a5e340dc4..9e6a0cda43d0b023bb27bf346c19ede4b0ed612a 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -5,7 +5,7 @@ * Copyright 2012 Philippe Retornaz, philippe.retornaz@epfl.ch * * Initial development of this code was funded by - * Phytec Messtechnik GmbH, http://www.phytec.de + * Phytec Messtechnik GmbH, https://www.phytec.de */ #include #include diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 55823bc95d06f577499fe056b570a22ab67c347c..70c17be455cae424bdbe9c2e22dbe59559e940d2 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -372,7 +372,7 @@ static int ml26124_hw_params(struct snd_pcm_substream *substream, return 0; } -static int ml26124_mute(struct snd_soc_dai *dai, int mute) +static int ml26124_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct ml26124_priv *priv = snd_soc_component_get_drvdata(component); @@ -492,9 +492,10 @@ static int ml26124_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops ml26124_dai_ops = { .hw_params = ml26124_hw_params, - .digital_mute = ml26124_mute, + .mute_stream = ml26124_mute, .set_fmt = ml26124_set_dai_fmt, .set_sysclk = ml26124_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ml26124_dai = { diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 85bc7ae4d26712f6f37b0a32c4d2557b45c2bf7b..4428c62e25cf03e3ea0fe070c6d00ceb30928f9e 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -510,7 +510,7 @@ static void pm8916_wcd_setup_mbhc(struct pm8916_wcd_analog_priv *wcd) DIG_CLK_CTL_D_MBHC_CLK_EN_MASK, DIG_CLK_CTL_D_MBHC_CLK_EN); - if (snd_soc_component_read32(component, CDC_A_MICB_2_EN) & CDC_A_MICB_2_EN_ENABLE) + if (snd_soc_component_read(component, CDC_A_MICB_2_EN) & CDC_A_MICB_2_EN_ENABLE) micbias_enabled = true; pm8916_mbhc_configure_bias(wcd, micbias_enabled); @@ -608,7 +608,7 @@ static int pm8916_wcd_analog_enable_adc(struct snd_soc_dapm_widget *w, case CDC_A_TX_2_EN: snd_soc_component_update_bits(component, CDC_A_MICB_1_CTL, MICB_1_CTL_CFILT_REF_SEL_MASK, 0); - /* fall through */ + fallthrough; case CDC_A_TX_3_EN: snd_soc_component_update_bits(component, CDC_D_CDC_CONN_TX2_CTL, CONN_TX2_SERIAL_TX2_MUX, @@ -730,8 +730,8 @@ static int pm8916_wcd_analog_probe(struct snd_soc_component *component) snd_soc_component_init_regmap(component, dev_get_regmap(component->dev->parent, NULL)); snd_soc_component_set_drvdata(component, priv); - priv->pmic_rev = snd_soc_component_read32(component, CDC_D_REVISION1); - priv->codec_version = snd_soc_component_read32(component, CDC_D_PERPH_SUBTYPE); + priv->pmic_rev = snd_soc_component_read(component, CDC_D_REVISION1); + priv->codec_version = snd_soc_component_read(component, CDC_D_PERPH_SUBTYPE); dev_info(component->dev, "PMIC REV: %d\t CODEC Version: %d\n", priv->pmic_rev, priv->codec_version); @@ -990,7 +990,7 @@ static irqreturn_t mbhc_btn_release_irq_handler(int irq, void *arg) if (priv->detect_accessory_type) { struct snd_soc_component *component = priv->component; - u32 val = snd_soc_component_read32(component, CDC_A_MBHC_RESULT_1); + u32 val = snd_soc_component_read(component, CDC_A_MBHC_RESULT_1); /* check if its BTN0 thats released */ if ((val != -1) && !(val & CDC_A_MBHC_RESULT_1_BTN_RESULT_MASK)) @@ -1009,7 +1009,7 @@ static irqreturn_t mbhc_btn_press_irq_handler(int irq, void *arg) struct snd_soc_component *component = priv->component; u32 btn_result; - btn_result = snd_soc_component_read32(component, CDC_A_MBHC_RESULT_1) & + btn_result = snd_soc_component_read(component, CDC_A_MBHC_RESULT_1) & CDC_A_MBHC_RESULT_1_BTN_RESULT_MASK; switch (btn_result) { @@ -1046,7 +1046,7 @@ static irqreturn_t pm8916_mbhc_switch_irq_handler(int irq, void *arg) struct snd_soc_component *component = priv->component; bool ins = false; - if (snd_soc_component_read32(component, CDC_A_MBHC_DET_CTL_1) & + if (snd_soc_component_read(component, CDC_A_MBHC_DET_CTL_1) & CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_MASK) ins = true; @@ -1059,7 +1059,7 @@ static irqreturn_t pm8916_mbhc_switch_irq_handler(int irq, void *arg) if (ins) { /* hs insertion */ bool micbias_enabled = false; - if (snd_soc_component_read32(component, CDC_A_MICB_2_EN) & + if (snd_soc_component_read(component, CDC_A_MICB_2_EN) & CDC_A_MICB_2_EN_ENABLE) micbias_enabled = true; diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c index 09fccacadd6b1ec38c7d06d115c6e9df7f11d70f..fcc10c8bc625951c9ffb12699cf05f3fb6f4b50b 100644 --- a/sound/soc/codecs/msm8916-wcd-digital.c +++ b/sound/soc/codecs/msm8916-wcd-digital.c @@ -366,7 +366,7 @@ static int msm8x16_wcd_codec_set_iir_gain(struct snd_soc_dapm_widget *w, reg = LPASS_CDC_IIR1_GAIN_B1_CTL; else if (w->shift == 1) reg = LPASS_CDC_IIR2_GAIN_B1_CTL; - value = snd_soc_component_read32(component, reg); + value = snd_soc_component_read(component, reg); snd_soc_component_write(component, reg, value); break; default: @@ -387,7 +387,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t)) & 0x7F); - value |= snd_soc_component_read32(component, + value |= snd_soc_component_read(component, (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)); snd_soc_component_write(component, @@ -395,7 +395,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t) + 1) & 0x7F); - value |= (snd_soc_component_read32(component, + value |= (snd_soc_component_read(component, (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 8); snd_soc_component_write(component, @@ -403,7 +403,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t) + 2) & 0x7F); - value |= (snd_soc_component_read32(component, + value |= (snd_soc_component_read(component, (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 16); snd_soc_component_write(component, @@ -412,7 +412,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, * sizeof(uint32_t) + 3) & 0x7F); /* Mask bits top 2 bits since they are reserved */ - value |= ((snd_soc_component_read32(component, + value |= ((snd_soc_component_read(component, (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) & 0x3f) << 24); return value; @@ -584,7 +584,7 @@ static int msm8916_wcd_digital_enable_interpolator( /* apply the digital gain after the interpolator is enabled */ usleep_range(10000, 10100); snd_soc_component_write(component, rx_gain_reg[w->shift], - snd_soc_component_read32(component, rx_gain_reg[w->shift])); + snd_soc_component_read(component, rx_gain_reg[w->shift])); break; case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(component, LPASS_CDC_CLK_RX_RESET_CTL, @@ -615,7 +615,7 @@ static int msm8916_wcd_digital_enable_dec(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, tx_vol_ctl_reg, TX_VOL_CTL_CFG_MUTE_EN_MASK, TX_VOL_CTL_CFG_MUTE_EN_ENABLE); - dec_hpf_cut_of_freq = snd_soc_component_read32(component, tx_mux_ctl_reg) & + dec_hpf_cut_of_freq = snd_soc_component_read(component, tx_mux_ctl_reg) & TX_MUX_CTL_CUT_OFF_FREQ_MASK; dec_hpf_cut_of_freq >>= TX_MUX_CTL_CUT_OFF_FREQ_SHIFT; if (dec_hpf_cut_of_freq != TX_MUX_CTL_CF_NEG_3DB_150HZ) { @@ -632,7 +632,7 @@ static int msm8916_wcd_digital_enable_dec(struct snd_soc_dapm_widget *w, TX_MUX_CTL_HPF_BP_SEL_NO_BYPASS); /* apply the digital gain after the decimator is enabled */ snd_soc_component_write(component, tx_gain_reg[w->shift], - snd_soc_component_read32(component, tx_gain_reg[w->shift])); + snd_soc_component_read(component, tx_gain_reg[w->shift])); snd_soc_component_update_bits(component, tx_vol_ctl_reg, TX_VOL_CTL_CFG_MUTE_EN_MASK, 0); break; diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 1b830ea4f6ed0c9687b1265a1f6300849d52d47c..1f39d5998cf67518807f04fd30ddd7306af7132c 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -95,6 +95,8 @@ struct mt6358_priv { struct regulator *avdd_reg; int wov_enabled; + + unsigned int dmic_one_wire_mode; }; int mt6358_set_mtkaif_protocol(struct snd_soc_component *cmpnt, @@ -1831,7 +1833,10 @@ static int mt6358_dmic_enable(struct mt6358_priv *priv) mt6358_mtkaif_tx_enable(priv); /* UL dmic setting */ - regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0080); + if (priv->dmic_one_wire_mode) + regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0400); + else + regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0080); /* UL turn on */ regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_L, 0x0003); @@ -2426,6 +2431,20 @@ static const struct snd_soc_component_driver mt6358_soc_component_driver = { .num_dapm_routes = ARRAY_SIZE(mt6358_dapm_routes), }; +static void mt6358_parse_dt(struct mt6358_priv *priv) +{ + int ret; + struct device *dev = priv->dev; + + ret = of_property_read_u32(dev->of_node, "mediatek,dmic-mode", + &priv->dmic_one_wire_mode); + if (ret) { + dev_warn(priv->dev, "%s() failed to read dmic-mode\n", + __func__); + priv->dmic_one_wire_mode = 0; + } +} + static int mt6358_platform_driver_probe(struct platform_device *pdev) { struct mt6358_priv *priv; @@ -2445,6 +2464,8 @@ static int mt6358_platform_driver_probe(struct platform_device *pdev) if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); + mt6358_parse_dt(priv); + dev_info(priv->dev, "%s(), dev name %s\n", __func__, dev_name(&pdev->dev)); diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c index 78db3bd0b3bcb432f009ebd060bdab76683ac53f..609aeeb27818939d24a5636bbcde79895f47fdee 100644 --- a/sound/soc/codecs/nau8822.c +++ b/sound/soc/codecs/nau8822.c @@ -188,7 +188,7 @@ static int nau8822_eq_get(struct snd_kcontrol *kcontrol, val = (u16 *)ucontrol->value.bytes.data; reg = NAU8822_REG_EQ1; for (i = 0; i < params->max / sizeof(u16); i++) { - reg_val = snd_soc_component_read32(component, reg + i); + reg_val = snd_soc_component_read(component, reg + i); /* conversion of 16-bit integers between native CPU format * and big endian format */ @@ -445,7 +445,7 @@ static int check_mclk_select_pll(struct snd_soc_dapm_widget *source, snd_soc_dapm_to_component(source->dapm); unsigned int value; - value = snd_soc_component_read32(component, NAU8822_REG_CLOCKING); + value = snd_soc_component_read(component, NAU8822_REG_CLOCKING); return (value & NAU8822_CLKM_MASK); } @@ -831,7 +831,7 @@ static int nau8822_hw_params(struct snd_pcm_substream *substream, unsigned int ctrl_val, bclk_fs, bclk_div; /* make BCLK and LRC divide configuration if the codec as master. */ - snd_soc_component_read(component, NAU8822_REG_CLOCKING, &ctrl_val); + ctrl_val = snd_soc_component_read(component, NAU8822_REG_CLOCKING); if (ctrl_val & NAU8822_CLK_MASTER) { /* get the bclk and fs ratio */ bclk_fs = snd_soc_params_to_bclk(params) / params_rate(params); @@ -900,7 +900,7 @@ static int nau8822_hw_params(struct snd_pcm_substream *substream, return 0; } -static int nau8822_mute(struct snd_soc_dai *dai, int mute) +static int nau8822_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -967,10 +967,11 @@ static int nau8822_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops nau8822_dai_ops = { .hw_params = nau8822_hw_params, - .digital_mute = nau8822_mute, + .mute_stream = nau8822_mute, .set_fmt = nau8822_set_dai_fmt, .set_sysclk = nau8822_set_dai_sysclk, .set_pll = nau8822_set_pll, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver nau8822_dai = { diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 4767e158cd5ece91ccf1619ae29fe5dd7ecfed4d..07ed8fded471afc3874dc8e41301dff8ac1e67dd 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -147,7 +147,7 @@ static int pcm1681_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int pcm1681_digital_mute(struct snd_soc_dai *dai, int mute) +static int pcm1681_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct pcm1681_private *priv = snd_soc_component_get_drvdata(component); @@ -205,7 +205,8 @@ static int pcm1681_hw_params(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops pcm1681_dai_ops = { .set_fmt = pcm1681_set_dai_fmt, .hw_params = pcm1681_hw_params, - .digital_mute = pcm1681_digital_mute, + .mute_stream = pcm1681_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dapm_widget pcm1681_dapm_widgets[] = { diff --git a/sound/soc/codecs/pcm1789.c b/sound/soc/codecs/pcm1789.c index 8df6447c76a668d9c301f41303fae9e86cd4c5e7..620dec172ce77f3d2e86da7d4bad854e48ad32f5 100644 --- a/sound/soc/codecs/pcm1789.c +++ b/sound/soc/codecs/pcm1789.c @@ -60,7 +60,7 @@ static int pcm1789_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int pcm1789_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int pcm1789_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; struct pcm1789_private *priv = snd_soc_component_get_drvdata(component); @@ -167,8 +167,9 @@ static int pcm1789_trigger(struct snd_pcm_substream *substream, int cmd, static const struct snd_soc_dai_ops pcm1789_dai_ops = { .set_fmt = pcm1789_set_dai_fmt, .hw_params = pcm1789_hw_params, - .digital_mute = pcm1789_digital_mute, + .mute_stream = pcm1789_mute, .trigger = pcm1789_trigger, + .no_capture_mute = 1, }; static const DECLARE_TLV_DB_SCALE(pcm1789_dac_tlv, -12000, 50, 1); diff --git a/sound/soc/codecs/pcm179x.c b/sound/soc/codecs/pcm179x.c index 9e70b7385c692251bbd03f35b1e01d140869e989..ee60373d7d25426bdfa6b2a7acc6c6949dd5c44f 100644 --- a/sound/soc/codecs/pcm179x.c +++ b/sound/soc/codecs/pcm179x.c @@ -76,7 +76,7 @@ static int pcm179x_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int pcm179x_digital_mute(struct snd_soc_dai *dai, int mute) +static int pcm179x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct pcm179x_private *priv = snd_soc_component_get_drvdata(component); @@ -145,7 +145,8 @@ static int pcm179x_hw_params(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops pcm179x_dai_ops = { .set_fmt = pcm179x_set_dai_fmt, .hw_params = pcm179x_hw_params, - .digital_mute = pcm179x_digital_mute, + .mute_stream = pcm179x_mute, + .no_capture_mute = 1, }; static const DECLARE_TLV_DB_SCALE(pcm179x_dac_tlv, -12000, 50, 1); diff --git a/sound/soc/codecs/pcm186x-i2c.c b/sound/soc/codecs/pcm186x-i2c.c index 0214dc6d84d049d04a0ae1bfdbf0361ced357f24..f8382b74391d3630dcf3936f6066feea5d788c5d 100644 --- a/sound/soc/codecs/pcm186x-i2c.c +++ b/sound/soc/codecs/pcm186x-i2c.c @@ -2,7 +2,7 @@ /* * Texas Instruments PCM186x Universal Audio ADC - I2C * - * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com * Andreas Dannenberg * Andrew F. Davis */ diff --git a/sound/soc/codecs/pcm186x-spi.c b/sound/soc/codecs/pcm186x-spi.c index b56e198274979a8fa3403992e05d0089c0f243c4..bc1b0f0698ed39a7dbae4022f974af1c90e94010 100644 --- a/sound/soc/codecs/pcm186x-spi.c +++ b/sound/soc/codecs/pcm186x-spi.c @@ -2,7 +2,7 @@ /* * Texas Instruments PCM186x Universal Audio ADC - SPI * - * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com * Andreas Dannenberg * Andrew F. Davis */ diff --git a/sound/soc/codecs/pcm186x.c b/sound/soc/codecs/pcm186x.c index c5fcc632f67044a4bcc17f45a2420186a01a052d..f0da55901dcbe3e0c35a30f4452d758e9b795824 100644 --- a/sound/soc/codecs/pcm186x.c +++ b/sound/soc/codecs/pcm186x.c @@ -2,7 +2,7 @@ /* * Texas Instruments PCM186x Universal Audio ADC * - * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com * Andreas Dannenberg * Andrew F. Davis */ diff --git a/sound/soc/codecs/pcm186x.h b/sound/soc/codecs/pcm186x.h index bb3f0c42a1cdddb31a603948c39bafa56a42a654..4d493754a3e292252a998dfba3608ea1a4a2d672 100644 --- a/sound/soc/codecs/pcm186x.h +++ b/sound/soc/codecs/pcm186x.h @@ -2,7 +2,7 @@ /* * Texas Instruments PCM186x Universal Audio ADC * - * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com * Andreas Dannenberg * Andrew F. Davis */ diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 9711fab296ebc44a5aa469fd498a0cae952007b3..5e445fee4ef578ee959630ce37ac8e73c033cce2 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -290,7 +290,7 @@ static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a) PCM3168A_MRST_MASK | PCM3168A_SRST_MASK); } -static int pcm3168a_digital_mute(struct snd_soc_dai *dai, int mute) +static int pcm3168a_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); @@ -570,8 +570,9 @@ static const struct snd_soc_dai_ops pcm3168a_dai_ops = { .set_fmt = pcm3168a_set_dai_fmt, .set_sysclk = pcm3168a_set_dai_sysclk, .hw_params = pcm3168a_hw_params, - .digital_mute = pcm3168a_digital_mute, + .mute_stream = pcm3168a_mute, .set_tdm_slot = pcm3168a_set_tdm_slot, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver pcm3168a_dais[] = { diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 4cbef9affffda95ce6af991a40d8310cf11ed13d..8153d3d01654fc4061165f27965efaabb7094248 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -1394,7 +1394,7 @@ static int pcm512x_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) return 0; } -static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute) +static int pcm512x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component); @@ -1445,8 +1445,9 @@ static const struct snd_soc_dai_ops pcm512x_dai_ops = { .startup = pcm512x_dai_startup, .hw_params = pcm512x_hw_params, .set_fmt = pcm512x_set_fmt, - .digital_mute = pcm512x_digital_mute, + .mute_stream = pcm512x_mute, .set_bclk_ratio = pcm512x_set_bclk_ratio, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver pcm512x_dai = { diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c index 115706a55577d13189cd56032bd1950f845a13e9..940a2fa933edb458dc0588449e83ba49ae068d63 100644 --- a/sound/soc/codecs/rk3328_codec.c +++ b/sound/soc/codecs/rk3328_codec.c @@ -107,7 +107,7 @@ static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) return 0; } -static int rk3328_digital_mute(struct snd_soc_dai *dai, int mute) +static int rk3328_mute_stream(struct snd_soc_dai *dai, int mute, int direction) { struct rk3328_codec_priv *rk3328 = snd_soc_component_get_drvdata(dai->component); @@ -316,9 +316,10 @@ static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops rk3328_dai_ops = { .hw_params = rk3328_hw_params, .set_fmt = rk3328_set_dai_fmt, - .digital_mute = rk3328_digital_mute, + .mute_stream = rk3328_mute_stream, .startup = rk3328_pcm_startup, .shutdown = rk3328_pcm_shutdown, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver rk3328_dai[] = { diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c index 8c9daf32bab8460f797e817bc10e567a830d0856..d1fc1706422f6a845c241cd3593becc2754cb3c6 100644 --- a/sound/soc/codecs/rl6231.c +++ b/sound/soc/codecs/rl6231.c @@ -103,7 +103,9 @@ struct pll_calc_map { static const struct pll_calc_map pll_preset_table[] = { {19200000, 4096000, 23, 14, 1, false, false}, {19200000, 24576000, 3, 30, 3, false, false}, + {48000000, 3840000, 23, 2, 0, false, false}, {3840000, 24576000, 3, 30, 0, true, false}, + {3840000, 22579200, 3, 5, 0, true, false}, }; static unsigned int find_best_div(unsigned int in, diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index dec5638060c3c0ada8b681ce928e187d6d6a40de..098ecf13814d6b527af63ef11ed3d2f06e07e7a6 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -1849,13 +1849,13 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai, /* Rx slot configuration */ rx_slotnum = hweight_long(rx_mask); - first_bit = find_next_bit((unsigned long *)&rx_mask, 32, 0); - if (rx_slotnum > 1 || rx_slotnum == 0) { + if (rx_slotnum > 1 || !rx_slotnum) { ret = -EINVAL; - dev_dbg(component->dev, "too many rx slots or zero slot\n"); + dev_err(component->dev, "too many rx slots or zero slot\n"); goto _set_tdm_err_; } + first_bit = __ffs(rx_mask); switch (first_bit) { case 0: case 2: @@ -1892,11 +1892,17 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai, /* Tx slot configuration */ tx_slotnum = hweight_long(tx_mask); - first_bit = find_next_bit((unsigned long *)&tx_mask, 32, 0); - last_bit = find_last_bit((unsigned long *)&tx_mask, 32); - if (tx_slotnum > 2 || (last_bit-first_bit) > 1) { + if (tx_slotnum > 2 || !tx_slotnum) { ret = -EINVAL; - dev_dbg(component->dev, "too many tx slots or tx slot location error\n"); + dev_err(component->dev, "too many tx slots or zero slot\n"); + goto _set_tdm_err_; + } + + first_bit = __ffs(tx_mask); + last_bit = __fls(tx_mask); + if (last_bit - first_bit > 1) { + ret = -EINVAL; + dev_err(component->dev, "tx slot location error\n"); goto _set_tdm_err_; } diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 2cccb310fa968adaa19c22c4e549fd91764a615f..548f686490643c640d68e782169daecfca405247 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -8,23 +8,24 @@ // // +#include +#include +#include #include +#include +#include +#include #include #include -#include -#include +#include #include #include -#include -#include -#include -#include #include +#include #include #include -#include #include -#include +#include #include #include "rl6231.h" @@ -493,7 +494,7 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, if (!rt1015->dac_is_used) { rt1015->bypass_boost = ucontrol->value.integer.value[0]; - if (rt1015->bypass_boost == 1) { + if (rt1015->bypass_boost == RT1015_Bypass_Boost) { snd_soc_component_write(component, RT1015_PWR4, 0x00b2); snd_soc_component_write(component, @@ -549,7 +550,7 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: rt1015->dac_is_used = 1; - if (rt1015->bypass_boost == 0) { + if (rt1015->bypass_boost == RT1015_Enable_Boost) { snd_soc_component_write(component, RT1015_SYS_RST1, 0x05f7); snd_soc_component_write(component, @@ -566,8 +567,17 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, } break; + case SND_SOC_DAPM_POST_PMU: + if (rt1015->bypass_boost == RT1015_Bypass_Boost) { + regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x00a8); + regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597); + regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x05f7); + regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x0028); + } + break; + case SND_SOC_DAPM_POST_PMD: - if (rt1015->bypass_boost == 0) { + if (rt1015->bypass_boost == RT1015_Enable_Boost) { snd_soc_component_write(component, RT1015_PWR9, 0xa800); snd_soc_component_write(component, @@ -617,7 +627,8 @@ static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = { SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC_E("DAC", NULL, RT1015_PWR1, RT1015_PWR_DAC_BIT, 0, - r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_OUTPUT("SPO"), }; diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h index 8169962935a56a5c75769044dcf6034f066feb04..7bd159e8f9587b133c746ea8a8f6bc2d98864394 100644 --- a/sound/soc/codecs/rt1015.h +++ b/sound/soc/codecs/rt1015.h @@ -368,6 +368,11 @@ enum { FIXED_ADAPTIVE, }; +enum { + RT1015_Enable_Boost = 0, + RT1015_Bypass_Boost, +}; + struct rt1015_priv { struct snd_soc_component *component; struct regmap *regmap; diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c index e27742abfa765fcc989ea068f789c7b7fcbc493a..4e9dfd235e59abbb38bc3ab3759bf692fc6e96e9 100644 --- a/sound/soc/codecs/rt1305.c +++ b/sound/soc/codecs/rt1305.c @@ -411,7 +411,7 @@ static int rt1305_is_rc_clk_from_pll(struct snd_soc_dapm_widget *source, struct rt1305_priv *rt1305 = snd_soc_component_get_drvdata(component); unsigned int val; - snd_soc_component_read(component, RT1305_CLK_1, &val); + val = snd_soc_component_read(component, RT1305_CLK_1); if (rt1305->sysclk_src == RT1305_FS_SYS_PRE_S_PLL1 && (val & RT1305_SEL_PLL_SRC_2_RCCLK)) diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c index cbb5e176d11a882907a303a86c052f71fe21dd56..70cf17c0aa99ec13a1c557b5bae2fd324629386d 100644 --- a/sound/soc/codecs/rt274.c +++ b/sound/soc/codecs/rt274.c @@ -760,7 +760,7 @@ static int rt274_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, break; default: dev_warn(component->dev, "invalid pll source, use BCLK\n"); - /* fall through */ + fallthrough; case RT274_PLL2_S_BCLK: snd_soc_component_update_bits(component, RT274_PLL2_CTRL, RT274_PLL2_SRC_MASK, RT274_PLL2_SRC_BCLK); @@ -788,7 +788,7 @@ static int rt274_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, break; default: dev_warn(component->dev, "invalid freq_in, assume 4.8M\n"); - /* fall through */ + fallthrough; case 100: snd_soc_component_write(component, 0x7a, 0xaab6); snd_soc_component_write(component, 0x7b, 0x0301); @@ -1105,12 +1105,14 @@ static const struct i2c_device_id rt274_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt274_i2c_id); +#ifdef CONFIG_ACPI static const struct acpi_device_id rt274_acpi_match[] = { { "10EC0274", 0 }, { "INT34C2", 0 }, {}, }; MODULE_DEVICE_TABLE(acpi, rt274_acpi_match); +#endif static int rt274_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index e8d14eefc41bb973d09a1b48a84418a49f47f77a..5fb9653d9131f313d0b4f4c00bf6107be9f9f7a4 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1079,11 +1079,13 @@ static const struct i2c_device_id rt286_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); +#ifdef CONFIG_ACPI static const struct acpi_device_id rt286_acpi_match[] = { { "INT343A", 0 }, {}, }; MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); +#endif static const struct dmi_system_id force_combo_jack_table[] = { { diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index f8c0f977206c1bb35cf157bdb2a179c459f7cd8e..dc0273a5a11f7d9a2c0fb2e45432429fded5628f 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -508,7 +508,7 @@ static int rt298_adc_event(struct snd_soc_dapm_widget *w, VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), 0x7080, 0x7000); /* If MCLK doesn't exist, reset AD filter */ - if (!(snd_soc_component_read32(component, RT298_VAD_CTRL) & 0x200)) { + if (!(snd_soc_component_read(component, RT298_VAD_CTRL) & 0x200)) { pr_info("NO MCLK\n"); switch (nid) { case RT298_ADC_IN1: @@ -1145,11 +1145,13 @@ static const struct i2c_device_id rt298_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt298_i2c_id); +#ifdef CONFIG_ACPI static const struct acpi_device_id rt298_acpi_match[] = { { "INT343A", 0 }, {}, }; MODULE_DEVICE_TABLE(acpi, rt298_acpi_match); +#endif static const struct dmi_system_id force_combo_jack_table[] = { { diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index fcf16ec64d10b9f47244a79dc619ba9e4a464881..fd0d3a08e9dda716203de6597e1c9d5de8bb9048 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -348,7 +348,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, { unsigned int val; - val = snd_soc_component_read32(snd_soc_dapm_to_component(source->dapm), RT5616_GLB_CLK); + val = snd_soc_component_read(snd_soc_dapm_to_component(source->dapm), RT5616_GLB_CLK); val &= RT5616_SCLK_SRC_MASK; if (val == RT5616_SCLK_SRC_PLL1) return 1; diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index f70b9f7e68bbabf08b6888fdcd9351a6dec6328f..653da3eaf3559658dbb213025db359778aa687aa 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -64,7 +64,7 @@ static const struct reg_default rt5631_reg[] = { { RT5631_PSEUDO_SPATL_CTRL, 0x0553 }, }; -/** +/* * rt5631_write_index - write index register of 2nd layer */ static void rt5631_write_index(struct snd_soc_component *component, @@ -74,7 +74,7 @@ static void rt5631_write_index(struct snd_soc_component *component, snd_soc_component_write(component, RT5631_INDEX_DATA, value); } -/** +/* * rt5631_read_index - read index register of 2nd layer */ static unsigned int rt5631_read_index(struct snd_soc_component *component, @@ -83,7 +83,7 @@ static unsigned int rt5631_read_index(struct snd_soc_component *component, unsigned int value; snd_soc_component_write(component, RT5631_INDEX_ADD, reg); - value = snd_soc_component_read32(component, RT5631_INDEX_DATA); + value = snd_soc_component_read(component, RT5631_INDEX_DATA); return value; } @@ -285,7 +285,7 @@ static int check_sysclk1_source(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_GLOBAL_CLK_CTRL); + reg = snd_soc_component_read(component, RT5631_GLOBAL_CLK_CTRL); return reg & RT5631_SYSCLK_SOUR_SEL_PLL; } @@ -303,7 +303,7 @@ static int check_dacl_to_outmixl(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_OUTMIXER_L_CTRL); + reg = snd_soc_component_read(component, RT5631_OUTMIXER_L_CTRL); return !(reg & RT5631_M_DAC_L_TO_OUTMIXER_L); } @@ -313,7 +313,7 @@ static int check_dacr_to_outmixr(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_OUTMIXER_R_CTRL); + reg = snd_soc_component_read(component, RT5631_OUTMIXER_R_CTRL); return !(reg & RT5631_M_DAC_R_TO_OUTMIXER_R); } @@ -323,7 +323,7 @@ static int check_dacl_to_spkmixl(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_SPK_MIXER_CTRL); + reg = snd_soc_component_read(component, RT5631_SPK_MIXER_CTRL); return !(reg & RT5631_M_DAC_L_TO_SPKMIXER_L); } @@ -333,7 +333,7 @@ static int check_dacr_to_spkmixr(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_SPK_MIXER_CTRL); + reg = snd_soc_component_read(component, RT5631_SPK_MIXER_CTRL); return !(reg & RT5631_M_DAC_R_TO_SPKMIXER_R); } @@ -343,7 +343,7 @@ static int check_adcl_select(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_ADC_REC_MIXER); + reg = snd_soc_component_read(component, RT5631_ADC_REC_MIXER); return !(reg & RT5631_M_MIC1_TO_RECMIXER_L); } @@ -353,12 +353,13 @@ static int check_adcr_select(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, RT5631_ADC_REC_MIXER); + reg = snd_soc_component_read(component, RT5631_ADC_REC_MIXER); return !(reg & RT5631_M_MIC2_TO_RECMIXER_R); } /** * onebit_depop_power_stage - auto depop in power stage. + * @component: ASoC component * @enable: power on/off * * When power on/off headphone, the depop sequence is done by hardware. @@ -372,9 +373,9 @@ static void onebit_depop_power_stage(struct snd_soc_component *component, int en RT5631_EN_ONE_BIT_DEPOP, 0); /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_component_read32(component, RT5631_SOFT_VOL_CTRL); + soft_vol = snd_soc_component_read(component, RT5631_SOFT_VOL_CTRL); snd_soc_component_write(component, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_component_read32(component, RT5631_INT_ST_IRQ_CTRL_2); + hp_zc = snd_soc_component_read(component, RT5631_INT_ST_IRQ_CTRL_2); snd_soc_component_write(component, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); if (enable) { /* config one-bit depop parameter */ @@ -397,6 +398,7 @@ static void onebit_depop_power_stage(struct snd_soc_component *component, int en /** * onebit_depop_mute_stage - auto depop in mute stage. + * @component: ASoC component * @enable: mute/unmute * * When mute/unmute headphone, the depop sequence is done by hardware. @@ -410,9 +412,9 @@ static void onebit_depop_mute_stage(struct snd_soc_component *component, int ena RT5631_EN_ONE_BIT_DEPOP, 0); /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_component_read32(component, RT5631_SOFT_VOL_CTRL); + soft_vol = snd_soc_component_read(component, RT5631_SOFT_VOL_CTRL); snd_soc_component_write(component, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_component_read32(component, RT5631_INT_ST_IRQ_CTRL_2); + hp_zc = snd_soc_component_read(component, RT5631_INT_ST_IRQ_CTRL_2); snd_soc_component_write(component, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); if (enable) { schedule_timeout_uninterruptible(msecs_to_jiffies(10)); @@ -435,6 +437,7 @@ static void onebit_depop_mute_stage(struct snd_soc_component *component, int ena /** * onebit_depop_power_stage - step by step depop sequence in power stage. + * @component: ASoC component * @enable: power on/off * * When power on/off headphone, the depop sequence is done in step by step. @@ -448,9 +451,9 @@ static void depop_seq_power_stage(struct snd_soc_component *component, int enabl RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP); /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_component_read32(component, RT5631_SOFT_VOL_CTRL); + soft_vol = snd_soc_component_read(component, RT5631_SOFT_VOL_CTRL); snd_soc_component_write(component, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_component_read32(component, RT5631_INT_ST_IRQ_CTRL_2); + hp_zc = snd_soc_component_read(component, RT5631_INT_ST_IRQ_CTRL_2); snd_soc_component_write(component, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); if (enable) { /* config depop sequence parameter */ @@ -507,6 +510,7 @@ static void depop_seq_power_stage(struct snd_soc_component *component, int enabl /** * depop_seq_mute_stage - step by step depop sequence in mute stage. + * @component: ASoC component * @enable: mute/unmute * * When mute/unmute headphone, the depop sequence is done in step by step. @@ -520,9 +524,9 @@ static void depop_seq_mute_stage(struct snd_soc_component *component, int enable RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP); /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_component_read32(component, RT5631_SOFT_VOL_CTRL); + soft_vol = snd_soc_component_read(component, RT5631_SOFT_VOL_CTRL); snd_soc_component_write(component, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_component_read32(component, RT5631_INT_ST_IRQ_CTRL_2); + hp_zc = snd_soc_component_read(component, RT5631_INT_ST_IRQ_CTRL_2); snd_soc_component_write(component, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); if (enable) { schedule_timeout_uninterruptible(msecs_to_jiffies(10)); diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 747ca248bf10c9e4b1dc763ab25e3cffdefcde3c..1414ad15d01cff3478239f647e212e51d57f3ba1 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1651,7 +1651,7 @@ static int get_sdp_info(struct snd_soc_component *component, int dai_id) if (component == NULL) return -EINVAL; - val = snd_soc_component_read32(component, RT5640_I2S1_SDP); + val = snd_soc_component_read(component, RT5640_I2S1_SDP); val = (val & RT5640_I2S_IF_MASK) >> RT5640_I2S_IF_SFT; switch (dai_id) { case RT5640_AIF1: @@ -1662,7 +1662,7 @@ static int get_sdp_info(struct snd_soc_component *component, int dai_id) break; case RT5640_IF_113: ret |= RT5640_U_IF1; - /* fall through */ + fallthrough; case RT5640_IF_312: case RT5640_IF_213: ret |= RT5640_U_IF2; @@ -1678,7 +1678,7 @@ static int get_sdp_info(struct snd_soc_component *component, int dai_id) break; case RT5640_IF_223: ret |= RT5640_U_IF1; - /* fall through */ + fallthrough; case RT5640_IF_123: case RT5640_IF_321: ret |= RT5640_U_IF2; @@ -2081,7 +2081,7 @@ int rt5640_sel_asrc_clk_src(struct snd_soc_component *component, snd_soc_component_update_bits(component, RT5640_ASRC_2, asrc2_mask, asrc2_value); - if (snd_soc_component_read32(component, RT5640_ASRC_2)) { + if (snd_soc_component_read(component, RT5640_ASRC_2)) { rt5640->asrc_en = true; snd_soc_component_update_bits(component, RT5640_JD_CTRL, 0x3, 0x3); } else { @@ -2146,7 +2146,7 @@ static bool rt5640_micbias1_ovcd(struct snd_soc_component *component) { int val; - val = snd_soc_component_read32(component, RT5640_IRQ_CTRL2); + val = snd_soc_component_read(component, RT5640_IRQ_CTRL2); dev_dbg(component->dev, "irq ctrl2 %#04x\n", val); return (val & RT5640_MB1_OC_STATUS); @@ -2157,7 +2157,7 @@ static bool rt5640_jack_inserted(struct snd_soc_component *component) struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component); int val; - val = snd_soc_component_read32(component, RT5640_INT_IRQ_ST); + val = snd_soc_component_read(component, RT5640_INT_IRQ_ST); dev_dbg(component->dev, "irq status %#04x\n", val); if (rt5640->jd_inverted) @@ -2484,7 +2484,7 @@ static int rt5640_probe(struct snd_soc_component *component) snd_soc_component_update_bits(component, RT5640_MICBIAS, 0x0030, 0x0030); snd_soc_component_update_bits(component, RT5640_DSP_PATH2, 0xfc00, 0x0c00); - switch (snd_soc_component_read32(component, RT5640_RESET) & RT5640_ID_MASK) { + switch (snd_soc_component_read(component, RT5640_RESET) & RT5640_ID_MASK) { case RT5640_ID_5640: case RT5640_ID_5642: snd_soc_add_component_controls(component, diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index e2e1d5b03b38114b5c8d1bb90e64fa68fb75345c..420003d062c7f782aef04687149bbe4f62d8c7d1 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -866,7 +866,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int val; - val = snd_soc_component_read32(component, RT5645_GLB_CLK); + val = snd_soc_component_read(component, RT5645_GLB_CLK); val &= RT5645_SCLK_SRC_MASK; if (val == RT5645_SCLK_SRC_PLL1) return 1; @@ -909,7 +909,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case 1: case 2: @@ -3121,9 +3121,9 @@ static void rt5645_enable_push_button_irq(struct snd_soc_component *component, RT5645_INT_IRQ_ST, 0x8, 0x8); snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 0x8000, 0x8000); - snd_soc_component_read32(component, RT5650_4BTN_IL_CMD1); + snd_soc_component_read(component, RT5650_4BTN_IL_CMD1); pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1, - snd_soc_component_read32(component, RT5650_4BTN_IL_CMD1)); + snd_soc_component_read(component, RT5650_4BTN_IL_CMD1)); } else { snd_soc_component_update_bits(component, RT5650_4BTN_IL_CMD2, 0x8000, 0x0); snd_soc_component_update_bits(component, RT5645_INT_IRQ_ST, 0x8, 0x0); @@ -3216,7 +3216,7 @@ static int rt5645_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5650_4BTN_IL_CMD1); + val = snd_soc_component_read(component, RT5650_4BTN_IL_CMD1); pr_debug("val=0x%x\n", val); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5650_4BTN_IL_CMD1, val); @@ -3271,10 +3271,10 @@ static void rt5645_jack_detect_work(struct work_struct *work) report, SND_JACK_MICROPHONE); return; case 4: - val = snd_soc_component_read32(rt5645->component, RT5645_A_JD_CTRL1) & 0x0020; + val = snd_soc_component_read(rt5645->component, RT5645_A_JD_CTRL1) & 0x0020; break; default: /* read rt5645 jd1_1 status */ - val = snd_soc_component_read32(rt5645->component, RT5645_INT_IRQ_ST) & 0x1000; + val = snd_soc_component_read(rt5645->component, RT5645_INT_IRQ_ST) & 0x1000; break; } @@ -3284,7 +3284,7 @@ static void rt5645_jack_detect_work(struct work_struct *work) } else if (!val && rt5645->jack_type != 0) { /* for push button and jack out */ btn_type = 0; - if (snd_soc_component_read32(rt5645->component, RT5645_INT_IRQ_ST) & 0x4) { + if (snd_soc_component_read(rt5645->component, RT5645_INT_IRQ_ST) & 0x4) { /* button pressed */ report = SND_JACK_HEADSET; btn_type = rt5645_button_detect(rt5645->component); diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index c506c9305043e115711cbac86fb22e77734b0d54..d198e191fb0c9b7f93611d725fc88647983ad4fc 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1514,7 +1514,7 @@ static int rt5651_set_bias_level(struct snd_soc_component *component, switch (level) { case SND_SOC_BIAS_PREPARE: if (SND_SOC_BIAS_STANDBY == snd_soc_component_get_bias_level(component)) { - if (snd_soc_component_read32(component, RT5651_PLL_MODE_1) & 0x9200) + if (snd_soc_component_read(component, RT5651_PLL_MODE_1) & 0x9200) snd_soc_component_update_bits(component, RT5651_D_MISC, 0xc00, 0xc00); } @@ -1608,7 +1608,7 @@ static bool rt5651_micbias1_ovcd(struct snd_soc_component *component) { int val; - val = snd_soc_component_read32(component, RT5651_IRQ_CTRL2); + val = snd_soc_component_read(component, RT5651_IRQ_CTRL2); dev_dbg(component->dev, "irq ctrl2 %#04x\n", val); return (val & RT5651_MB1_OC_CLR); @@ -1625,7 +1625,7 @@ static bool rt5651_jack_inserted(struct snd_soc_component *component) return val; } - val = snd_soc_component_read32(component, RT5651_INT_IRQ_ST); + val = snd_soc_component_read(component, RT5651_INT_IRQ_ST); dev_dbg(component->dev, "irq status %#04x\n", val); switch (rt5651->jd_src) { diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 89e0f58512fa415e20c094894c51cae02702f1c2..41e5917b16a5eb8119282ef34ce146d855777ad8 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -1195,50 +1195,13 @@ static const struct snd_kcontrol_new rt5659_if3_dac_swap_mux = static const struct snd_kcontrol_new rt5659_if3_adc_swap_mux = SOC_DAPM_ENUM("IF3 ADC Swap Source", rt5659_if3_adc_enum); -static const char * const rt5659_asrc_clk_src[] = { - "clk_sysy_div_out", "clk_i2s1_track", "clk_i2s2_track", - "clk_i2s3_track", "clk_sys2", "clk_sys3" -}; - -static unsigned int rt5659_asrc_clk_map_values[] = { - 0, 1, 2, 3, 5, 6, -}; - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_da_sto_asrc_enum, RT5659_ASRC_2, RT5659_DA_STO_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_da_monol_asrc_enum, RT5659_ASRC_2, RT5659_DA_MONO_L_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_da_monor_asrc_enum, RT5659_ASRC_2, RT5659_DA_MONO_R_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_ad_sto1_asrc_enum, RT5659_ASRC_2, RT5659_AD_STO1_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_ad_sto2_asrc_enum, RT5659_ASRC_3, RT5659_AD_STO2_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_ad_monol_asrc_enum, RT5659_ASRC_3, RT5659_AD_MONO_L_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - -static SOC_VALUE_ENUM_SINGLE_DECL( - rt5659_ad_monor_asrc_enum, RT5659_ASRC_3, RT5659_AD_MONO_R_T_SFT, 0x7, - rt5659_asrc_clk_src, rt5659_asrc_clk_map_values); - static int rt5659_hp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); int ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (snd_soc_component_read32(component, RT5659_STO_NG2_CTRL_1) & RT5659_NG2_EN) { + if (snd_soc_component_read(component, RT5659_STO_NG2_CTRL_1) & RT5659_NG2_EN) { snd_soc_component_update_bits(component, RT5659_STO_NG2_CTRL_1, RT5659_NG2_EN_MASK, RT5659_NG2_DIS); snd_soc_component_update_bits(component, RT5659_STO_NG2_CTRL_1, @@ -1305,7 +1268,7 @@ static int rt5659_headset_detect(struct snd_soc_component *component, int jack_i snd_soc_dapm_force_enable_pin(dapm, "Mic Det Power"); snd_soc_dapm_sync(dapm); - reg_63 = snd_soc_component_read32(component, RT5659_PWR_ANLG_1); + reg_63 = snd_soc_component_read(component, RT5659_PWR_ANLG_1); snd_soc_component_update_bits(component, RT5659_PWR_ANLG_1, RT5659_PWR_VREF2 | RT5659_PWR_MB, @@ -1323,7 +1286,7 @@ static int rt5659_headset_detect(struct snd_soc_component *component, int jack_i while (i < 5) { msleep(sleep_time[i]); - val = snd_soc_component_read32(component, RT5659_EJD_CTRL_2) & 0x0003; + val = snd_soc_component_read(component, RT5659_EJD_CTRL_2) & 0x0003; i++; if (val == 0x1 || val == 0x2 || val == 0x3) break; @@ -1357,7 +1320,7 @@ static int rt5659_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5659_4BTN_IL_CMD_1); + val = snd_soc_component_read(component, RT5659_4BTN_IL_CMD_1); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5659_4BTN_IL_CMD_1, val); @@ -1396,7 +1359,7 @@ static void rt5659_jack_detect_work(struct work_struct *work) if (!rt5659->component) return; - val = snd_soc_component_read32(rt5659->component, RT5659_INT_ST_1) & 0x0080; + val = snd_soc_component_read(rt5659->component, RT5659_INT_ST_1) & 0x0080; if (!val) { /* jack in */ if (rt5659->jack_type == 0) { @@ -1696,7 +1659,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *w, unsigned int val; struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5659_GLB_CLK); + val = snd_soc_component_read(component, RT5659_GLB_CLK); val &= RT5659_SCLK_SRC_MASK; if (val == RT5659_SCLK_SRC_PLL1) return 1; @@ -1739,7 +1702,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *w, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case 1: case 2: diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c index efa145e9173118688c70d79d064efae732b003fe..9e3813f7583d97948ccc2b64f384076649bf242d 100644 --- a/sound/soc/codecs/rt5660.c +++ b/sound/soc/codecs/rt5660.c @@ -373,7 +373,7 @@ static int rt5660_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); unsigned int val; - val = snd_soc_component_read32(component, RT5660_GLB_CLK); + val = snd_soc_component_read(component, RT5660_GLB_CLK); val &= RT5660_SCLK_SRC_MASK; if (val == RT5660_SCLK_SRC_PLL1) return 1; @@ -1241,12 +1241,14 @@ static const struct of_device_id rt5660_of_match[] = { }; MODULE_DEVICE_TABLE(of, rt5660_of_match); +#ifdef CONFIG_ACPI static const struct acpi_device_id rt5660_acpi_match[] = { { "10EC5660", 0 }, { "10EC3277", 0 }, { }, }; MODULE_DEVICE_TABLE(acpi, rt5660_acpi_match); +#endif static int rt5660_parse_dt(struct rt5660_priv *rt5660, struct device *dev) { diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index e6c1ec6c426e5826060a57b11624566b3a4b6af9..619fb9a031e39a8a03e5134d7b8006e88292618a 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -1482,7 +1482,7 @@ static int rt5663_v2_jack_detect(struct snd_soc_component *component, int jack_i while (i < 5) { msleep(sleep_time[i]); - val = snd_soc_component_read32(component, RT5663_CBJ_TYPE_2) & 0x0003; + val = snd_soc_component_read(component, RT5663_CBJ_TYPE_2) & 0x0003; if (val == 0x1 || val == 0x2 || val == 0x3) break; dev_dbg(component->dev, "%s: MX-0011 val=%x sleep %d\n", @@ -1595,7 +1595,7 @@ static int rt5663_jack_detect(struct snd_soc_component *component, int jack_inse i++; } - val = snd_soc_component_read32(component, RT5663_EM_JACK_TYPE_2) & 0x0003; + val = snd_soc_component_read(component, RT5663_EM_JACK_TYPE_2) & 0x0003; dev_dbg(component->dev, "%s val = %d\n", __func__, val); snd_soc_component_update_bits(component, RT5663_HP_CHARGE_PUMP_1, @@ -1698,12 +1698,12 @@ static int rt5663_impedance_sensing(struct snd_soc_component *component) rt5663->imp_table[i].dc_offset_r_manual & 0xffff); } - reg84 = snd_soc_component_read32(component, RT5663_ASRC_2); - reg26 = snd_soc_component_read32(component, RT5663_STO1_ADC_MIXER); - reg2fa = snd_soc_component_read32(component, RT5663_DUMMY_1); - reg91 = snd_soc_component_read32(component, RT5663_HP_CHARGE_PUMP_1); - reg10 = snd_soc_component_read32(component, RT5663_RECMIX); - reg80 = snd_soc_component_read32(component, RT5663_GLB_CLK); + reg84 = snd_soc_component_read(component, RT5663_ASRC_2); + reg26 = snd_soc_component_read(component, RT5663_STO1_ADC_MIXER); + reg2fa = snd_soc_component_read(component, RT5663_DUMMY_1); + reg91 = snd_soc_component_read(component, RT5663_HP_CHARGE_PUMP_1); + reg10 = snd_soc_component_read(component, RT5663_RECMIX); + reg80 = snd_soc_component_read(component, RT5663_GLB_CLK); snd_soc_component_update_bits(component, RT5663_STO_DRE_1, 0x8000, 0); snd_soc_component_write(component, RT5663_ASRC_2, 0); @@ -1768,11 +1768,11 @@ static int rt5663_impedance_sensing(struct snd_soc_component *component) for (i = 0; i < 100; i++) { msleep(20); - if (snd_soc_component_read32(component, RT5663_INT_ST_1) & 0x2) + if (snd_soc_component_read(component, RT5663_INT_ST_1) & 0x2) break; } - value = snd_soc_component_read32(component, RT5663_HP_IMP_SEN_4); + value = snd_soc_component_read(component, RT5663_HP_IMP_SEN_4); snd_soc_component_update_bits(component, RT5663_DEPOP_1, 0x3000, 0); snd_soc_component_write(component, RT5663_INT_ST_1, 0); @@ -1843,7 +1843,7 @@ static int rt5663_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5663_IL_CMD_5); + val = snd_soc_component_read(component, RT5663_IL_CMD_5); dev_dbg(component->dev, "%s: val=0x%x\n", __func__, val); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5663_IL_CMD_5, val); @@ -1879,7 +1879,7 @@ static int rt5663_set_jack_detect(struct snd_soc_component *component, static bool rt5663_check_jd_status(struct snd_soc_component *component) { struct rt5663_priv *rt5663 = snd_soc_component_get_drvdata(component); - int val = snd_soc_component_read32(component, RT5663_INT_ST_1); + int val = snd_soc_component_read(component, RT5663_INT_ST_1); dev_dbg(component->dev, "%s val=%x\n", __func__, val); @@ -2072,7 +2072,7 @@ static int rt5663_is_sys_clk_from_pll(struct snd_soc_dapm_widget *w, unsigned int val; struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5663_GLB_CLK); + val = snd_soc_component_read(component, RT5663_GLB_CLK); val &= RT5663_SCLK_SRC_MASK; if (val == RT5663_SCLK_SRC_PLL1) return 1; @@ -2115,7 +2115,7 @@ static int rt5663_is_using_asrc(struct snd_soc_dapm_widget *w, } } - val = (snd_soc_component_read32(component, reg) >> shift) & 0x7; + val = (snd_soc_component_read(component, reg) >> shift) & 0x7; if (val) return 1; @@ -2130,15 +2130,15 @@ static int rt5663_i2s_use_asrc(struct snd_soc_dapm_widget *source, struct rt5663_priv *rt5663 = snd_soc_component_get_drvdata(component); int da_asrc_en, ad_asrc_en; - da_asrc_en = (snd_soc_component_read32(component, RT5663_ASRC_2) & + da_asrc_en = (snd_soc_component_read(component, RT5663_ASRC_2) & RT5663_DA_STO1_TRACK_MASK) ? 1 : 0; switch (rt5663->codec_ver) { case CODEC_VER_1: - ad_asrc_en = (snd_soc_component_read32(component, RT5663_ASRC_3) & + ad_asrc_en = (snd_soc_component_read(component, RT5663_ASRC_3) & RT5663_V2_AD_STO1_TRACK_MASK) ? 1 : 0; break; case CODEC_VER_0: - ad_asrc_en = (snd_soc_component_read32(component, RT5663_ASRC_2) & + ad_asrc_en = (snd_soc_component_read(component, RT5663_ASRC_2) & RT5663_AD_STO1_TRACK_MASK) ? 1 : 0; break; default: diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 68299ce26d3e44564ea26826cd4b21930c7a7816..8a915cdce0fe9949556af24e30dde9579b83dbcb 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -1000,7 +1000,7 @@ static int rt5665_hp_vol_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); int ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (snd_soc_component_read32(component, RT5665_STO_NG2_CTRL_1) & RT5665_NG2_EN) { + if (snd_soc_component_read(component, RT5665_STO_NG2_CTRL_1) & RT5665_NG2_EN) { snd_soc_component_update_bits(component, RT5665_STO_NG2_CTRL_1, RT5665_NG2_EN_MASK, RT5665_NG2_DIS); snd_soc_component_update_bits(component, RT5665_STO_NG2_CTRL_1, @@ -1016,7 +1016,7 @@ static int rt5665_mono_vol_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); int ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (snd_soc_component_read32(component, RT5665_MONO_NG2_CTRL_1) & RT5665_NG2_EN) { + if (snd_soc_component_read(component, RT5665_MONO_NG2_CTRL_1) & RT5665_NG2_EN) { snd_soc_component_update_bits(component, RT5665_MONO_NG2_CTRL_1, RT5665_NG2_EN_MASK, RT5665_NG2_DIS); snd_soc_component_update_bits(component, RT5665_MONO_NG2_CTRL_1, @@ -1126,7 +1126,7 @@ static int rt5665_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5665_4BTN_IL_CMD_1); + val = snd_soc_component_read(component, RT5665_4BTN_IL_CMD_1); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5665_4BTN_IL_CMD_1, val); @@ -1198,7 +1198,7 @@ static int rt5665_headset_detect(struct snd_soc_component *component, int jack_i usleep_range(10000, 15000); - rt5665->sar_adc_value = snd_soc_component_read32(rt5665->component, + rt5665->sar_adc_value = snd_soc_component_read(rt5665->component, RT5665_SAR_IL_CMD_4) & 0x7ff; sar_hs_type = rt5665->pdata.sar_hs_type ? @@ -1245,7 +1245,7 @@ static void rt5665_jd_check_handler(struct work_struct *work) struct rt5665_priv *rt5665 = container_of(work, struct rt5665_priv, jd_check_work.work); - if (snd_soc_component_read32(rt5665->component, RT5665_AJD1_CTRL) & 0x0010) { + if (snd_soc_component_read(rt5665->component, RT5665_AJD1_CTRL) & 0x0010) { /* jack out */ rt5665->jack_type = rt5665_headset_detect(rt5665->component, 0); @@ -1310,7 +1310,7 @@ static void rt5665_jack_detect_handler(struct work_struct *work) mutex_lock(&rt5665->calibrate_mutex); - val = snd_soc_component_read32(rt5665->component, RT5665_AJD1_CTRL) & 0x0010; + val = snd_soc_component_read(rt5665->component, RT5665_AJD1_CTRL) & 0x0010; if (!val) { /* jack in */ if (rt5665->jack_type == 0) { @@ -1522,7 +1522,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *w, unsigned int val; struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5665_GLB_CLK); + val = snd_soc_component_read(component, RT5665_GLB_CLK); val &= RT5665_SCLK_SRC_MASK; if (val == RT5665_SCLK_SRC_PLL1) return 1; @@ -1573,7 +1573,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *w, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case RT5665_CLK_SEL_I2S1_ASRC: case RT5665_CLK_SEL_I2S2_ASRC: diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c index 5716cede99cb4ecc3c6a60a0fbc9bf401044c4a2..bc69adc9c8b707bb8c3e292e35cd7a9ec474e093 100644 --- a/sound/soc/codecs/rt5668.c +++ b/sound/soc/codecs/rt5668.c @@ -847,7 +847,7 @@ static int rt5668_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5668_4BTN_IL_CMD_1); + val = snd_soc_component_read(component, RT5668_4BTN_IL_CMD_1); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5668_4BTN_IL_CMD_1, val); pr_debug("%s btn_type=%x\n", __func__, btn_type); @@ -907,11 +907,11 @@ static int rt5668_headset_detect(struct snd_soc_component *component, RT5668_TRIG_JD_MASK, RT5668_TRIG_JD_HIGH); count = 0; - val = snd_soc_component_read32(component, RT5668_CBJ_CTRL_2) + val = snd_soc_component_read(component, RT5668_CBJ_CTRL_2) & RT5668_JACK_TYPE_MASK; while (val == 0 && count < 50) { usleep_range(10000, 15000); - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, RT5668_CBJ_CTRL_2) & RT5668_JACK_TYPE_MASK; count++; } @@ -955,7 +955,7 @@ static void rt5668_jd_check_handler(struct work_struct *work) struct rt5668_priv *rt5668 = container_of(work, struct rt5668_priv, jd_check_work.work); - if (snd_soc_component_read32(rt5668->component, RT5668_AJD1_CTRL) + if (snd_soc_component_read(rt5668->component, RT5668_AJD1_CTRL) & RT5668_JDH_RS_MASK) { /* jack out */ rt5668->jack_type = rt5668_headset_detect(rt5668->component, 0); @@ -1030,7 +1030,7 @@ static void rt5668_jack_detect_handler(struct work_struct *work) mutex_lock(&rt5668->calibrate_mutex); - val = snd_soc_component_read32(rt5668->component, RT5668_AJD1_CTRL) + val = snd_soc_component_read(rt5668->component, RT5668_AJD1_CTRL) & RT5668_JDH_RS_MASK; if (!val) { /* jack in */ @@ -1191,7 +1191,7 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, int ref, val, reg, idx = -EINVAL; static const int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48}; - val = snd_soc_component_read32(component, RT5668_GPIO_CTRL_1) & + val = snd_soc_component_read(component, RT5668_GPIO_CTRL_1) & RT5668_GP4_PIN_MASK; if (w->shift == RT5668_PWR_ADC_S1F_BIT && val == RT5668_GP4_PIN_ADCDAT2) @@ -1219,7 +1219,7 @@ static int is_sys_clk_from_pll1(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5668_GLB_CLK); + val = snd_soc_component_read(component, RT5668_GLB_CLK); val &= RT5668_SCLK_SRC_MASK; if (val == RT5668_SCLK_SRC_PLL1) return 1; @@ -1247,7 +1247,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *w, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case RT5668_CLK_SEL_I2S1_ASRC: case RT5668_CLK_SEL_I2S2_ASRC: diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index dfbc0ca38ff7fef36d7c6b4e06066157cfd5ea23..a0c8f58d729b3ece5ae88a7770d2afe0f394475d 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -25,13 +25,12 @@ #include #include #include -#include #include "rl6231.h" #include "rt5670.h" #include "rt5670-dsp.h" -#define RT5670_DEV_GPIO BIT(0) +#define RT5670_GPIO1_IS_IRQ BIT(0) #define RT5670_IN2_DIFF BIT(1) #define RT5670_DMIC_EN BIT(2) #define RT5670_DMIC1_IN2P BIT(3) @@ -453,13 +452,13 @@ static int rt5670_headset_detect(struct snd_soc_component *component, int jack_i snd_soc_component_update_bits(component, RT5670_CJ_CTRL2, RT5670_CBJ_MN_JD, 0); msleep(300); - val = snd_soc_component_read32(component, RT5670_CJ_CTRL3) & 0x7; + val = snd_soc_component_read(component, RT5670_CJ_CTRL3) & 0x7; if (val == 0x1 || val == 0x2) { rt5670->jack_type = SND_JACK_HEADSET; /* for push button */ snd_soc_component_update_bits(component, RT5670_INT_IRQ_ST, 0x8, 0x8); snd_soc_component_update_bits(component, RT5670_IL_CMD, 0x40, 0x40); - snd_soc_component_read32(component, RT5670_IL_CMD); + snd_soc_component_read(component, RT5670_IL_CMD); } else { snd_soc_component_update_bits(component, RT5670_GEN_CTRL3, 0x4, 0x4); rt5670->jack_type = SND_JACK_HEADPHONE; @@ -499,12 +498,12 @@ static int rt5670_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5670_IL_CMD); + val = snd_soc_component_read(component, RT5670_IL_CMD); btn_type = val & 0xff80; snd_soc_component_write(component, RT5670_IL_CMD, val); if (btn_type != 0) { msleep(20); - val = snd_soc_component_read32(component, RT5670_IL_CMD); + val = snd_soc_component_read(component, RT5670_IL_CMD); snd_soc_component_write(component, RT5670_IL_CMD, val); } @@ -518,10 +517,10 @@ static int rt5670_irq_detection(void *data) struct snd_soc_jack *jack = rt5670->jack; int val, btn_type, report = jack->status; - if (rt5670->pdata.jd_mode == 1) /* 2 port */ - val = snd_soc_component_read32(rt5670->component, RT5670_A_JD_CTRL1) & 0x0070; + if (rt5670->jd_mode == 1) /* 2 port */ + val = snd_soc_component_read(rt5670->component, RT5670_A_JD_CTRL1) & 0x0070; else - val = snd_soc_component_read32(rt5670->component, RT5670_A_JD_CTRL1) & 0x0020; + val = snd_soc_component_read(rt5670->component, RT5670_A_JD_CTRL1) & 0x0020; switch (val) { /* jack in */ @@ -534,7 +533,7 @@ static int rt5670_irq_detection(void *data) break; } btn_type = 0; - if (snd_soc_component_read32(rt5670->component, RT5670_INT_IRQ_ST) & 0x4) { + if (snd_soc_component_read(rt5670->component, RT5670_INT_IRQ_ST) & 0x4) { /* button pressed */ report = SND_JACK_HEADSET; btn_type = rt5670_button_detect(rt5670->component); @@ -763,7 +762,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case 1: case 2: @@ -1454,7 +1453,7 @@ static int rt5670_spk_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component); - if (!rt5670->pdata.gpio1_is_ext_spk_en) + if (!rt5670->gpio1_is_ext_spk_en) return 0; switch (event) { @@ -2624,7 +2623,7 @@ static int rt5670_set_bias_level(struct snd_soc_component *component, RT5670_LDO_SEL_MASK, 0x3); break; case SND_SOC_BIAS_OFF: - if (rt5670->pdata.jd_mode) + if (rt5670->jd_mode) snd_soc_component_update_bits(component, RT5670_PWR_ANLG1, RT5670_PWR_VREF1 | RT5670_PWR_MB | RT5670_PWR_BG | RT5670_PWR_VREF2 | @@ -2651,7 +2650,7 @@ static int rt5670_probe(struct snd_soc_component *component) struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component); - switch (snd_soc_component_read32(component, RT5670_RESET) & RT5670_ID_MASK) { + switch (snd_soc_component_read(component, RT5670_RESET) & RT5670_ID_MASK) { case RT5670_ID_5670: case RT5670_ID_5671: snd_soc_dapm_new_controls(dapm, @@ -2834,7 +2833,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC1_IN2P | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE1), }, { @@ -2846,7 +2845,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC1_IN2P | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE1), }, { @@ -2858,7 +2857,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC2_INR | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE1), }, { @@ -2870,7 +2869,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC1_IN2P | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE1), }, { @@ -2882,7 +2881,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC1_IN2P | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE1), }, { @@ -2906,7 +2905,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC2_INR | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE3), }, { @@ -2918,7 +2917,7 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC2_INR | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE3), }, {} @@ -2927,7 +2926,6 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { static int rt5670_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct rt5670_platform_data *pdata = dev_get_platdata(&i2c->dev); struct rt5670_priv *rt5670; int ret; unsigned int val; @@ -2940,9 +2938,6 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, rt5670); - if (pdata) - rt5670->pdata = *pdata; - dmi_check_system(dmi_platform_intel_quirks); if (quirk_override) { dev_info(&i2c->dev, "Overriding quirk 0x%x => 0x%x\n", @@ -2950,57 +2945,57 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, rt5670_quirk = quirk_override; } - if (rt5670_quirk & RT5670_DEV_GPIO) { - rt5670->pdata.dev_gpio = true; - dev_info(&i2c->dev, "quirk dev_gpio\n"); + if (rt5670_quirk & RT5670_GPIO1_IS_IRQ) { + rt5670->gpio1_is_irq = true; + dev_info(&i2c->dev, "quirk GPIO1 is IRQ\n"); } if (rt5670_quirk & RT5670_GPIO1_IS_EXT_SPK_EN) { - rt5670->pdata.gpio1_is_ext_spk_en = true; + rt5670->gpio1_is_ext_spk_en = true; dev_info(&i2c->dev, "quirk GPIO1 is external speaker enable\n"); } if (rt5670_quirk & RT5670_IN2_DIFF) { - rt5670->pdata.in2_diff = true; + rt5670->in2_diff = true; dev_info(&i2c->dev, "quirk IN2_DIFF\n"); } if (rt5670_quirk & RT5670_DMIC_EN) { - rt5670->pdata.dmic_en = true; + rt5670->dmic_en = true; dev_info(&i2c->dev, "quirk DMIC enabled\n"); } if (rt5670_quirk & RT5670_DMIC1_IN2P) { - rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; + rt5670->dmic1_data_pin = RT5670_DMIC_DATA_IN2P; dev_info(&i2c->dev, "quirk DMIC1 on IN2P pin\n"); } if (rt5670_quirk & RT5670_DMIC1_GPIO6) { - rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_GPIO6; + rt5670->dmic1_data_pin = RT5670_DMIC_DATA_GPIO6; dev_info(&i2c->dev, "quirk DMIC1 on GPIO6 pin\n"); } if (rt5670_quirk & RT5670_DMIC1_GPIO7) { - rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_GPIO7; + rt5670->dmic1_data_pin = RT5670_DMIC_DATA_GPIO7; dev_info(&i2c->dev, "quirk DMIC1 on GPIO7 pin\n"); } if (rt5670_quirk & RT5670_DMIC2_INR) { - rt5670->pdata.dmic2_data_pin = RT5670_DMIC_DATA_IN3N; + rt5670->dmic2_data_pin = RT5670_DMIC_DATA_IN3N; dev_info(&i2c->dev, "quirk DMIC2 on INR pin\n"); } if (rt5670_quirk & RT5670_DMIC2_GPIO8) { - rt5670->pdata.dmic2_data_pin = RT5670_DMIC_DATA_GPIO8; + rt5670->dmic2_data_pin = RT5670_DMIC_DATA_GPIO8; dev_info(&i2c->dev, "quirk DMIC2 on GPIO8 pin\n"); } if (rt5670_quirk & RT5670_DMIC3_GPIO5) { - rt5670->pdata.dmic3_data_pin = RT5670_DMIC_DATA_GPIO5; + rt5670->dmic3_data_pin = RT5670_DMIC_DATA_GPIO5; dev_info(&i2c->dev, "quirk DMIC3 on GPIO5 pin\n"); } if (rt5670_quirk & RT5670_JD_MODE1) { - rt5670->pdata.jd_mode = 1; + rt5670->jd_mode = 1; dev_info(&i2c->dev, "quirk JD mode 1\n"); } if (rt5670_quirk & RT5670_JD_MODE2) { - rt5670->pdata.jd_mode = 2; + rt5670->jd_mode = 2; dev_info(&i2c->dev, "quirk JD mode 2\n"); } if (rt5670_quirk & RT5670_JD_MODE3) { - rt5670->pdata.jd_mode = 3; + rt5670->jd_mode = 3; dev_info(&i2c->dev, "quirk JD mode 3\n"); } @@ -3041,11 +3036,11 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, regmap_update_bits(rt5670->regmap, RT5670_DIG_MISC, RT5670_MCLK_DET, RT5670_MCLK_DET); - if (rt5670->pdata.in2_diff) + if (rt5670->in2_diff) regmap_update_bits(rt5670->regmap, RT5670_IN2, RT5670_IN_DF2, RT5670_IN_DF2); - if (rt5670->pdata.dev_gpio) { + if (rt5670->gpio1_is_irq) { /* for push button */ regmap_write(rt5670->regmap, RT5670_IL_CMD, 0x0000); regmap_write(rt5670->regmap, RT5670_IL_CMD2, 0x0010); @@ -3057,14 +3052,14 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); } - if (rt5670->pdata.gpio1_is_ext_spk_en) { + if (rt5670->gpio1_is_ext_spk_en) { regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_GPIO1); regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); } - if (rt5670->pdata.jd_mode) { + if (rt5670->jd_mode) { regmap_update_bits(rt5670->regmap, RT5670_GLB_CLK, RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_RCCLK); rt5670->sysclk = 0; @@ -3079,7 +3074,7 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, RT5670_JD_TRI_CBJ_SEL_MASK | RT5670_JD_TRI_HPO_SEL_MASK, RT5670_JD_CBJ_JD1_1 | RT5670_JD_HPO_JD1_1); - switch (rt5670->pdata.jd_mode) { + switch (rt5670->jd_mode) { case 1: regmap_update_bits(rt5670->regmap, RT5670_A_JD_CTRL1, RT5670_JD1_MODE_MASK, @@ -3100,12 +3095,12 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, } } - if (rt5670->pdata.dmic_en) { + if (rt5670->dmic_en) { regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, RT5670_GP2_PIN_MASK, RT5670_GP2_PIN_DMIC1_SCL); - switch (rt5670->pdata.dmic1_data_pin) { + switch (rt5670->dmic1_data_pin) { case RT5670_DMIC_DATA_IN2P: regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, RT5670_DMIC_1_DP_MASK, @@ -3134,7 +3129,7 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, break; } - switch (rt5670->pdata.dmic2_data_pin) { + switch (rt5670->dmic2_data_pin) { case RT5670_DMIC_DATA_IN3N: regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL1, RT5670_DMIC_2_DP_MASK, @@ -3154,7 +3149,7 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, break; } - switch (rt5670->pdata.dmic3_data_pin) { + switch (rt5670->dmic3_data_pin) { case RT5670_DMIC_DATA_GPIO5: regmap_update_bits(rt5670->regmap, RT5670_DMIC_CTRL2, RT5670_DMIC_3_DP_MASK, diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index de0203369b7cd92bb872cc82ab25c9c759e39916..56b13fe6bd3cb9167ab4e6d81997ad8d3432f485 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h @@ -9,8 +9,6 @@ #ifndef __RT5670_H__ #define __RT5670_H__ -#include - /* Info */ #define RT5670_RESET 0x00 #define RT5670_VENDOR_ID 0xfd @@ -1988,11 +1986,23 @@ int rt5670_sel_asrc_clk_src(struct snd_soc_component *component, struct rt5670_priv { struct snd_soc_component *component; - struct rt5670_platform_data pdata; struct regmap *regmap; struct snd_soc_jack *jack; struct snd_soc_jack_gpio hp_gpio; + int jd_mode; + bool in2_diff; + bool gpio1_is_irq; + bool gpio1_is_ext_spk_en; + + bool dmic_en; + unsigned int dmic1_data_pin; + /* 0 = GPIO6; 1 = IN2P; 3 = GPIO7*/ + unsigned int dmic2_data_pin; + /* 0 = GPIO8; 1 = IN3N; */ + unsigned int dmic3_data_pin; + /* 0 = GPIO9; 1 = GPIO10; 2 = GPIO5*/ + int sysclk; int sysclk_src; int lrck[RT5670_AIFS]; diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index 7bfade8b3d6e8ad5b66c45ec716ce7f581b77912..8f3993a4c1cc71102cf59813c2e8c52611df56fe 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c @@ -112,7 +112,7 @@ static int rt5677_spi_pcm_close( struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *codec_component = snd_soc_rtdcom_lookup(rtd, "rt5677"); struct rt5677_priv *rt5677 = @@ -158,7 +158,7 @@ static int rt5677_spi_prepare( struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *rt5677_component = snd_soc_rtdcom_lookup(rtd, "rt5677"); struct rt5677_priv *rt5677 = @@ -614,11 +614,13 @@ static int rt5677_spi_probe(struct spi_device *spi) return ret; } +#ifdef CONFIG_ACPI static const struct acpi_device_id rt5677_spi_acpi_id[] = { { "RT5677AA", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, rt5677_spi_acpi_id); +#endif static struct spi_driver rt5677_spi_driver = { .driver = { diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index e9a051a50ab2d106516c2bf2c89301e9912d601c..9e449d35fc2820cd717d70cf7d3258e5a1bda8b3 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -4609,7 +4609,7 @@ static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, break; case 25: slot_width_25 = 0x8080; - /* fall through */ + fallthrough; case 24: val |= (2 << 8); break; diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index e28d08b1cd65d7ee9d5a390e54fe1bd86eb64683..85aba311bdc8ea6a26b656f637729c7f43df4bfb 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -59,7 +59,7 @@ static void rt5682_jd_check_handler(struct work_struct *work) struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv, jd_check_work.work); - if (snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL) + if (snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) & RT5682_JDH_RS_MASK) { /* jack out */ rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0); @@ -232,7 +232,7 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); - regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); + regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0080); regmap_update_bits(rt5682->regmap, RT5682_GPIO_CTRL_1, RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK, RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1); diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 4cecc5ce545cb9999c4621d6f1ebf67456546ec4..94bf6bee78e6921ef4f2a543836d370118b738e5 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -431,7 +431,7 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1, RT5682_LDO1_DVO_MASK | RT5682_HP_DRIVER_MASK, RT5682_LDO1_DVO_12 | RT5682_HP_DRIVER_5X); - regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); + regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0080); regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8, RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index d503b5bef4ba9ba62dc33c48a2660c6d2d652593..a4713bd6508d52bfed3087a97d96bd1e425fa202 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -859,7 +859,7 @@ static int rt5682_button_detect(struct snd_soc_component *component) { int btn_type, val; - val = snd_soc_component_read32(component, RT5682_4BTN_IL_CMD_1); + val = snd_soc_component_read(component, RT5682_4BTN_IL_CMD_1); btn_type = val & 0xfff0; snd_soc_component_write(component, RT5682_4BTN_IL_CMD_1, val); dev_dbg(component->dev, "%s btn_type=%x\n", __func__, btn_type); @@ -939,11 +939,11 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_HIGH); count = 0; - val = snd_soc_component_read32(component, RT5682_CBJ_CTRL_2) + val = snd_soc_component_read(component, RT5682_CBJ_CTRL_2) & RT5682_JACK_TYPE_MASK; while (val == 0 && count < 50) { usleep_range(10000, 15000); - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, RT5682_CBJ_CTRL_2) & RT5682_JACK_TYPE_MASK; count++; } @@ -963,6 +963,9 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) RT5682_HP_CHARGE_PUMP_1, RT5682_OSW_L_MASK | RT5682_OSW_R_MASK, RT5682_OSW_L_EN | RT5682_OSW_R_EN); + snd_soc_component_update_bits(component, RT5682_MICBIAS_2, + RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK, + RT5682_PWR_CLK25M_PU | RT5682_PWR_CLK1M_PU); } else { rt5682_enable_push_button_irq(component, false); snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, @@ -975,6 +978,9 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) RT5682_PWR_ANLG_1, RT5682_PWR_VREF2, 0); snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3, RT5682_PWR_CBJ, 0); + snd_soc_component_update_bits(component, RT5682_MICBIAS_2, + RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK, + RT5682_PWR_CLK25M_PD | RT5682_PWR_CLK1M_PD); rt5682->jack_type = 0; } @@ -1022,8 +1028,7 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, RT5682_POW_ANA, RT5682_POW_IRQ | RT5682_POW_JDH | RT5682_POW_ANA); regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_2, - RT5682_PWR_JDH | RT5682_PWR_JDL, - RT5682_PWR_JDH | RT5682_PWR_JDL); + RT5682_PWR_JDH, RT5682_PWR_JDH); regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, RT5682_JD1_EN_MASK | RT5682_JD1_POL_MASK, RT5682_JD1_EN | RT5682_JD1_POL_NOR); @@ -1074,7 +1079,7 @@ void rt5682_jack_detect_handler(struct work_struct *work) mutex_lock(&rt5682->calibrate_mutex); - val = snd_soc_component_read32(rt5682->component, RT5682_AJD1_CTRL) + val = snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) & RT5682_JDH_RS_MASK; if (!val) { /* jack in */ @@ -1240,7 +1245,7 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, if (rt5682->is_sdw) return 0; - val = snd_soc_component_read32(component, RT5682_GPIO_CTRL_1) & + val = snd_soc_component_read(component, RT5682_GPIO_CTRL_1) & RT5682_GP4_PIN_MASK; if (w->shift == RT5682_PWR_ADC_S1F_BIT && val == RT5682_GP4_PIN_ADCDAT2) @@ -1278,7 +1283,7 @@ static int is_sys_clk_from_pll1(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5682_GLB_CLK); + val = snd_soc_component_read(component, RT5682_GLB_CLK); val &= RT5682_SCLK_SRC_MASK; if (val == RT5682_SCLK_SRC_PLL1) return 1; @@ -1293,7 +1298,7 @@ static int is_sys_clk_from_pll2(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - val = snd_soc_component_read32(component, RT5682_GLB_CLK); + val = snd_soc_component_read(component, RT5682_GLB_CLK); val &= RT5682_SCLK_SRC_MASK; if (val == RT5682_SCLK_SRC_PLL2) return 1; @@ -1321,7 +1326,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *w, return 0; } - val = (snd_soc_component_read32(component, reg) >> shift) & 0xf; + val = (snd_soc_component_read(component, reg) >> shift) & 0xf; switch (val) { case RT5682_CLK_SEL_I2S1_ASRC: case RT5682_CLK_SEL_I2S2_ASRC: @@ -2255,7 +2260,7 @@ static int rt5682_set_component_pll(struct snd_soc_component *component, { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); struct rl6231_pll_code pll_code, pll2f_code, pll2b_code; - unsigned int pll2_fout1; + unsigned int pll2_fout1, pll2_ps_val; int ret; if (source == rt5682->pll_src[pll_id] && @@ -2324,8 +2329,15 @@ static int rt5682_set_component_pll(struct snd_soc_component *component, pll2b_code.n_code); snd_soc_component_write(component, RT5682_PLL2_CTRL_3, pll2f_code.n_code << RT5682_PLL2F_N_SFT); + + if (freq_out == 22579200) + pll2_ps_val = 1 << RT5682_PLL2B_SEL_PS_SFT; + else + pll2_ps_val = 1 << RT5682_PLL2B_PS_BYP_SFT; snd_soc_component_update_bits(component, RT5682_PLL2_CTRL_4, + RT5682_PLL2B_SEL_PS_MASK | RT5682_PLL2B_PS_BYP_MASK | RT5682_PLL2B_M_BP_MASK | RT5682_PLL2F_M_BP_MASK | 0xf, + pll2_ps_val | (pll2b_code.m_bp ? 1 : 0) << RT5682_PLL2B_M_BP_SFT | (pll2f_code.m_bp ? 1 : 0) << RT5682_PLL2F_M_BP_SFT | 0xf); @@ -2463,8 +2475,8 @@ static int rt5682_set_bias_level(struct snd_soc_component *component, #ifdef CONFIG_COMMON_CLK #define CLK_PLL2_FIN 48000000 -#define CLK_PLL2_FOUT 24576000 #define CLK_48 48000 +#define CLK_44 44100 static bool rt5682_clk_check(struct rt5682_priv *rt5682) { @@ -2546,13 +2558,22 @@ static unsigned long rt5682_wclk_recalc_rate(struct clk_hw *hw, struct rt5682_priv *rt5682 = container_of(hw, struct rt5682_priv, dai_clks_hw[RT5682_DAI_WCLK_IDX]); + struct snd_soc_component *component = rt5682->component; + const char * const clk_name = __clk_get_name(hw->clk); if (!rt5682_clk_check(rt5682)) return 0; /* - * Only accept to set wclk rate to 48kHz temporarily. + * Only accept to set wclk rate to 44.1k or 48kHz. */ - return CLK_48; + if (rt5682->lrck[RT5682_AIF1] != CLK_48 && + rt5682->lrck[RT5682_AIF1] != CLK_44) { + dev_warn(component->dev, "%s: clk %s only support %d or %d Hz output\n", + __func__, clk_name, CLK_44, CLK_48); + return 0; + } + + return rt5682->lrck[RT5682_AIF1]; } static long rt5682_wclk_round_rate(struct clk_hw *hw, unsigned long rate, @@ -2561,13 +2582,22 @@ static long rt5682_wclk_round_rate(struct clk_hw *hw, unsigned long rate, struct rt5682_priv *rt5682 = container_of(hw, struct rt5682_priv, dai_clks_hw[RT5682_DAI_WCLK_IDX]); + struct snd_soc_component *component = rt5682->component; + const char * const clk_name = __clk_get_name(hw->clk); if (!rt5682_clk_check(rt5682)) return -EINVAL; /* - * Only accept to set wclk rate to 48kHz temporarily. + * Only accept to set wclk rate to 44.1k or 48kHz. + * It will force to 48kHz if not both. */ - return CLK_48; + if (rate != CLK_48 && rate != CLK_44) { + dev_warn(component->dev, "%s: clk %s only support %d or %d Hz output\n", + __func__, clk_name, CLK_44, CLK_48); + rate = CLK_48; + } + + return rate; } static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, @@ -2580,6 +2610,7 @@ static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, struct clk *parent_clk; const char * const clk_name = __clk_get_name(hw->clk); int pre_div; + unsigned int clk_pll2_out; if (!rt5682_clk_check(rt5682)) return -EINVAL; @@ -2602,23 +2633,17 @@ static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, clk_name, CLK_PLL2_FIN); /* - * It's a temporary limitation. Only accept to set wclk rate to 48kHz. - * It will force wclk to 48kHz even it's not. - */ - if (rate != CLK_48) { - dev_warn(component->dev, "clk %s only support %d Hz output\n", - clk_name, CLK_48); - rate = CLK_48; - } - - /* - * To achieve the rate conversion from 48MHz to 48kHz, PLL2 is needed. + * To achieve the rate conversion from 48MHz to 44.1k or 48kHz, + * PLL2 is needed. */ + clk_pll2_out = rate * 512; rt5682_set_component_pll(component, RT5682_PLL2, RT5682_PLL2_S_MCLK, - CLK_PLL2_FIN, CLK_PLL2_FOUT); + CLK_PLL2_FIN, clk_pll2_out); rt5682_set_component_sysclk(component, RT5682_SCLK_S_PLL2, 0, - CLK_PLL2_FOUT, SND_SOC_CLOCK_IN); + clk_pll2_out, SND_SOC_CLOCK_IN); + + rt5682->lrck[RT5682_AIF1] = rate; pre_div = rl6231_get_clk_info(rt5682->sysclk, rate); @@ -2639,8 +2664,7 @@ static unsigned long rt5682_bclk_recalc_rate(struct clk_hw *hw, struct snd_soc_component *component = rt5682->component; unsigned int bclks_per_wclk; - snd_soc_component_read(component, RT5682_TDM_TCON_CTRL, - &bclks_per_wclk); + bclks_per_wclk = snd_soc_component_read(component, RT5682_TDM_TCON_CTRL); switch (bclks_per_wclk & RT5682_TDM_BCLK_MS1_MASK) { case RT5682_TDM_BCLK_MS1_256: @@ -2823,6 +2847,7 @@ static int rt5682_probe(struct snd_soc_component *component) struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); struct sdw_slave *slave; unsigned long time; + struct snd_soc_dapm_context *dapm = &component->dapm; #ifdef CONFIG_COMMON_CLK int ret; @@ -2860,6 +2885,9 @@ static int rt5682_probe(struct snd_soc_component *component) #endif } + snd_soc_dapm_disable_pin(dapm, "MICBIAS"); + snd_soc_dapm_disable_pin(dapm, "Vref2"); + snd_soc_dapm_sync(dapm); return 0; } @@ -3012,13 +3040,14 @@ void rt5682_calibrate(struct rt5682_priv *rt5682) dev_err(rt5682->component->dev, "HP Calibration Failure\n"); /* restore settings */ - regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0x02af); + regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0x002f); regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0080); regmap_write(rt5682->regmap, RT5682_GLB_CLK, 0x0000); regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0000); regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x2000); regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x2005); regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0xc0c4); + regmap_write(rt5682->regmap, RT5682_CAL_REC, 0x0c0c); mutex_unlock(&rt5682->calibrate_mutex); } diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index f172c9ebd227f4da7e10b8da6927157dda02ddfc..6d94327beae5247c5fb4829a6c48e5e0ff66ac27 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -1080,6 +1080,10 @@ #define RT5682_PLL2F_N_SFT 8 /* PLL2 M/N/K Code Control 2 (0x009e) */ +#define RT5682_PLL2B_SEL_PS_MASK (0x1 << 13) +#define RT5682_PLL2B_SEL_PS_SFT 13 +#define RT5682_PLL2B_PS_BYP_MASK (0x1 << 12) +#define RT5682_PLL2B_PS_BYP_SFT 12 #define RT5682_PLL2B_M_BP_MASK (0x1 << 11) #define RT5682_PLL2B_M_BP_SFT 11 #define RT5682_PLL2F_M_BP_MASK (0x1 << 7) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index e8a8bf7b4ffed041e6e1b48430fb0702a9a74fa8..4d6ff811462287c0c32ba730ffc184564085ee8d 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -156,14 +156,14 @@ struct sgtl5000_priv { static inline int hp_sel_input(struct snd_soc_component *component) { - return (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_CTRL) & + return (snd_soc_component_read(component, SGTL5000_CHIP_ANA_CTRL) & SGTL5000_HP_SEL_MASK) >> SGTL5000_HP_SEL_SHIFT; } static inline u16 mute_output(struct snd_soc_component *component, u16 mute_mask) { - u16 mute_reg = snd_soc_component_read32(component, + u16 mute_reg = snd_soc_component_read(component, SGTL5000_CHIP_ANA_CTRL); snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL, @@ -180,7 +180,7 @@ static inline void restore_output(struct snd_soc_component *component, static void vag_power_on(struct snd_soc_component *component, u32 source) { - if (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) & + if (snd_soc_component_read(component, SGTL5000_CHIP_ANA_POWER) & SGTL5000_VAG_POWERUP) return; @@ -225,7 +225,7 @@ static int vag_power_consumers(struct snd_soc_component *component, static void vag_power_off(struct snd_soc_component *component, u32 source) { - u16 ana_pwr = snd_soc_component_read32(component, + u16 ana_pwr = snd_soc_component_read(component, SGTL5000_CHIP_ANA_POWER); if (!(ana_pwr & SGTL5000_VAG_POWERUP)) @@ -545,7 +545,7 @@ static int dac_get_volsw(struct snd_kcontrol *kcontrol, int l; int r; - reg = snd_soc_component_read32(component, SGTL5000_CHIP_DAC_VOL); + reg = snd_soc_component_read(component, SGTL5000_CHIP_DAC_VOL); /* get left channel volume */ l = (reg & SGTL5000_DAC_VOL_LEFT_MASK) >> SGTL5000_DAC_VOL_LEFT_SHIFT; @@ -633,7 +633,7 @@ static int avc_get_threshold(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); int db, i; - u16 reg = snd_soc_component_read32(component, SGTL5000_DAP_AVC_THRESHOLD); + u16 reg = snd_soc_component_read(component, SGTL5000_DAP_AVC_THRESHOLD); /* register value 0 => -96dB */ if (!reg) { @@ -775,7 +775,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { }; /* mute the codec used by alsa core */ -static int sgtl5000_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int sgtl5000_mute_stream(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; u16 i2s_pwr = SGTL5000_I2S_IN_POWERUP; @@ -1160,9 +1160,10 @@ static int sgtl5000_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops sgtl5000_ops = { .hw_params = sgtl5000_pcm_hw_params, - .digital_mute = sgtl5000_digital_mute, + .mute_stream = sgtl5000_mute_stream, .set_fmt = sgtl5000_set_dai_fmt, .set_sysclk = sgtl5000_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver sgtl5000_dai = { @@ -1325,11 +1326,11 @@ static int sgtl5000_set_power_regs(struct snd_soc_component *component) } /* reset value */ - ana_pwr = snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER); + ana_pwr = snd_soc_component_read(component, SGTL5000_CHIP_ANA_POWER); ana_pwr |= SGTL5000_DAC_STEREO | SGTL5000_ADC_STEREO | SGTL5000_REFTOP_POWERUP; - lreg_ctrl = snd_soc_component_read32(component, SGTL5000_CHIP_LINREG_CTRL); + lreg_ctrl = snd_soc_component_read(component, SGTL5000_CHIP_LINREG_CTRL); if (vddio < 3100 && vdda < 3100) { /* enable internal oscillator used for charge pump */ diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index c47e3c4762fede9e9e532b9c07daaf8e8605acc3..09449c6c4024d8153816aabc8e12d5bfdeff17c4 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -388,7 +388,7 @@ static int ssm2518_hw_params(struct snd_pcm_substream *substream, SSM2518_POWER1_MCS_MASK, mcs << 1); } -static int ssm2518_mute(struct snd_soc_dai *dai, int mute) +static int ssm2518_mute(struct snd_soc_dai *dai, int mute, int direction) { struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(dai->component); unsigned int val; @@ -623,9 +623,10 @@ static int ssm2518_startup(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops ssm2518_dai_ops = { .startup = ssm2518_startup, .hw_params = ssm2518_hw_params, - .digital_mute = ssm2518_mute, + .mute_stream = ssm2518_mute, .set_fmt = ssm2518_set_dai_fmt, .set_tdm_slot = ssm2518_set_tdm_slot, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ssm2518_dai = { diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 464a4d7873bbad173fffd64b04d1589e2d40da97..90516024661463ad32feee2a01b2bf220ff2d289 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -338,7 +338,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, return 0; } -static int ssm2602_mute(struct snd_soc_dai *dai, int mute) +static int ssm2602_mute(struct snd_soc_dai *dai, int mute, int direction) { struct ssm2602_priv *ssm2602 = snd_soc_component_get_drvdata(dai->component); @@ -505,9 +505,10 @@ static int ssm2602_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops ssm2602_dai_ops = { .startup = ssm2602_startup, .hw_params = ssm2602_hw_params, - .digital_mute = ssm2602_mute, + .mute_stream = ssm2602_mute, .set_sysclk = ssm2602_set_dai_sysclk, .set_fmt = ssm2602_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ssm2602_dai = { diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index bb4958bb8fe963758cefaac7b028763f9784e201..811b1a2c404a2f0caf7256dec45a3961facacd3d 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c @@ -220,7 +220,7 @@ static int ssm4567_hw_params(struct snd_pcm_substream *substream, SSM4567_DAC_FS_MASK, dacfs); } -static int ssm4567_mute(struct snd_soc_dai *dai, int mute) +static int ssm4567_mute(struct snd_soc_dai *dai, int mute, int direction) { struct ssm4567 *ssm4567 = snd_soc_component_get_drvdata(dai->component); unsigned int val; @@ -390,9 +390,10 @@ static int ssm4567_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops ssm4567_dai_ops = { .hw_params = ssm4567_hw_params, - .digital_mute = ssm4567_mute, + .mute_stream = ssm4567_mute, .set_fmt = ssm4567_set_dai_fmt, .set_tdm_slot = ssm4567_set_tdm_slot, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver ssm4567_dai = { diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index e9ccebbc31e485a79451596e0d7ed8f06d4b1abd..86528b930de891b7d4051092c16ee289e1f20048 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -397,9 +397,9 @@ static void sta32x_watchdog(struct work_struct *work) unsigned int confa, confa_cached; /* check if sta32x has reset itself */ - confa_cached = snd_soc_component_read32(component, STA32X_CONFA); + confa_cached = snd_soc_component_read(component, STA32X_CONFA); regcache_cache_bypass(sta32x->regmap, true); - confa = snd_soc_component_read32(component, STA32X_CONFA); + confa = snd_soc_component_read(component, STA32X_CONFA); regcache_cache_bypass(sta32x->regmap, false); if (confa != confa_cached) { regcache_mark_dirty(sta32x->regmap); @@ -697,7 +697,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, switch (params_width(params)) { case 24: dev_dbg(component->dev, "24bit\n"); - /* fall through */ + fallthrough; case 32: dev_dbg(component->dev, "24bit or 32bit\n"); switch (sta32x->format) { diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index ccb7100b66444cb9bb72933d9aa4889dfa05469b..75d3b0618ab500ab557b67485c939065d0356737 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -726,7 +726,7 @@ static int sta350_hw_params(struct snd_pcm_substream *substream, switch (params_width(params)) { case 24: dev_dbg(component->dev, "24bit\n"); - /* fall through */ + fallthrough; case 32: dev_dbg(component->dev, "24bit or 32bit\n"); switch (sta350->format) { diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 2881a0f7bb399a9aaf6e02bf16da7e6b9ce8db61..97b5f34027c0c4b77bb94153c755aa2bd4225767 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -251,7 +251,7 @@ static int sta529_hw_params(struct snd_pcm_substream *substream, return 0; } -static int sta529_mute(struct snd_soc_dai *dai, int mute) +static int sta529_mute(struct snd_soc_dai *dai, int mute, int direction) { u8 val = 0; @@ -291,7 +291,8 @@ static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) static const struct snd_soc_dai_ops sta529_dai_ops = { .hw_params = sta529_hw_params, .set_fmt = sta529_set_dai_fmt, - .digital_mute = sta529_mute, + .mute_stream = sta529_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver sta529_dai = { diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index d90e5f2b6f27bc9b7cf08b2923b0ec3caf24cc82..bd00c35116cd5863cae2c2e82c7b534bc9acb67c 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -2,7 +2,7 @@ /* * tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com * * Author: Dan Murphy */ @@ -169,7 +169,7 @@ static int tas2552_setup_pll(struct snd_soc_component *component, pll_clkin += tas2552->tdm_delay; } - pll_enable = snd_soc_component_read32(component, TAS2552_CFG_2) & TAS2552_PLL_ENABLE; + pll_enable = snd_soc_component_read(component, TAS2552_CFG_2) & TAS2552_PLL_ENABLE; snd_soc_component_update_bits(component, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0); if (pll_clkin == pll_clk) @@ -187,7 +187,7 @@ static int tas2552_setup_pll(struct snd_soc_component *component, unsigned int d, q, t; u8 j; u8 pll_sel = (tas2552->pll_clk_id << 3) & TAS2552_PLL_SRC_MASK; - u8 p = snd_soc_component_read32(component, TAS2552_PLL_CTRL_1); + u8 p = snd_soc_component_read(component, TAS2552_PLL_CTRL_1); p = (p >> 7); @@ -407,7 +407,7 @@ static int tas2552_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, clk_id = TAS2552_PLL_CLKIN_BCLK; freq = 0; } - /* fall through */ + fallthrough; case TAS2552_PLL_CLKIN_BCLK: case TAS2552_PLL_CLKIN_1_8_FIXED: mask = TAS2552_PLL_SRC_MASK; @@ -465,7 +465,7 @@ static int tas2552_set_dai_tdm_slot(struct snd_soc_dai *dai, return 0; } -static int tas2552_mute(struct snd_soc_dai *dai, int mute) +static int tas2552_mute(struct snd_soc_dai *dai, int mute, int direction) { u8 cfg1_reg = 0; struct snd_soc_component *component = dai->component; @@ -519,7 +519,8 @@ static const struct snd_soc_dai_ops tas2552_speaker_dai_ops = { .set_sysclk = tas2552_set_dai_sysclk, .set_fmt = tas2552_set_dai_fmt, .set_tdm_slot = tas2552_set_dai_tdm_slot, - .digital_mute = tas2552_mute, + .mute_stream = tas2552_mute, + .no_capture_mute = 1, }; /* Formats supported by TAS2552 driver. */ diff --git a/sound/soc/codecs/tas2552.h b/sound/soc/codecs/tas2552.h index d0958315d6a22f3f7493baa20076fb998702ea11..b9c2e70df57e24f249499eaa9d7941da4f4d6b2a 100644 --- a/sound/soc/codecs/tas2552.h +++ b/sound/soc/codecs/tas2552.h @@ -2,7 +2,7 @@ /* * tas2552.h - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com * * Author: Dan Murphy */ diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c index 7fae88655a0fa581d3dd121a091e3273300cf4bf..99920c691d28284d017a6c4dbb326e19ace8a2c4 100644 --- a/sound/soc/codecs/tas2562.c +++ b/sound/soc/codecs/tas2562.c @@ -175,7 +175,37 @@ static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai, { struct snd_soc_component *component = dai->component; struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); - int ret = 0; + int left_slot, right_slot; + int slots_cfg; + int ret; + + if (!tx_mask) { + dev_err(component->dev, "tx masks must not be 0\n"); + return -EINVAL; + } + + if (slots == 1) { + if (tx_mask != 1) + return -EINVAL; + + left_slot = 0; + right_slot = 0; + } else { + left_slot = __ffs(tx_mask); + tx_mask &= ~(1 << left_slot); + if (tx_mask == 0) { + right_slot = left_slot; + } else { + right_slot = __ffs(tx_mask); + tx_mask &= ~(1 << right_slot); + } + } + + slots_cfg = (right_slot << TAS2562_RIGHT_SLOT_SHIFT) | left_slot; + + ret = snd_soc_component_write(component, TAS2562_TDM_CFG3, slots_cfg); + if (ret < 0) + return ret; switch (slot_width) { case 16: @@ -208,12 +238,38 @@ static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai, if (ret < 0) return ret; + ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG5, + TAS2562_TDM_CFG5_VSNS_SLOT_MASK, + tas2562->v_sense_slot); + if (ret < 0) + return ret; + + ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG6, + TAS2562_TDM_CFG6_ISNS_SLOT_MASK, + tas2562->i_sense_slot); + if (ret < 0) + return ret; + + ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG5, + TAS2562_TDM_CFG5_VSNS_SLOT_MASK, + tas2562->v_sense_slot); + if (ret < 0) + return ret; + + ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG6, + TAS2562_TDM_CFG6_ISNS_SLOT_MASK, + tas2562->i_sense_slot); + if (ret < 0) + return ret; + return 0; } static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth) { int ret; + int val; + int sense_en; switch (bitwidth) { case SNDRV_PCM_FORMAT_S16_LE: @@ -221,21 +277,18 @@ static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth) TAS2562_TDM_CFG2, TAS2562_TDM_CFG2_RXWLEN_MASK, TAS2562_TDM_CFG2_RXWLEN_16B); - tas2562->v_sense_slot = tas2562->i_sense_slot + 2; break; case SNDRV_PCM_FORMAT_S24_LE: snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG2, TAS2562_TDM_CFG2_RXWLEN_MASK, TAS2562_TDM_CFG2_RXWLEN_24B); - tas2562->v_sense_slot = tas2562->i_sense_slot + 4; break; case SNDRV_PCM_FORMAT_S32_LE: snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG2, TAS2562_TDM_CFG2_RXWLEN_MASK, TAS2562_TDM_CFG2_RXWLEN_32B); - tas2562->v_sense_slot = tas2562->i_sense_slot + 4; break; default: @@ -243,17 +296,27 @@ static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth) return -EINVAL; } - ret = snd_soc_component_update_bits(tas2562->component, - TAS2562_TDM_CFG5, - TAS2562_TDM_CFG5_VSNS_EN | TAS2562_TDM_CFG5_VSNS_SLOT_MASK, - TAS2562_TDM_CFG5_VSNS_EN | tas2562->v_sense_slot); + val = snd_soc_component_read(tas2562->component, TAS2562_PWR_CTRL); + if (val < 0) + return val; + + if (val & (1 << TAS2562_VSENSE_POWER_EN)) + sense_en = 0; + else + sense_en = TAS2562_TDM_CFG5_VSNS_EN; + + ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG5, + TAS2562_TDM_CFG5_VSNS_EN, sense_en); if (ret < 0) return ret; - ret = snd_soc_component_update_bits(tas2562->component, - TAS2562_TDM_CFG6, - TAS2562_TDM_CFG6_ISNS_EN | TAS2562_TDM_CFG6_ISNS_SLOT_MASK, - TAS2562_TDM_CFG6_ISNS_EN | tas2562->i_sense_slot); + if (val & (1 << TAS2562_ISENSE_POWER_EN)) + sense_en = 0; + else + sense_en = TAS2562_TDM_CFG6_ISNS_EN; + + ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG6, + TAS2562_TDM_CFG6_ISNS_EN, sense_en); if (ret < 0) return ret; @@ -285,7 +348,8 @@ static int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct snd_soc_component *component = dai->component; struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); - u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0; + u8 asi_cfg_1 = 0; + u8 tdm_rx_start_slot = 0; int ret; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { @@ -307,34 +371,30 @@ static int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) dev_err(tas2562->dev, "Failed to set RX edge\n"); return ret; } - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case (SND_SOC_DAIFMT_I2S): - case (SND_SOC_DAIFMT_DSP_A): - case (SND_SOC_DAIFMT_DSP_B): - tdm_rx_start_slot = BIT(1); - break; - case (SND_SOC_DAIFMT_LEFT_J): + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_DSP_B: tdm_rx_start_slot = 0; break; - default: - dev_err(tas2562->dev, "DAI Format is not found, fmt=0x%x\n", - fmt); - ret = -EINVAL; + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_DSP_A: + tdm_rx_start_slot = 1; break; + default: + dev_err(tas2562->dev, + "DAI Format is not found, fmt=0x%x\n", fmt); + return -EINVAL; } ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1, - TAS2562_TDM_CFG1_RX_OFFSET_MASK, - tdm_rx_start_slot); - + TAS2562_RX_OFF_MASK, (tdm_rx_start_slot << 1)); if (ret < 0) return ret; return 0; } -static int tas2562_mute(struct snd_soc_dai *dai, int mute) +static int tas2562_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -504,7 +564,7 @@ static const struct snd_kcontrol_new tas2562_snd_controls[] = { .info = snd_soc_info_volsw, .get = tas2562_volume_control_get, .put = tas2562_volume_control_put, - .private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0) , + .private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0), }, }; @@ -552,7 +612,8 @@ static const struct snd_soc_dai_ops tas2562_speaker_dai_ops = { .hw_params = tas2562_hw_params, .set_fmt = tas2562_set_dai_fmt, .set_tdm_slot = tas2562_set_dai_tdm_slot, - .digital_mute = tas2562_mute, + .mute_stream = tas2562_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver tas2562_dai[] = { @@ -619,20 +680,49 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562) struct device *dev = tas2562->dev; int ret = 0; - tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down-gpio", - GPIOD_OUT_HIGH); + tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); if (IS_ERR(tas2562->sdz_gpio)) { - if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) { - tas2562->sdz_gpio = NULL; + if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) return -EPROBE_DEFER; - } + + tas2562->sdz_gpio = NULL; + } + + /* + * The shut-down property is deprecated but needs to be checked for + * backwards compatibility. + */ + if (tas2562->sdz_gpio == NULL) { + tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down", + GPIOD_OUT_HIGH); + if (IS_ERR(tas2562->sdz_gpio)) + if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + tas2562->sdz_gpio = NULL; } ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no", &tas2562->i_sense_slot); - if (ret) - dev_err(dev, "Looking up %s property failed %d\n", - "ti,imon-slot-no", ret); + if (ret) { + dev_err(dev, "Property %s is missing setting default slot\n", + "ti,imon-slot-no"); + tas2562->i_sense_slot = 0; + } + + + ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no", + &tas2562->v_sense_slot); + if (ret) { + dev_info(dev, "Property %s is missing setting default slot\n", + "ti,vmon-slot-no"); + tas2562->v_sense_slot = 2; + } + + if (tas2562->v_sense_slot < tas2562->i_sense_slot) { + dev_err(dev, "Vsense slot must be greater than Isense slot\n"); + return -EINVAL; + } return ret; } diff --git a/sound/soc/codecs/tas2562.h b/sound/soc/codecs/tas2562.h index 28e75fc431d0d8105db587ffa4757bee790c6386..81866aeb3fbfadc321dc1500778990485b4e3d4c 100644 --- a/sound/soc/codecs/tas2562.h +++ b/sound/soc/codecs/tas2562.h @@ -2,7 +2,7 @@ /* * tas2562.h - ALSA SoC Texas Instruments TAS2562 Mono Audio Amplifier * - * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com * * Author: Dan Murphy */ @@ -34,6 +34,10 @@ #define TAS2562_TDM_DET TAS2562_REG(0, 0x11) #define TAS2562_REV_ID TAS2562_REG(0, 0x7d) +#define TAS2562_RX_OFF_MASK GENMASK(5, 1) +#define TAS2562_TX_OFF_MASK GENMASK(3, 1) +#define TAS2562_RIGHT_SLOT_SHIFT 4 + /* Page 2 */ #define TAS2562_DVC_CFG1 TAS2562_REG(2, 0x0c) #define TAS2562_DVC_CFG2 TAS2562_REG(2, 0x0d) @@ -49,7 +53,6 @@ #define TAS2562_TDM_CFG1_RX_EDGE_MASK BIT(0) #define TAS2562_TDM_CFG1_RX_FALLING 1 -#define TAS2562_TDM_CFG1_RX_OFFSET_MASK GENMASK(4, 0) #define TAS2562_TDM_CFG0_RAMPRATE_MASK BIT(5) #define TAS2562_TDM_CFG0_RAMPRATE_44_1 BIT(5) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 54c8135fe43c17ba068dd8efc017eabe1a296ee1..c098518343959cbbb36c427d4396a5d4fd8c9146 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -3,7 +3,7 @@ // ALSA SoC Texas Instruments TAS2770 20-W Digital Input Mono Class-D // Audio Amplifier with Speaker I/V Sense // -// Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ +// Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ // Author: Tracy Yi // Frank Shi @@ -189,7 +189,7 @@ static const struct snd_soc_dapm_route tas2770_audio_map[] = { {"VSENSE", "Switch", "VMON"}, }; -static int tas2770_mute(struct snd_soc_dai *dai, int mute) +static int tas2770_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int ret; @@ -530,10 +530,11 @@ static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai, } static struct snd_soc_dai_ops tas2770_dai_ops = { - .digital_mute = tas2770_mute, + .mute_stream = tas2770_mute, .hw_params = tas2770_hw_params, .set_fmt = tas2770_set_fmt, .set_tdm_slot = tas2770_set_dai_tdm_slot, + .no_capture_mute = 1, }; #define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ @@ -758,8 +759,7 @@ static int tas2770_i2c_probe(struct i2c_client *client, } } - tas2770->reset_gpio = devm_gpiod_get_optional(tas2770->dev, - "reset-gpio", + tas2770->reset_gpio = devm_gpiod_get_optional(tas2770->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(tas2770->reset_gpio)) { if (PTR_ERR(tas2770->reset_gpio) == -EPROBE_DEFER) { diff --git a/sound/soc/codecs/tas2770.h b/sound/soc/codecs/tas2770.h index cbb858369fe6f252832d2ba8410c120f3bdc4bf3..96683971ee9bfd42814ae14d2ce54e9153362be2 100644 --- a/sound/soc/codecs/tas2770.h +++ b/sound/soc/codecs/tas2770.h @@ -2,7 +2,7 @@ * * ALSA SoC TAS2770 codec driver * - * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ */ #ifndef __TAS2770__ #define __TAS2770__ diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index 5b7f9fcf6cbf3b2781f0f38df83f37cfb7efb110..835a723ce5bc082eebe1c6c95f9edf8b32b6a6cd 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -301,7 +301,7 @@ static int tas571x_hw_params(struct snd_pcm_substream *substream, TAS571X_SDI_FMT_MASK, val); } -static int tas571x_mute(struct snd_soc_dai *dai, int mute) +static int tas571x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u8 sysctl2; @@ -354,7 +354,8 @@ static int tas571x_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops tas571x_dai_ops = { .set_fmt = tas571x_set_dai_fmt, .hw_params = tas571x_hw_params, - .digital_mute = tas571x_mute, + .mute_stream = tas571x_mute, + .no_capture_mute = 1, }; diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c index 37fab8f22800d761d19371ad3caa0a4be2a4459a..9ff644ddb470a61fa15fb7450a0a89224444b03c 100644 --- a/sound/soc/codecs/tas5720.c +++ b/sound/soc/codecs/tas5720.c @@ -2,7 +2,7 @@ /* * tas5720.c - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier * - * Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C)2015-2016 Texas Instruments Incorporated - https://www.ti.com * * Author: Andreas Dannenberg */ @@ -199,7 +199,7 @@ error_snd_soc_component_update_bits: return ret; } -static int tas5720_mute(struct snd_soc_dai *dai, int mute) +static int tas5720_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int ret; @@ -508,10 +508,10 @@ static int tas5722_volume_get(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); unsigned int val; - snd_soc_component_read(component, TAS5720_VOLUME_CTRL_REG, &val); + val = snd_soc_component_read(component, TAS5720_VOLUME_CTRL_REG); ucontrol->value.integer.value[0] = val << 1; - snd_soc_component_read(component, TAS5722_DIGITAL_CTRL2_REG, &val); + val = snd_soc_component_read(component, TAS5722_DIGITAL_CTRL2_REG); ucontrol->value.integer.value[0] |= val & TAS5722_VOL_CONTROL_LSB; return 0; @@ -604,7 +604,8 @@ static const struct snd_soc_dai_ops tas5720_speaker_dai_ops = { .hw_params = tas5720_hw_params, .set_fmt = tas5720_set_dai_fmt, .set_tdm_slot = tas5720_set_dai_tdm_slot, - .digital_mute = tas5720_mute, + .mute_stream = tas5720_mute, + .no_capture_mute = 1, }; /* diff --git a/sound/soc/codecs/tas5720.h b/sound/soc/codecs/tas5720.h index 93079f954f09b69bb745ebd0845131adaeea4bf9..223858f0de71363b6f52509e32ac8cc55ec05d1c 100644 --- a/sound/soc/codecs/tas5720.h +++ b/sound/soc/codecs/tas5720.h @@ -2,7 +2,7 @@ /* * tas5720.h - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier * - * Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C)2015-2016 Texas Instruments Incorporated - https://www.ti.com * * Author: Andreas Dannenberg */ diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c index aaba3929507993d9e84206cbcae28e176258b9bf..59543d392110a0201cbf3379f5bac123d1e046ad 100644 --- a/sound/soc/codecs/tas6424.c +++ b/sound/soc/codecs/tas6424.c @@ -2,7 +2,7 @@ /* * ALSA SoC Texas Instruments TAS6424 Quad-Channel Audio Amplifier * - * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ * Author: Andreas Dannenberg * Andrew F. Davis */ @@ -252,7 +252,7 @@ static int tas6424_set_dai_tdm_slot(struct snd_soc_dai *dai, return 0; } -static int tas6424_mute(struct snd_soc_dai *dai, int mute) +static int tas6424_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct tas6424_data *tas6424 = snd_soc_component_get_drvdata(component); @@ -382,7 +382,8 @@ static const struct snd_soc_dai_ops tas6424_speaker_dai_ops = { .hw_params = tas6424_hw_params, .set_fmt = tas6424_set_dai_fmt, .set_tdm_slot = tas6424_set_dai_tdm_slot, - .digital_mute = tas6424_mute, + .mute_stream = tas6424_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver tas6424_dai[] = { diff --git a/sound/soc/codecs/tas6424.h b/sound/soc/codecs/tas6424.h index c67a7835ca666ebf6b65609b0c8d7391aecc4850..a6a0d00e519079e7f28a2d0b81159efd270e31d0 100644 --- a/sound/soc/codecs/tas6424.h +++ b/sound/soc/codecs/tas6424.h @@ -2,7 +2,7 @@ /* * ALSA SoC Texas Instruments TAS6424 Quad-Channel Audio Amplifier * - * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ * Author: Andreas Dannenberg * Andrew F. Davis */ diff --git a/sound/soc/codecs/tda7419.c b/sound/soc/codecs/tda7419.c index 2bf4f5e8af2753f8ab8d23c964505c772e788d6d..83d220054c96f0c41d9d2265a3ba3f962f22a906 100644 --- a/sound/soc/codecs/tda7419.c +++ b/sound/soc/codecs/tda7419.c @@ -187,18 +187,13 @@ static int tda7419_vol_get(struct snd_kcontrol *kcontrol, int thresh = tvc->thresh; unsigned int invert = tvc->invert; int val; - int ret; - ret = snd_soc_component_read(component, reg, &val); - if (ret < 0) - return ret; + val = snd_soc_component_read(component, reg); ucontrol->value.integer.value[0] = tda7419_vol_get_value(val, mask, min, thresh, invert); if (tda7419_vol_is_stereo(tvc)) { - ret = snd_soc_component_read(component, rreg, &val); - if (ret < 0) - return ret; + val = snd_soc_component_read(component, rreg); ucontrol->value.integer.value[1] = tda7419_vol_get_value(val, mask, min, thresh, invert); } diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c index abc114a3ae2bdfd736ca0c9d0b4af01527f785b4..3d8e8c2276f086e9c4f31fc31918c7b0149145a1 100644 --- a/sound/soc/codecs/tfa9879.c +++ b/sound/soc/codecs/tfa9879.c @@ -93,7 +93,7 @@ static int tfa9879_hw_params(struct snd_pcm_substream *substream, return 0; } -static int tfa9879_digital_mute(struct snd_soc_dai *dai, int mute) +static int tfa9879_mute_stream(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -251,8 +251,9 @@ static const struct regmap_config tfa9879_regmap = { static const struct snd_soc_dai_ops tfa9879_dai_ops = { .hw_params = tfa9879_hw_params, - .digital_mute = tfa9879_digital_mute, + .mute_stream = tfa9879_mute_stream, .set_fmt = tfa9879_set_fmt, + .no_capture_mute = 1, }; #define TFA9879_RATES SNDRV_PCM_RATE_8000_96000 diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 35fe8ee5bce9facffdaf2ff354438ba20cc48f2d..5cd50d8411778d62d7fb12e0bfc44b83e42db17f 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // TLV320ADCX140 Sound driver -// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ +// Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/ #include #include @@ -37,6 +37,13 @@ struct adcx140_priv { unsigned int slot_width; }; +static const char * const gpo_config_names[] = { + "ti,gpo-config-1", + "ti,gpo-config-2", + "ti,gpo-config-3", + "ti,gpo-config-4", +}; + static const struct reg_default adcx140_reg_defaults[] = { { ADCX140_PAGE_SELECT, 0x00 }, { ADCX140_SW_RESET, 0x00 }, @@ -60,10 +67,10 @@ static const struct reg_default adcx140_reg_defaults[] = { { ADCX140_PDMCLK_CFG, 0x40 }, { ADCX140_PDM_CFG, 0x00 }, { ADCX140_GPIO_CFG0, 0x22 }, + { ADCX140_GPO_CFG0, 0x00 }, { ADCX140_GPO_CFG1, 0x00 }, { ADCX140_GPO_CFG2, 0x00 }, { ADCX140_GPO_CFG3, 0x00 }, - { ADCX140_GPO_CFG4, 0x00 }, { ADCX140_GPO_VAL, 0x00 }, { ADCX140_GPIO_MON, 0x00 }, { ADCX140_GPI_CFG0, 0x00 }, @@ -218,8 +225,8 @@ static const struct snd_kcontrol_new in4_resistor_controls[] = { }; /* Analog/Digital Selection */ -static const char *adcx140_mic_sel_text[] = {"Analog", "Line In", "Digital"}; -static const char *adcx140_analog_sel_text[] = {"Analog", "Line In"}; +static const char * const adcx140_mic_sel_text[] = {"Analog", "Line In", "Digital"}; +static const char * const adcx140_analog_sel_text[] = {"Analog", "Line In"}; static SOC_ENUM_SINGLE_DECL(adcx140_mic1p_enum, ADCX140_CH1_CFG0, 5, @@ -313,6 +320,14 @@ static const struct snd_kcontrol_new adcx140_dapm_ch3_en_switch = SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 5, 1, 0); static const struct snd_kcontrol_new adcx140_dapm_ch4_en_switch = SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 4, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch5_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 3, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch6_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 2, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch7_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 1, 1, 0); +static const struct snd_kcontrol_new adcx140_dapm_ch8_en_switch = + SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 0, 1, 0); static const struct snd_kcontrol_new adcx140_dapm_ch1_dre_en_switch = SOC_DAPM_SINGLE("Switch", ADCX140_CH1_CFG0, 0, 1, 0); @@ -406,6 +421,15 @@ static const struct snd_soc_dapm_widget adcx140_dapm_widgets[] = { SND_SOC_DAPM_SWITCH("CH4_ASI_EN", SND_SOC_NOPM, 0, 0, &adcx140_dapm_ch4_en_switch), + SND_SOC_DAPM_SWITCH("CH5_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch5_en_switch), + SND_SOC_DAPM_SWITCH("CH6_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch6_en_switch), + SND_SOC_DAPM_SWITCH("CH7_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch7_en_switch), + SND_SOC_DAPM_SWITCH("CH8_ASI_EN", SND_SOC_NOPM, 0, 0, + &adcx140_dapm_ch8_en_switch), + SND_SOC_DAPM_SWITCH("DRE_ENABLE", SND_SOC_NOPM, 0, 0, &adcx140_dapm_dre_en_switch), @@ -446,6 +470,11 @@ static const struct snd_soc_dapm_route adcx140_audio_map[] = { {"CH3_ASI_EN", "Switch", "CH3_ADC"}, {"CH4_ASI_EN", "Switch", "CH4_ADC"}, + {"CH5_ASI_EN", "Switch", "CH5_OUT"}, + {"CH6_ASI_EN", "Switch", "CH6_OUT"}, + {"CH7_ASI_EN", "Switch", "CH7_OUT"}, + {"CH8_ASI_EN", "Switch", "CH8_OUT"}, + {"Decimation Filter", "Linear Phase", "DRE_ENABLE"}, {"Decimation Filter", "Low Latency", "DRE_ENABLE"}, {"Decimation Filter", "Ultra-low Latency", "DRE_ENABLE"}, @@ -576,7 +605,7 @@ static int adcx140_reset(struct adcx140_priv *adcx140) gpiod_direction_output(adcx140->gpio_reset, 1); } else { ret = regmap_write(adcx140->regmap, ADCX140_SW_RESET, - ADCX140_RESET); + ADCX140_RESET); } /* 8.4.2: wait >= 10 ms after entering sleep mode. */ @@ -624,6 +653,8 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); u8 iface_reg1 = 0; u8 iface_reg2 = 0; + int offset = 0; + int width = adcx140->slot_width; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -666,7 +697,10 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, iface_reg1 |= ADCX140_LEFT_JUST_BIT; break; case SND_SOC_DAIFMT_DSP_A: + offset += (adcx140->tdm_delay * width + 1); + break; case SND_SOC_DAIFMT_DSP_B: + offset += adcx140->tdm_delay * width; break; default: dev_err(component->dev, "Invalid DAI interface format\n"); @@ -683,6 +717,11 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, snd_soc_component_update_bits(component, ADCX140_MST_CFG0, ADCX140_BCLK_FSYNC_MASTER, iface_reg2); + /* Configure data offset */ + snd_soc_component_update_bits(component, ADCX140_ASI_CFG1, + ADCX140_TX_OFFSET_MASK, offset); + + return 0; } @@ -694,11 +733,6 @@ static int adcx140_set_dai_tdm_slot(struct snd_soc_dai *codec_dai, struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); unsigned int lsb; - if (tx_mask != rx_mask) { - dev_err(component->dev, "tx and rx masks must be symmetric\n"); - return -EINVAL; - } - /* TDM based on DSP mode requires slots to be adjacent */ lsb = __ffs(tx_mask); if ((lsb + 1) != __fls(tx_mask)) { @@ -723,36 +757,48 @@ static int adcx140_set_dai_tdm_slot(struct snd_soc_dai *codec_dai, return 0; } -static int adcx140_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) +static const struct snd_soc_dai_ops adcx140_dai_ops = { + .hw_params = adcx140_hw_params, + .set_fmt = adcx140_set_dai_fmt, + .set_tdm_slot = adcx140_set_dai_tdm_slot, +}; + +static int adcx140_configure_gpo(struct adcx140_priv *adcx140) { - struct snd_soc_component *component = dai->component; - struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); - int offset = 0; - int width = adcx140->slot_width; + u32 gpo_outputs[ADCX140_NUM_GPOS]; + u32 gpo_output_val = 0; + int ret; + int i; - if (!width) - width = substream->runtime->sample_bits; + for (i = 0; i < ADCX140_NUM_GPOS; i++) { + ret = device_property_read_u32_array(adcx140->dev, + gpo_config_names[i], + gpo_outputs, + ADCX140_NUM_GPO_CFGS); + if (ret) + continue; - /* TDM slot selection only valid in DSP_A/_B mode */ - if (adcx140->dai_fmt == SND_SOC_DAIFMT_DSP_A) - offset += (adcx140->tdm_delay * width + 1); - else if (adcx140->dai_fmt == SND_SOC_DAIFMT_DSP_B) - offset += adcx140->tdm_delay * width; + if (gpo_outputs[0] > ADCX140_GPO_CFG_MAX) { + dev_err(adcx140->dev, "GPO%d config out of range\n", i + 1); + return -EINVAL; + } - /* Configure data offset */ - snd_soc_component_update_bits(component, ADCX140_ASI_CFG1, - ADCX140_TX_OFFSET_MASK, offset); + if (gpo_outputs[1] > ADCX140_GPO_DRV_MAX) { + dev_err(adcx140->dev, "GPO%d drive out of range\n", i + 1); + return -EINVAL; + } + + gpo_output_val = gpo_outputs[0] << ADCX140_GPO_SHIFT | + gpo_outputs[1]; + ret = regmap_write(adcx140->regmap, ADCX140_GPO_CFG0 + i, + gpo_output_val); + if (ret) + return ret; + } return 0; -} -static const struct snd_soc_dai_ops adcx140_dai_ops = { - .hw_params = adcx140_hw_params, - .set_fmt = adcx140_set_dai_fmt, - .prepare = adcx140_prepare, - .set_tdm_slot = adcx140_set_dai_tdm_slot, -}; +} static int adcx140_codec_probe(struct snd_soc_component *component) { @@ -792,6 +838,10 @@ static int adcx140_codec_probe(struct snd_soc_component *component) bias_cfg = bias_source << ADCX140_MIC_BIAS_SHIFT | vref_source; + ret = adcx140_reset(adcx140); + if (ret) + goto out; + pdm_count = device_property_count_u32(adcx140->dev, "ti,pdm-edge-select"); if (pdm_count <= ADCX140_NUM_PDM_EDGES && pdm_count > 0) { @@ -835,11 +885,11 @@ static int adcx140_codec_probe(struct snd_soc_component *component) return ret; } - ret = adcx140_reset(adcx140); + ret = adcx140_configure_gpo(adcx140); if (ret) goto out; - if(adcx140->supply_areg == NULL) + if (adcx140->supply_areg == NULL) sleep_cfg_val |= ADCX140_AREG_INTERNAL; ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val); @@ -940,8 +990,8 @@ static int adcx140_i2c_probe(struct i2c_client *i2c, if (IS_ERR(adcx140->supply_areg)) { if (PTR_ERR(adcx140->supply_areg) == -EPROBE_DEFER) return -EPROBE_DEFER; - else - adcx140->supply_areg = NULL; + + adcx140->supply_areg = NULL; } else { ret = regulator_enable(adcx140->supply_areg); if (ret) { diff --git a/sound/soc/codecs/tlv320adcx140.h b/sound/soc/codecs/tlv320adcx140.h index 39206bf1af12edd470ffebb33452eb4551fa4ea6..eedbc1d7221ff75f75fb08e8c4aa32129ef2fd69 100644 --- a/sound/soc/codecs/tlv320adcx140.h +++ b/sound/soc/codecs/tlv320adcx140.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // TLV320ADCX104 Sound driver -// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ +// Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/ #ifndef _TLV320ADCX140_H #define _TLV320ADCX140_H @@ -36,10 +36,10 @@ #define ADCX140_PDMCLK_CFG 0x1f #define ADCX140_PDM_CFG 0x20 #define ADCX140_GPIO_CFG0 0x21 -#define ADCX140_GPO_CFG1 0x22 -#define ADCX140_GPO_CFG2 0x23 -#define ADCX140_GPO_CFG3 0x24 -#define ADCX140_GPO_CFG4 0x25 +#define ADCX140_GPO_CFG0 0x22 +#define ADCX140_GPO_CFG1 0x23 +#define ADCX140_GPO_CFG2 0x24 +#define ADCX140_GPO_CFG3 0x25 #define ADCX140_GPO_VAL 0x29 #define ADCX140_GPIO_MON 0x2a #define ADCX140_GPI_CFG0 0x2b @@ -139,4 +139,10 @@ #define ADCX140_GPI3_INDEX 2 #define ADCX140_GPI4_INDEX 3 +#define ADCX140_NUM_GPOS 4 +#define ADCX140_NUM_GPO_CFGS 2 +#define ADCX140_GPO_SHIFT 4 +#define ADCX140_GPO_CFG_MAX 4 +#define ADCX140_GPO_DRV_MAX 5 + #endif /* _TLV320ADCX140_ */ diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 9868fb22323c5f393cac98aebac39d2eb8d0e86c..2400093e2c9909cc7cffa5e3d845fae9bbac87ca 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -91,7 +91,7 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol, */ val = (val >= 4) ? 4 : (3 - val); - reg = snd_soc_component_read32(component, TLV320AIC23_ANLG) & (~0x1C0); + reg = snd_soc_component_read(component, TLV320AIC23_ANLG) & (~0x1C0); snd_soc_component_write(component, TLV320AIC23_ANLG, reg | (val << 6)); return 0; @@ -103,7 +103,7 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); u16 val; - val = snd_soc_component_read32(component, TLV320AIC23_ANLG) & (0x1C0); + val = snd_soc_component_read(component, TLV320AIC23_ANLG) & (0x1C0); val = val >> 6; val = (val >= 4) ? 4 : (3 - val); ucontrol->value.integer.value[0] = val; @@ -294,7 +294,7 @@ static int find_rate(int mclk, u32 need_adc, u32 need_dac) static void get_current_sample_rates(struct snd_soc_component *component, int mclk, u32 *sample_rate_adc, u32 *sample_rate_dac) { - int src = snd_soc_component_read32(component, TLV320AIC23_SRATE); + int src = snd_soc_component_read(component, TLV320AIC23_SRATE); int sr = (src >> 2) & 0x0f; int val = (mclk / bosr_usb_divisor_table[src & 3]); int adc = (val * sr_adc_mult_table[sr]) / SR_MULT; @@ -356,7 +356,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - iface_reg = snd_soc_component_read32(component, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); + iface_reg = snd_soc_component_read(component, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); switch (params_width(params)) { case 16: @@ -404,12 +404,12 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, aic23->requested_adc = 0; } -static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute) +static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u16 reg; - reg = snd_soc_component_read32(component, TLV320AIC23_DIGT); + reg = snd_soc_component_read(component, TLV320AIC23_DIGT); if (mute) reg |= TLV320AIC23_DACM_MUTE; @@ -427,7 +427,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_component *component = codec_dai->component; u16 iface_reg; - iface_reg = snd_soc_component_read32(component, TLV320AIC23_DIGT_FMT) & (~0x03); + iface_reg = snd_soc_component_read(component, TLV320AIC23_DIGT_FMT) & (~0x03); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -449,7 +449,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, break; case SND_SOC_DAIFMT_DSP_A: iface_reg |= TLV320AIC23_LRP_ON; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_B: iface_reg |= TLV320AIC23_FOR_DSP; break; @@ -479,7 +479,7 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int tlv320aic23_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { - u16 reg = snd_soc_component_read32(component, TLV320AIC23_PWR) & 0x17f; + u16 reg = snd_soc_component_read(component, TLV320AIC23_PWR) & 0x17f; switch (level) { case SND_SOC_BIAS_ON: @@ -512,9 +512,10 @@ static const struct snd_soc_dai_ops tlv320aic23_dai_ops = { .prepare = tlv320aic23_pcm_prepare, .hw_params = tlv320aic23_hw_params, .shutdown = tlv320aic23_shutdown, - .digital_mute = tlv320aic23_mute, + .mute_stream = tlv320aic23_mute, .set_fmt = tlv320aic23_set_dai_fmt, .set_sysclk = tlv320aic23_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver tlv320aic23_dai = { diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index b9ca3afd47766218b0e375d60be25e7c0afc2499..c7baef8948d4792346c8a216951268d5d56d3eea 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -131,10 +131,10 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, return 0; } -/** +/* * aic26_mute - Mute control to reduce noise when changing audio format */ -static int aic26_mute(struct snd_soc_dai *dai, int mute) +static int aic26_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct aic26 *aic26 = snd_soc_component_get_drvdata(component); @@ -211,9 +211,10 @@ static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) static const struct snd_soc_dai_ops aic26_dai_ops = { .hw_params = aic26_hw_params, - .digital_mute = aic26_mute, + .mute_stream = aic26_mute, .set_sysclk = aic26_set_sysclk, .set_fmt = aic26_set_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver aic26_dai = { @@ -266,7 +267,7 @@ static ssize_t aic26_keyclick_show(struct device *dev, struct aic26 *aic26 = dev_get_drvdata(dev); int val, amp, freq, len; - val = snd_soc_component_read32(aic26->component, AIC26_REG_AUDIO_CTRL2); + val = snd_soc_component_read(aic26->component, AIC26_REG_AUDIO_CTRL2); amp = (val >> 12) & 0x7; freq = (125 << ((val >> 8) & 0x7)) >> 1; len = 2 * (1 + ((val >> 4) & 0xf)); @@ -306,7 +307,7 @@ static int aic26_probe(struct snd_soc_component *component) snd_soc_component_write(component, AIC26_REG_POWER_CTRL, 0); /* Audio Control 3 (master mode, fsref rate) */ - reg = snd_soc_component_read32(component, AIC26_REG_AUDIO_CTRL3); + reg = snd_soc_component_read(component, AIC26_REG_AUDIO_CTRL3); reg &= ~0xf800; reg |= 0x0800; /* set master mode */ snd_soc_component_write(component, AIC26_REG_AUDIO_CTRL3, reg); diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 31daa60695bdae21cdc4d390653546ca656e370d..5ac7ce26443117268ed5b647cde097d20e2164f0 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -2,7 +2,7 @@ /* * ALSA SoC TLV320AIC31xx CODEC Driver * - * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2014-2017 Texas Instruments Incorporated - https://www.ti.com/ * Jyri Sarha * * Based on ground work by: Ajit Kulkarni @@ -877,7 +877,7 @@ static int aic31xx_setup_pll(struct snd_soc_component *component, there may be trouble. To fix the issue edit the aic31xx_divs table for your mclk and sample rate. Details can be found from: - http://www.ti.com/lit/ds/symlink/tlv320aic3100.pdf + https://www.ti.com/lit/ds/symlink/tlv320aic3100.pdf Section: 5.6 CLOCK Generation and PLL */ } @@ -972,7 +972,8 @@ static int aic31xx_hw_params(struct snd_pcm_substream *substream, return aic31xx_setup_pll(component, params); } -static int aic31xx_dac_mute(struct snd_soc_dai *codec_dai, int mute) +static int aic31xx_dac_mute(struct snd_soc_dai *codec_dai, int mute, + int direction) { struct snd_soc_component *component = codec_dai->component; @@ -1080,7 +1081,8 @@ static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai, case SND_SOC_DAIFMT_I2S: break; case SND_SOC_DAIFMT_DSP_A: - dsp_a_val = 0x1; /* fall through */ + dsp_a_val = 0x1; + fallthrough; case SND_SOC_DAIFMT_DSP_B: /* * NOTE: This CODEC samples on the falling edge of BCLK in @@ -1378,7 +1380,8 @@ static const struct snd_soc_dai_ops aic31xx_dai_ops = { .hw_params = aic31xx_hw_params, .set_sysclk = aic31xx_set_dai_sysclk, .set_fmt = aic31xx_set_dai_fmt, - .digital_mute = aic31xx_dac_mute, + .mute_stream = aic31xx_dac_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver dac31xx_dai_driver[] = { diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h index 0523884cee74786e70a520977b0376b72ebba262..81952984613d2f3f984b184c5019507f1437f21a 100644 --- a/sound/soc/codecs/tlv320aic31xx.h +++ b/sound/soc/codecs/tlv320aic31xx.h @@ -2,7 +2,7 @@ /* * ALSA SoC TLV320AIC31xx CODEC Driver Definitions * - * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2014-2017 Texas Instruments Incorporated - https://www.ti.com/ */ #ifndef _TLV320AIC31XX_H diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index d087f3b20b1d5a2e60790efd1eedac6431d4b649..467802875c133e45e6916bacadc1bb5fde9f3e14 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -82,7 +82,7 @@ static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); u8 val; - val = snd_soc_component_read32(component, AIC32X4_DINCTL); + val = snd_soc_component_read(component, AIC32X4_DINCTL); ucontrol->value.integer.value[0] = (val & 0x01); @@ -96,7 +96,7 @@ static int aic32x4_set_mfp2_gpio(struct snd_kcontrol *kcontrol, u8 val; u8 gpio_check; - val = snd_soc_component_read32(component, AIC32X4_DOUTCTL); + val = snd_soc_component_read(component, AIC32X4_DOUTCTL); gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED); if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) { printk(KERN_ERR "%s: MFP2 is not configure as a GPIO output\n", @@ -123,7 +123,7 @@ static int aic32x4_get_mfp3_gpio(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); u8 val; - val = snd_soc_component_read32(component, AIC32X4_SCLKCTL); + val = snd_soc_component_read(component, AIC32X4_SCLKCTL); ucontrol->value.integer.value[0] = (val & 0x01); @@ -137,7 +137,7 @@ static int aic32x4_set_mfp4_gpio(struct snd_kcontrol *kcontrol, u8 val; u8 gpio_check; - val = snd_soc_component_read32(component, AIC32X4_MISOCTL); + val = snd_soc_component_read(component, AIC32X4_MISOCTL); gpio_check = (val & AIC32X4_MFP_GPIO_ENABLED); if (gpio_check != AIC32X4_MFP_GPIO_ENABLED) { printk(KERN_ERR "%s: MFP4 is not configure as a GPIO output\n", @@ -164,7 +164,7 @@ static int aic32x4_get_mfp5_gpio(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); u8 val; - val = snd_soc_component_read32(component, AIC32X4_GPIOCTL); + val = snd_soc_component_read(component, AIC32X4_GPIOCTL); ucontrol->value.integer.value[0] = ((val & 0x2) >> 1); return 0; @@ -177,7 +177,7 @@ static int aic32x4_set_mfp5_gpio(struct snd_kcontrol *kcontrol, u8 val; u8 gpio_check; - val = snd_soc_component_read32(component, AIC32X4_GPIOCTL); + val = snd_soc_component_read(component, AIC32X4_GPIOCTL); gpio_check = (val & AIC32X4_MFP5_GPIO_OUTPUT); if (gpio_check != AIC32X4_MFP5_GPIO_OUTPUT) { printk(KERN_ERR "%s: MFP5 is not configure as a GPIO output\n", @@ -812,7 +812,7 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream, return 0; } -static int aic32x4_mute(struct snd_soc_dai *dai, int mute) +static int aic32x4_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -866,9 +866,10 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops aic32x4_ops = { .hw_params = aic32x4_hw_params, - .digital_mute = aic32x4_mute, + .mute_stream = aic32x4_mute, .set_fmt = aic32x4_set_dai_fmt, .set_sysclk = aic32x4_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver aic32x4_dai = { @@ -978,7 +979,7 @@ static int aic32x4_component_probe(struct snd_soc_component *component) AIC32X4_LDOCTLEN : 0; snd_soc_component_write(component, AIC32X4_LDOCTL, tmp_reg); - tmp_reg = snd_soc_component_read32(component, AIC32X4_CMMODE); + tmp_reg = snd_soc_component_read(component, AIC32X4_CMMODE); if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) tmp_reg |= AIC32X4_LDOIN_18_36; if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) @@ -1004,7 +1005,7 @@ static int aic32x4_component_probe(struct snd_soc_component *component) * and down for the first capture to work properly. It seems related to * a HW BUG or some kind of behavior not documented in the datasheet. */ - tmp_reg = snd_soc_component_read32(component, AIC32X4_ADCSETUP); + tmp_reg = snd_soc_component_read(component, AIC32X4_ADCSETUP); snd_soc_component_write(component, AIC32X4_ADCSETUP, tmp_reg | AIC32X4_LADC_EN | AIC32X4_RADC_EN); snd_soc_component_write(component, AIC32X4_ADCSETUP, tmp_reg); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 424faafcb85b9de74c05a1a0fdc052e602e04437..6d066bc58ac8adc0bf6ae4e7bc636cdcc3250ef9 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1056,7 +1056,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, width = params_width(params); /* select data word length */ - data = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); + data = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); switch (width) { case 16: break; @@ -1216,11 +1216,11 @@ static int aic3x_prepare(struct snd_pcm_substream *substream, return 0; } -static int aic3x_mute(struct snd_soc_dai *dai, int mute) +static int aic3x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u8 ldac_reg = snd_soc_component_read32(component, LDAC_VOL) & ~MUTE_ON; - u8 rdac_reg = snd_soc_component_read32(component, RDAC_VOL) & ~MUTE_ON; + u8 ldac_reg = snd_soc_component_read(component, LDAC_VOL) & ~MUTE_ON; + u8 rdac_reg = snd_soc_component_read(component, RDAC_VOL) & ~MUTE_ON; if (mute) { snd_soc_component_write(component, LDAC_VOL, ldac_reg | MUTE_ON); @@ -1256,8 +1256,8 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component); u8 iface_areg, iface_breg; - iface_areg = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLA) & 0x3f; - iface_breg = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLB) & 0x3f; + iface_areg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLA) & 0x3f; + iface_breg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLB) & 0x3f; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1407,8 +1407,8 @@ static int aic3x_set_power(struct snd_soc_component *component, int power) * writing one of them and thus caused other one also not * being written */ - pll_c = snd_soc_component_read32(component, AIC3X_PLL_PROGC_REG); - pll_d = snd_soc_component_read32(component, AIC3X_PLL_PROGD_REG); + pll_c = snd_soc_component_read(component, AIC3X_PLL_PROGC_REG); + pll_d = snd_soc_component_read(component, AIC3X_PLL_PROGD_REG); if (pll_c == aic3x_reg[AIC3X_PLL_PROGC_REG].def || pll_d == aic3x_reg[AIC3X_PLL_PROGD_REG].def) { snd_soc_component_write(component, AIC3X_PLL_PROGC_REG, pll_c); @@ -1481,10 +1481,11 @@ static int aic3x_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops aic3x_dai_ops = { .hw_params = aic3x_hw_params, .prepare = aic3x_prepare, - .digital_mute = aic3x_mute, + .mute_stream = aic3x_mute, .set_sysclk = aic3x_set_dai_sysclk, .set_fmt = aic3x_set_dai_fmt, .set_tdm_slot = aic3x_set_dai_tdm_slot, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver aic3x_dai = { diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 0b1f1a5e2a2d77fced279dfd9804370ed91f5e8a..e2d7ae615c528c68569914415c49bd9ec1dcc538 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -261,7 +261,7 @@ static int tpa6130a2_probe(struct i2c_client *client, default: dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n", data->id); - /* fall through */ + fallthrough; case TPA6130A2: regulator = "Vdd"; break; diff --git a/sound/soc/codecs/tscs42xx.c b/sound/soc/codecs/tscs42xx.c index 27b8c6ba72fa87a0ac1cf43c90a8e35cc60a6483..3265d3e8cb28e9dd8695cbcc5c524a00b363a7f2 100644 --- a/sound/soc/codecs/tscs42xx.c +++ b/sound/soc/codecs/tscs42xx.c @@ -103,7 +103,7 @@ static bool plls_locked(struct snd_soc_component *component) int count = MAX_PLL_LOCK_20MS_WAITS; do { - ret = snd_soc_component_read32(component, R_PLLCTL0); + ret = snd_soc_component_read(component, R_PLLCTL0); if (ret < 0) { dev_err(component->dev, "Failed to read PLL lock status (%d)\n", ret); @@ -148,7 +148,7 @@ static int write_coeff_ram(struct snd_soc_component *component, u8 *coeff_ram, for (cnt = 0; cnt < coeff_cnt; cnt++, addr++) { for (trys = 0; trys < DACCRSTAT_MAX_TRYS; trys++) { - ret = snd_soc_component_read32(component, R_DACCRSTAT); + ret = snd_soc_component_read(component, R_DACCRSTAT); if (ret < 0) { dev_err(component->dev, "Failed to read stat (%d)\n", ret); diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c index c3587af9985c0b7a03768a1b25b448be1c73dd86..d0af16b4db2f40acbfbb64917813e62dc8957e3f 100644 --- a/sound/soc/codecs/tscs454.c +++ b/sound/soc/codecs/tscs454.c @@ -353,12 +353,7 @@ static int write_coeff_ram(struct snd_soc_component *component, u8 *coeff_ram, for (cnt = 0; cnt < coeff_cnt; cnt++, coeff_addr++) { for (trys = 0; trys < DACCRSTAT_MAX_TRYS; trys++) { - ret = snd_soc_component_read(component, r_stat, &val); - if (ret < 0) { - dev_err(component->dev, - "Failed to read stat (%d)\n", ret); - return ret; - } + val = snd_soc_component_read(component, r_stat); if (!val) break; } @@ -444,12 +439,7 @@ static int coeff_ram_put(struct snd_kcontrol *kcontrol, mutex_lock(&tscs454->pll1.lock); mutex_lock(&tscs454->pll2.lock); - ret = snd_soc_component_read(component, R_PLLSTAT, &val); - if (ret < 0) { - dev_err(component->dev, "Failed to read PLL status (%d)\n", - ret); - goto exit; - } + val = snd_soc_component_read(component, R_PLLSTAT); if (val) { /* PLLs locked */ ret = write_coeff_ram(component, coeff_ram, r_stat, r_addr, r_wr, @@ -2642,13 +2632,10 @@ static int tscs454_set_sysclk(struct snd_soc_dai *dai, struct tscs454 *tscs454 = snd_soc_component_get_drvdata(component); unsigned int val; int bclk_dai; - int ret; dev_dbg(component->dev, "%s(): freq = %u\n", __func__, freq); - ret = snd_soc_component_read(component, R_PLLCTL, &val); - if (ret < 0) - return ret; + val = snd_soc_component_read(component, R_PLLCTL); bclk_dai = (val & FM_PLLCTL_BCLKSEL) >> FB_PLLCTL_BCLKSEL; if (bclk_dai != dai->id) @@ -3204,10 +3191,7 @@ static int tscs454_hw_params(struct snd_pcm_substream *substream, } if (!aifs_active(&tscs454->aifs_status)) { /* First active aif */ - ret = snd_soc_component_read(component, R_ISRC, &val); - if (ret < 0) - goto exit; - + val = snd_soc_component_read(component, R_ISRC); if ((val & FM_ISRC_IBR) == FV_IBR_48) tscs454->internal_rate.pll = &tscs454->pll1; else diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index f34637afee515872b66581144abe0335aa65b8a5..b37203336c4e0a92dd7bf656d4440dae89e179da 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -997,7 +997,7 @@ static void twl6040_mute_path(struct snd_soc_component *component, enum twl6040_ } } -static int twl6040_digital_mute(struct snd_soc_dai *dai, int mute) +static int twl6040_mute_stream(struct snd_soc_dai *dai, int mute, int direction) { switch (dai->id) { case TWL6040_DAI_LEGACY: @@ -1020,7 +1020,8 @@ static const struct snd_soc_dai_ops twl6040_dai_ops = { .hw_params = twl6040_hw_params, .prepare = twl6040_prepare, .set_sysclk = twl6040_set_dai_sysclk, - .digital_mute = twl6040_digital_mute, + .mute_stream = twl6040_mute_stream, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver twl6040_dai[] = { diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index 1cc7f56912dc779bbe4caa85652d2feb71a1be32..bf9182cedb8294461ea31ec8126f5e8fb49c634c 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -117,7 +117,7 @@ static inline void uda134x_reset(struct snd_soc_component *component) regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, 0); } -static int uda134x_mute(struct snd_soc_dai *dai, int mute) +static int uda134x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct uda134x_priv *uda134x = snd_soc_component_get_drvdata(dai->component); unsigned int mask = 1<<2; @@ -416,9 +416,10 @@ static const struct snd_soc_dai_ops uda134x_dai_ops = { .startup = uda134x_startup, .shutdown = uda134x_shutdown, .hw_params = uda134x_hw_params, - .digital_mute = uda134x_mute, + .mute_stream = uda134x_mute, .set_sysclk = uda134x_set_dai_sysclk, .set_fmt = uda134x_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver uda134x_dai = { diff --git a/sound/soc/codecs/wcd-clsh-v2.c b/sound/soc/codecs/wcd-clsh-v2.c index cc5a9c9b918bed21dedbdc614811ab2323eef049..1be82113c59aecda7b3760e445864e735e85f74b 100644 --- a/sound/soc/codecs/wcd-clsh-v2.c +++ b/sound/soc/codecs/wcd-clsh-v2.c @@ -119,7 +119,7 @@ static inline void wcd_enable_clsh_block(struct wcd_clsh_ctrl *ctrl, static inline bool wcd_clsh_enable_status(struct snd_soc_component *comp) { - return snd_soc_component_read32(comp, WCD9XXX_A_CDC_CLSH_CRC) & + return snd_soc_component_read(comp, WCD9XXX_A_CDC_CLSH_CRC) & WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK; } diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index fb073f4dc7eda586ba06852157f34ab34a8f1008..f2d9d52ee171b81a5ffc4304b8e4914e67b55add 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -1617,7 +1617,7 @@ static int wcd9335_set_mix_interpolator_rate(struct snd_soc_dai *dai, list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) { for (j = 0; j < WCD9335_NUM_INTERPOLATORS; j++) { - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, WCD9335_CDC_RX_INP_MUX_RX_INT_CFG1(j)) & WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK; @@ -1650,9 +1650,9 @@ static int wcd9335_set_prim_interpolator_rate(struct snd_soc_dai *dai, * is connected */ for (j = 0; j < WCD9335_NUM_INTERPOLATORS; j++) { - cfg0 = snd_soc_component_read32(comp, + cfg0 = snd_soc_component_read(comp, WCD9335_CDC_RX_INP_MUX_RX_INT_CFG0(j)); - cfg1 = snd_soc_component_read32(comp, + cfg1 = snd_soc_component_read(comp, WCD9335_CDC_RX_INP_MUX_RX_INT_CFG1(j)); inp0_sel = cfg0 & @@ -1826,7 +1826,7 @@ static int wcd9335_set_decimator_rate(struct snd_soc_dai *dai, return -EINVAL; } - tx_mux_sel = snd_soc_component_read32(comp, tx_port_reg) & + tx_mux_sel = snd_soc_component_read(comp, tx_port_reg) & (shift_val << shift); tx_mux_sel = tx_mux_sel >> shift; @@ -2678,17 +2678,17 @@ static int wcd9335_codec_find_amic_input(struct snd_soc_component *comp, if (adc_mux_n < 4) { reg = WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG1 + 2 * adc_mux_n; mreg = WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG0 + 2 * adc_mux_n; - mux_sel = snd_soc_component_read32(comp, reg) & 0x3; + mux_sel = snd_soc_component_read(comp, reg) & 0x3; } else { reg = WCD9335_CDC_TX_INP_MUX_ADC_MUX4_CFG0 + adc_mux_n - 4; mreg = reg; - mux_sel = snd_soc_component_read32(comp, reg) >> 6; + mux_sel = snd_soc_component_read(comp, reg) >> 6; } if (mux_sel != WCD9335_CDC_TX_INP_MUX_SEL_AMIC) return 0; - return snd_soc_component_read32(comp, mreg) & 0x07; + return snd_soc_component_read(comp, mreg) & 0x07; } static u16 wcd9335_codec_get_amic_pwlvl_reg(struct snd_soc_component *comp, @@ -2776,7 +2776,7 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w, amic_n); if (pwr_level_reg) { - switch ((snd_soc_component_read32(comp, pwr_level_reg) & + switch ((snd_soc_component_read(comp, pwr_level_reg) & WCD9335_AMIC_PWR_LVL_MASK) >> WCD9335_AMIC_PWR_LVL_SHIFT) { case WCD9335_AMIC_PWR_LEVEL_LP: @@ -2798,7 +2798,7 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w, break; } } - hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) & + hpf_coff_freq = (snd_soc_component_read(comp, dec_cfg_reg) & TX_HPF_CUT_OFF_FREQ_MASK) >> 5; if (hpf_coff_freq != CF_MIN_3DB_150HZ) @@ -2830,10 +2830,10 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(comp, tx_vol_ctl_reg, 0x10, 0x00); snd_soc_component_write(comp, tx_gain_ctl_reg, - snd_soc_component_read32(comp, tx_gain_ctl_reg)); + snd_soc_component_read(comp, tx_gain_ctl_reg)); break; case SND_SOC_DAPM_PRE_PMD: - hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) & + hpf_coff_freq = (snd_soc_component_read(comp, dec_cfg_reg) & TX_HPF_CUT_OFF_FREQ_MASK) >> 5; snd_soc_component_update_bits(comp, tx_vol_ctl_reg, 0x10, 0x10); snd_soc_component_update_bits(comp, dec_cfg_reg, 0x08, 0x00); @@ -3080,7 +3080,7 @@ static int wcd9335_codec_enable_mix_path(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - val = snd_soc_component_read32(comp, gain_reg); + val = snd_soc_component_read(comp, gain_reg); val += offset_val; snd_soc_component_write(comp, gain_reg, val); break; @@ -3208,7 +3208,7 @@ static int wcd9335_codec_enable_prim_interpolator( } if ((reg != prim_int_reg) && - ((snd_soc_component_read32(comp, prim_int_reg)) & + ((snd_soc_component_read(comp, prim_int_reg)) & WCD9335_CDC_RX_PGA_MUTE_EN_MASK)) snd_soc_component_update_bits(comp, reg, WCD9335_CDC_RX_PGA_MUTE_EN_MASK, @@ -3344,7 +3344,7 @@ static int wcd9335_codec_enable_interpolator(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMU: wcd9335_config_compander(comp, w->shift, event); - val = snd_soc_component_read32(comp, gain_reg); + val = snd_soc_component_read(comp, gain_reg); val += offset_val; snd_soc_component_write(comp, gain_reg, val); break; @@ -3366,12 +3366,12 @@ static void wcd9335_codec_hph_mode_gain_opt(struct snd_soc_component *component, u8 hph_pa_status; bool is_hphl_pa, is_hphr_pa; - hph_pa_status = snd_soc_component_read32(component, WCD9335_ANA_HPH); + hph_pa_status = snd_soc_component_read(component, WCD9335_ANA_HPH); is_hphl_pa = hph_pa_status >> 7; is_hphr_pa = (hph_pa_status & 0x40) >> 6; - hph_l_en = snd_soc_component_read32(component, WCD9335_HPH_L_EN); - hph_r_en = snd_soc_component_read32(component, WCD9335_HPH_R_EN); + hph_l_en = snd_soc_component_read(component, WCD9335_HPH_L_EN); + hph_r_en = snd_soc_component_read(component, WCD9335_HPH_R_EN); l_val = (hph_l_en & 0xC0) | 0x20 | gain; r_val = (hph_r_en & 0xC0) | 0x20 | gain; @@ -3542,7 +3542,7 @@ static int wcd9335_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: /* Read DEM INP Select */ - dem_inp = snd_soc_component_read32(comp, + dem_inp = snd_soc_component_read(comp, WCD9335_CDC_RX1_RX_PATH_SEC0) & 0x03; if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) || (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) { @@ -3694,7 +3694,7 @@ static int wcd9335_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_PRE_PMU: /* Read DEM INP Select */ - dem_inp = snd_soc_component_read32(comp, + dem_inp = snd_soc_component_read(comp, WCD9335_CDC_RX2_RX_PATH_SEC0) & WCD9335_CDC_RX_PATH_DEM_INP_SEL_MASK; if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) || @@ -3755,7 +3755,7 @@ static int wcd9335_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, WCD9335_CDC_RX_PGA_MUTE_DISABLE); /* Remove mix path mute if it is enabled */ - if ((snd_soc_component_read32(comp, + if ((snd_soc_component_read(comp, WCD9335_CDC_RX1_RX_PATH_MIX_CTL)) & WCD9335_CDC_RX_PGA_MUTE_EN_MASK) snd_soc_component_update_bits(comp, @@ -3817,7 +3817,7 @@ static int wcd9335_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w, WCD9335_CDC_RX_PGA_MUTE_DISABLE); /* Remove mix path mute if it is enabled */ - if ((snd_soc_component_read32(comp, mix_vol_reg)) & + if ((snd_soc_component_read(comp, mix_vol_reg)) & WCD9335_CDC_RX_PGA_MUTE_EN_MASK) snd_soc_component_update_bits(comp, mix_vol_reg, WCD9335_CDC_RX_PGA_MUTE_EN_MASK, @@ -3902,7 +3902,7 @@ static int wcd9335_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, WCD9335_CDC_RX_PGA_MUTE_EN_MASK, WCD9335_CDC_RX_PGA_MUTE_DISABLE); /* Remove mix path mute if it is enabled */ - if ((snd_soc_component_read32(comp, + if ((snd_soc_component_read(comp, WCD9335_CDC_RX2_RX_PATH_MIX_CTL)) & WCD9335_CDC_RX_PGA_MUTE_EN_MASK) snd_soc_component_update_bits(comp, @@ -3942,7 +3942,7 @@ static int wcd9335_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, WCD9335_CDC_RX_PGA_MUTE_EN_MASK, WCD9335_CDC_RX_PGA_MUTE_DISABLE); /* Remove mix path mute if it is enabled */ - if ((snd_soc_component_read32(comp, + if ((snd_soc_component_read(comp, WCD9335_CDC_RX0_RX_PATH_MIX_CTL)) & WCD9335_CDC_RX_PGA_MUTE_EN_MASK) snd_soc_component_update_bits(comp, @@ -4808,7 +4808,7 @@ static int wcd9335_enable_efuse_sensing(struct snd_soc_component *comp) */ usleep_range(5000, 5500); - if (!(snd_soc_component_read32(comp, + if (!(snd_soc_component_read(comp, WCD9335_CHIP_TIER_CTRL_EFUSE_STATUS) & WCD9335_CHIP_TIER_CTRL_EFUSE_EN_MASK)) WARN(1, "%s: Efuse sense is not complete\n", __func__); diff --git a/sound/soc/codecs/wcd9335.h b/sound/soc/codecs/wcd9335.h index 72060824c7436f95672156dd948e05167aa270f8..490fc44144a2a2f46e95d4426e267f26b1e77d76 100644 --- a/sound/soc/codecs/wcd9335.h +++ b/sound/soc/codecs/wcd9335.h @@ -4,9 +4,9 @@ #define __WCD9335_H__ /* - * WCD9335 register base can change according to the mode it works in - * in slimbus mode the reg base starts from 0x800 - * in i2s/i2c mode the reg base is 0x0 + * WCD9335 register base can change according to the mode it works in. + * In slimbus mode the reg base starts from 0x800. + * In i2s/i2c mode the reg base is 0x0. */ #define WCD9335_REG(pg, r) ((pg << 8) | (r)) #define WCD9335_REG_OFFSET(r) (r & 0xFF) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 531b8b79e55fd43237836748199f0af4a6c4f426..35697b072367aced19099f6b90b84d48f19e6d19 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -1464,9 +1464,9 @@ static int wcd934x_set_prim_interpolator_rate(struct snd_soc_dai *dai, if (j == INTERP_LO3_NA || j == INTERP_LO4_NA) continue; - cfg0 = snd_soc_component_read32(comp, + cfg0 = snd_soc_component_read(comp, WCD934X_CDC_RX_INP_MUX_RX_INT_CFG0(j)); - cfg1 = snd_soc_component_read32(comp, + cfg1 = snd_soc_component_read(comp, WCD934X_CDC_RX_INP_MUX_RX_INT_CFG1(j)); inp0_sel = cfg0 & @@ -1513,7 +1513,7 @@ static int wcd934x_set_mix_interpolator_rate(struct snd_soc_dai *dai, /* Interpolators 5 and 6 are not aviliable in Tavil */ if (j == INTERP_LO3_NA || j == INTERP_LO4_NA) continue; - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, WCD934X_CDC_RX_INP_MUX_RX_INT_CFG1(j)) & WCD934X_CDC_RX_INP_MUX_RX_INT_SEL_MASK; @@ -1616,7 +1616,7 @@ static int wcd934x_set_decimator_rate(struct snd_soc_dai *dai, return -EINVAL; } - tx_mux_sel = snd_soc_component_read32(comp, tx_port_reg) & + tx_mux_sel = snd_soc_component_read(comp, tx_port_reg) & (shift_val << shift); tx_mux_sel = tx_mux_sel >> shift; @@ -2346,23 +2346,23 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t)) & 0x7F); - value |= snd_soc_component_read32(component, b2_reg); + value |= snd_soc_component_read(component, b2_reg); snd_soc_component_write(component, reg, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t) + 1) & 0x7F); - value |= (snd_soc_component_read32(component, b2_reg) << 8); + value |= (snd_soc_component_read(component, b2_reg) << 8); snd_soc_component_write(component, reg, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t) + 2) & 0x7F); - value |= (snd_soc_component_read32(component, b2_reg) << 16); + value |= (snd_soc_component_read(component, b2_reg) << 16); snd_soc_component_write(component, reg, ((band_idx * BAND_MAX + coeff_idx) * sizeof(uint32_t) + 3) & 0x7F); /* Mask bits top 2 bits since they are reserved */ - value |= (snd_soc_component_read32(component, b2_reg) << 24); + value |= (snd_soc_component_read(component, b2_reg) << 24); return value; } @@ -3535,7 +3535,7 @@ static int wcd934x_codec_enable_mix_path(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMU: - val = snd_soc_component_read32(comp, gain_reg); + val = snd_soc_component_read(comp, gain_reg); val += offset_val; snd_soc_component_write(comp, gain_reg, val); break; @@ -3554,23 +3554,23 @@ static int wcd934x_codec_set_iir_gain(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: /* B1 GAIN */ snd_soc_component_write(comp, reg, - snd_soc_component_read32(comp, reg)); + snd_soc_component_read(comp, reg)); /* B2 GAIN */ reg++; snd_soc_component_write(comp, reg, - snd_soc_component_read32(comp, reg)); + snd_soc_component_read(comp, reg)); /* B3 GAIN */ reg++; snd_soc_component_write(comp, reg, - snd_soc_component_read32(comp, reg)); + snd_soc_component_read(comp, reg)); /* B4 GAIN */ reg++; snd_soc_component_write(comp, reg, - snd_soc_component_read32(comp, reg)); + snd_soc_component_read(comp, reg)); /* B5 GAIN */ reg++; snd_soc_component_write(comp, reg, - snd_soc_component_read32(comp, reg)); + snd_soc_component_read(comp, reg)); break; default: break; @@ -3591,7 +3591,7 @@ static int wcd934x_codec_enable_main_path(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: snd_soc_component_write(comp, gain_reg, - snd_soc_component_read32(comp, gain_reg)); + snd_soc_component_read(comp, gain_reg)); break; } @@ -3635,7 +3635,7 @@ static int wcd934x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: /* Read DEM INP Select */ - dem_inp = snd_soc_component_read32(comp, + dem_inp = snd_soc_component_read(comp, WCD934X_CDC_RX1_RX_PATH_SEC0) & 0x03; if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) || @@ -3686,7 +3686,7 @@ static int wcd934x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - dem_inp = snd_soc_component_read32(comp, + dem_inp = snd_soc_component_read(comp, WCD934X_CDC_RX2_RX_PATH_SEC0) & 0x03; if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) || (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) { @@ -3837,7 +3837,7 @@ static int wcd934x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK, WCD934X_HPH_AUTOCHOP_TIMER_ENABLE); /* Remove mix path mute if it is enabled */ - if ((snd_soc_component_read32(comp, + if ((snd_soc_component_read(comp, WCD934X_CDC_RX2_RX_PATH_MIX_CTL)) & 0x10) snd_soc_component_update_bits(comp, WCD934X_CDC_RX2_RX_PATH_MIX_CTL, @@ -3889,7 +3889,7 @@ static u32 wcd934x_get_dmic_sample_rate(struct snd_soc_component *comp, ++adc_mux_index; continue; } - adc_mux_sel = ((snd_soc_component_read32(comp, adc_mux_ctl_reg) + adc_mux_sel = ((snd_soc_component_read(comp, adc_mux_ctl_reg) & 0xF8) >> 3) - 1; if (adc_mux_sel == dmic) { @@ -3902,7 +3902,7 @@ static u32 wcd934x_get_dmic_sample_rate(struct snd_soc_component *comp, if (dec_found && adc_mux_index <= 8) { tx_fs_reg = WCD934X_CDC_TX0_TX_PATH_CTL + (16 * adc_mux_index); - tx_stream_fs = snd_soc_component_read32(comp, tx_fs_reg) & 0x0F; + tx_stream_fs = snd_soc_component_read(comp, tx_fs_reg) & 0x0F; if (tx_stream_fs <= 4) { if (wcd->dmic_sample_rate <= WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ) @@ -4104,12 +4104,12 @@ static int wcd934x_codec_find_amic_input(struct snd_soc_component *comp, adc_mux_n - 4; } - is_amic = (((snd_soc_component_read32(comp, adc_mux_in_reg) + is_amic = (((snd_soc_component_read(comp, adc_mux_in_reg) & mask) >> shift) == 1); if (!is_amic) return 0; - return snd_soc_component_read32(comp, amic_mux_sel_reg) & 0x07; + return snd_soc_component_read(comp, amic_mux_sel_reg) & 0x07; } static u16 wcd934x_codec_get_amic_pwlvl_reg(struct snd_soc_component *comp, @@ -4193,7 +4193,7 @@ static int wcd934x_codec_enable_dec(struct snd_soc_dapm_widget *w, if (!pwr_level_reg) break; - switch ((snd_soc_component_read32(comp, pwr_level_reg) & + switch ((snd_soc_component_read(comp, pwr_level_reg) & WCD934X_AMIC_PWR_LVL_MASK) >> WCD934X_AMIC_PWR_LVL_SHIFT) { case WCD934X_AMIC_PWR_LEVEL_LP: @@ -4216,7 +4216,7 @@ static int wcd934x_codec_enable_dec(struct snd_soc_dapm_widget *w, } break; case SND_SOC_DAPM_POST_PMU: - hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) & + hpf_coff_freq = (snd_soc_component_read(comp, dec_cfg_reg) & TX_HPF_CUT_OFF_FREQ_MASK) >> 5; if (hpf_coff_freq != CF_MIN_3DB_150HZ) { snd_soc_component_update_bits(comp, dec_cfg_reg, @@ -4236,11 +4236,11 @@ static int wcd934x_codec_enable_dec(struct snd_soc_dapm_widget *w, } /* apply gain after decimator is enabled */ snd_soc_component_write(comp, tx_gain_ctl_reg, - snd_soc_component_read32(comp, + snd_soc_component_read(comp, tx_gain_ctl_reg)); break; case SND_SOC_DAPM_PRE_PMD: - hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) & + hpf_coff_freq = (snd_soc_component_read(comp, dec_cfg_reg) & TX_HPF_CUT_OFF_FREQ_MASK) >> 5; if (hpf_coff_freq != CF_MIN_3DB_150HZ) { diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index fbcee21736e85e0acacd2e0fe31371705801d8e8..2f2b2f5d55e44b4d6dd6e03f11b2f8c0e7b8d382 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -515,7 +515,7 @@ static int wm0010_stage2_load(struct snd_soc_component *component) dev_dbg(component->dev, "Downloading %zu byte stage 2 loader\n", fw->size); /* Copy to local buffer first as vmalloc causes problems for dma */ - img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); + img = kmemdup(&fw->data[0], fw->size, GFP_KERNEL | GFP_DMA); if (!img) { ret = -ENOMEM; goto abort2; @@ -527,8 +527,6 @@ static int wm0010_stage2_load(struct snd_soc_component *component) goto abort1; } - memcpy(img, &fw->data[0], fw->size); - spi_message_init(&m); memset(&t, 0, sizeof(t)); t.rx_buf = out; diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 7b087d94141bd1d81e4d6d0fb67813896002e325..c62f7ad0022ca1a7457d5f9d6b594436123d1549 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2027,7 +2027,7 @@ static int wm2200_set_fll(struct snd_soc_component *component, int fll_id, int s msleep(1); } - ret = snd_soc_component_read32(component, + ret = snd_soc_component_read(component, WM2200_INTERRUPT_RAW_STATUS_2); if (ret < 0) { dev_err(component->dev, @@ -2060,7 +2060,7 @@ static int wm2200_dai_probe(struct snd_soc_dai *dai) unsigned int val = 0; int ret; - ret = snd_soc_component_read32(component, WM2200_GPIO_CTRL_1); + ret = snd_soc_component_read(component, WM2200_GPIO_CTRL_1); if (ret >= 0) { if ((ret & WM2200_GP1_FN_MASK) != 0) { wm2200->symmetric_rates = true; diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 91cc63c5a51fadfb78c0ddd11fe2a50c009b3399..9cab01ee4ee91626ff1c9359ccf322deb0120efc 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -137,7 +137,7 @@ static int wm5100_alloc_sr(struct snd_soc_component *component, int rate) sr_free = i; continue; } - if ((snd_soc_component_read32(component, wm5100_sr_regs[i]) & + if ((snd_soc_component_read(component, wm5100_sr_regs[i]) & WM5100_SAMPLE_RATE_1_MASK) == sr_code) break; } @@ -189,7 +189,7 @@ static void wm5100_free_sr(struct snd_soc_component *component, int rate) if (!wm5100->sr_ref[i]) continue; - if ((snd_soc_component_read32(component, wm5100_sr_regs[i]) & + if ((snd_soc_component_read(component, wm5100_sr_regs[i]) & WM5100_SAMPLE_RATE_1_MASK) == sr_code) break; } @@ -738,9 +738,9 @@ static void wm5100_seq_notifier(struct snd_soc_component *component, /* Wait for the outputs to flag themselves as enabled */ if (wm5100->out_ena[0]) { - expect = snd_soc_component_read32(component, WM5100_CHANNEL_ENABLES_1); + expect = snd_soc_component_read(component, WM5100_CHANNEL_ENABLES_1); for (i = 0; i < 200; i++) { - val = snd_soc_component_read32(component, WM5100_OUTPUT_STATUS_1); + val = snd_soc_component_read(component, WM5100_OUTPUT_STATUS_1); if (val == expect) { wm5100->out_ena[0] = false; break; @@ -753,9 +753,9 @@ static void wm5100_seq_notifier(struct snd_soc_component *component, } if (wm5100->out_ena[1]) { - expect = snd_soc_component_read32(component, WM5100_OUTPUT_ENABLES_2); + expect = snd_soc_component_read(component, WM5100_OUTPUT_ENABLES_2); for (i = 0; i < 200; i++) { - val = snd_soc_component_read32(component, WM5100_OUTPUT_STATUS_2); + val = snd_soc_component_read(component, WM5100_OUTPUT_STATUS_2); if (val == expect) { wm5100->out_ena[1] = false; break; @@ -841,13 +841,13 @@ static int wm5100_post_ev(struct snd_soc_dapm_widget *w, struct wm5100_priv *wm5100 = snd_soc_component_get_drvdata(component); int ret; - ret = snd_soc_component_read32(component, WM5100_INTERRUPT_RAW_STATUS_3); + ret = snd_soc_component_read(component, WM5100_INTERRUPT_RAW_STATUS_3); ret &= WM5100_SPK_SHUTDOWN_WARN_STS | WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS | WM5100_CLKGEN_ERR_ASYNC_STS; wm5100_log_status3(wm5100, ret); - ret = snd_soc_component_read32(component, WM5100_INTERRUPT_RAW_STATUS_4); + ret = snd_soc_component_read(component, WM5100_INTERRUPT_RAW_STATUS_4); wm5100_log_status4(wm5100, ret); return 0; @@ -1848,7 +1848,7 @@ static int wm5100_set_fll(struct snd_soc_component *component, int fll_id, int s msleep(1); } - ret = snd_soc_component_read32(component, + ret = snd_soc_component_read(component, WM5100_INTERRUPT_RAW_STATUS_3); if (ret < 0) { dev_err(component->dev, diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 44de44bff4234556e9bd883b3bace21d798e7483..4238929b237510a41d96fae7dc97d4e5becb36cb 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -290,7 +290,7 @@ static int wm5110_hp_pre_enable(struct snd_soc_dapm_widget *w) struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct arizona_priv *priv = snd_soc_component_get_drvdata(component); struct arizona *arizona = priv->arizona; - unsigned int val = snd_soc_component_read32(component, ARIZONA_DRE_ENABLE); + unsigned int val = snd_soc_component_read(component, ARIZONA_DRE_ENABLE); const struct reg_sequence *wseq; int nregs; @@ -326,7 +326,7 @@ static int wm5110_hp_pre_disable(struct snd_soc_dapm_widget *w) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct arizona_priv *priv = snd_soc_component_get_drvdata(component); - unsigned int val = snd_soc_component_read32(component, ARIZONA_DRE_ENABLE); + unsigned int val = snd_soc_component_read(component, ARIZONA_DRE_ENABLE); switch (w->shift) { case ARIZONA_OUT1L_ENA_SHIFT: @@ -524,7 +524,7 @@ static int wm5110_in_analog_ev(struct snd_soc_dapm_widget *w, wm5110->in_post_pending++; return 0; case SND_SOC_DAPM_PRE_PMU: - wm5110->in_pga_cache[w->shift] = snd_soc_component_read32(component, reg); + wm5110->in_pga_cache[w->shift] = snd_soc_component_read(component, reg); snd_soc_component_update_bits(component, reg, mask, 0x40 << ARIZONA_IN1L_PGA_VOL_SHIFT); diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index fe99584c917f8bb0825b530a8da8408edc1ae13d..a6aa212fa0c89faa2865755cf68da635226f27a6 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -331,7 +331,7 @@ static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol, return ret; /* now hit the volume update bits (always bit 8) */ - val = snd_soc_component_read32(component, reg); + val = snd_soc_component_read(component, reg); snd_soc_component_write(component, reg, val | WM8350_OUT1_VU); return 1; } @@ -766,7 +766,7 @@ static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai, case WM8350_MCLK_SEL_PLL_32K: wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_1, WM8350_MCLK_SEL); - fll_4 = snd_soc_component_read32(component, WM8350_FLL_CONTROL_4) & + fll_4 = snd_soc_component_read(component, WM8350_FLL_CONTROL_4) & ~WM8350_FLL_CLK_SRC_MASK; snd_soc_component_write(component, WM8350_FLL_CONTROL_4, fll_4 | clk_id); break; @@ -790,37 +790,37 @@ static int wm8350_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div) switch (div_id) { case WM8350_ADC_CLKDIV: - val = snd_soc_component_read32(component, WM8350_ADC_DIVIDER) & + val = snd_soc_component_read(component, WM8350_ADC_DIVIDER) & ~WM8350_ADC_CLKDIV_MASK; snd_soc_component_write(component, WM8350_ADC_DIVIDER, val | div); break; case WM8350_DAC_CLKDIV: - val = snd_soc_component_read32(component, WM8350_DAC_CLOCK_CONTROL) & + val = snd_soc_component_read(component, WM8350_DAC_CLOCK_CONTROL) & ~WM8350_DAC_CLKDIV_MASK; snd_soc_component_write(component, WM8350_DAC_CLOCK_CONTROL, val | div); break; case WM8350_BCLK_CLKDIV: - val = snd_soc_component_read32(component, WM8350_CLOCK_CONTROL_1) & + val = snd_soc_component_read(component, WM8350_CLOCK_CONTROL_1) & ~WM8350_BCLK_DIV_MASK; snd_soc_component_write(component, WM8350_CLOCK_CONTROL_1, val | div); break; case WM8350_OPCLK_CLKDIV: - val = snd_soc_component_read32(component, WM8350_CLOCK_CONTROL_1) & + val = snd_soc_component_read(component, WM8350_CLOCK_CONTROL_1) & ~WM8350_OPCLK_DIV_MASK; snd_soc_component_write(component, WM8350_CLOCK_CONTROL_1, val | div); break; case WM8350_SYS_CLKDIV: - val = snd_soc_component_read32(component, WM8350_CLOCK_CONTROL_1) & + val = snd_soc_component_read(component, WM8350_CLOCK_CONTROL_1) & ~WM8350_MCLK_DIV_MASK; snd_soc_component_write(component, WM8350_CLOCK_CONTROL_1, val | div); break; case WM8350_DACLR_CLKDIV: - val = snd_soc_component_read32(component, WM8350_DAC_LR_RATE) & + val = snd_soc_component_read(component, WM8350_DAC_LR_RATE) & ~WM8350_DACLRC_RATE_MASK; snd_soc_component_write(component, WM8350_DAC_LR_RATE, val | div); break; case WM8350_ADCLR_CLKDIV: - val = snd_soc_component_read32(component, WM8350_ADC_LR_RATE) & + val = snd_soc_component_read(component, WM8350_ADC_LR_RATE) & ~WM8350_ADCLRC_RATE_MASK; snd_soc_component_write(component, WM8350_ADC_LR_RATE, val | div); break; @@ -834,13 +834,13 @@ static int wm8350_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div) static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 iface = snd_soc_component_read32(component, WM8350_AI_FORMATING) & + u16 iface = snd_soc_component_read(component, WM8350_AI_FORMATING) & ~(WM8350_AIF_BCLK_INV | WM8350_AIF_LRCLK_INV | WM8350_AIF_FMT_MASK); - u16 master = snd_soc_component_read32(component, WM8350_AI_DAC_CONTROL) & + u16 master = snd_soc_component_read(component, WM8350_AI_DAC_CONTROL) & ~WM8350_BCLK_MSTR; - u16 dac_lrc = snd_soc_component_read32(component, WM8350_DAC_LR_RATE) & + u16 dac_lrc = snd_soc_component_read(component, WM8350_DAC_LR_RATE) & ~WM8350_DACLRC_ENA; - u16 adc_lrc = snd_soc_component_read32(component, WM8350_ADC_LR_RATE) & + u16 adc_lrc = snd_soc_component_read(component, WM8350_ADC_LR_RATE) & ~WM8350_ADCLRC_ENA; /* set master/slave audio interface */ @@ -907,7 +907,7 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = codec_dai->component; struct wm8350_data *wm8350_data = snd_soc_component_get_drvdata(component); struct wm8350 *wm8350 = wm8350_data->wm8350; - u16 iface = snd_soc_component_read32(component, WM8350_AI_FORMATING) & + u16 iface = snd_soc_component_read(component, WM8350_AI_FORMATING) & ~WM8350_AIF_WL_MASK; /* bit size */ @@ -942,7 +942,7 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8350_mute(struct snd_soc_dai *dai, int mute) +static int wm8350_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; unsigned int val; @@ -1047,7 +1047,7 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai, fll_div.ratio); /* set up N.K & dividers */ - fll_1 = snd_soc_component_read32(component, WM8350_FLL_CONTROL_1) & + fll_1 = snd_soc_component_read(component, WM8350_FLL_CONTROL_1) & ~(WM8350_FLL_OUTDIV_MASK | WM8350_FLL_RSP_RATE_MASK | 0xc000); snd_soc_component_write(component, WM8350_FLL_CONTROL_1, fll_1 | (fll_div.div << 8) | 0x50); @@ -1055,7 +1055,7 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai, (fll_div.ratio << 11) | (fll_div. n & WM8350_FLL_N_MASK)); snd_soc_component_write(component, WM8350_FLL_CONTROL_3, fll_div.k); - fll_4 = snd_soc_component_read32(component, WM8350_FLL_CONTROL_4) & + fll_4 = snd_soc_component_read(component, WM8350_FLL_CONTROL_4) & ~(WM8350_FLL_FRAC | WM8350_FLL_SLOW_LOCK_REF); snd_soc_component_write(component, WM8350_FLL_CONTROL_4, fll_4 | (fll_div.k ? WM8350_FLL_FRAC : 0) | @@ -1426,11 +1426,12 @@ EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect); static const struct snd_soc_dai_ops wm8350_dai_ops = { .hw_params = wm8350_pcm_hw_params, - .digital_mute = wm8350_mute, + .mute_stream = wm8350_mute, .set_fmt = wm8350_set_dai_fmt, .set_sysclk = wm8350_set_dai_sysclk, .set_pll = wm8350_set_fll, .set_clkdiv = wm8350_set_clkdiv, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8350_dai = { diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index e25c09b8a6938a3fc2211efbeec813d7481aace8..bf5e77c86aed659b202ce8faac7af7f65faafb74 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -67,16 +67,12 @@ static void wm8400_component_reset(struct snd_soc_component *component) wm8400_reset_codec_reg_cache(wm8400->wm8400); } -static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 600, 0); - static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1650, 3000, 0); static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -2100, 0, 0); static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -7300, 600, 0); -static const DECLARE_TLV_DB_SCALE(out_omix_tlv, -600, 0, 0); - static const DECLARE_TLV_DB_SCALE(out_dac_tlv, -7163, 0, 0); static const DECLARE_TLV_DB_SCALE(in_adc_tlv, -7163, 1763, 0); @@ -98,7 +94,7 @@ static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, return ret; /* now hit the volume update bits (always bit 8) */ - val = snd_soc_component_read32(component, reg); + val = snd_soc_component_read(component, reg); return snd_soc_component_write(component, reg, val | 0x0100); } @@ -328,7 +324,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, switch (reg_shift) { case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) : - reg = snd_soc_component_read32(component, WM8400_OUTPUT_MIXER1); + reg = snd_soc_component_read(component, WM8400_OUTPUT_MIXER1); if (reg & WM8400_LDLO) { printk(KERN_WARNING "Cannot set as Output Mixer 1 LDLO Set\n"); @@ -336,7 +332,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, } break; case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8): - reg = snd_soc_component_read32(component, WM8400_OUTPUT_MIXER2); + reg = snd_soc_component_read(component, WM8400_OUTPUT_MIXER2); if (reg & WM8400_RDRO) { printk(KERN_WARNING "Cannot set as Output Mixer 2 RDRO Set\n"); @@ -344,7 +340,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, } break; case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8): - reg = snd_soc_component_read32(component, WM8400_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8400_SPEAKER_MIXER); if (reg & WM8400_LDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer LDSPK Set\n"); @@ -352,7 +348,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, } break; case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8): - reg = snd_soc_component_read32(component, WM8400_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8400_SPEAKER_MIXER); if (reg & WM8400_RDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer RDSPK Set\n"); @@ -439,14 +435,6 @@ static SOC_ENUM_SINGLE_DECL(wm8400_ainrmux_enum, static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum); -/* RXVOICE */ -static const struct snd_kcontrol_new wm8400_dapm_rxvoice_controls[] = { -SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8400_INPUT_MIXER5, WM8400_LR4BVOL_SHIFT, - WM8400_LR4BVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8400_INPUT_MIXER6, WM8400_RL4BVOL_SHIFT, - WM8400_RL4BVOL_MASK, 0, in_mix_tlv), -}; - /* LOMIX */ static const struct snd_kcontrol_new wm8400_dapm_lomix_controls[] = { SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER1, @@ -957,11 +945,11 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, wm8400->fll_in = freq_in; /* We *must* disable the FLL before any changes */ - reg = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_2); + reg = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_2); reg &= ~WM8400_FLL_ENA; snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_2, reg); - reg = snd_soc_component_read32(component, WM8400_FLL_CONTROL_1); + reg = snd_soc_component_read(component, WM8400_FLL_CONTROL_1); reg &= ~WM8400_FLL_OSC_ENA; snd_soc_component_write(component, WM8400_FLL_CONTROL_1, reg); @@ -976,7 +964,7 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_component_write(component, WM8400_FLL_CONTROL_2, factors.k); snd_soc_component_write(component, WM8400_FLL_CONTROL_3, factors.n); - reg = snd_soc_component_read32(component, WM8400_FLL_CONTROL_4); + reg = snd_soc_component_read(component, WM8400_FLL_CONTROL_4); reg &= ~WM8400_FLL_OUTDIV_MASK; reg |= factors.outdiv; snd_soc_component_write(component, WM8400_FLL_CONTROL_4, reg); @@ -993,8 +981,8 @@ static int wm8400_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_component *component = codec_dai->component; u16 audio1, audio3; - audio1 = snd_soc_component_read32(component, WM8400_AUDIO_INTERFACE_1); - audio3 = snd_soc_component_read32(component, WM8400_AUDIO_INTERFACE_3); + audio1 = snd_soc_component_read(component, WM8400_AUDIO_INTERFACE_1); + audio3 = snd_soc_component_read(component, WM8400_AUDIO_INTERFACE_3); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1048,22 +1036,22 @@ static int wm8400_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8400_MCLK_DIV: - reg = snd_soc_component_read32(component, WM8400_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8400_CLOCKING_2) & ~WM8400_MCLK_DIV_MASK; snd_soc_component_write(component, WM8400_CLOCKING_2, reg | div); break; case WM8400_DACCLK_DIV: - reg = snd_soc_component_read32(component, WM8400_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8400_CLOCKING_2) & ~WM8400_DAC_CLKDIV_MASK; snd_soc_component_write(component, WM8400_CLOCKING_2, reg | div); break; case WM8400_ADCCLK_DIV: - reg = snd_soc_component_read32(component, WM8400_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8400_CLOCKING_2) & ~WM8400_ADC_CLKDIV_MASK; snd_soc_component_write(component, WM8400_CLOCKING_2, reg | div); break; case WM8400_BCLK_DIV: - reg = snd_soc_component_read32(component, WM8400_CLOCKING_1) & + reg = snd_soc_component_read(component, WM8400_CLOCKING_1) & ~WM8400_BCLK_DIV_MASK; snd_soc_component_write(component, WM8400_CLOCKING_1, reg | div); break; @@ -1082,7 +1070,7 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 audio1 = snd_soc_component_read32(component, WM8400_AUDIO_INTERFACE_1); + u16 audio1 = snd_soc_component_read(component, WM8400_AUDIO_INTERFACE_1); audio1 &= ~WM8400_AIF_WL_MASK; /* bit size */ @@ -1104,10 +1092,10 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8400_mute(struct snd_soc_dai *dai, int mute) +static int wm8400_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 val = snd_soc_component_read32(component, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE; + u16 val = snd_soc_component_read(component, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE; if (mute) snd_soc_component_write(component, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); @@ -1131,7 +1119,7 @@ static int wm8400_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_PREPARE: /* VMID=2*50k */ - val = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1) & + val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1) & ~WM8400_VMID_MODE_MASK; snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val | 0x2); break; @@ -1157,7 +1145,7 @@ static int wm8400_set_bias_level(struct snd_soc_component *component, msleep(50); /* Enable VREF & VMID at 2x50k */ - val = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1); + val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1); val |= 0x2 | WM8400_VREF_ENA; snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val); @@ -1171,7 +1159,7 @@ static int wm8400_set_bias_level(struct snd_soc_component *component, } /* VMID=2*300k */ - val = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1) & + val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1) & ~WM8400_VMID_MODE_MASK; snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, val | 0x4); break; @@ -1187,11 +1175,11 @@ static int wm8400_set_bias_level(struct snd_soc_component *component, WM8400_BUFIOEN); /* mute DAC */ - val = snd_soc_component_read32(component, WM8400_DAC_CTRL); + val = snd_soc_component_read(component, WM8400_DAC_CTRL); snd_soc_component_write(component, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); /* Enable any disabled outputs */ - val = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1); + val = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1); val |= WM8400_SPK_ENA | WM8400_OUT3_ENA | WM8400_OUT4_ENA | WM8400_LOUT_ENA | WM8400_ROUT_ENA; @@ -1234,11 +1222,12 @@ static int wm8400_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8400_dai_ops = { .hw_params = wm8400_hw_params, - .digital_mute = wm8400_mute, + .mute_stream = wm8400_mute, .set_fmt = wm8400_set_dai_fmt, .set_clkdiv = wm8400_set_dai_clkdiv, .set_sysclk = wm8400_set_dai_sysclk, .set_pll = wm8400_set_dai_pll, + .no_capture_mute = 1, }; /* @@ -1293,14 +1282,14 @@ static int wm8400_component_probe(struct snd_soc_component *component) wm8400_component_reset(component); - reg = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1); + reg = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1); snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, reg | WM8400_CODEC_ENA); /* Latch volume update bits */ - reg = snd_soc_component_read32(component, WM8400_LEFT_LINE_INPUT_1_2_VOLUME); + reg = snd_soc_component_read(component, WM8400_LEFT_LINE_INPUT_1_2_VOLUME); snd_soc_component_write(component, WM8400_LEFT_LINE_INPUT_1_2_VOLUME, reg & WM8400_IPVU); - reg = snd_soc_component_read32(component, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME); + reg = snd_soc_component_read(component, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME); snd_soc_component_write(component, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, reg & WM8400_IPVU); @@ -1314,7 +1303,7 @@ static void wm8400_component_remove(struct snd_soc_component *component) { u16 reg; - reg = snd_soc_component_read32(component, WM8400_POWER_MANAGEMENT_1); + reg = snd_soc_component_read(component, WM8400_POWER_MANAGEMENT_1); snd_soc_component_write(component, WM8400_POWER_MANAGEMENT_1, reg & (~WM8400_CODEC_ENA)); } diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index cd3e0c848caefdc13143574b7f42871448688b57..73c4a8b9f59e333bff00e7f45e2149c934e8e27f 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -318,11 +318,11 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (freq_in == 0 || freq_out == 0) { /* Clock CODEC directly from MCLK */ - reg = snd_soc_component_read32(component, WM8510_CLOCK); + reg = snd_soc_component_read(component, WM8510_CLOCK); snd_soc_component_write(component, WM8510_CLOCK, reg & 0x0ff); /* Turn off PLL */ - reg = snd_soc_component_read32(component, WM8510_POWER1); + reg = snd_soc_component_read(component, WM8510_POWER1); snd_soc_component_write(component, WM8510_POWER1, reg & 0x1df); return 0; } @@ -333,11 +333,11 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_component_write(component, WM8510_PLLK1, pll_div.k >> 18); snd_soc_component_write(component, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff); snd_soc_component_write(component, WM8510_PLLK3, pll_div.k & 0x1ff); - reg = snd_soc_component_read32(component, WM8510_POWER1); + reg = snd_soc_component_read(component, WM8510_POWER1); snd_soc_component_write(component, WM8510_POWER1, reg | 0x020); /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_component_read32(component, WM8510_CLOCK); + reg = snd_soc_component_read(component, WM8510_CLOCK); snd_soc_component_write(component, WM8510_CLOCK, reg | 0x100); return 0; @@ -354,23 +354,23 @@ static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8510_OPCLKDIV: - reg = snd_soc_component_read32(component, WM8510_GPIO) & 0x1cf; + reg = snd_soc_component_read(component, WM8510_GPIO) & 0x1cf; snd_soc_component_write(component, WM8510_GPIO, reg | div); break; case WM8510_MCLKDIV: - reg = snd_soc_component_read32(component, WM8510_CLOCK) & 0x11f; + reg = snd_soc_component_read(component, WM8510_CLOCK) & 0x11f; snd_soc_component_write(component, WM8510_CLOCK, reg | div); break; case WM8510_ADCCLK: - reg = snd_soc_component_read32(component, WM8510_ADC) & 0x1f7; + reg = snd_soc_component_read(component, WM8510_ADC) & 0x1f7; snd_soc_component_write(component, WM8510_ADC, reg | div); break; case WM8510_DACCLK: - reg = snd_soc_component_read32(component, WM8510_DAC) & 0x1f7; + reg = snd_soc_component_read(component, WM8510_DAC) & 0x1f7; snd_soc_component_write(component, WM8510_DAC, reg | div); break; case WM8510_BCLKDIV: - reg = snd_soc_component_read32(component, WM8510_CLOCK) & 0x1e3; + reg = snd_soc_component_read(component, WM8510_CLOCK) & 0x1e3; snd_soc_component_write(component, WM8510_CLOCK, reg | div); break; default: @@ -385,7 +385,7 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai, { struct snd_soc_component *component = codec_dai->component; u16 iface = 0; - u16 clk = snd_soc_component_read32(component, WM8510_CLOCK) & 0x1fe; + u16 clk = snd_soc_component_read(component, WM8510_CLOCK) & 0x1fe; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -442,8 +442,8 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 iface = snd_soc_component_read32(component, WM8510_IFACE) & 0x19f; - u16 adn = snd_soc_component_read32(component, WM8510_ADD) & 0x1f1; + u16 iface = snd_soc_component_read(component, WM8510_IFACE) & 0x19f; + u16 adn = snd_soc_component_read(component, WM8510_ADD) & 0x1f1; /* bit size */ switch (params_width(params)) { @@ -487,10 +487,10 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8510_mute(struct snd_soc_dai *dai, int mute) +static int wm8510_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8510_DAC) & 0xffbf; + u16 mute_reg = snd_soc_component_read(component, WM8510_DAC) & 0xffbf; if (mute) snd_soc_component_write(component, WM8510_DAC, mute_reg | 0x40); @@ -504,7 +504,7 @@ static int wm8510_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8510_priv *wm8510 = snd_soc_component_get_drvdata(component); - u16 power1 = snd_soc_component_read32(component, WM8510_POWER1) & ~0x3; + u16 power1 = snd_soc_component_read(component, WM8510_POWER1) & ~0x3; switch (level) { case SND_SOC_BIAS_ON: @@ -547,10 +547,11 @@ static int wm8510_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8510_dai_ops = { .hw_params = wm8510_pcm_hw_params, - .digital_mute = wm8510_mute, + .mute_stream = wm8510_mute, .set_fmt = wm8510_set_dai_fmt, .set_clkdiv = wm8510_set_dai_clkdiv, .set_pll = wm8510_set_dai_pll, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8510_dai = { diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 04d67ee8203b0337eedcde6dc06a5d96081f7cc1..c8b50aac6c180ed9f88f9f71496d8beda1ab538a 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -147,8 +147,8 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component); int i; - u16 aifctrl1 = snd_soc_component_read32(component, WM8523_AIF_CTRL1); - u16 aifctrl2 = snd_soc_component_read32(component, WM8523_AIF_CTRL2); + u16 aifctrl1 = snd_soc_component_read(component, WM8523_AIF_CTRL1); + u16 aifctrl2 = snd_soc_component_read(component, WM8523_AIF_CTRL2); /* Find a supported LRCLK ratio */ for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { @@ -258,7 +258,7 @@ static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 aifctrl1 = snd_soc_component_read32(component, WM8523_AIF_CTRL1); + u16 aifctrl1 = snd_soc_component_read(component, WM8523_AIF_CTRL1); aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK | WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK); diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 0227c769937f183757a2710de7ef20f1cdf1180f..85ad2f03cfd0c00844212c5049a25af8c914ec48 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -511,7 +511,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_component_write(component, WM8580_PLLA3 + offset, (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); - reg = snd_soc_component_read32(component, WM8580_PLLA4 + offset); + reg = snd_soc_component_read(component, WM8580_PLLA4 + offset); reg &= ~0x1b; reg |= pll_div.prescale | pll_div.postscale << 1 | pll_div.freqmode << 3; @@ -608,8 +608,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int aifb; int can_invert_lrclk; - aifa = snd_soc_component_read32(component, WM8580_PAIF1 + codec_dai->driver->id); - aifb = snd_soc_component_read32(component, WM8580_PAIF3 + codec_dai->driver->id); + aifa = snd_soc_component_read(component, WM8580_PAIF1 + codec_dai->driver->id); + aifb = snd_soc_component_read(component, WM8580_PAIF3 + codec_dai->driver->id); aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); @@ -689,7 +689,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8580_MCLK: - reg = snd_soc_component_read32(component, WM8580_PLLB4); + reg = snd_soc_component_read(component, WM8580_PLLB4); reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK; switch (div) { @@ -715,7 +715,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, break; case WM8580_CLKOUTSRC: - reg = snd_soc_component_read32(component, WM8580_PLLB4); + reg = snd_soc_component_read(component, WM8580_PLLB4); reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; switch (div) { @@ -800,12 +800,12 @@ static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id, return 0; } -static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8580_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; unsigned int reg; - reg = snd_soc_component_read32(component, WM8580_DAC_CONTROL5); + reg = snd_soc_component_read(component, WM8580_DAC_CONTROL5); if (mute) reg |= WM8580_DAC_CONTROL5_MUTEALL; @@ -866,7 +866,8 @@ static const struct snd_soc_dai_ops wm8580_dai_ops_playback = { .set_fmt = wm8580_set_paif_dai_fmt, .set_clkdiv = wm8580_set_dai_clkdiv, .set_pll = wm8580_set_dai_pll, - .digital_mute = wm8580_digital_mute, + .mute_stream = wm8580_mute, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8580_dai_ops_capture = { diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 5ad905dd78b727ee04e4f13bade85e775d28eddb..bc4d161c59e5c586adbdef50567985f015f53c58 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -158,7 +158,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8711_priv *wm8711 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8711_IFACE) & 0xfff3; + u16 iface = snd_soc_component_read(component, WM8711_IFACE) & 0xfff3; int i = get_coeff(wm8711->sysclk, params_rate(params)); u16 srate = (coeff_div[i].sr << 2) | (coeff_div[i].bosr << 1) | coeff_div[i].usb; @@ -204,10 +204,10 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream, } } -static int wm8711_mute(struct snd_soc_dai *dai, int mute) +static int wm8711_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8711_APDIGI) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8711_APDIGI) & 0xfff7; if (mute) snd_soc_component_write(component, WM8711_APDIGI, mute_reg | 0x8); @@ -239,7 +239,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 iface = snd_soc_component_read32(component, WM8711_IFACE) & 0x000c; + u16 iface = snd_soc_component_read(component, WM8711_IFACE) & 0x000c; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -298,7 +298,7 @@ static int wm8711_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8711_priv *wm8711 = snd_soc_component_get_drvdata(component); - u16 reg = snd_soc_component_read32(component, WM8711_PWR) & 0xff7f; + u16 reg = snd_soc_component_read(component, WM8711_PWR) & 0xff7f; switch (level) { case SND_SOC_BIAS_ON: @@ -329,9 +329,10 @@ static const struct snd_soc_dai_ops wm8711_ops = { .prepare = wm8711_pcm_prepare, .hw_params = wm8711_hw_params, .shutdown = wm8711_shutdown, - .digital_mute = wm8711_mute, + .mute_stream = wm8711_mute, .set_sysclk = wm8711_set_dai_sysclk, .set_fmt = wm8711_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8711_dai = { diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 8b876659f29cc90e3afe99992002e42f99e8306a..2cd58d133899da0468bda1fe09d9385f275c2e25 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -69,10 +69,10 @@ static const struct snd_soc_dapm_route wm8728_intercon[] = { {"VOUTR", NULL, "DAC"}, }; -static int wm8728_mute(struct snd_soc_dai *dai, int mute) +static int wm8728_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8728_DACCTL); + u16 mute_reg = snd_soc_component_read(component, WM8728_DACCTL); if (mute) snd_soc_component_write(component, WM8728_DACCTL, mute_reg | 1); @@ -87,7 +87,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 dac = snd_soc_component_read32(component, WM8728_DACCTL); + u16 dac = snd_soc_component_read(component, WM8728_DACCTL); dac &= ~0x18; @@ -113,7 +113,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 iface = snd_soc_component_read32(component, WM8728_IFCTL); + u16 iface = snd_soc_component_read(component, WM8728_IFCTL); /* Currently only I2S is supported by the driver, though the * hardware is more flexible. @@ -169,7 +169,7 @@ static int wm8728_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_STANDBY: if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { /* Power everything up... */ - reg = snd_soc_component_read32(component, WM8728_DACCTL); + reg = snd_soc_component_read(component, WM8728_DACCTL); snd_soc_component_write(component, WM8728_DACCTL, reg & ~0x4); /* ..then sync in the register cache. */ @@ -178,7 +178,7 @@ static int wm8728_set_bias_level(struct snd_soc_component *component, break; case SND_SOC_BIAS_OFF: - reg = snd_soc_component_read32(component, WM8728_DACCTL); + reg = snd_soc_component_read(component, WM8728_DACCTL); snd_soc_component_write(component, WM8728_DACCTL, reg | 0x4); break; } @@ -192,8 +192,9 @@ static int wm8728_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8728_dai_ops = { .hw_params = wm8728_hw_params, - .digital_mute = wm8728_mute, + .mute_stream = wm8728_mute, .set_fmt = wm8728_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8728_dai = { diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 6fd1bef848ed9e48fc7223b5e18be1b9f1f82b23..304bf725a6132524731db01f0931f6207c1cafa6 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -336,7 +336,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8731_priv *wm8731 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8731_IFACE) & 0xfff3; + u16 iface = snd_soc_component_read(component, WM8731_IFACE) & 0xfff3; int i = get_coeff(wm8731->sysclk, params_rate(params)); u16 srate = (coeff_div[i].sr << 2) | (coeff_div[i].bosr << 1) | coeff_div[i].usb; @@ -366,10 +366,10 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8731_mute(struct snd_soc_dai *dai, int mute) +static int wm8731_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8731_APDIGI) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8731_APDIGI) & 0xfff7; if (mute) snd_soc_component_write(component, WM8731_APDIGI, mute_reg | 0x8); @@ -510,7 +510,7 @@ static int wm8731_set_bias_level(struct snd_soc_component *component, } /* Clear PWROFF, gate CLKOUT, everything else as-is */ - reg = snd_soc_component_read32(component, WM8731_PWR) & 0xff7f; + reg = snd_soc_component_read(component, WM8731_PWR) & 0xff7f; snd_soc_component_write(component, WM8731_PWR, reg | 0x0040); break; case SND_SOC_BIAS_OFF: @@ -546,9 +546,10 @@ static int wm8731_startup(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops wm8731_dai_ops = { .startup = wm8731_startup, .hw_params = wm8731_hw_params, - .digital_mute = wm8731_mute, + .mute_stream = wm8731_mute, .set_sysclk = wm8731_set_dai_sysclk, .set_fmt = wm8731_set_dai_fmt, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8731_dai = { diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 328df81ee8394033ded73dc62115b70d370013a3..0e3994326936d89182945833511490f617b6f72b 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -364,7 +364,7 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int wm8741_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8741_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; @@ -386,7 +386,8 @@ static const struct snd_soc_dai_ops wm8741_dai_ops = { .hw_params = wm8741_hw_params, .set_sysclk = wm8741_set_dai_sysclk, .set_fmt = wm8741_set_dai_fmt, - .digital_mute = wm8741_mute, + .mute_stream = wm8741_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8741_dai = { diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 5f3466170f78828c7ccc96aa12d9faccbd114271..9491817020d85cb9e247ec9dfd661099cac5ff6a 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -578,8 +578,8 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8750_priv *wm8750 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8750_IFACE) & 0x1f3; - u16 srate = snd_soc_component_read32(component, WM8750_SRATE) & 0x1c0; + u16 iface = snd_soc_component_read(component, WM8750_IFACE) & 0x1f3; + u16 srate = snd_soc_component_read(component, WM8750_SRATE) & 0x1c0; int coeff = get_coeff(wm8750->sysclk, params_rate(params)); /* bit size */ @@ -606,10 +606,10 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8750_mute(struct snd_soc_dai *dai, int mute) +static int wm8750_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8750_ADCDAC) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8750_ADCDAC) & 0xfff7; if (mute) snd_soc_component_write(component, WM8750_ADCDAC, mute_reg | 0x8); @@ -621,7 +621,7 @@ static int wm8750_mute(struct snd_soc_dai *dai, int mute) static int wm8750_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { - u16 pwr_reg = snd_soc_component_read32(component, WM8750_PWR1) & 0xfe3e; + u16 pwr_reg = snd_soc_component_read(component, WM8750_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: @@ -660,9 +660,10 @@ static int wm8750_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8750_dai_ops = { .hw_params = wm8750_pcm_hw_params, - .digital_mute = wm8750_mute, + .mute_stream = wm8750_mute, .set_fmt = wm8750_set_dai_fmt, .set_sysclk = wm8750_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8750_dai = { diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 8753c55c73fad6975aabdce6a8d17babce48313f..deaa54be6268ab886a8d9a34f71002ac23199fae 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -244,7 +244,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, if (snd_soc_component_active(component)) return -EBUSY; - ioctl = snd_soc_component_read32(component, WM8753_IOCTL); + ioctl = snd_soc_component_read(component, WM8753_IOCTL); wm8753->dai_func = ucontrol->value.enumerated.item[0]; @@ -748,11 +748,11 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (pll_id == WM8753_PLL1) { offset = 0; enable = 0x10; - reg = snd_soc_component_read32(component, WM8753_CLOCK) & 0xffef; + reg = snd_soc_component_read(component, WM8753_CLOCK) & 0xffef; } else { offset = 4; enable = 0x8; - reg = snd_soc_component_read32(component, WM8753_CLOCK) & 0xfff7; + reg = snd_soc_component_read(component, WM8753_CLOCK) & 0xfff7; } if (!freq_in || !freq_out) { @@ -888,7 +888,7 @@ static int wm8753_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_component *component, unsigned int fmt) { - u16 voice = snd_soc_component_read32(component, WM8753_PCM) & 0x01ec; + u16 voice = snd_soc_component_read(component, WM8753_PCM) & 0x01ec; /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -923,8 +923,8 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8753_priv *wm8753 = snd_soc_component_get_drvdata(component); - u16 voice = snd_soc_component_read32(component, WM8753_PCM) & 0x01f3; - u16 srate = snd_soc_component_read32(component, WM8753_SRATE1) & 0x017f; + u16 voice = snd_soc_component_read(component, WM8753_PCM) & 0x01f3; + u16 srate = snd_soc_component_read(component, WM8753_SRATE1) & 0x017f; /* bit size */ switch (params_width(params)) { @@ -958,15 +958,16 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_component *component, { u16 voice, ioctl; - voice = snd_soc_component_read32(component, WM8753_PCM) & 0x011f; - ioctl = snd_soc_component_read32(component, WM8753_IOCTL) & 0x015d; + voice = snd_soc_component_read(component, WM8753_PCM) & 0x011f; + ioctl = snd_soc_component_read(component, WM8753_IOCTL) & 0x015d; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: break; case SND_SOC_DAIFMT_CBM_CFM: - ioctl |= 0x2; /* fall through */ + ioctl |= 0x2; + fallthrough; case SND_SOC_DAIFMT_CBM_CFS: voice |= 0x0040; break; @@ -1026,15 +1027,15 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8753_PCMDIV: - reg = snd_soc_component_read32(component, WM8753_CLOCK) & 0x003f; + reg = snd_soc_component_read(component, WM8753_CLOCK) & 0x003f; snd_soc_component_write(component, WM8753_CLOCK, reg | div); break; case WM8753_BCLKDIV: - reg = snd_soc_component_read32(component, WM8753_SRATE2) & 0x01c7; + reg = snd_soc_component_read(component, WM8753_SRATE2) & 0x01c7; snd_soc_component_write(component, WM8753_SRATE2, reg | div); break; case WM8753_VXCLKDIV: - reg = snd_soc_component_read32(component, WM8753_SRATE2) & 0x003f; + reg = snd_soc_component_read(component, WM8753_SRATE2) & 0x003f; snd_soc_component_write(component, WM8753_SRATE2, reg | div); break; default: @@ -1049,7 +1050,7 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai, static int wm8753_hdac_set_dai_fmt(struct snd_soc_component *component, unsigned int fmt) { - u16 hifi = snd_soc_component_read32(component, WM8753_HIFI) & 0x01e0; + u16 hifi = snd_soc_component_read(component, WM8753_HIFI) & 0x01e0; /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -1083,15 +1084,16 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_component *component, { u16 ioctl, hifi; - hifi = snd_soc_component_read32(component, WM8753_HIFI) & 0x013f; - ioctl = snd_soc_component_read32(component, WM8753_IOCTL) & 0x00ae; + hifi = snd_soc_component_read(component, WM8753_HIFI) & 0x013f; + ioctl = snd_soc_component_read(component, WM8753_IOCTL) & 0x00ae; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: break; case SND_SOC_DAIFMT_CBM_CFM: - ioctl |= 0x1; /* fall through */ + ioctl |= 0x1; + fallthrough; case SND_SOC_DAIFMT_CBM_CFS: hifi |= 0x0040; break; @@ -1152,8 +1154,8 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8753_priv *wm8753 = snd_soc_component_get_drvdata(component); - u16 srate = snd_soc_component_read32(component, WM8753_SRATE1) & 0x01c0; - u16 hifi = snd_soc_component_read32(component, WM8753_HIFI) & 0x01f3; + u16 srate = snd_soc_component_read(component, WM8753_SRATE1) & 0x01c0; + u16 hifi = snd_soc_component_read(component, WM8753_HIFI) & 0x01f3; int coeff; /* is digital filter coefficient valid ? */ @@ -1190,7 +1192,7 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_component *component, u16 clock; /* set clk source as pcmclk */ - clock = snd_soc_component_read32(component, WM8753_CLOCK) & 0xfffb; + clock = snd_soc_component_read(component, WM8753_CLOCK) & 0xfffb; snd_soc_component_write(component, WM8753_CLOCK, clock); return wm8753_vdac_adc_set_dai_fmt(component, fmt); @@ -1208,7 +1210,7 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_component *component, u16 clock; /* set clk source as pcmclk */ - clock = snd_soc_component_read32(component, WM8753_CLOCK) & 0xfffb; + clock = snd_soc_component_read(component, WM8753_CLOCK) & 0xfffb; snd_soc_component_write(component, WM8753_CLOCK, clock); return wm8753_vdac_adc_set_dai_fmt(component, fmt); @@ -1220,7 +1222,7 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_component *component, u16 clock; /* set clk source as mclk */ - clock = snd_soc_component_read32(component, WM8753_CLOCK) & 0xfffb; + clock = snd_soc_component_read(component, WM8753_CLOCK) & 0xfffb; snd_soc_component_write(component, WM8753_CLOCK, clock | 0x4); if (wm8753_hdac_set_dai_fmt(component, fmt) < 0) @@ -1295,10 +1297,10 @@ static int wm8753_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, return wm8753_voice_write_dai_fmt(component, fmt); }; -static int wm8753_mute(struct snd_soc_dai *dai, int mute) +static int wm8753_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8753_DAC) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8753_DAC) & 0xfff7; struct wm8753_priv *wm8753 = snd_soc_component_get_drvdata(component); /* the digital mute covers the HiFi and Voice DAC's on the WM8753. @@ -1329,7 +1331,7 @@ static int wm8753_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8753_priv *wm8753 = snd_soc_component_get_drvdata(component); - u16 pwr_reg = snd_soc_component_read32(component, WM8753_PWR1) & 0xfe3e; + u16 pwr_reg = snd_soc_component_read(component, WM8753_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: @@ -1380,20 +1382,22 @@ static int wm8753_set_bias_level(struct snd_soc_component *component, */ static const struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = { .hw_params = wm8753_i2s_hw_params, - .digital_mute = wm8753_mute, + .mute_stream = wm8753_mute, .set_fmt = wm8753_hifi_set_dai_fmt, .set_clkdiv = wm8753_set_dai_clkdiv, .set_pll = wm8753_set_dai_pll, .set_sysclk = wm8753_set_dai_sysclk, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = { .hw_params = wm8753_pcm_hw_params, - .digital_mute = wm8753_mute, + .mute_stream = wm8753_mute, .set_fmt = wm8753_voice_set_dai_fmt, .set_clkdiv = wm8753_set_dai_clkdiv, .set_pll = wm8753_set_dai_pll, .set_sysclk = wm8753_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8753_dai[] = { diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index bc8243443b9d03fd2359d4feb20d0e8a94441615..1176a6ad269d4eadc8268f6e9b701f4f40592c0b 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -447,7 +447,7 @@ static int wm8770_hw_params(struct snd_pcm_substream *substream, } /* Only need to set MCLK/LRCLK ratio if we're master */ - if (snd_soc_component_read32(component, WM8770_MSTRCTRL) & 0x100) { + if (snd_soc_component_read(component, WM8770_MSTRCTRL) & 0x100) { for (; i < ARRAY_SIZE(mclk_ratios); ++i) { ratio = wm8770->sysclk / params_rate(params); if (ratio == mclk_ratios[i]) @@ -472,7 +472,7 @@ static int wm8770_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8770_mute(struct snd_soc_dai *dai, int mute) +static int wm8770_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component; @@ -538,10 +538,11 @@ static int wm8770_set_bias_level(struct snd_soc_component *component, SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) static const struct snd_soc_dai_ops wm8770_dai_ops = { - .digital_mute = wm8770_mute, + .mute_stream = wm8770_mute, .hw_params = wm8770_hw_params, .set_fmt = wm8770_set_fmt, .set_sysclk = wm8770_set_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8770_dai = { diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 9143eb1ce2f7c657c17f086b6e9f6f28eab5a82a..554acf56130caee2400504e4811dfb147e1af902 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -282,7 +282,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, } /* Only need to set MCLK/LRCLK ratio if we're master */ - if (snd_soc_component_read32(component, WM8776_MSTRCTRL) & master) { + if (snd_soc_component_read(component, WM8776_MSTRCTRL) & master) { for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { if (wm8776->sysclk[dai->driver->id] / params_rate(params) == mclk_ratios[i]) @@ -309,7 +309,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8776_mute(struct snd_soc_dai *dai, int mute) +static int wm8776_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -361,10 +361,11 @@ static int wm8776_set_bias_level(struct snd_soc_component *component, SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) static const struct snd_soc_dai_ops wm8776_dac_ops = { - .digital_mute = wm8776_mute, + .mute_stream = wm8776_mute, .hw_params = wm8776_hw_params, .set_fmt = wm8776_set_fmt, .set_sysclk = wm8776_set_sysclk, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8776_adc_ops = { diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 09302550c12b19073c664423b8ad88fcbbb6e20a..4ddb5e32df5df23f29e3ed5569ddc6771e9098c3 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -172,7 +172,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol, if (snd_soc_component_test_bits(component, e->reg, mask, val)) { /* save the current power state of the transmitter */ - txpwr = snd_soc_component_read32(component, WM8804_PWRDN) & 0x4; + txpwr = snd_soc_component_read(component, WM8804_PWRDN) & 0x4; /* power down the transmitter */ snd_soc_component_update_bits(component, WM8804_PWRDN, 0x4, 0x4); diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 3e239fa9bc8d4377f5f51237a270ce4fe8bd01a2..a9a6d766a176319cbfd45f00f7d08b135a1fa7e3 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -222,7 +222,7 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - u16 hpctl1 = snd_soc_component_read32(component, WM8900_REG_HPCTL1); + u16 hpctl1 = snd_soc_component_read(component, WM8900_REG_HPCTL1); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -629,7 +629,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; u16 reg; - reg = snd_soc_component_read32(component, WM8900_REG_AUDIO1) & ~0x60; + reg = snd_soc_component_read(component, WM8900_REG_AUDIO1) & ~0x60; switch (params_width(params)) { case 16: @@ -650,7 +650,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, snd_soc_component_write(component, WM8900_REG_AUDIO1, reg); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - reg = snd_soc_component_read32(component, WM8900_REG_DACCTRL); + reg = snd_soc_component_read(component, WM8900_REG_DACCTRL); if (params_rate(params) <= 24000) reg |= WM8900_REG_DACCTRL_DAC_SB_FILT; @@ -860,10 +860,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_component *component = codec_dai->component; unsigned int clocking1, aif1, aif3, aif4; - clocking1 = snd_soc_component_read32(component, WM8900_REG_CLOCKING1); - aif1 = snd_soc_component_read32(component, WM8900_REG_AUDIO1); - aif3 = snd_soc_component_read32(component, WM8900_REG_AUDIO3); - aif4 = snd_soc_component_read32(component, WM8900_REG_AUDIO4); + clocking1 = snd_soc_component_read(component, WM8900_REG_CLOCKING1); + aif1 = snd_soc_component_read(component, WM8900_REG_AUDIO1); + aif3 = snd_soc_component_read(component, WM8900_REG_AUDIO3); + aif4 = snd_soc_component_read(component, WM8900_REG_AUDIO4); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -967,12 +967,12 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8900_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; u16 reg; - reg = snd_soc_component_read32(component, WM8900_REG_DACCTRL); + reg = snd_soc_component_read(component, WM8900_REG_DACCTRL); if (mute) reg |= WM8900_REG_DACCTRL_MUTE; @@ -997,7 +997,8 @@ static const struct snd_soc_dai_ops wm8900_dai_ops = { .set_clkdiv = wm8900_set_dai_clkdiv, .set_pll = wm8900_set_dai_pll, .set_fmt = wm8900_set_dai_fmt, - .digital_mute = wm8900_digital_mute, + .mute_stream = wm8900_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8900_dai = { @@ -1068,7 +1069,7 @@ static int wm8900_set_bias_level(struct snd_soc_component *component, WM8900_REG_POWER1_BIAS_ENA | 0x1); } - reg = snd_soc_component_read32(component, WM8900_REG_POWER1); + reg = snd_soc_component_read(component, WM8900_REG_POWER1); snd_soc_component_write(component, WM8900_REG_POWER1, (reg & WM8900_REG_POWER1_FLL_ENA) | WM8900_REG_POWER1_BIAS_ENA | 0x1); @@ -1079,7 +1080,7 @@ static int wm8900_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_OFF: /* Startup bias enable */ - reg = snd_soc_component_read32(component, WM8900_REG_POWER1); + reg = snd_soc_component_read(component, WM8900_REG_POWER1); snd_soc_component_write(component, WM8900_REG_POWER1, reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA); snd_soc_component_write(component, WM8900_REG_ADDCTL, @@ -1170,7 +1171,7 @@ static int wm8900_probe(struct snd_soc_component *component) { int reg; - reg = snd_soc_component_read32(component, WM8900_REG_ID); + reg = snd_soc_component_read(component, WM8900_REG_ID); if (reg != 0x8900) { dev_err(component->dev, "Device is not a WM8900 - ID %x\n", reg); return -ENODEV; diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index fa2f67850f1878f679aa23053e4d3f51e12de013..09f4980630c7e9cefadfa2e125324576ce3bc2c6 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -342,7 +342,7 @@ static void wm8903_seq_notifier(struct snd_soc_component *component, if (!(wm8903->dcs_pending & (1 << i))) continue; - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, WM8903_DC_SERVO_READBACK_1 + i); dev_dbg(component->dev, "DC servo %d: %x\n", 3 - i, val); @@ -375,7 +375,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, u16 reg; int ret; - reg = snd_soc_component_read32(component, WM8903_CLASS_W_0); + reg = snd_soc_component_read(component, WM8903_CLASS_W_0); /* Turn it off if we're about to enable bypass */ if (ucontrol->value.integer.value[0]) { @@ -1224,7 +1224,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 aif1 = snd_soc_component_read32(component, WM8903_AUDIO_INTERFACE_1); + u16 aif1 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_1); aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK | WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV); @@ -1307,12 +1307,12 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8903_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; u16 reg; - reg = snd_soc_component_read32(component, WM8903_DAC_DIGITAL_1); + reg = snd_soc_component_read(component, WM8903_DAC_DIGITAL_1); if (mute) reg |= WM8903_DAC_MUTE; @@ -1451,12 +1451,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, int cur_val; int clk_sys; - u16 aif1 = snd_soc_component_read32(component, WM8903_AUDIO_INTERFACE_1); - u16 aif2 = snd_soc_component_read32(component, WM8903_AUDIO_INTERFACE_2); - u16 aif3 = snd_soc_component_read32(component, WM8903_AUDIO_INTERFACE_3); - u16 clock0 = snd_soc_component_read32(component, WM8903_CLOCK_RATES_0); - u16 clock1 = snd_soc_component_read32(component, WM8903_CLOCK_RATES_1); - u16 dac_digital1 = snd_soc_component_read32(component, WM8903_DAC_DIGITAL_1); + u16 aif1 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_1); + u16 aif2 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_2); + u16 aif3 = snd_soc_component_read(component, WM8903_AUDIO_INTERFACE_3); + u16 clock0 = snd_soc_component_read(component, WM8903_CLOCK_RATES_0); + u16 clock1 = snd_soc_component_read(component, WM8903_CLOCK_RATES_1); + u16 dac_digital1 = snd_soc_component_read(component, WM8903_DAC_DIGITAL_1); /* Enable sloping stopband filter for low sample rates */ if (fs <= 24000) @@ -1737,9 +1737,10 @@ static irqreturn_t wm8903_irq(int irq, void *data) static const struct snd_soc_dai_ops wm8903_dai_ops = { .hw_params = wm8903_hw_params, - .digital_mute = wm8903_digital_mute, + .mute_stream = wm8903_mute, .set_fmt = wm8903_set_dai_fmt, .set_sysclk = wm8903_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8903_dai = { @@ -1927,7 +1928,7 @@ static int wm8903_set_pdata_irq_trigger(struct i2c_client *i2c, * We assume the controller imposes no restrictions, * so we are able to select active-high */ - /* Fall-through */ + fallthrough; case IRQ_TYPE_LEVEL_HIGH: pdata->irq_active_low = false; break; diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 5ffbaddd6e499579ef98d3c35b146ab645fc2c4b..1c360bae5652c56fa8f954c1a30dca603ec36a5c 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -317,7 +317,7 @@ static int wm8904_configure_clocking(struct snd_soc_component *component) unsigned int clock0, clock2, rate; /* Gate the clock while we're updating to avoid misclocking */ - clock2 = snd_soc_component_read32(component, WM8904_CLOCK_RATES_2); + clock2 = snd_soc_component_read(component, WM8904_CLOCK_RATES_2); snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_2, WM8904_SYSCLK_SRC, 0); @@ -374,7 +374,7 @@ static void wm8904_set_drc(struct snd_soc_component *component) int save, i; /* Save any enables; the configuration should clear them. */ - save = snd_soc_component_read32(component, WM8904_DRC_0); + save = snd_soc_component_read(component, WM8904_DRC_0); for (i = 0; i < WM8904_DRC_REGS; i++) snd_soc_component_update_bits(component, WM8904_DRC_0 + i, 0xffff, @@ -447,7 +447,7 @@ static void wm8904_set_retune_mobile(struct snd_soc_component *component) /* The EQ will be disabled while reconfiguring it, remember the * current configuration. */ - save = snd_soc_component_read32(component, WM8904_EQ1); + save = snd_soc_component_read(component, WM8904_EQ1); for (i = 0; i < WM8904_EQ_REGS; i++) snd_soc_component_update_bits(component, WM8904_EQ1 + i, 0xffff, @@ -776,7 +776,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, /* Wait for DC servo to complete */ dcs_mask <<= WM8904_DCS_CAL_COMPLETE_SHIFT; do { - val = snd_soc_component_read32(component, WM8904_DC_SERVO_READBACK_0); + val = snd_soc_component_read(component, WM8904_DC_SERVO_READBACK_0); if ((val & dcs_mask) == dcs_mask) break; @@ -814,8 +814,8 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMD: /* Cache the DC servo configuration; this will be * invalidated if we change the configuration. */ - wm8904->dcs_state[dcs_l] = snd_soc_component_read32(component, dcs_l_reg); - wm8904->dcs_state[dcs_r] = snd_soc_component_read32(component, dcs_r_reg); + wm8904->dcs_state[dcs_l] = snd_soc_component_read(component, dcs_l_reg); + wm8904->dcs_state[dcs_r] = snd_soc_component_read(component, dcs_r_reg); snd_soc_component_update_bits(component, WM8904_DC_SERVO_0, dcs_mask, 0); @@ -1436,7 +1436,7 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif1 |= 0x3 | WM8904_AIF_LRCLK_INV; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif1 |= 0x3; break; @@ -1671,7 +1671,7 @@ static int wm8904_set_fll(struct snd_soc_dai *dai, int fll_id, int source, Fout == wm8904->fll_fout) return 0; - clock2 = snd_soc_component_read32(component, WM8904_CLOCK_RATES_2); + clock2 = snd_soc_component_read(component, WM8904_CLOCK_RATES_2); if (Fout == 0) { dev_dbg(component->dev, "FLL disabled\n"); @@ -1716,7 +1716,7 @@ static int wm8904_set_fll(struct snd_soc_dai *dai, int fll_id, int source, /* Save current state then disable the FLL and SYSCLK to avoid * misclocking */ - fll1 = snd_soc_component_read32(component, WM8904_FLL_CONTROL_1); + fll1 = snd_soc_component_read(component, WM8904_FLL_CONTROL_1); snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_2, WM8904_CLK_SYS_ENA, 0); snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_1, @@ -1824,7 +1824,7 @@ static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id, break; } clk_id = WM8904_CLK_MCLK; - /* fallthrough */ + fallthrough; case WM8904_CLK_MCLK: priv->sysclk_src = clk_id; @@ -1846,7 +1846,7 @@ static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id, return 0; } -static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8904_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; int val; @@ -1962,7 +1962,8 @@ static const struct snd_soc_dai_ops wm8904_dai_ops = { .set_tdm_slot = wm8904_set_tdm_slot, .set_pll = wm8904_set_fll, .hw_params = wm8904_hw_params, - .digital_mute = wm8904_digital_mute, + .mute_stream = wm8904_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8904_dai = { diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index c194fbde8ad6e027c83dcc334ec3b9311599acd3..016cd8aeef37c6892715f5680f96519d7eab243a 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -337,8 +337,8 @@ static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 iface = snd_soc_component_read32(component, WM8940_IFACE) & 0xFE67; - u16 clk = snd_soc_component_read32(component, WM8940_CLOCK) & 0x1fe; + u16 iface = snd_soc_component_read(component, WM8940_IFACE) & 0xFE67; + u16 clk = snd_soc_component_read(component, WM8940_CLOCK) & 0x1fe; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: @@ -392,9 +392,9 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 iface = snd_soc_component_read32(component, WM8940_IFACE) & 0xFD9F; - u16 addcntrl = snd_soc_component_read32(component, WM8940_ADDCNTRL) & 0xFFF1; - u16 companding = snd_soc_component_read32(component, + u16 iface = snd_soc_component_read(component, WM8940_IFACE) & 0xFD9F; + u16 addcntrl = snd_soc_component_read(component, WM8940_ADDCNTRL) & 0xFFF1; + u16 companding = snd_soc_component_read(component, WM8940_COMPANDINGCTL) & 0xFFDF; int ret; @@ -452,10 +452,10 @@ error_ret: return ret; } -static int wm8940_mute(struct snd_soc_dai *dai, int mute) +static int wm8940_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8940_DAC) & 0xffbf; + u16 mute_reg = snd_soc_component_read(component, WM8940_DAC) & 0xffbf; if (mute) mute_reg |= 0x40; @@ -468,7 +468,7 @@ static int wm8940_set_bias_level(struct snd_soc_component *component, { struct wm8940_priv *wm8940 = snd_soc_component_get_drvdata(component); u16 val; - u16 pwr_reg = snd_soc_component_read32(component, WM8940_POWER1) & 0x1F0; + u16 pwr_reg = snd_soc_component_read(component, WM8940_POWER1) & 0x1F0; int ret = 0; switch (level) { @@ -476,7 +476,7 @@ static int wm8940_set_bias_level(struct snd_soc_component *component, /* ensure bufioen and biasen */ pwr_reg |= (1 << 2) | (1 << 3); /* Enable thermal shutdown */ - val = snd_soc_component_read32(component, WM8940_OUTPUTCTL); + val = snd_soc_component_read(component, WM8940_OUTPUTCTL); ret = snd_soc_component_write(component, WM8940_OUTPUTCTL, val | 0x2); if (ret) break; @@ -577,12 +577,12 @@ static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, u16 reg; /* Turn off PLL */ - reg = snd_soc_component_read32(component, WM8940_POWER1); + reg = snd_soc_component_read(component, WM8940_POWER1); snd_soc_component_write(component, WM8940_POWER1, reg & 0x1df); if (freq_in == 0 || freq_out == 0) { /* Clock CODEC directly from MCLK */ - reg = snd_soc_component_read32(component, WM8940_CLOCK); + reg = snd_soc_component_read(component, WM8940_CLOCK); snd_soc_component_write(component, WM8940_CLOCK, reg & 0x0ff); /* Pll power down */ snd_soc_component_write(component, WM8940_PLLN, (1 << 7)); @@ -601,11 +601,11 @@ static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_component_write(component, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff); snd_soc_component_write(component, WM8940_PLLK3, pll_div.k & 0x1ff); /* Enable the PLL */ - reg = snd_soc_component_read32(component, WM8940_POWER1); + reg = snd_soc_component_read(component, WM8940_POWER1); snd_soc_component_write(component, WM8940_POWER1, reg | 0x020); /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_component_read32(component, WM8940_CLOCK); + reg = snd_soc_component_read(component, WM8940_CLOCK); snd_soc_component_write(component, WM8940_CLOCK, reg | 0x100); return 0; @@ -638,15 +638,15 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8940_BCLKDIV: - reg = snd_soc_component_read32(component, WM8940_CLOCK) & 0xFFE3; + reg = snd_soc_component_read(component, WM8940_CLOCK) & 0xFFE3; ret = snd_soc_component_write(component, WM8940_CLOCK, reg | (div << 2)); break; case WM8940_MCLKDIV: - reg = snd_soc_component_read32(component, WM8940_CLOCK) & 0xFF1F; + reg = snd_soc_component_read(component, WM8940_CLOCK) & 0xFF1F; ret = snd_soc_component_write(component, WM8940_CLOCK, reg | (div << 5)); break; case WM8940_OPCLKDIV: - reg = snd_soc_component_read32(component, WM8940_GPIO) & 0xFFCF; + reg = snd_soc_component_read(component, WM8940_GPIO) & 0xFFCF; ret = snd_soc_component_write(component, WM8940_GPIO, reg | (div << 4)); break; } @@ -664,10 +664,11 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai, static const struct snd_soc_dai_ops wm8940_dai_ops = { .hw_params = wm8940_i2s_hw_params, .set_sysclk = wm8940_set_dai_sysclk, - .digital_mute = wm8940_mute, + .mute_stream = wm8940_mute, .set_fmt = wm8940_set_dai_fmt, .set_clkdiv = wm8940_set_dai_clkdiv, .set_pll = wm8940_set_dai_pll, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8940_dai = { @@ -711,7 +712,7 @@ static int wm8940_probe(struct snd_soc_component *component) if (!pdata) dev_warn(component->dev, "No platform data supplied\n"); else { - reg = snd_soc_component_read32(component, WM8940_OUTPUTCTL); + reg = snd_soc_component_read(component, WM8940_OUTPUTCTL); ret = snd_soc_component_write(component, WM8940_OUTPUTCTL, reg | pdata->vroi); if (ret < 0) return ret; diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 9c7e2892c8cbe32cd1a00eb8f305844885082205..513df47bd87d60e9581e9c72882c2f4fdc14a913 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -619,7 +619,7 @@ static int wm8955_hw_params(struct snd_pcm_substream *substream, /* If the chip is clocked then disable the clocks and force a * reconfiguration, otherwise DAPM will power up the * clocks for us later. */ - ret = snd_soc_component_read32(component, WM8955_POWER_MANAGEMENT_1); + ret = snd_soc_component_read(component, WM8955_POWER_MANAGEMENT_1); if (ret < 0) return ret; if (ret & WM8955_DIGENB) { @@ -683,7 +683,7 @@ static int wm8955_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif |= WM8955_LRP; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif |= 0x3; break; @@ -745,7 +745,7 @@ static int wm8955_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } -static int wm8955_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8955_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; int val; @@ -848,7 +848,8 @@ static const struct snd_soc_dai_ops wm8955_dai_ops = { .set_sysclk = wm8955_set_sysclk, .set_fmt = wm8955_set_fmt, .hw_params = wm8955_hw_params, - .digital_mute = wm8955_digital_mute, + .mute_stream = wm8955_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8955_dai = { diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index ca42445b649d4aea77a2ec51aee2eee081cc435a..68a3b48e6b31f16c15bc1bf11739127583c8149d 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -192,7 +192,7 @@ static void wm8958_dsp_start_mbc(struct snd_soc_component *component, int path) int i; /* If the DSP is already running then noop */ - if (snd_soc_component_read32(component, WM8958_DSP2_PROGRAM) & WM8958_DSP2_ENA) + if (snd_soc_component_read(component, WM8958_DSP2_PROGRAM) & WM8958_DSP2_ENA) return; /* If we have MBC firmware download it */ @@ -324,7 +324,7 @@ static void wm8958_dsp_start_enh_eq(struct snd_soc_component *component, int pat static void wm8958_dsp_apply(struct snd_soc_component *component, int path, int start) { struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component); - int pwr_reg = snd_soc_component_read32(component, WM8994_POWER_MANAGEMENT_5); + int pwr_reg = snd_soc_component_read(component, WM8994_POWER_MANAGEMENT_5); int ena, reg, aif; switch (path) { @@ -352,7 +352,7 @@ static void wm8958_dsp_apply(struct snd_soc_component *component, int path, int if (!pwr_reg) ena = 0; - reg = snd_soc_component_read32(component, WM8958_DSP2_PROGRAM); + reg = snd_soc_component_read(component, WM8958_DSP2_PROGRAM); dev_dbg(component->dev, "DSP path %d %d startup: %d, power: %x, DSP: %x\n", path, wm8994->dsp_active, start, pwr_reg, reg); @@ -363,9 +363,9 @@ static void wm8958_dsp_apply(struct snd_soc_component *component, int path, int return; /* If either AIFnCLK is not yet enabled postpone */ - if (!(snd_soc_component_read32(component, WM8994_AIF1_CLOCKING_1) + if (!(snd_soc_component_read(component, WM8994_AIF1_CLOCKING_1) & WM8994_AIF1CLK_ENA_MASK) && - !(snd_soc_component_read32(component, WM8994_AIF2_CLOCKING_1) + !(snd_soc_component_read(component, WM8994_AIF2_CLOCKING_1) & WM8994_AIF2CLK_ENA_MASK)) return; @@ -456,7 +456,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol, int reg; /* Don't allow on the fly reconfiguration */ - reg = snd_soc_component_read32(component, WM8994_CLOCKING_1); + reg = snd_soc_component_read(component, WM8994_CLOCKING_1); if (reg < 0 || reg & WM8958_DSP2CLK_ENA) return -EBUSY; @@ -546,7 +546,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol, int reg; /* Don't allow on the fly reconfiguration */ - reg = snd_soc_component_read32(component, WM8994_CLOCKING_1); + reg = snd_soc_component_read(component, WM8994_CLOCKING_1); if (reg < 0 || reg & WM8958_DSP2CLK_ENA) return -EBUSY; @@ -579,7 +579,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol, int reg; /* Don't allow on the fly reconfiguration */ - reg = snd_soc_component_read32(component, WM8994_CLOCKING_1); + reg = snd_soc_component_read(component, WM8994_CLOCKING_1); if (reg < 0 || reg & WM8958_DSP2CLK_ENA) return -EBUSY; @@ -746,7 +746,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol, int reg; /* Don't allow on the fly reconfiguration */ - reg = snd_soc_component_read32(component, WM8994_CLOCKING_1); + reg = snd_soc_component_read(component, WM8994_CLOCKING_1); if (reg < 0 || reg & WM8958_DSP2CLK_ENA) return -EBUSY; diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 6cf0f6612bdaf44685a20f7b99847e4f45675b44..660ec46eecf2588d7a277c8ff4a2b63a67242145 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -612,7 +612,7 @@ static const int bclk_divs[] = { * triplet, we relax the bclk such that bclk is chosen as the * closest available frequency greater than expected bclk. * - * @wm8960_priv: wm8960 codec private data + * @wm8960: codec private data * @mclk: MCLK used to derive sysclk * @sysclk_idx: sysclk_divs index for found sysclk * @dac_idx: dac_divs index for found lrclk @@ -742,7 +742,7 @@ static int wm8960_configure_clocking(struct snd_soc_component *component) { struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component); int freq_out, freq_in; - u16 iface1 = snd_soc_component_read32(component, WM8960_IFACE1); + u16 iface1 = snd_soc_component_read(component, WM8960_IFACE1); int i, j, k; int ret; @@ -812,7 +812,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8960_IFACE1) & 0xfff3; + u16 iface = snd_soc_component_read(component, WM8960_IFACE1) & 0xfff3; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; int i; @@ -836,7 +836,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, iface |= 0x000c; break; } - /* fall through */ + fallthrough; default: dev_err(component->dev, "unsupported width %d\n", params_width(params)); @@ -878,7 +878,7 @@ static int wm8960_hw_free(struct snd_pcm_substream *substream, return 0; } -static int wm8960_mute(struct snd_soc_dai *dai, int mute) +static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -893,7 +893,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component); - u16 pm2 = snd_soc_component_read32(component, WM8960_POWER2); + u16 pm2 = snd_soc_component_read(component, WM8960_POWER2); int ret; switch (level) { @@ -983,7 +983,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component); - u16 pm2 = snd_soc_component_read32(component, WM8960_POWER2); + u16 pm2 = snd_soc_component_read(component, WM8960_POWER2); int reg, ret; switch (level) { @@ -1202,7 +1202,7 @@ static int wm8960_set_pll(struct snd_soc_component *component, if (!freq_in || !freq_out) return 0; - reg = snd_soc_component_read32(component, WM8960_PLL1) & ~0x3f; + reg = snd_soc_component_read(component, WM8960_PLL1) & ~0x3f; reg |= pll_div.pre_div << 4; reg |= pll_div.n; @@ -1245,23 +1245,23 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8960_SYSCLKDIV: - reg = snd_soc_component_read32(component, WM8960_CLOCK1) & 0x1f9; + reg = snd_soc_component_read(component, WM8960_CLOCK1) & 0x1f9; snd_soc_component_write(component, WM8960_CLOCK1, reg | div); break; case WM8960_DACDIV: - reg = snd_soc_component_read32(component, WM8960_CLOCK1) & 0x1c7; + reg = snd_soc_component_read(component, WM8960_CLOCK1) & 0x1c7; snd_soc_component_write(component, WM8960_CLOCK1, reg | div); break; case WM8960_OPCLKDIV: - reg = snd_soc_component_read32(component, WM8960_PLL1) & 0x03f; + reg = snd_soc_component_read(component, WM8960_PLL1) & 0x03f; snd_soc_component_write(component, WM8960_PLL1, reg | div); break; case WM8960_DCLKDIV: - reg = snd_soc_component_read32(component, WM8960_CLOCK2) & 0x03f; + reg = snd_soc_component_read(component, WM8960_CLOCK2) & 0x03f; snd_soc_component_write(component, WM8960_CLOCK2, reg | div); break; case WM8960_TOCLKSEL: - reg = snd_soc_component_read32(component, WM8960_ADDCTL1) & 0x1fd; + reg = snd_soc_component_read(component, WM8960_ADDCTL1) & 0x1fd; snd_soc_component_write(component, WM8960_ADDCTL1, reg | div); break; default: @@ -1315,11 +1315,12 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, static const struct snd_soc_dai_ops wm8960_dai_ops = { .hw_params = wm8960_hw_params, .hw_free = wm8960_hw_free, - .digital_mute = wm8960_mute, + .mute_stream = wm8960_mute, .set_fmt = wm8960_set_dai_fmt, .set_clkdiv = wm8960_set_dai_clkdiv, .set_pll = wm8960_set_dai_pll, .set_sysclk = wm8960_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8960_dai = { @@ -1389,6 +1390,12 @@ static void wm8960_set_pdata_from_of(struct i2c_client *i2c, if (of_property_read_bool(np, "wlf,shared-lrclk")) pdata->shared_lrclk = true; + + of_property_read_u32_array(np, "wlf,gpio-cfg", pdata->gpio_cfg, + ARRAY_SIZE(pdata->gpio_cfg)); + + of_property_read_u32_array(np, "wlf,hp-cfg", pdata->hp_cfg, + ARRAY_SIZE(pdata->hp_cfg)); } static int wm8960_i2c_probe(struct i2c_client *i2c, @@ -1446,6 +1453,20 @@ static int wm8960_i2c_probe(struct i2c_client *i2c, regmap_update_bits(wm8960->regmap, WM8960_LOUT2, 0x100, 0x100); regmap_update_bits(wm8960->regmap, WM8960_ROUT2, 0x100, 0x100); + /* ADCLRC pin configured as GPIO. */ + regmap_update_bits(wm8960->regmap, WM8960_IFACE2, 1 << 6, + wm8960->pdata.gpio_cfg[0] << 6); + regmap_update_bits(wm8960->regmap, WM8960_ADDCTL4, 0xF << 4, + wm8960->pdata.gpio_cfg[1] << 4); + + /* Enable headphone jack detect */ + regmap_update_bits(wm8960->regmap, WM8960_ADDCTL4, 3 << 2, + wm8960->pdata.hp_cfg[0] << 2); + regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2, 3 << 5, + wm8960->pdata.hp_cfg[1] << 5); + regmap_update_bits(wm8960->regmap, WM8960_ADDCTL1, 3, + wm8960->pdata.hp_cfg[2]); + i2c_set_clientdata(i2c, wm8960); ret = devm_snd_soc_register_component(&i2c->dev, diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 72504f3b702dbb1724412962e286977121785469..ef80d9fc1eec21d1d34203ed624132beb5d7df25 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -192,10 +192,10 @@ static int wm8961_hp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - u16 hp_reg = snd_soc_component_read32(component, WM8961_ANALOGUE_HP_0); - u16 cp_reg = snd_soc_component_read32(component, WM8961_CHARGE_PUMP_1); - u16 pwr_reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_2); - u16 dcs_reg = snd_soc_component_read32(component, WM8961_DC_SERVO_1); + u16 hp_reg = snd_soc_component_read(component, WM8961_ANALOGUE_HP_0); + u16 cp_reg = snd_soc_component_read(component, WM8961_CHARGE_PUMP_1); + u16 pwr_reg = snd_soc_component_read(component, WM8961_PWR_MGMT_2); + u16 dcs_reg = snd_soc_component_read(component, WM8961_DC_SERVO_1); int timeout = 500; if (event & SND_SOC_DAPM_POST_PMU) { @@ -229,7 +229,7 @@ static int wm8961_hp_event(struct snd_soc_dapm_widget *w, snd_soc_component_write(component, WM8961_DC_SERVO_1, dcs_reg); do { msleep(1); - dcs_reg = snd_soc_component_read32(component, WM8961_DC_SERVO_1); + dcs_reg = snd_soc_component_read(component, WM8961_DC_SERVO_1); } while (--timeout && dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR | WM8961_DCS_TRIG_STARTUP_HPL)); @@ -284,8 +284,8 @@ static int wm8961_spk_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - u16 pwr_reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_2); - u16 spk_reg = snd_soc_component_read32(component, WM8961_CLASS_D_CONTROL_1); + u16 pwr_reg = snd_soc_component_read(component, WM8961_PWR_MGMT_2); + u16 spk_reg = snd_soc_component_read(component, WM8961_CLASS_D_CONTROL_1); if (event & SND_SOC_DAPM_POST_PMU) { /* Enable the PGA */ @@ -521,7 +521,7 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream, abs(wm8961_srate[best].rate - fs)) best = i; } - reg = snd_soc_component_read32(component, WM8961_ADDITIONAL_CONTROL_3); + reg = snd_soc_component_read(component, WM8961_ADDITIONAL_CONTROL_3); reg &= ~WM8961_SAMPLE_RATE_MASK; reg |= wm8961_srate[best].val; snd_soc_component_write(component, WM8961_ADDITIONAL_CONTROL_3, reg); @@ -554,12 +554,12 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream, wm8961_clk_sys_ratio[i].ratio, wm8961->sysclk, fs, wm8961->sysclk / fs); - reg = snd_soc_component_read32(component, WM8961_CLOCKING_4); + reg = snd_soc_component_read(component, WM8961_CLOCKING_4); reg &= ~WM8961_CLK_SYS_RATE_MASK; reg |= wm8961_clk_sys_ratio[i].val << WM8961_CLK_SYS_RATE_SHIFT; snd_soc_component_write(component, WM8961_CLOCKING_4, reg); - reg = snd_soc_component_read32(component, WM8961_AUDIO_INTERFACE_0); + reg = snd_soc_component_read(component, WM8961_AUDIO_INTERFACE_0); reg &= ~WM8961_WL_MASK; switch (params_width(params)) { case 16: @@ -579,7 +579,7 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream, snd_soc_component_write(component, WM8961_AUDIO_INTERFACE_0, reg); /* Sloping stop-band filter is recommended for <= 24kHz */ - reg = snd_soc_component_read32(component, WM8961_ADC_DAC_CONTROL_2); + reg = snd_soc_component_read(component, WM8961_ADC_DAC_CONTROL_2); if (fs <= 24000) reg |= WM8961_DACSLOPE; else @@ -595,7 +595,7 @@ static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id, { struct snd_soc_component *component = dai->component; struct wm8961_priv *wm8961 = snd_soc_component_get_drvdata(component); - u16 reg = snd_soc_component_read32(component, WM8961_CLOCKING1); + u16 reg = snd_soc_component_read(component, WM8961_CLOCKING1); if (freq > 33000000) { dev_err(component->dev, "MCLK must be <33MHz\n"); @@ -621,7 +621,7 @@ static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id, static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct snd_soc_component *component = dai->component; - u16 aif = snd_soc_component_read32(component, WM8961_AUDIO_INTERFACE_0); + u16 aif = snd_soc_component_read(component, WM8961_AUDIO_INTERFACE_0); aif &= ~(WM8961_BCLKINV | WM8961_LRP | WM8961_MS | WM8961_FORMAT_MASK); @@ -650,7 +650,7 @@ static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_B: aif |= WM8961_LRP; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif |= 3; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { @@ -688,7 +688,7 @@ static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate) { struct snd_soc_component *component = dai->component; - u16 reg = snd_soc_component_read32(component, WM8961_ADDITIONAL_CONTROL_2); + u16 reg = snd_soc_component_read(component, WM8961_ADDITIONAL_CONTROL_2); if (tristate) reg |= WM8961_TRIS; @@ -698,10 +698,10 @@ static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate) return snd_soc_component_write(component, WM8961_ADDITIONAL_CONTROL_2, reg); } -static int wm8961_digital_mute(struct snd_soc_dai *dai, int mute) +static int wm8961_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 reg = snd_soc_component_read32(component, WM8961_ADC_DAC_CONTROL_1); + u16 reg = snd_soc_component_read(component, WM8961_ADC_DAC_CONTROL_1); if (mute) reg |= WM8961_DACMU; @@ -720,14 +720,14 @@ static int wm8961_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) switch (div_id) { case WM8961_BCLK: - reg = snd_soc_component_read32(component, WM8961_CLOCKING2); + reg = snd_soc_component_read(component, WM8961_CLOCKING2); reg &= ~WM8961_BCLKDIV_MASK; reg |= div; snd_soc_component_write(component, WM8961_CLOCKING2, reg); break; case WM8961_LRCLK: - reg = snd_soc_component_read32(component, WM8961_AUDIO_INTERFACE_2); + reg = snd_soc_component_read(component, WM8961_AUDIO_INTERFACE_2); reg &= ~WM8961_LRCLK_RATE_MASK; reg |= div; snd_soc_component_write(component, WM8961_AUDIO_INTERFACE_2, reg); @@ -757,12 +757,12 @@ static int wm8961_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_PREPARE: if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_STANDBY) { /* Enable bias generation */ - reg = snd_soc_component_read32(component, WM8961_ANTI_POP); + reg = snd_soc_component_read(component, WM8961_ANTI_POP); reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN; snd_soc_component_write(component, WM8961_ANTI_POP, reg); /* VMID=2*50k, VREF */ - reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_1); + reg = snd_soc_component_read(component, WM8961_PWR_MGMT_1); reg &= ~WM8961_VMIDSEL_MASK; reg |= (1 << WM8961_VMIDSEL_SHIFT) | WM8961_VREF; snd_soc_component_write(component, WM8961_PWR_MGMT_1, reg); @@ -772,17 +772,17 @@ static int wm8961_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_STANDBY: if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_PREPARE) { /* VREF off */ - reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_1); + reg = snd_soc_component_read(component, WM8961_PWR_MGMT_1); reg &= ~WM8961_VREF; snd_soc_component_write(component, WM8961_PWR_MGMT_1, reg); /* Bias generation off */ - reg = snd_soc_component_read32(component, WM8961_ANTI_POP); + reg = snd_soc_component_read(component, WM8961_ANTI_POP); reg &= ~(WM8961_BUFIOEN | WM8961_BUFDCOPEN); snd_soc_component_write(component, WM8961_ANTI_POP, reg); /* VMID off */ - reg = snd_soc_component_read32(component, WM8961_PWR_MGMT_1); + reg = snd_soc_component_read(component, WM8961_PWR_MGMT_1); reg &= ~WM8961_VMIDSEL_MASK; snd_soc_component_write(component, WM8961_PWR_MGMT_1, reg); } @@ -806,9 +806,10 @@ static const struct snd_soc_dai_ops wm8961_dai_ops = { .hw_params = wm8961_hw_params, .set_sysclk = wm8961_set_sysclk, .set_fmt = wm8961_set_fmt, - .digital_mute = wm8961_digital_mute, + .mute_stream = wm8961_mute, .set_tristate = wm8961_set_tristate, .set_clkdiv = wm8961_set_clkdiv, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8961_dai = { @@ -833,35 +834,35 @@ static int wm8961_probe(struct snd_soc_component *component) u16 reg; /* Enable class W */ - reg = snd_soc_component_read32(component, WM8961_CHARGE_PUMP_B); + reg = snd_soc_component_read(component, WM8961_CHARGE_PUMP_B); reg |= WM8961_CP_DYN_PWR_MASK; snd_soc_component_write(component, WM8961_CHARGE_PUMP_B, reg); /* Latch volume update bits (right channel only, we always * write both out) and default ZC on. */ - reg = snd_soc_component_read32(component, WM8961_ROUT1_VOLUME); + reg = snd_soc_component_read(component, WM8961_ROUT1_VOLUME); snd_soc_component_write(component, WM8961_ROUT1_VOLUME, reg | WM8961_LO1ZC | WM8961_OUT1VU); snd_soc_component_write(component, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC); - reg = snd_soc_component_read32(component, WM8961_ROUT2_VOLUME); + reg = snd_soc_component_read(component, WM8961_ROUT2_VOLUME); snd_soc_component_write(component, WM8961_ROUT2_VOLUME, reg | WM8961_SPKRZC | WM8961_SPKVU); snd_soc_component_write(component, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC); - reg = snd_soc_component_read32(component, WM8961_RIGHT_ADC_VOLUME); + reg = snd_soc_component_read(component, WM8961_RIGHT_ADC_VOLUME); snd_soc_component_write(component, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU); - reg = snd_soc_component_read32(component, WM8961_RIGHT_INPUT_VOLUME); + reg = snd_soc_component_read(component, WM8961_RIGHT_INPUT_VOLUME); snd_soc_component_write(component, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU); /* Use soft mute by default */ - reg = snd_soc_component_read32(component, WM8961_ADC_DAC_CONTROL_2); + reg = snd_soc_component_read(component, WM8961_ADC_DAC_CONTROL_2); reg |= WM8961_DACSMM; snd_soc_component_write(component, WM8961_ADC_DAC_CONTROL_2, reg); /* Use automatic clocking mode by default; for now this is all * we support. */ - reg = snd_soc_component_read32(component, WM8961_CLOCKING_3); + reg = snd_soc_component_read(component, WM8961_CLOCKING_3); reg &= ~WM8961_MANUAL_MODE; snd_soc_component_write(component, WM8961_CLOCKING_3, reg); diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 1cc23a05ffe46dc5c5be1ba2df34ee3128caeaab..317916cb4e27bd184874531373b8077cec4eb9b0 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -151,6 +151,7 @@ static const struct reg_default wm8962_reg[] = { { 40, 0x0000 }, /* R40 - SPKOUTL volume */ { 41, 0x0000 }, /* R41 - SPKOUTR volume */ + { 48, 0x0000 }, /* R48 - Additional control(4) */ { 49, 0x0010 }, /* R49 - Class D Control 1 */ { 51, 0x0003 }, /* R51 - Class D Control 2 */ @@ -841,7 +842,6 @@ static bool wm8962_readable_register(struct device *dev, unsigned int reg) case WM8962_SPKOUTL_VOLUME: case WM8962_SPKOUTR_VOLUME: case WM8962_THERMAL_SHUTDOWN_STATUS: - case WM8962_ADDITIONAL_CONTROL_4: case WM8962_CLASS_D_CONTROL_1: case WM8962_CLASS_D_CONTROL_2: case WM8962_CLOCKING_4: @@ -956,7 +956,6 @@ static bool wm8962_readable_register(struct device *dev, unsigned int reg) case WM8962_EQ39: case WM8962_EQ40: case WM8962_EQ41: - case WM8962_GPIO_BASE: case WM8962_GPIO_2: case WM8962_GPIO_3: case WM8962_GPIO_5: @@ -1480,9 +1479,9 @@ static int wm8962_dsp2_write_config(struct snd_soc_component *component) static int wm8962_dsp2_set_enable(struct snd_soc_component *component, u16 val) { - u16 adcl = snd_soc_component_read32(component, WM8962_LEFT_ADC_VOLUME); - u16 adcr = snd_soc_component_read32(component, WM8962_RIGHT_ADC_VOLUME); - u16 dac = snd_soc_component_read32(component, WM8962_ADC_DAC_CONTROL_1); + u16 adcl = snd_soc_component_read(component, WM8962_LEFT_ADC_VOLUME); + u16 adcr = snd_soc_component_read(component, WM8962_RIGHT_ADC_VOLUME); + u16 dac = snd_soc_component_read(component, WM8962_ADC_DAC_CONTROL_1); /* Mute the ADCs and DACs */ snd_soc_component_write(component, WM8962_LEFT_ADC_VOLUME, 0); @@ -1561,7 +1560,7 @@ static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol, struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component); int old = wm8962->dsp2_ena; int ret = 0; - int dsp2_running = snd_soc_component_read32(component, WM8962_DSP2_POWER_MANAGEMENT) & + int dsp2_running = snd_soc_component_read(component, WM8962_DSP2_POWER_MANAGEMENT) & WM8962_DSP2_ENA; mutex_lock(&wm8962->dsp2_ena_lock); @@ -1604,17 +1603,17 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, return 0; /* If the left PGA is enabled hit that VU bit... */ - ret = snd_soc_component_read32(component, WM8962_PWR_MGMT_2); + ret = snd_soc_component_read(component, WM8962_PWR_MGMT_2); if (ret & WM8962_HPOUTL_PGA_ENA) { snd_soc_component_write(component, WM8962_HPOUTL_VOLUME, - snd_soc_component_read32(component, WM8962_HPOUTL_VOLUME)); + snd_soc_component_read(component, WM8962_HPOUTL_VOLUME)); return 1; } /* ...otherwise the right. The VU is stereo. */ if (ret & WM8962_HPOUTR_PGA_ENA) snd_soc_component_write(component, WM8962_HPOUTR_VOLUME, - snd_soc_component_read32(component, WM8962_HPOUTR_VOLUME)); + snd_soc_component_read(component, WM8962_HPOUTR_VOLUME)); return 1; } @@ -1634,17 +1633,17 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, return 0; /* If the left PGA is enabled hit that VU bit... */ - ret = snd_soc_component_read32(component, WM8962_PWR_MGMT_2); + ret = snd_soc_component_read(component, WM8962_PWR_MGMT_2); if (ret & WM8962_SPKOUTL_PGA_ENA) { snd_soc_component_write(component, WM8962_SPKOUTL_VOLUME, - snd_soc_component_read32(component, WM8962_SPKOUTL_VOLUME)); + snd_soc_component_read(component, WM8962_SPKOUTL_VOLUME)); return 1; } /* ...otherwise the right. The VU is stereo. */ if (ret & WM8962_SPKOUTR_PGA_ENA) snd_soc_component_write(component, WM8962_SPKOUTR_VOLUME, - snd_soc_component_read32(component, WM8962_SPKOUTR_VOLUME)); + snd_soc_component_read(component, WM8962_SPKOUTR_VOLUME)); return 1; } @@ -1888,7 +1887,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, timeout = 0; do { msleep(1); - reg = snd_soc_component_read32(component, WM8962_DC_SERVO_6); + reg = snd_soc_component_read(component, WM8962_DC_SERVO_6); if (reg < 0) { dev_err(component->dev, "Failed to read DCS status: %d\n", @@ -1975,7 +1974,8 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - return snd_soc_component_write(component, reg, snd_soc_component_read32(component, reg)); + return snd_soc_component_write(component, reg, + snd_soc_component_read(component, reg)); default: WARN(1, "Invalid event %d\n", event); return -EINVAL; @@ -2442,7 +2442,7 @@ static void wm8962_configure_bclk(struct snd_soc_component *component) snd_soc_component_update_bits(component, WM8962_CLOCKING2, WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA); - dspclk = snd_soc_component_read32(component, WM8962_CLOCKING1); + dspclk = snd_soc_component_read(component, WM8962_CLOCKING1); if (snd_soc_component_get_bias_level(component) != SND_SOC_BIAS_ON) snd_soc_component_update_bits(component, WM8962_CLOCKING2, @@ -2644,7 +2644,7 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif0 |= WM8962_LRCLK_INV | 3; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif0 |= 3; @@ -2917,7 +2917,7 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s return 0; } -static int wm8962_mute(struct snd_soc_dai *dai, int mute) +static int wm8962_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int val, ret; @@ -2950,7 +2950,8 @@ static const struct snd_soc_dai_ops wm8962_dai_ops = { .hw_params = wm8962_hw_params, .set_sysclk = wm8962_set_dai_sysclk, .set_fmt = wm8962_set_dai_fmt, - .digital_mute = wm8962_mute, + .mute_stream = wm8962_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8962_dai = { @@ -2983,7 +2984,7 @@ static void wm8962_mic_work(struct work_struct *work) int irq_pol = 0; int reg; - reg = snd_soc_component_read32(component, WM8962_ADDITIONAL_CONTROL_4); + reg = snd_soc_component_read(component, WM8962_ADDITIONAL_CONTROL_4); if (reg & WM8962_MICDET_STS) { status |= SND_JACK_MICROPHONE; @@ -3436,8 +3437,14 @@ static int wm8962_probe(struct snd_soc_component *component) /* Save boards having to disable DMIC when not in use */ dmicclk = false; dmicdat = false; - for (i = 0; i < WM8962_MAX_GPIO; i++) { - switch (snd_soc_component_read32(component, WM8962_GPIO_BASE + i) + for (i = 1; i < WM8962_MAX_GPIO; i++) { + /* + * Register 515 (WM8962_GPIO_BASE + 3) does not exist, + * so skip its access + */ + if (i == 3) + continue; + switch (snd_soc_component_read(component, WM8962_GPIO_BASE + i) & WM8962_GP2_FN_MASK) { case WM8962_GPIO_FN_DMICCLK: dmicclk = true; diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 5266eabd96506bc4b8f9c0c6ba872d439b1ab542..21ae55c32a6ded0526468630543696eec08e042a 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -508,8 +508,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8971_priv *wm8971 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8971_IFACE) & 0x1f3; - u16 srate = snd_soc_component_read32(component, WM8971_SRATE) & 0x1c0; + u16 iface = snd_soc_component_read(component, WM8971_IFACE) & 0x1f3; + u16 srate = snd_soc_component_read(component, WM8971_SRATE) & 0x1c0; int coeff = get_coeff(wm8971->sysclk, params_rate(params)); /* bit size */ @@ -536,10 +536,10 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8971_mute(struct snd_soc_dai *dai, int mute) +static int wm8971_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8971_ADCDAC) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8971_ADCDAC) & 0xfff7; if (mute) snd_soc_component_write(component, WM8971_ADCDAC, mute_reg | 0x8); @@ -561,7 +561,7 @@ static int wm8971_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8971_priv *wm8971 = snd_soc_component_get_drvdata(component); - u16 pwr_reg = snd_soc_component_read32(component, WM8971_PWR1) & 0xfe3e; + u16 pwr_reg = snd_soc_component_read(component, WM8971_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: @@ -602,9 +602,10 @@ static int wm8971_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8971_dai_ops = { .hw_params = wm8971_pcm_hw_params, - .digital_mute = wm8971_mute, + .mute_stream = wm8971_mute, .set_fmt = wm8971_set_dai_fmt, .set_sysclk = wm8971_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8971_dai = { diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 7cfc89602fc397bc941e3790917c9497a7efe4ce..c86231dfcf4f84d68cf127addfe704c203b4bab8 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -318,11 +318,11 @@ static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (freq_in == 0 || freq_out == 0) { /* Clock CODEC directly from MCLK */ - reg = snd_soc_component_read32(component, WM8974_CLOCK); + reg = snd_soc_component_read(component, WM8974_CLOCK); snd_soc_component_write(component, WM8974_CLOCK, reg & 0x0ff); /* Turn off PLL */ - reg = snd_soc_component_read32(component, WM8974_POWER1); + reg = snd_soc_component_read(component, WM8974_POWER1); snd_soc_component_write(component, WM8974_POWER1, reg & 0x1df); return 0; } @@ -333,11 +333,11 @@ static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, snd_soc_component_write(component, WM8974_PLLK1, pll_div.k >> 18); snd_soc_component_write(component, WM8974_PLLK2, (pll_div.k >> 9) & 0x1ff); snd_soc_component_write(component, WM8974_PLLK3, pll_div.k & 0x1ff); - reg = snd_soc_component_read32(component, WM8974_POWER1); + reg = snd_soc_component_read(component, WM8974_POWER1); snd_soc_component_write(component, WM8974_POWER1, reg | 0x020); /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_component_read32(component, WM8974_CLOCK); + reg = snd_soc_component_read(component, WM8974_CLOCK); snd_soc_component_write(component, WM8974_CLOCK, reg | 0x100); return 0; @@ -354,15 +354,15 @@ static int wm8974_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8974_OPCLKDIV: - reg = snd_soc_component_read32(component, WM8974_GPIO) & 0x1cf; + reg = snd_soc_component_read(component, WM8974_GPIO) & 0x1cf; snd_soc_component_write(component, WM8974_GPIO, reg | div); break; case WM8974_MCLKDIV: - reg = snd_soc_component_read32(component, WM8974_CLOCK) & 0x11f; + reg = snd_soc_component_read(component, WM8974_CLOCK) & 0x11f; snd_soc_component_write(component, WM8974_CLOCK, reg | div); break; case WM8974_BCLKDIV: - reg = snd_soc_component_read32(component, WM8974_CLOCK) & 0x1e3; + reg = snd_soc_component_read(component, WM8974_CLOCK) & 0x1e3; snd_soc_component_write(component, WM8974_CLOCK, reg | div); break; default: @@ -450,7 +450,7 @@ static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai, { struct snd_soc_component *component = codec_dai->component; u16 iface = 0; - u16 clk = snd_soc_component_read32(component, WM8974_CLOCK) & 0x1fe; + u16 clk = snd_soc_component_read(component, WM8974_CLOCK) & 0x1fe; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -512,8 +512,8 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8974_priv *priv = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8974_IFACE) & 0x19f; - u16 adn = snd_soc_component_read32(component, WM8974_ADD) & 0x1f1; + u16 iface = snd_soc_component_read(component, WM8974_IFACE) & 0x19f; + u16 adn = snd_soc_component_read(component, WM8974_ADD) & 0x1f1; int err; priv->fs = params_rate(params); @@ -563,10 +563,10 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8974_mute(struct snd_soc_dai *dai, int mute) +static int wm8974_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8974_DAC) & 0xffbf; + u16 mute_reg = snd_soc_component_read(component, WM8974_DAC) & 0xffbf; if (mute) snd_soc_component_write(component, WM8974_DAC, mute_reg | 0x40); @@ -579,7 +579,7 @@ static int wm8974_mute(struct snd_soc_dai *dai, int mute) static int wm8974_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { - u16 power1 = snd_soc_component_read32(component, WM8974_POWER1) & ~0x3; + u16 power1 = snd_soc_component_read(component, WM8974_POWER1) & ~0x3; switch (level) { case SND_SOC_BIAS_ON: @@ -620,11 +620,12 @@ static int wm8974_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8974_ops = { .hw_params = wm8974_pcm_hw_params, - .digital_mute = wm8974_mute, + .mute_stream = wm8974_mute, .set_fmt = wm8974_set_dai_fmt, .set_clkdiv = wm8974_set_dai_clkdiv, .set_pll = wm8974_set_dai_pll, .set_sysclk = wm8974_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8974_dai = { diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index af35ae10136748932cf93a56b508e9b3ae96f711..a7acb898171592cad66d75f73628b767cae1448a 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -653,8 +653,8 @@ static int wm8978_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) * BCLK polarity mask = 0x100, LRC clock polarity mask = 0x80, * Data Format mask = 0x18: all will be calculated anew */ - u16 iface = snd_soc_component_read32(component, WM8978_AUDIO_INTERFACE) & ~0x198; - u16 clk = snd_soc_component_read32(component, WM8978_CLOCKING); + u16 iface = snd_soc_component_read(component, WM8978_AUDIO_INTERFACE) & ~0x198; + u16 clk = snd_soc_component_read(component, WM8978_CLOCKING); dev_dbg(component->dev, "%s\n", __func__); @@ -720,10 +720,10 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct wm8978_priv *wm8978 = snd_soc_component_get_drvdata(component); /* Word length mask = 0x60 */ - u16 iface_ctl = snd_soc_component_read32(component, WM8978_AUDIO_INTERFACE) & ~0x60; + u16 iface_ctl = snd_soc_component_read(component, WM8978_AUDIO_INTERFACE) & ~0x60; /* Sampling rate mask = 0xe (for filters) */ - u16 add_ctl = snd_soc_component_read32(component, WM8978_ADDITIONAL_CONTROL) & ~0xe; - u16 clking = snd_soc_component_read32(component, WM8978_CLOCKING); + u16 add_ctl = snd_soc_component_read(component, WM8978_ADDITIONAL_CONTROL) & ~0xe; + u16 clking = snd_soc_component_read(component, WM8978_CLOCKING); enum wm8978_sysclk_src current_clk_id = clking & 0x100 ? WM8978_PLL : WM8978_MCLK; unsigned int f_sel, diff, diff_best = INT_MAX; @@ -836,7 +836,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8978_mute(struct snd_soc_dai *dai, int mute) +static int wm8978_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -853,7 +853,7 @@ static int wm8978_mute(struct snd_soc_dai *dai, int mute) static int wm8978_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { - u16 power1 = snd_soc_component_read32(component, WM8978_POWER_MANAGEMENT_1) & ~3; + u16 power1 = snd_soc_component_read(component, WM8978_POWER_MANAGEMENT_1) & ~3; switch (level) { case SND_SOC_BIAS_ON: @@ -893,10 +893,11 @@ static int wm8978_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8978_dai_ops = { .hw_params = wm8978_hw_params, - .digital_mute = wm8978_mute, + .mute_stream = wm8978_mute, .set_fmt = wm8978_set_dai_fmt, .set_clkdiv = wm8978_set_dai_clkdiv, .set_sysclk = wm8978_set_dai_sysclk, + .no_capture_mute = 1, }; /* Also supports 12kHz */ diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index a7e0376f9cf680af27c3b9646362202342615099..d1d2d408ad952fd8f7ad63c0243ad70bac43acf2 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -492,7 +492,7 @@ static int eqmode_get(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); unsigned int reg; - reg = snd_soc_component_read32(component, WM8983_EQ1_LOW_SHELF); + reg = snd_soc_component_read(component, WM8983_EQ1_LOW_SHELF); if (reg & WM8983_EQ3DMODE) ucontrol->value.enumerated.item[0] = 1; else @@ -512,7 +512,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, && ucontrol->value.enumerated.item[0] != 1) return -EINVAL; - reg_eq = snd_soc_component_read32(component, WM8983_EQ1_LOW_SHELF); + reg_eq = snd_soc_component_read(component, WM8983_EQ1_LOW_SHELF); switch ((reg_eq & WM8983_EQ3DMODE) >> WM8983_EQ3DMODE_SHIFT) { case 0: if (!ucontrol->value.enumerated.item[0]) @@ -524,8 +524,8 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, break; } - regpwr2 = snd_soc_component_read32(component, WM8983_POWER_MANAGEMENT_2); - regpwr3 = snd_soc_component_read32(component, WM8983_POWER_MANAGEMENT_3); + regpwr2 = snd_soc_component_read(component, WM8983_POWER_MANAGEMENT_2); + regpwr3 = snd_soc_component_read(component, WM8983_POWER_MANAGEMENT_3); /* disable the DACs and ADCs */ snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_2, WM8983_ADCENR_MASK | WM8983_ADCENL_MASK, 0); @@ -557,7 +557,7 @@ static bool wm8983_writeable(struct device *dev, unsigned int reg) } } -static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute) +static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -943,11 +943,12 @@ static int wm8983_probe(struct snd_soc_component *component) } static const struct snd_soc_dai_ops wm8983_dai_ops = { - .digital_mute = wm8983_dac_mute, + .mute_stream = wm8983_dac_mute, .hw_params = wm8983_hw_params, .set_fmt = wm8983_set_fmt, .set_sysclk = wm8983_set_sysclk, - .set_pll = wm8983_set_pll + .set_pll = wm8983_set_pll, + .no_capture_mute = 1, }; #define WM8983_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index a62907d0f34066c4b887ecec5075e1ec1207ea3b..3f27482349b2a36438bd7e1d8406d386f84a6a95 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -592,7 +592,7 @@ static int eqmode_get(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); unsigned int reg; - reg = snd_soc_component_read32(component, WM8985_EQ1_LOW_SHELF); + reg = snd_soc_component_read(component, WM8985_EQ1_LOW_SHELF); if (reg & WM8985_EQ3DMODE) ucontrol->value.enumerated.item[0] = 1; else @@ -612,7 +612,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, && ucontrol->value.enumerated.item[0] != 1) return -EINVAL; - reg_eq = snd_soc_component_read32(component, WM8985_EQ1_LOW_SHELF); + reg_eq = snd_soc_component_read(component, WM8985_EQ1_LOW_SHELF); switch ((reg_eq & WM8985_EQ3DMODE) >> WM8985_EQ3DMODE_SHIFT) { case 0: if (!ucontrol->value.enumerated.item[0]) @@ -624,8 +624,8 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, break; } - regpwr2 = snd_soc_component_read32(component, WM8985_POWER_MANAGEMENT_2); - regpwr3 = snd_soc_component_read32(component, WM8985_POWER_MANAGEMENT_3); + regpwr2 = snd_soc_component_read(component, WM8985_POWER_MANAGEMENT_2); + regpwr3 = snd_soc_component_read(component, WM8985_POWER_MANAGEMENT_3); /* disable the DACs and ADCs */ snd_soc_component_update_bits(component, WM8985_POWER_MANAGEMENT_2, WM8985_ADCENR_MASK | WM8985_ADCENL_MASK, 0); @@ -649,7 +649,7 @@ static int wm8985_reset(struct snd_soc_component *component) return snd_soc_component_write(component, WM8985_SOFTWARE_RESET, 0x0); } -static int wm8985_dac_mute(struct snd_soc_dai *dai, int mute) +static int wm8985_dac_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; @@ -1072,11 +1072,12 @@ err_reg_enable: } static const struct snd_soc_dai_ops wm8985_dai_ops = { - .digital_mute = wm8985_dac_mute, + .mute_stream = wm8985_dac_mute, .hw_params = wm8985_hw_params, .set_fmt = wm8985_set_fmt, .set_sysclk = wm8985_set_sysclk, - .set_pll = wm8985_set_pll + .set_pll = wm8985_set_pll, + .no_capture_mute = 1, }; #define WM8985_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 85bfd041d5465af13ce5993a5449fb6df23ee325..d2c2d0d943f09ecc408ad00fd81f77d667d6d3de 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -242,10 +242,10 @@ static int wm8988_lrc_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - u16 adctl2 = snd_soc_component_read32(component, WM8988_ADCTL2); + u16 adctl2 = snd_soc_component_read(component, WM8988_ADCTL2); /* Use the DAC to gate LRC if active, otherwise use ADC */ - if (snd_soc_component_read32(component, WM8988_PWR2) & 0x180) + if (snd_soc_component_read(component, WM8988_PWR2) & 0x180) adctl2 &= ~0x4; else adctl2 |= 0x4; @@ -667,8 +667,8 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component); - u16 iface = snd_soc_component_read32(component, WM8988_IFACE) & 0x1f3; - u16 srate = snd_soc_component_read32(component, WM8988_SRATE) & 0x180; + u16 iface = snd_soc_component_read(component, WM8988_IFACE) & 0x1f3; + u16 srate = snd_soc_component_read(component, WM8988_SRATE) & 0x180; int coeff; coeff = get_coeff(wm8988->sysclk, params_rate(params)); @@ -707,10 +707,10 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8988_mute(struct snd_soc_dai *dai, int mute) +static int wm8988_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u16 mute_reg = snd_soc_component_read32(component, WM8988_ADCDAC) & 0xfff7; + u16 mute_reg = snd_soc_component_read(component, WM8988_ADCDAC) & 0xfff7; if (mute) snd_soc_component_write(component, WM8988_ADCDAC, mute_reg | 0x8); @@ -723,7 +723,7 @@ static int wm8988_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component); - u16 pwr_reg = snd_soc_component_read32(component, WM8988_PWR1) & ~0x1c1; + u16 pwr_reg = snd_soc_component_read(component, WM8988_PWR1) & ~0x1c1; switch (level) { case SND_SOC_BIAS_ON: @@ -766,7 +766,8 @@ static const struct snd_soc_dai_ops wm8988_ops = { .hw_params = wm8988_pcm_hw_params, .set_fmt = wm8988_set_dai_fmt, .set_sysclk = wm8988_set_dai_sysclk, - .digital_mute = wm8988_mute, + .mute_stream = wm8988_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8988_dai = { diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 499a29b47d5e493beae12090933e2c9fd9c9beb6..938940777e5dcdc0b55e070989111fac3c4c8c65 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -61,7 +61,7 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, return ret; /* now hit the volume update bits (always bit 8) */ - val = snd_soc_component_read32(component, reg); + val = snd_soc_component_read(component, reg); return snd_soc_component_write(component, reg, val | 0x0100); } @@ -298,7 +298,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, switch (reg_shift) { case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) : - reg = snd_soc_component_read32(component, WM8990_OUTPUT_MIXER1); + reg = snd_soc_component_read(component, WM8990_OUTPUT_MIXER1); if (reg & WM8990_LDLO) { printk(KERN_WARNING "Cannot set as Output Mixer 1 LDLO Set\n"); @@ -306,7 +306,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, } break; case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8): - reg = snd_soc_component_read32(component, WM8990_OUTPUT_MIXER2); + reg = snd_soc_component_read(component, WM8990_OUTPUT_MIXER2); if (reg & WM8990_RDRO) { printk(KERN_WARNING "Cannot set as Output Mixer 2 RDRO Set\n"); @@ -314,7 +314,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, } break; case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8): - reg = snd_soc_component_read32(component, WM8990_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8990_SPEAKER_MIXER); if (reg & WM8990_LDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer LDSPK Set\n"); @@ -322,7 +322,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, } break; case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8): - reg = snd_soc_component_read32(component, WM8990_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8990_SPEAKER_MIXER); if (reg & WM8990_RDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer RDSPK Set\n"); @@ -892,8 +892,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_component *component = codec_dai->component; u16 audio1, audio3; - audio1 = snd_soc_component_read32(component, WM8990_AUDIO_INTERFACE_1); - audio3 = snd_soc_component_read32(component, WM8990_AUDIO_INTERFACE_3); + audio1 = snd_soc_component_read(component, WM8990_AUDIO_INTERFACE_1); + audio3 = snd_soc_component_read(component, WM8990_AUDIO_INTERFACE_3); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -976,7 +976,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 audio1 = snd_soc_component_read32(component, WM8990_AUDIO_INTERFACE_1); + u16 audio1 = snd_soc_component_read(component, WM8990_AUDIO_INTERFACE_1); audio1 &= ~WM8990_AIF_WL_MASK; /* bit size */ @@ -998,12 +998,12 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8990_mute(struct snd_soc_dai *dai, int mute) +static int wm8990_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u16 val; - val = snd_soc_component_read32(component, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE; + val = snd_soc_component_read(component, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE; if (mute) snd_soc_component_write(component, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); @@ -1152,11 +1152,12 @@ static int wm8990_set_bias_level(struct snd_soc_component *component, */ static const struct snd_soc_dai_ops wm8990_dai_ops = { .hw_params = wm8990_hw_params, - .digital_mute = wm8990_mute, + .mute_stream = wm8990_mute, .set_fmt = wm8990_set_dai_fmt, .set_clkdiv = wm8990_set_dai_clkdiv, .set_pll = wm8990_set_dai_pll, .set_sysclk = wm8990_set_dai_sysclk, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver wm8990_dai = { diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index f8375d67e901dc3e6b9794c7f2f3018631622851..16bc8609d0d2091640bf4fefc81510a9ce7d4934 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -139,7 +139,7 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, return ret; /* now hit the volume update bits (always bit 8) */ - val = snd_soc_component_read32(component, reg); + val = snd_soc_component_read(component, reg); return snd_soc_component_write(component, reg, val | 0x0100); } @@ -364,7 +364,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, switch (reg_shift) { case WM8991_SPEAKER_MIXER | (WM8991_LDSPK_BIT << 8): - reg = snd_soc_component_read32(component, WM8991_OUTPUT_MIXER1); + reg = snd_soc_component_read(component, WM8991_OUTPUT_MIXER1); if (reg & WM8991_LDLO) { printk(KERN_WARNING "Cannot set as Output Mixer 1 LDLO Set\n"); @@ -373,7 +373,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, break; case WM8991_SPEAKER_MIXER | (WM8991_RDSPK_BIT << 8): - reg = snd_soc_component_read32(component, WM8991_OUTPUT_MIXER2); + reg = snd_soc_component_read(component, WM8991_OUTPUT_MIXER2); if (reg & WM8991_RDRO) { printk(KERN_WARNING "Cannot set as Output Mixer 2 RDRO Set\n"); @@ -382,7 +382,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, break; case WM8991_OUTPUT_MIXER1 | (WM8991_LDLO_BIT << 8): - reg = snd_soc_component_read32(component, WM8991_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8991_SPEAKER_MIXER); if (reg & WM8991_LDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer LDSPK Set\n"); @@ -391,7 +391,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, break; case WM8991_OUTPUT_MIXER2 | (WM8991_RDRO_BIT << 8): - reg = snd_soc_component_read32(component, WM8991_SPEAKER_MIXER); + reg = snd_soc_component_read(component, WM8991_SPEAKER_MIXER); if (reg & WM8991_RDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer RDSPK Set\n"); @@ -922,12 +922,12 @@ static int wm8991_set_dai_pll(struct snd_soc_dai *codec_dai, pll_factors(&pll_div, freq_out * 4, freq_in); /* Turn on PLL */ - reg = snd_soc_component_read32(component, WM8991_POWER_MANAGEMENT_2); + reg = snd_soc_component_read(component, WM8991_POWER_MANAGEMENT_2); reg |= WM8991_PLL_ENA; snd_soc_component_write(component, WM8991_POWER_MANAGEMENT_2, reg); /* sysclk comes from PLL */ - reg = snd_soc_component_read32(component, WM8991_CLOCKING_2); + reg = snd_soc_component_read(component, WM8991_CLOCKING_2); snd_soc_component_write(component, WM8991_CLOCKING_2, reg | WM8991_SYSCLK_SRC); /* set up N , fractional mode and pre-divisor if necessary */ @@ -937,7 +937,7 @@ static int wm8991_set_dai_pll(struct snd_soc_dai *codec_dai, snd_soc_component_write(component, WM8991_PLL3, (u8)(pll_div.k & 0xFF)); } else { /* Turn on PLL */ - reg = snd_soc_component_read32(component, WM8991_POWER_MANAGEMENT_2); + reg = snd_soc_component_read(component, WM8991_POWER_MANAGEMENT_2); reg &= ~WM8991_PLL_ENA; snd_soc_component_write(component, WM8991_POWER_MANAGEMENT_2, reg); } @@ -953,8 +953,8 @@ static int wm8991_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_component *component = codec_dai->component; u16 audio1, audio3; - audio1 = snd_soc_component_read32(component, WM8991_AUDIO_INTERFACE_1); - audio3 = snd_soc_component_read32(component, WM8991_AUDIO_INTERFACE_3); + audio1 = snd_soc_component_read(component, WM8991_AUDIO_INTERFACE_1); + audio3 = snd_soc_component_read(component, WM8991_AUDIO_INTERFACE_3); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1008,22 +1008,22 @@ static int wm8991_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8991_MCLK_DIV: - reg = snd_soc_component_read32(component, WM8991_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8991_CLOCKING_2) & ~WM8991_MCLK_DIV_MASK; snd_soc_component_write(component, WM8991_CLOCKING_2, reg | div); break; case WM8991_DACCLK_DIV: - reg = snd_soc_component_read32(component, WM8991_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8991_CLOCKING_2) & ~WM8991_DAC_CLKDIV_MASK; snd_soc_component_write(component, WM8991_CLOCKING_2, reg | div); break; case WM8991_ADCCLK_DIV: - reg = snd_soc_component_read32(component, WM8991_CLOCKING_2) & + reg = snd_soc_component_read(component, WM8991_CLOCKING_2) & ~WM8991_ADC_CLKDIV_MASK; snd_soc_component_write(component, WM8991_CLOCKING_2, reg | div); break; case WM8991_BCLK_DIV: - reg = snd_soc_component_read32(component, WM8991_CLOCKING_1) & + reg = snd_soc_component_read(component, WM8991_CLOCKING_1) & ~WM8991_BCLK_DIV_MASK; snd_soc_component_write(component, WM8991_CLOCKING_1, reg | div); break; @@ -1042,7 +1042,7 @@ static int wm8991_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - u16 audio1 = snd_soc_component_read32(component, WM8991_AUDIO_INTERFACE_1); + u16 audio1 = snd_soc_component_read(component, WM8991_AUDIO_INTERFACE_1); audio1 &= ~WM8991_AIF_WL_MASK; /* bit size */ @@ -1064,12 +1064,12 @@ static int wm8991_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8991_mute(struct snd_soc_dai *dai, int mute) +static int wm8991_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; u16 val; - val = snd_soc_component_read32(component, WM8991_DAC_CTRL) & ~WM8991_DAC_MUTE; + val = snd_soc_component_read(component, WM8991_DAC_CTRL) & ~WM8991_DAC_MUTE; if (mute) snd_soc_component_write(component, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE); else @@ -1089,7 +1089,7 @@ static int wm8991_set_bias_level(struct snd_soc_component *component, case SND_SOC_BIAS_PREPARE: /* VMID=2*50k */ - val = snd_soc_component_read32(component, WM8991_POWER_MANAGEMENT_1) & + val = snd_soc_component_read(component, WM8991_POWER_MANAGEMENT_1) & ~WM8991_VMID_MODE_MASK; snd_soc_component_write(component, WM8991_POWER_MANAGEMENT_1, val | 0x2); break; @@ -1146,7 +1146,7 @@ static int wm8991_set_bias_level(struct snd_soc_component *component, } /* VMID=2*250k */ - val = snd_soc_component_read32(component, WM8991_POWER_MANAGEMENT_1) & + val = snd_soc_component_read(component, WM8991_POWER_MANAGEMENT_1) & ~WM8991_VMID_MODE_MASK; snd_soc_component_write(component, WM8991_POWER_MANAGEMENT_1, val | 0x4); break; @@ -1162,7 +1162,7 @@ static int wm8991_set_bias_level(struct snd_soc_component *component, WM8991_BUFIOEN); /* mute DAC */ - val = snd_soc_component_read32(component, WM8991_DAC_CTRL); + val = snd_soc_component_read(component, WM8991_DAC_CTRL); snd_soc_component_write(component, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE); /* Enable any disabled outputs */ @@ -1196,10 +1196,11 @@ static int wm8991_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_dai_ops wm8991_ops = { .hw_params = wm8991_hw_params, - .digital_mute = wm8991_mute, + .mute_stream = wm8991_mute, .set_fmt = wm8991_set_dai_fmt, .set_clkdiv = wm8991_set_dai_clkdiv, - .set_pll = wm8991_set_dai_pll + .set_pll = wm8991_set_dai_pll, + .no_capture_mute = 1, }; /* diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 3fb8f37a3fade3f4bac742cb14a7ef7ae6a24bb0..9f310082e3c1a0653df367bc6a8ae128a53b0b07 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -483,7 +483,7 @@ static int _wm8993_set_fll(struct snd_soc_component *component, int fll_id, int wm8993->fll_fref = 0; wm8993->fll_fout = 0; - reg1 = snd_soc_component_read32(component, WM8993_FLL_CONTROL_1); + reg1 = snd_soc_component_read(component, WM8993_FLL_CONTROL_1); reg1 &= ~WM8993_FLL_ENA; snd_soc_component_write(component, WM8993_FLL_CONTROL_1, reg1); @@ -494,7 +494,7 @@ static int _wm8993_set_fll(struct snd_soc_component *component, int fll_id, int if (ret != 0) return ret; - reg5 = snd_soc_component_read32(component, WM8993_FLL_CONTROL_5); + reg5 = snd_soc_component_read(component, WM8993_FLL_CONTROL_5); reg5 &= ~WM8993_FLL_CLK_SRC_MASK; switch (fll_id) { @@ -516,7 +516,7 @@ static int _wm8993_set_fll(struct snd_soc_component *component, int fll_id, int /* Any FLL configuration change requires that the FLL be * disabled first. */ - reg1 = snd_soc_component_read32(component, WM8993_FLL_CONTROL_1); + reg1 = snd_soc_component_read(component, WM8993_FLL_CONTROL_1); reg1 &= ~WM8993_FLL_ENA; snd_soc_component_write(component, WM8993_FLL_CONTROL_1, reg1); @@ -532,7 +532,7 @@ static int _wm8993_set_fll(struct snd_soc_component *component, int fll_id, int (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT)); snd_soc_component_write(component, WM8993_FLL_CONTROL_3, fll_div.k); - reg4 = snd_soc_component_read32(component, WM8993_FLL_CONTROL_4); + reg4 = snd_soc_component_read(component, WM8993_FLL_CONTROL_4); reg4 &= ~WM8993_FLL_N_MASK; reg4 |= fll_div.n << WM8993_FLL_N_SHIFT; snd_soc_component_write(component, WM8993_FLL_CONTROL_4, reg4); @@ -583,7 +583,7 @@ static int configure_clock(struct snd_soc_component *component) case WM8993_SYSCLK_MCLK: dev_dbg(component->dev, "Using %dHz MCLK\n", wm8993->mclk_rate); - reg = snd_soc_component_read32(component, WM8993_CLOCKING_2); + reg = snd_soc_component_read(component, WM8993_CLOCKING_2); reg &= ~(WM8993_MCLK_DIV | WM8993_SYSCLK_SRC); if (wm8993->mclk_rate > 13500000) { reg |= WM8993_MCLK_DIV; @@ -599,7 +599,7 @@ static int configure_clock(struct snd_soc_component *component) dev_dbg(component->dev, "Using %dHz FLL clock\n", wm8993->fll_fout); - reg = snd_soc_component_read32(component, WM8993_CLOCKING_2); + reg = snd_soc_component_read(component, WM8993_CLOCKING_2); reg |= WM8993_SYSCLK_SRC; if (wm8993->fll_fout > 13500000) { reg |= WM8993_MCLK_DIV; @@ -1073,7 +1073,7 @@ static int wm8993_set_sysclk(struct snd_soc_dai *codec_dai, switch (clk_id) { case WM8993_SYSCLK_MCLK: wm8993->mclk_rate = freq; - /* fall through */ + fallthrough; case WM8993_SYSCLK_FLL: wm8993->sysclk_source = clk_id; break; @@ -1090,8 +1090,8 @@ static int wm8993_set_dai_fmt(struct snd_soc_dai *dai, { struct snd_soc_component *component = dai->component; struct wm8993_priv *wm8993 = snd_soc_component_get_drvdata(component); - unsigned int aif1 = snd_soc_component_read32(component, WM8993_AUDIO_INTERFACE_1); - unsigned int aif4 = snd_soc_component_read32(component, WM8993_AUDIO_INTERFACE_4); + unsigned int aif1 = snd_soc_component_read(component, WM8993_AUDIO_INTERFACE_1); + unsigned int aif4 = snd_soc_component_read(component, WM8993_AUDIO_INTERFACE_4); aif1 &= ~(WM8993_BCLK_DIR | WM8993_AIF_BCLK_INV | WM8993_AIF_LRCLK_INV | WM8993_AIF_FMT_MASK); @@ -1121,7 +1121,7 @@ static int wm8993_set_dai_fmt(struct snd_soc_dai *dai, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif1 |= WM8993_AIF_LRCLK_INV; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif1 |= 0x18; break; @@ -1190,16 +1190,16 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream, int ret, i, best, best_val, cur_val; unsigned int clocking1, clocking3, aif1, aif4; - clocking1 = snd_soc_component_read32(component, WM8993_CLOCKING_1); + clocking1 = snd_soc_component_read(component, WM8993_CLOCKING_1); clocking1 &= ~WM8993_BCLK_DIV_MASK; - clocking3 = snd_soc_component_read32(component, WM8993_CLOCKING_3); + clocking3 = snd_soc_component_read(component, WM8993_CLOCKING_3); clocking3 &= ~(WM8993_CLK_SYS_RATE_MASK | WM8993_SAMPLE_RATE_MASK); - aif1 = snd_soc_component_read32(component, WM8993_AUDIO_INTERFACE_1); + aif1 = snd_soc_component_read(component, WM8993_AUDIO_INTERFACE_1); aif1 &= ~WM8993_AIF_WL_MASK; - aif4 = snd_soc_component_read32(component, WM8993_AUDIO_INTERFACE_4); + aif4 = snd_soc_component_read(component, WM8993_AUDIO_INTERFACE_4); aif4 &= ~WM8993_LRCLK_RATE_MASK; /* What BCLK do we need? */ @@ -1299,7 +1299,7 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream, /* ReTune Mobile? */ if (wm8993->pdata.num_retune_configs) { - u16 eq1 = snd_soc_component_read32(component, WM8993_EQ1); + u16 eq1 = snd_soc_component_read(component, WM8993_EQ1); struct wm8993_retune_mobile_setting *s; best = 0; @@ -1330,12 +1330,12 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8993_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8993_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; unsigned int reg; - reg = snd_soc_component_read32(component, WM8993_DAC_CTRL); + reg = snd_soc_component_read(component, WM8993_DAC_CTRL); if (mute) reg |= WM8993_DAC_MUTE; @@ -1444,9 +1444,10 @@ static const struct snd_soc_dai_ops wm8993_ops = { .set_sysclk = wm8993_set_sysclk, .set_fmt = wm8993_set_dai_fmt, .hw_params = wm8993_hw_params, - .digital_mute = wm8993_digital_mute, + .mute_stream = wm8993_mute, .set_pll = wm8993_set_fll, .set_tdm_slot = wm8993_set_tdm_slot, + .no_capture_mute = 1, }; #define WM8993_RATES SNDRV_PCM_RATE_8000_48000 diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 55d0b9be6ff006f82022377147d016e2f63d30bb..a84ae879d37e673b3da0bd26362d46ba2368059e 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -113,7 +113,7 @@ static void wm8958_micd_set_rate(struct snd_soc_component *component) idle = !wm8994->jack_mic; - sysclk = snd_soc_component_read32(component, WM8994_CLOCKING_1); + sysclk = snd_soc_component_read(component, WM8994_CLOCKING_1); if (sysclk & WM8994_SYSCLK_SRC) sysclk = wm8994->aifclk[1]; else @@ -247,7 +247,7 @@ static int check_clk_sys(struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink) { struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); - int reg = snd_soc_component_read32(component, WM8994_CLOCKING_1); + int reg = snd_soc_component_read(component, WM8994_CLOCKING_1); const char *clk; /* Check what we're currently using for CLK_SYS */ @@ -305,7 +305,7 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, else mask = WM8994_AIF1DAC1_DRC_ENA_MASK; - ret = snd_soc_component_read32(component, mc->reg); + ret = snd_soc_component_read(component, mc->reg); if (ret < 0) return ret; if (ret & mask) @@ -324,7 +324,7 @@ static void wm8994_set_drc(struct snd_soc_component *component, int drc) int save, i; /* Save any enables; the configuration should clear them. */ - save = snd_soc_component_read32(component, base); + save = snd_soc_component_read(component, base); save &= WM8994_AIF1DAC1_DRC_ENA | WM8994_AIF1ADC1L_DRC_ENA | WM8994_AIF1ADC1R_DRC_ENA; @@ -434,7 +434,7 @@ static void wm8994_set_retune_mobile(struct snd_soc_component *component, int bl /* The EQ will be disabled while reconfiguring it, remember the * current configuration. */ - save = snd_soc_component_read32(component, base); + save = snd_soc_component_read(component, base); save &= WM8994_AIF1DAC1_EQ_ENA; for (i = 0; i < WM8994_EQ_REGS; i++) @@ -853,7 +853,7 @@ static void vmid_reference(struct snd_soc_component *component) switch (wm8994->vmid_mode) { default: WARN_ON(NULL == "Invalid VMID mode"); - /* fall through */ + fallthrough; case WM8994_VMID_NORMAL: /* Startup bias, VMID ramp & buffer */ snd_soc_component_update_bits(component, WM8994_ANTIPOP_2, @@ -998,7 +998,7 @@ static bool wm8994_check_class_w_digital(struct snd_soc_component *component) int reg, reg_r; /* We also need the same AIF source for L/R and only one path */ - reg = snd_soc_component_read32(component, WM8994_DAC1_LEFT_MIXER_ROUTING); + reg = snd_soc_component_read(component, WM8994_DAC1_LEFT_MIXER_ROUTING); switch (reg) { case WM8994_AIF2DACL_TO_DAC1L: dev_vdbg(component->dev, "Class W source AIF2DAC\n"); @@ -1017,7 +1017,7 @@ static bool wm8994_check_class_w_digital(struct snd_soc_component *component) return false; } - reg_r = snd_soc_component_read32(component, WM8994_DAC1_RIGHT_MIXER_ROUTING); + reg_r = snd_soc_component_read(component, WM8994_DAC1_RIGHT_MIXER_ROUTING); if (reg_r != reg) { dev_vdbg(component->dev, "Left and right DAC mixers different\n"); return false; @@ -1041,7 +1041,7 @@ static int aif_mclk_set(struct snd_soc_component *component, int aif, bool enabl else offset = 0; - val = snd_soc_component_read32(component, WM8994_AIF1_CLOCKING_1 + offset); + val = snd_soc_component_read(component, WM8994_AIF1_CLOCKING_1 + offset); val &= WM8994_AIF1CLK_SRC_MASK; switch (val) { @@ -1100,7 +1100,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, if (wm8994->channels[0] <= 2) mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA); - val = snd_soc_component_read32(component, WM8994_AIF1_CONTROL_1); + val = snd_soc_component_read(component, WM8994_AIF1_CONTROL_1); if ((val & WM8994_AIF1ADCL_SRC) && (val & WM8994_AIF1ADCR_SRC)) adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA; @@ -1111,7 +1111,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA | WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC2L_ENA; - val = snd_soc_component_read32(component, WM8994_AIF1_CONTROL_2); + val = snd_soc_component_read(component, WM8994_AIF1_CONTROL_2); if ((val & WM8994_AIF1DACL_SRC) && (val & WM8994_AIF1DACR_SRC)) dac = WM8994_AIF1DAC1R_ENA | WM8994_AIF1DAC2R_ENA; @@ -1146,7 +1146,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) snd_soc_component_write(component, wm8994_vu_bits[i].reg, - snd_soc_component_read32(component, + snd_soc_component_read(component, wm8994_vu_bits[i].reg)); break; @@ -1157,7 +1157,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_4, mask, 0); - val = snd_soc_component_read32(component, WM8994_CLOCKING_1); + val = snd_soc_component_read(component, WM8994_CLOCKING_1); if (val & WM8994_AIF2DSPCLK_ENA) val = WM8994_SYSDSPCLK_ENA; else @@ -1192,7 +1192,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, if (ret < 0) return ret; - val = snd_soc_component_read32(component, WM8994_AIF2_CONTROL_1); + val = snd_soc_component_read(component, WM8994_AIF2_CONTROL_1); if ((val & WM8994_AIF2ADCL_SRC) && (val & WM8994_AIF2ADCR_SRC)) adc = WM8994_AIF2ADCR_ENA; @@ -1203,7 +1203,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, adc = WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA; - val = snd_soc_component_read32(component, WM8994_AIF2_CONTROL_2); + val = snd_soc_component_read(component, WM8994_AIF2_CONTROL_2); if ((val & WM8994_AIF2DACL_SRC) && (val & WM8994_AIF2DACR_SRC)) dac = WM8994_AIF2DACR_ENA; @@ -1239,7 +1239,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) snd_soc_component_write(component, wm8994_vu_bits[i].reg, - snd_soc_component_read32(component, + snd_soc_component_read(component, wm8994_vu_bits[i].reg)); break; @@ -1252,7 +1252,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA, 0); - val = snd_soc_component_read32(component, WM8994_CLOCKING_1); + val = snd_soc_component_read(component, WM8994_CLOCKING_1); if (val & WM8994_AIF1DSPCLK_ENA) val = WM8994_SYSDSPCLK_ENA; else @@ -1429,7 +1429,7 @@ static int post_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); dev_dbg(component->dev, "SRC status: %x\n", - snd_soc_component_read32(component, + snd_soc_component_read(component, WM8994_RATE_STATUS)); return 0; } @@ -2209,7 +2209,7 @@ static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src, return -EINVAL; } - reg = snd_soc_component_read32(component, WM8994_FLL1_CONTROL_1 + reg_offset); + reg = snd_soc_component_read(component, WM8994_FLL1_CONTROL_1 + reg_offset); was_enabled = reg & WM8994_FLL1_ENA; switch (src) { @@ -2250,12 +2250,12 @@ static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src, return ret; /* Make sure that we're not providing SYSCLK right now */ - clk1 = snd_soc_component_read32(component, WM8994_CLOCKING_1); + clk1 = snd_soc_component_read(component, WM8994_CLOCKING_1); if (clk1 & WM8994_SYSCLK_SRC) aif_reg = WM8994_AIF2_CLOCKING_1; else aif_reg = WM8994_AIF1_CLOCKING_1; - reg = snd_soc_component_read32(component, aif_reg); + reg = snd_soc_component_read(component, aif_reg); if ((reg & WM8994_AIF1CLK_ENA) && (reg & WM8994_AIF1CLK_SRC_MASK) == aif_src) { @@ -2270,7 +2270,7 @@ static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src, /* Disable MCLK if needed before we possibly change to new clock parent */ if (was_enabled) { - reg = snd_soc_component_read32(component, WM8994_FLL1_CONTROL_5 + reg = snd_soc_component_read(component, WM8994_FLL1_CONTROL_5 + reg_offset); reg = ((reg & WM8994_FLL1_REFCLK_SRC_MASK) >> WM8994_FLL1_REFCLK_SRC_SHIFT) + 1; @@ -2423,9 +2423,9 @@ out: if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { dev_dbg(component->dev, "Configuring AIFs for 128fs\n"); - wm8994->aifdiv[0] = snd_soc_component_read32(component, WM8994_AIF1_RATE) + wm8994->aifdiv[0] = snd_soc_component_read(component, WM8994_AIF1_RATE) & WM8994_AIF1CLK_RATE_MASK; - wm8994->aifdiv[1] = snd_soc_component_read32(component, WM8994_AIF2_RATE) + wm8994->aifdiv[1] = snd_soc_component_read(component, WM8994_AIF2_RATE) & WM8994_AIF1CLK_RATE_MASK; snd_soc_component_update_bits(component, WM8994_AIF1_RATE, @@ -2567,9 +2567,9 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { dev_dbg(component->dev, "Configuring AIFs for 128fs\n"); - wm8994->aifdiv[0] = snd_soc_component_read32(component, WM8994_AIF1_RATE) + wm8994->aifdiv[0] = snd_soc_component_read(component, WM8994_AIF1_RATE) & WM8994_AIF1CLK_RATE_MASK; - wm8994->aifdiv[1] = snd_soc_component_read32(component, WM8994_AIF2_RATE) + wm8994->aifdiv[1] = snd_soc_component_read(component, WM8994_AIF2_RATE) & WM8994_AIF1CLK_RATE_MASK; snd_soc_component_update_bits(component, WM8994_AIF1_RATE, @@ -2776,7 +2776,7 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_B: aif1 |= WM8994_AIF1_LRCLK_INV; lrclk |= WM8958_AIF1_LRCLK_INV; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif1 |= 0x18; break; @@ -2991,7 +2991,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, dai->id, wm8994->aifclk[id], bclk_rate); if (wm8994->channels[id] == 1 && - (snd_soc_component_read32(component, aif1_reg) & 0x18) == 0x18) + (snd_soc_component_read(component, aif1_reg) & 0x18) == 0x18) aif2 |= WM8994_AIF1_MONO; if (wm8994->aifclk[id] == 0) { @@ -3110,7 +3110,8 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream, return snd_soc_component_update_bits(component, aif1_reg, WM8994_AIF1_WL_MASK, aif1); } -static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute, + int direction) { struct snd_soc_component *component = codec_dai->component; int mute_reg; @@ -3187,18 +3188,20 @@ static const struct snd_soc_dai_ops wm8994_aif1_dai_ops = { .set_sysclk = wm8994_set_dai_sysclk, .set_fmt = wm8994_set_dai_fmt, .hw_params = wm8994_hw_params, - .digital_mute = wm8994_aif_mute, + .mute_stream = wm8994_aif_mute, .set_pll = wm8994_set_fll, .set_tristate = wm8994_set_tristate, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8994_aif2_dai_ops = { .set_sysclk = wm8994_set_dai_sysclk, .set_fmt = wm8994_set_dai_fmt, .hw_params = wm8994_hw_params, - .digital_mute = wm8994_aif_mute, + .mute_stream = wm8994_aif_mute, .set_pll = wm8994_set_fll, .set_tristate = wm8994_set_tristate, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8994_aif3_dai_ops = { @@ -3795,7 +3798,7 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) mutex_lock(&wm8994->accdet_lock); - reg = snd_soc_component_read32(component, WM1811_JACKDET_CTRL); + reg = snd_soc_component_read(component, WM1811_JACKDET_CTRL); if (reg < 0) { dev_err(component->dev, "Failed to read jack status: %d\n", reg); mutex_unlock(&wm8994->accdet_lock); @@ -3877,6 +3880,10 @@ static void wm1811_jackdet_bootstrap(struct work_struct *work) * * @component: WM8958 component * @jack: jack to report detection events on + * @det_cb: detection callback + * @det_cb_data: data for detection callback + * @id_cb: mic id callback + * @id_cb_data: data for mic id callback * * Enable microphone detection functionality for the WM8958. By * default simple detection which supports the detection of up to 6 @@ -4006,7 +4013,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) * with an update of the MICDET status; if so it will have * stopped detection and we can ignore this interrupt. */ - if (!(snd_soc_component_read32(component, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) + if (!(snd_soc_component_read(component, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) return IRQ_HANDLED; cancel_delayed_work_sync(&wm8994->mic_complete_work); @@ -4019,7 +4026,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) */ count = 10; do { - reg = snd_soc_component_read32(component, WM8958_MIC_DETECT_3); + reg = snd_soc_component_read(component, WM8958_MIC_DETECT_3); if (reg < 0) { dev_err(component->dev, "Failed to read mic detect status: %d\n", @@ -4048,7 +4055,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) /* Avoid a transient report when the accessory is being removed */ if (wm8994->jackdet) { - ret = snd_soc_component_read32(component, WM1811_JACKDET_CTRL); + ret = snd_soc_component_read(component, WM1811_JACKDET_CTRL); if (ret < 0) { dev_err(component->dev, "Failed to read jack status: %d\n", ret); diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 53e285caa92667812a21ec76e979949fc6ccac02..b896d9c5bea0b50f8a8ce2667404547fe1ad4cf5 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -489,7 +489,7 @@ static void wm8995_update_class_w(struct snd_soc_component *component) int reg, reg_r; /* We also need the same setting for L/R and only one path */ - reg = snd_soc_component_read32(component, WM8995_DAC1_LEFT_MIXER_ROUTING); + reg = snd_soc_component_read(component, WM8995_DAC1_LEFT_MIXER_ROUTING); switch (reg) { case WM8995_AIF2DACL_TO_DAC1L: dev_dbg(component->dev, "Class W source AIF2DAC\n"); @@ -509,7 +509,7 @@ static void wm8995_update_class_w(struct snd_soc_component *component) break; } - reg_r = snd_soc_component_read32(component, WM8995_DAC1_RIGHT_MIXER_ROUTING); + reg_r = snd_soc_component_read(component, WM8995_DAC1_RIGHT_MIXER_ROUTING); if (reg_r != reg) { dev_dbg(component->dev, "Left and right DAC mixers different\n"); enable = 0; @@ -535,7 +535,7 @@ static int check_clk_sys(struct snd_soc_dapm_widget *source, unsigned int reg; const char *clk; - reg = snd_soc_component_read32(component, WM8995_CLOCKING_1); + reg = snd_soc_component_read(component, WM8995_CLOCKING_1); /* Check what we're currently using for CLK_SYS */ if (reg & WM8995_SYSCLK_SRC) clk = "AIF2CLK"; @@ -596,7 +596,7 @@ static void dc_servo_cmd(struct snd_soc_component *component, snd_soc_component_write(component, reg, val); while (timeout--) { msleep(10); - val = snd_soc_component_read32(component, WM8995_DC_SERVO_READBACK_0); + val = snd_soc_component_read(component, WM8995_DC_SERVO_READBACK_0); if ((val & mask) == mask) return; } @@ -610,7 +610,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); unsigned int reg; - reg = snd_soc_component_read32(component, WM8995_ANALOGUE_HP_1); + reg = snd_soc_component_read(component, WM8995_ANALOGUE_HP_1); switch (event) { case SND_SOC_DAPM_POST_PMU: @@ -1417,7 +1417,7 @@ static bool wm8995_volatile(struct device *dev, unsigned int reg) } } -static int wm8995_aif_mute(struct snd_soc_dai *dai, int mute) +static int wm8995_aif_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; int mute_reg; @@ -1462,7 +1462,7 @@ static int wm8995_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif |= WM8995_AIF1_LRCLK_INV; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif |= (0x3 << WM8995_AIF1_FMT_SHIFT); break; @@ -1804,10 +1804,10 @@ static int wm8995_set_fll(struct snd_soc_dai *dai, int id, component = dai->component; wm8995 = snd_soc_component_get_drvdata(component); - aif1 = snd_soc_component_read32(component, WM8995_AIF1_CLOCKING_1) + aif1 = snd_soc_component_read(component, WM8995_AIF1_CLOCKING_1) & WM8995_AIF1CLK_ENA; - aif2 = snd_soc_component_read32(component, WM8995_AIF2_CLOCKING_1) + aif2 = snd_soc_component_read(component, WM8995_AIF2_CLOCKING_1) & WM8995_AIF2CLK_ENA; switch (id) { @@ -2040,7 +2040,7 @@ static int wm8995_probe(struct snd_soc_component *component) return ret; } - ret = snd_soc_component_read32(component, WM8995_SOFTWARE_RESET); + ret = snd_soc_component_read(component, WM8995_SOFTWARE_RESET); if (ret < 0) { dev_err(component->dev, "Failed to read device ID: %d\n", ret); goto err_reg_enable; @@ -2094,18 +2094,20 @@ static const struct snd_soc_dai_ops wm8995_aif1_dai_ops = { .set_sysclk = wm8995_set_dai_sysclk, .set_fmt = wm8995_set_dai_fmt, .hw_params = wm8995_hw_params, - .digital_mute = wm8995_aif_mute, + .mute_stream = wm8995_aif_mute, .set_pll = wm8995_set_fll, .set_tristate = wm8995_set_tristate, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8995_aif2_dai_ops = { .set_sysclk = wm8995_set_dai_sysclk, .set_fmt = wm8995_set_dai_fmt, .hw_params = wm8995_hw_params, - .digital_mute = wm8995_aif_mute, + .mute_stream = wm8995_aif_mute, .set_pll = wm8995_set_fll, .set_tristate = wm8995_set_tristate, + .no_capture_mute = 1, }; static const struct snd_soc_dai_ops wm8995_aif3_dai_ops = { diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 50eaa60d6cb3dddeefe0fec17df766185a2bb5a7..d303ef7571e9d38532828818f6aed5b58bbd6a04 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -343,7 +343,7 @@ static void wm8996_set_retune_mobile(struct snd_soc_component *component, int bl switch (block) { case 0: base = WM8996_DSP1_RX_EQ_GAINS_1; - if (snd_soc_component_read32(component, WM8996_POWER_MANAGEMENT_8) & + if (snd_soc_component_read(component, WM8996_POWER_MANAGEMENT_8) & WM8996_DSP1RX_SRC) iface = 1; else @@ -351,7 +351,7 @@ static void wm8996_set_retune_mobile(struct snd_soc_component *component, int bl break; case 1: base = WM8996_DSP1_RX_EQ_GAINS_2; - if (snd_soc_component_read32(component, WM8996_POWER_MANAGEMENT_8) & + if (snd_soc_component_read(component, WM8996_POWER_MANAGEMENT_8) & WM8996_DSP2RX_SRC) iface = 1; else @@ -386,7 +386,7 @@ static void wm8996_set_retune_mobile(struct snd_soc_component *component, int bl /* The EQ will be disabled while reconfiguring it, remember the * current configuration. */ - save = snd_soc_component_read32(component, base); + save = snd_soc_component_read(component, base); save &= WM8996_DSP1RX_EQ_ENA; for (i = 0; i < ARRAY_SIZE(pdata->retune_mobile_cfgs[best].regs); i++) @@ -672,7 +672,7 @@ static void wait_for_dc_servo(struct snd_soc_component *component, u16 mask) timeout--; } - ret = snd_soc_component_read32(component, WM8996_DC_SERVO_2); + ret = snd_soc_component_read(component, WM8996_DC_SERVO_2); dev_dbg(component->dev, "DC servo state: %x\n", ret); } while (timeout && ret & mask); @@ -1741,7 +1741,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream, switch (dai->id) { case 0: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - (snd_soc_component_read32(component, WM8996_GPIO_1)) & WM8996_GP1_FN_MASK) { + (snd_soc_component_read(component, WM8996_GPIO_1)) & WM8996_GP1_FN_MASK) { aifdata_reg = WM8996_AIF1RX_DATA_CONFIGURATION; lrclk_reg = WM8996_AIF1_RX_LRCLK_1; } else { @@ -1752,7 +1752,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream, break; case 1: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - (snd_soc_component_read32(component, WM8996_GPIO_2)) & WM8996_GP2_FN_MASK) { + (snd_soc_component_read(component, WM8996_GPIO_2)) & WM8996_GP2_FN_MASK) { aifdata_reg = WM8996_AIF2RX_DATA_CONFIGURATION; lrclk_reg = WM8996_AIF2_RX_LRCLK_1; } else { @@ -1822,7 +1822,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, return 0; /* Disable SYSCLK while we reconfigure */ - old = snd_soc_component_read32(component, WM8996_AIF_CLOCKING_1) & WM8996_SYSCLK_ENA; + old = snd_soc_component_read(component, WM8996_AIF_CLOCKING_1) & WM8996_SYSCLK_ENA; snd_soc_component_update_bits(component, WM8996_AIF_CLOCKING_1, WM8996_SYSCLK_ENA, 0); @@ -1854,7 +1854,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, case 24576000: ratediv = WM8996_SYSCLK_DIV; wm8996->sysclk /= 2; - /* fall through */ + fallthrough; case 11289600: case 12288000: snd_soc_component_update_bits(component, WM8996_AIF_RATE, @@ -2078,7 +2078,7 @@ static int wm8996_set_fll(struct snd_soc_component *component, int fll_id, int s snd_soc_component_write(component, WM8996_FLL_EFS_1, fll_div.lambda); /* Enable the bandgap if it's not already enabled */ - ret = snd_soc_component_read32(component, WM8996_FLL_CONTROL_1); + ret = snd_soc_component_read(component, WM8996_FLL_CONTROL_1); if (!(ret & WM8996_FLL_ENA)) wm8996_bg_enable(component); @@ -2117,7 +2117,7 @@ static int wm8996_set_fll(struct snd_soc_component *component, int fll_id, int s break; } - ret = snd_soc_component_read32(component, WM8996_INTERRUPT_RAW_STATUS_2); + ret = snd_soc_component_read(component, WM8996_INTERRUPT_RAW_STATUS_2); if (ret & WM8996_FLL_LOCK_STS) break; } @@ -2224,6 +2224,9 @@ static void wm8996_free_gpio(struct wm8996_priv *wm8996) /** * wm8996_detect - Enable default WM8996 jack detection + * @component: ASoC component + * @jack: jack pointer + * @polarity_cb: polarity callback * * The WM8996 has advanced accessory detection support for headsets. * This function provides a default implementation which integrates @@ -2291,7 +2294,7 @@ static void wm8996_hpdet_irq(struct snd_soc_component *component) */ report = SND_JACK_HEADPHONE; - reg = snd_soc_component_read32(component, WM8996_HEADPHONE_DETECT_2); + reg = snd_soc_component_read(component, WM8996_HEADPHONE_DETECT_2); if (reg < 0) { dev_err(component->dev, "Failed to read HPDET status\n"); goto out; @@ -2324,7 +2327,7 @@ out: wm8996->detecting = false; /* If the output isn't running re-clamp it */ - if (!(snd_soc_component_read32(component, WM8996_POWER_MANAGEMENT_1) & + if (!(snd_soc_component_read(component, WM8996_POWER_MANAGEMENT_1) & (WM8996_HPOUT1L_ENA | WM8996_HPOUT1R_RMV_SHORT))) snd_soc_component_update_bits(component, WM8996_ANALOGUE_HP_1, WM8996_HPOUT1L_RMV_SHORT | @@ -2383,7 +2386,7 @@ static void wm8996_micd(struct snd_soc_component *component) struct wm8996_priv *wm8996 = snd_soc_component_get_drvdata(component); int val, reg; - val = snd_soc_component_read32(component, WM8996_MIC_DETECT_3); + val = snd_soc_component_read(component, WM8996_MIC_DETECT_3); dev_dbg(component->dev, "Microphone event: %x\n", val); @@ -2449,7 +2452,7 @@ static void wm8996_micd(struct snd_soc_component *component) return; } - reg = snd_soc_component_read32(component, WM8996_ACCESSORY_DETECT_MODE_2); + reg = snd_soc_component_read(component, WM8996_ACCESSORY_DETECT_MODE_2); reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC | WM8996_MICD_BIAS_SRC; snd_soc_component_update_bits(component, WM8996_ACCESSORY_DETECT_MODE_2, @@ -2486,13 +2489,13 @@ static irqreturn_t wm8996_irq(int irq, void *data) struct wm8996_priv *wm8996 = snd_soc_component_get_drvdata(component); int irq_val; - irq_val = snd_soc_component_read32(component, WM8996_INTERRUPT_STATUS_2); + irq_val = snd_soc_component_read(component, WM8996_INTERRUPT_STATUS_2); if (irq_val < 0) { dev_err(component->dev, "Failed to read IRQ status: %d\n", irq_val); return IRQ_NONE; } - irq_val &= ~snd_soc_component_read32(component, WM8996_INTERRUPT_STATUS_2_MASK); + irq_val &= ~snd_soc_component_read(component, WM8996_INTERRUPT_STATUS_2_MASK); if (!irq_val) return IRQ_NONE; diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 7c1899219573333f385e7be97cfc8595569c066d..f6c5cc80c970b6507e806665b110b2c0bf04e72c 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -43,7 +43,7 @@ static int wm8998_asrc_ev(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - val = snd_soc_component_read32(component, ARIZONA_ASRC_RATE1); + val = snd_soc_component_read(component, ARIZONA_ASRC_RATE1); val &= ARIZONA_ASRC_RATE1_MASK; val >>= ARIZONA_ASRC_RATE1_SHIFT; @@ -51,7 +51,7 @@ static int wm8998_asrc_ev(struct snd_soc_dapm_widget *w, case 0: case 1: case 2: - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, ARIZONA_SAMPLE_RATE_1 + val); if (val >= 0x11) { dev_warn(component->dev, @@ -67,7 +67,7 @@ static int wm8998_asrc_ev(struct snd_soc_dapm_widget *w, return -EINVAL; } - val = snd_soc_component_read32(component, ARIZONA_ASRC_RATE2); + val = snd_soc_component_read(component, ARIZONA_ASRC_RATE2); val &= ARIZONA_ASRC_RATE2_MASK; val >>= ARIZONA_ASRC_RATE2_SHIFT; @@ -75,7 +75,7 @@ static int wm8998_asrc_ev(struct snd_soc_dapm_widget *w, case 8: case 9: val -= 0x8; - val = snd_soc_component_read32(component, + val = snd_soc_component_read(component, ARIZONA_ASYNC_SAMPLE_RATE_1 + val); if (val >= 0x11) { dev_warn(component->dev, diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index c42ea626a240f4a4bc79609bf532e74a158fe0c7..4a667ee82fe20effcef50294560ddb4b52e1074d 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -338,7 +338,7 @@ static int speaker_mode_get(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); unsigned int reg; - reg = snd_soc_component_read32(component, WM9081_ANALOGUE_SPEAKER_2); + reg = snd_soc_component_read(component, WM9081_ANALOGUE_SPEAKER_2); if (reg & WM9081_SPK_MODE) ucontrol->value.enumerated.item[0] = 1; else @@ -357,8 +357,8 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); - unsigned int reg_pwr = snd_soc_component_read32(component, WM9081_POWER_MANAGEMENT); - unsigned int reg2 = snd_soc_component_read32(component, WM9081_ANALOGUE_SPEAKER_2); + unsigned int reg_pwr = snd_soc_component_read(component, WM9081_POWER_MANAGEMENT); + unsigned int reg2 = snd_soc_component_read(component, WM9081_ANALOGUE_SPEAKER_2); /* Are we changing anything? */ if (ucontrol->value.enumerated.item[0] == @@ -568,7 +568,7 @@ static int wm9081_set_fll(struct snd_soc_component *component, int fll_id, if (ret != 0) return ret; - reg5 = snd_soc_component_read32(component, WM9081_FLL_CONTROL_5); + reg5 = snd_soc_component_read(component, WM9081_FLL_CONTROL_5); reg5 &= ~WM9081_FLL_CLK_SRC_MASK; switch (fll_id) { @@ -582,14 +582,14 @@ static int wm9081_set_fll(struct snd_soc_component *component, int fll_id, } /* Disable CLK_SYS while we reconfigure */ - clk_sys_reg = snd_soc_component_read32(component, WM9081_CLOCK_CONTROL_3); + clk_sys_reg = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_3); if (clk_sys_reg & WM9081_CLK_SYS_ENA) snd_soc_component_write(component, WM9081_CLOCK_CONTROL_3, clk_sys_reg & ~WM9081_CLK_SYS_ENA); /* Any FLL configuration change requires that the FLL be * disabled first. */ - reg1 = snd_soc_component_read32(component, WM9081_FLL_CONTROL_1); + reg1 = snd_soc_component_read(component, WM9081_FLL_CONTROL_1); reg1 &= ~WM9081_FLL_ENA; snd_soc_component_write(component, WM9081_FLL_CONTROL_1, reg1); @@ -605,7 +605,7 @@ static int wm9081_set_fll(struct snd_soc_component *component, int fll_id, (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT)); snd_soc_component_write(component, WM9081_FLL_CONTROL_3, fll_div.k); - reg4 = snd_soc_component_read32(component, WM9081_FLL_CONTROL_4); + reg4 = snd_soc_component_read(component, WM9081_FLL_CONTROL_4); reg4 &= ~WM9081_FLL_N_MASK; reg4 |= fll_div.n << WM9081_FLL_N_SHIFT; snd_soc_component_write(component, WM9081_FLL_CONTROL_4, reg4); @@ -707,14 +707,14 @@ static int configure_clock(struct snd_soc_component *component) return -EINVAL; } - reg = snd_soc_component_read32(component, WM9081_CLOCK_CONTROL_1); + reg = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_1); if (mclkdiv) reg |= WM9081_MCLKDIV2; else reg &= ~WM9081_MCLKDIV2; snd_soc_component_write(component, WM9081_CLOCK_CONTROL_1, reg); - reg = snd_soc_component_read32(component, WM9081_CLOCK_CONTROL_3); + reg = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_3); if (fll) reg |= WM9081_CLK_SRC_SEL; else @@ -901,7 +901,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai, { struct snd_soc_component *component = dai->component; struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component); - unsigned int aif2 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_2); + unsigned int aif2 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_2); aif2 &= ~(WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV | WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK); @@ -929,7 +929,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: aif2 |= WM9081_AIF_LRCLK_INV; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: aif2 |= 0x3; break; @@ -997,18 +997,18 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, int ret, i, best, best_val, cur_val; unsigned int clk_ctrl2, aif1, aif2, aif3, aif4; - clk_ctrl2 = snd_soc_component_read32(component, WM9081_CLOCK_CONTROL_2); + clk_ctrl2 = snd_soc_component_read(component, WM9081_CLOCK_CONTROL_2); clk_ctrl2 &= ~(WM9081_CLK_SYS_RATE_MASK | WM9081_SAMPLE_RATE_MASK); - aif1 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_1); + aif1 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_1); - aif2 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_2); + aif2 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_2); aif2 &= ~WM9081_AIF_WL_MASK; - aif3 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_3); + aif3 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_3); aif3 &= ~WM9081_BCLK_DIV_MASK; - aif4 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_4); + aif4 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_4); aif4 &= ~WM9081_LRCLK_RATE_MASK; wm9081->fs = params_rate(params); @@ -1127,7 +1127,7 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, s->name, s->rate); /* If the EQ is enabled then disable it while we write out */ - eq1 = snd_soc_component_read32(component, WM9081_EQ_1) & WM9081_EQ_ENA; + eq1 = snd_soc_component_read(component, WM9081_EQ_1) & WM9081_EQ_ENA; if (eq1 & WM9081_EQ_ENA) snd_soc_component_write(component, WM9081_EQ_1, 0); @@ -1147,12 +1147,12 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute) +static int wm9081_mute(struct snd_soc_dai *codec_dai, int mute, int direction) { struct snd_soc_component *component = codec_dai->component; unsigned int reg; - reg = snd_soc_component_read32(component, WM9081_DAC_DIGITAL_2); + reg = snd_soc_component_read(component, WM9081_DAC_DIGITAL_2); if (mute) reg |= WM9081_DAC_MUTE; @@ -1188,7 +1188,7 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, { struct snd_soc_component *component = dai->component; struct wm9081_priv *wm9081 = snd_soc_component_get_drvdata(component); - unsigned int aif1 = snd_soc_component_read32(component, WM9081_AUDIO_INTERFACE_1); + unsigned int aif1 = snd_soc_component_read(component, WM9081_AUDIO_INTERFACE_1); aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK); @@ -1232,8 +1232,9 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, static const struct snd_soc_dai_ops wm9081_dai_ops = { .hw_params = wm9081_hw_params, .set_fmt = wm9081_set_dai_fmt, - .digital_mute = wm9081_digital_mute, + .mute_stream = wm9081_mute, .set_tdm_slot = wm9081_set_tdm_slot, + .no_capture_mute = 1, }; /* We report two channels because the CODEC processes a stereo signal, even diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 6c001d118599c97775d528a89e245e64d68b6f6c..e0231a54609c9e964a45ab9622d2c9c98205feca 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -139,7 +139,7 @@ static void wait_for_dc_servo(struct snd_soc_component *component) do { count++; msleep(1); - reg = snd_soc_component_read32(component, WM9090_DC_SERVO_READBACK_0); + reg = snd_soc_component_read(component, WM9090_DC_SERVO_READBACK_0); dev_dbg(component->dev, "DC servo status: %x\n", reg); } while ((reg & WM9090_DCS_CAL_COMPLETE_MASK) != WM9090_DCS_CAL_COMPLETE_MASK && count < 1000); @@ -239,7 +239,7 @@ static int hp_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - unsigned int reg = snd_soc_component_read32(component, WM9090_ANALOGUE_HP_0); + unsigned int reg = snd_soc_component_read(component, WM9090_ANALOGUE_HP_0); switch (event) { case SND_SOC_DAPM_POST_PMU: diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 6497c1ea6228e42651463395f7ae61cbf9df176c..7072ffacbdfd49fc461d9d8ef75fa2481ea66594 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -807,7 +807,7 @@ static void pll_factors(struct snd_soc_component *component, pll_div->k = K; } -/** +/* * Please note that changing the PLL input frequency may require * resynchronisation with the AC97 controller. */ @@ -939,7 +939,7 @@ static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; - u16 gpio = snd_soc_component_read32(component, AC97_GPIO_CFG) & 0xffc5; + u16 gpio = snd_soc_component_read(component, AC97_GPIO_CFG) & 0xffc5; u16 reg = 0x8000; /* clock masters */ diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 519ca2e6963726a3f681ba4f87c3ca4665dc3090..410cca57da52ddbbd766d693ff0c6ec4f6143d5f 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -355,9 +355,11 @@ static void wm_adsp_buf_free(struct list_head *list) #define WM_ADSP_FW_ASR 7 #define WM_ADSP_FW_TRACE 8 #define WM_ADSP_FW_SPK_PROT 9 -#define WM_ADSP_FW_MISC 10 +#define WM_ADSP_FW_SPK_CALI 10 +#define WM_ADSP_FW_SPK_DIAG 11 +#define WM_ADSP_FW_MISC 12 -#define WM_ADSP_NUM_FW 11 +#define WM_ADSP_NUM_FW 13 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { [WM_ADSP_FW_MBC_VSS] = "MBC/VSS", @@ -370,6 +372,8 @@ static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { [WM_ADSP_FW_ASR] = "ASR Assist", [WM_ADSP_FW_TRACE] = "Dbg Trace", [WM_ADSP_FW_SPK_PROT] = "Protection", + [WM_ADSP_FW_SPK_CALI] = "Calibration", + [WM_ADSP_FW_SPK_DIAG] = "Diagnostic", [WM_ADSP_FW_MISC] = "Misc", }; @@ -586,6 +590,8 @@ static const struct { .caps = trace_caps, }, [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" }, + [WM_ADSP_FW_SPK_CALI] = { .file = "spk-cali" }, + [WM_ADSP_FW_SPK_DIAG] = { .file = "spk-diag" }, [WM_ADSP_FW_MISC] = { .file = "misc" }, }; @@ -2615,6 +2621,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) switch (type) { case (WMFW_NAME_TEXT << 8): case (WMFW_INFO_TEXT << 8): + case (WMFW_METADATA << 8): break; case (WMFW_ABSOLUTE << 8): /* diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index e93af7edd8f75028ba737d3ee7b576f1e1a7d53e..891effe220fec71e803dc0e6eb79d756f9aa5acc 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -85,7 +85,7 @@ static void wait_for_dc_servo(struct snd_soc_component *component, unsigned int else msleep(1); - reg = snd_soc_component_read32(component, WM8993_DC_SERVO_0); + reg = snd_soc_component_read(component, WM8993_DC_SERVO_0); dev_dbg(component->dev, "DC servo: %x\n", reg); } while (reg & op && count < timeout); @@ -109,7 +109,7 @@ static bool wm_hubs_dac_hp_direct(struct snd_soc_component *component) int reg; /* If we're going via the mixer we'll need to do additional checks */ - reg = snd_soc_component_read32(component, WM8993_OUTPUT_MIXER1); + reg = snd_soc_component_read(component, WM8993_OUTPUT_MIXER1); if (!(reg & WM8993_DACL_TO_HPOUT1L)) { if (reg & ~WM8993_DACL_TO_MIXOUTL) { dev_vdbg(component->dev, "Analogue paths connected: %x\n", @@ -122,7 +122,7 @@ static bool wm_hubs_dac_hp_direct(struct snd_soc_component *component) dev_vdbg(component->dev, "HPL connected to DAC\n"); } - reg = snd_soc_component_read32(component, WM8993_OUTPUT_MIXER2); + reg = snd_soc_component_read(component, WM8993_OUTPUT_MIXER2); if (!(reg & WM8993_DACR_TO_HPOUT1R)) { if (reg & ~WM8993_DACR_TO_MIXOUTR) { dev_vdbg(component->dev, "Analogue paths connected: %x\n", @@ -152,10 +152,10 @@ static bool wm_hubs_dcs_cache_get(struct snd_soc_component *component, struct wm_hubs_dcs_cache *cache; unsigned int left, right; - left = snd_soc_component_read32(component, WM8993_LEFT_OUTPUT_VOLUME); + left = snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME); left &= WM8993_HPOUT1L_VOL_MASK; - right = snd_soc_component_read32(component, WM8993_RIGHT_OUTPUT_VOLUME); + right = snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME); right &= WM8993_HPOUT1R_VOL_MASK; list_for_each_entry(cache, &hubs->dcs_cache, list) { @@ -181,10 +181,10 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_component *component, u16 dcs_c if (!cache) return; - cache->left = snd_soc_component_read32(component, WM8993_LEFT_OUTPUT_VOLUME); + cache->left = snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME); cache->left &= WM8993_HPOUT1L_VOL_MASK; - cache->right = snd_soc_component_read32(component, WM8993_RIGHT_OUTPUT_VOLUME); + cache->right = snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME); cache->right &= WM8993_HPOUT1R_VOL_MASK; cache->dcs_cfg = dcs_cfg; @@ -216,14 +216,14 @@ static int wm_hubs_read_dc_servo(struct snd_soc_component *component, */ switch (hubs->dcs_readback_mode) { case 0: - *reg_l = snd_soc_component_read32(component, WM8993_DC_SERVO_READBACK_1) + *reg_l = snd_soc_component_read(component, WM8993_DC_SERVO_READBACK_1) & WM8993_DCS_INTEG_CHAN_0_MASK; - *reg_r = snd_soc_component_read32(component, WM8993_DC_SERVO_READBACK_2) + *reg_r = snd_soc_component_read(component, WM8993_DC_SERVO_READBACK_2) & WM8993_DCS_INTEG_CHAN_1_MASK; break; case 2: case 1: - reg = snd_soc_component_read32(component, dcs_reg); + reg = snd_soc_component_read(component, dcs_reg); *reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; *reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; @@ -342,7 +342,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, return ret; /* Only need to do this if the outputs are active */ - if (snd_soc_component_read32(component, WM8993_POWER_MANAGEMENT_1) + if (snd_soc_component_read(component, WM8993_POWER_MANAGEMENT_1) & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) snd_soc_component_update_bits(component, WM8993_DC_SERVO_0, @@ -538,7 +538,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - unsigned int reg = snd_soc_component_read32(component, WM8993_ANALOGUE_HP_0); + unsigned int reg = snd_soc_component_read(component, WM8993_ANALOGUE_HP_0); switch (event) { case SND_SOC_DAPM_POST_PMU: @@ -590,7 +590,7 @@ static int earpiece_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *control, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - u16 reg = snd_soc_component_read32(component, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA; + u16 reg = snd_soc_component_read(component, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA; switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -680,9 +680,9 @@ void wm_hubs_update_class_w(struct snd_soc_component *component) WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable); snd_soc_component_write(component, WM8993_LEFT_OUTPUT_VOLUME, - snd_soc_component_read32(component, WM8993_LEFT_OUTPUT_VOLUME)); + snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME)); snd_soc_component_write(component, WM8993_RIGHT_OUTPUT_VOLUME, - snd_soc_component_read32(component, WM8993_RIGHT_OUTPUT_VOLUME)); + snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME)); } EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h index 4278aa6aeb01b2e50508706c9bbc55eafa9fb54e..7423272c30e94245d7058f766a436402e680eda8 100644 --- a/sound/soc/codecs/wmfw.h +++ b/sound/soc/codecs/wmfw.h @@ -180,6 +180,7 @@ struct wmfw_coeff_item { #define WMFW_ABSOLUTE 0xf0 #define WMFW_ALGORITHM_DATA 0xf2 +#define WMFW_METADATA 0xfc #define WMFW_NAME_TEXT 0xfe #define WMFW_INFO_TEXT 0xff diff --git a/sound/soc/dwc/dwc-pcm.c b/sound/soc/dwc/dwc-pcm.c index 9868e7373d369ad84c6c13b76297371c11ead96f..9f25631d43d3029bec4ef336f0bb089223049257 100644 --- a/sound/soc/dwc/dwc-pcm.c +++ b/sound/soc/dwc/dwc-pcm.c @@ -139,7 +139,7 @@ static int dw_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); snd_soc_set_runtime_hwparams(substream, &dw_pcm_hardware); diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index ea7b4787a8af98703319695b6afe7f2e5ce5f336..1c4ca5ec8cafb5f641536b845446050b3c4a93a0 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -315,6 +315,7 @@ config SND_SOC_FSL_ASOC_CARD depends on OF && I2C # enforce SND_SOC_FSL_ASOC_CARD=m if SND_AC97_CODEC=m: depends on SND_AC97_CODEC || SND_AC97_CODEC=n + select SND_SIMPLE_CARD_UTILS select SND_SOC_IMX_AUDMUX select SND_SOC_IMX_PCM_DMA select SND_SOC_FSL_ESAI diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 4ff2d21bb32fe2fad51211be436ea3002304e10b..e13271ea84ded1cf0706eda953b73c00dc111365 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -30,7 +30,7 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 00be73900888449a6c8139cbd762195507dee44e..de136c0a497dd8ba780213019860c31e019e6d6b 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -15,6 +15,8 @@ #endif #include #include +#include +#include #include "fsl_esai.h" #include "fsl_sai.h" @@ -33,8 +35,7 @@ #define DAI_FMT_BASE (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF) /** - * CODEC private data - * + * struct codec_priv - CODEC private data * @mclk_freq: Clock rate of MCLK * @mclk_id: MCLK (or main clock) id for set_sysclk() * @fll_id: FLL (or secordary clock) id for set_sysclk() @@ -48,11 +49,10 @@ struct codec_priv { }; /** - * CPU private data - * - * @sysclk_freq[2]: SYSCLK rates for set_sysclk() - * @sysclk_dir[2]: SYSCLK directions for set_sysclk() - * @sysclk_id[2]: SYSCLK ids for set_sysclk() + * struct cpu_priv - CPU private data + * @sysclk_freq: SYSCLK rates for set_sysclk() + * @sysclk_dir: SYSCLK directions for set_sysclk() + * @sysclk_id: SYSCLK ids for set_sysclk() * @slot_width: Slot width of each frame * * Note: [1] for tx and [0] for rx @@ -65,9 +65,10 @@ struct cpu_priv { }; /** - * Freescale Generic ASOC card private data - * - * @dai_link[3]: DAI link structure including normal one and DPCM link + * struct fsl_asoc_card_priv - Freescale Generic ASOC card private data + * @dai_link: DAI link structure including normal one and DPCM link + * @hp_jack: Headphone Jack structure + * @mic_jack: Microphone Jack structure * @pdev: platform device pointer * @codec_priv: CODEC private data * @cpu_priv: CPU private data @@ -82,6 +83,8 @@ struct cpu_priv { struct fsl_asoc_card_priv { struct snd_soc_dai_link dai_link[3]; + struct asoc_simple_jack hp_jack; + struct asoc_simple_jack mic_jack; struct platform_device *pdev; struct codec_priv codec_priv; struct cpu_priv cpu_priv; @@ -94,8 +97,8 @@ struct fsl_asoc_card_priv { char name[32]; }; -/** - * This dapm route map exsits for DPCM link only. +/* + * This dapm route map exists for DPCM link only. * The other routes shall go through Device Tree. * * Note: keep all ASRC routes in the second half @@ -119,6 +122,13 @@ static const struct snd_soc_dapm_route audio_map_ac97[] = { {"ASRC-Capture", NULL, "AC97 Capture"}, }; +static const struct snd_soc_dapm_route audio_map_tx[] = { + /* 1st half -- Normal DAPM routes */ + {"Playback", NULL, "CPU-Playback"}, + /* 2nd half -- ASRC DAPM routes */ + {"CPU-Playback", NULL, "ASRC-Playback"}, +}; + /* Add all possible widgets into here without being redundant */ static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = { SND_SOC_DAPM_LINE("Line Out Jack", NULL), @@ -138,7 +148,7 @@ static bool fsl_asoc_card_is_ac97(struct fsl_asoc_card_priv *priv) static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; struct cpu_priv *cpu_priv = &priv->cpu_priv; @@ -441,6 +451,44 @@ static int fsl_asoc_card_audmux_init(struct device_node *np, return 0; } +static int hp_jack_event(struct notifier_block *nb, unsigned long event, + void *data) +{ + struct snd_soc_jack *jack = (struct snd_soc_jack *)data; + struct snd_soc_dapm_context *dapm = &jack->card->dapm; + + if (event & SND_JACK_HEADPHONE) + /* Disable speaker if headphone is plugged in */ + snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + else + snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + + return 0; +} + +static struct notifier_block hp_jack_nb = { + .notifier_call = hp_jack_event, +}; + +static int mic_jack_event(struct notifier_block *nb, unsigned long event, + void *data) +{ + struct snd_soc_jack *jack = (struct snd_soc_jack *)data; + struct snd_soc_dapm_context *dapm = &jack->card->dapm; + + if (event & SND_JACK_MICROPHONE) + /* Disable dmic if microphone is plugged in */ + snd_soc_dapm_disable_pin(dapm, "DMIC"); + else + snd_soc_dapm_enable_pin(dapm, "DMIC"); + + return 0; +} + +static struct notifier_block mic_jack_nb = { + .notifier_call = mic_jack_event, +}; + static int fsl_asoc_card_late_probe(struct snd_soc_card *card) { struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card); @@ -483,10 +531,14 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) struct device_node *cpu_np, *codec_np, *asrc_np; struct device_node *np = pdev->dev.of_node; struct platform_device *asrc_pdev = NULL; + struct device_node *bitclkmaster = NULL; + struct device_node *framemaster = NULL; struct platform_device *cpu_pdev; struct fsl_asoc_card_priv *priv; - struct i2c_client *codec_dev; + struct device *codec_dev = NULL; const char *codec_dai_name; + const char *codec_dev_name; + unsigned int daifmt; u32 width; int ret; @@ -512,10 +564,23 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) } codec_np = of_parse_phandle(np, "audio-codec", 0); - if (codec_np) - codec_dev = of_find_i2c_device_by_node(codec_np); - else - codec_dev = NULL; + if (codec_np) { + struct platform_device *codec_pdev; + struct i2c_client *codec_i2c; + + codec_i2c = of_find_i2c_device_by_node(codec_np); + if (codec_i2c) { + codec_dev = &codec_i2c->dev; + codec_dev_name = codec_i2c->name; + } + if (!codec_dev) { + codec_pdev = of_find_device_by_node(codec_np); + if (codec_pdev) { + codec_dev = &codec_pdev->dev; + codec_dev_name = codec_pdev->name; + } + } + } asrc_np = of_parse_phandle(np, "audio-asrc", 0); if (asrc_np) @@ -523,7 +588,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) /* Get the MCLK rate only, and leave it controlled by CODEC drivers */ if (codec_dev) { - struct clk *codec_clk = clk_get(&codec_dev->dev, NULL); + struct clk *codec_clk = clk_get(codec_dev, NULL); if (!IS_ERR(codec_clk)) { priv->codec_priv.mclk_freq = clk_get_rate(codec_clk); @@ -538,6 +603,11 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) /* Assign a default DAI format, and allow each card to overwrite it */ priv->dai_fmt = DAI_FMT_BASE; + memcpy(priv->dai_link, fsl_asoc_card_dai, + sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link)); + + priv->card.dapm_routes = audio_map; + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); /* Diversify the card configurations */ if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { codec_dai_name = "cs42888"; @@ -573,12 +643,58 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) codec_dai_name = "ac97-hifi"; priv->card.set_bias_level = NULL; priv->dai_fmt = SND_SOC_DAIFMT_AC97; + priv->card.dapm_routes = audio_map_ac97; + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_ac97); + } else if (of_device_is_compatible(np, "fsl,imx-audio-mqs")) { + codec_dai_name = "fsl-mqs-dai"; + priv->card.set_bias_level = NULL; + priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J | + SND_SOC_DAIFMT_CBS_CFS | + SND_SOC_DAIFMT_NB_NF; + priv->dai_link[1].dpcm_capture = 0; + priv->dai_link[2].dpcm_capture = 0; + priv->card.dapm_routes = audio_map_tx; + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx); + } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8524")) { + codec_dai_name = "wm8524-hifi"; + priv->card.set_bias_level = NULL; + priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; + priv->dai_link[1].dpcm_capture = 0; + priv->dai_link[2].dpcm_capture = 0; + priv->cpu_priv.slot_width = 32; + priv->card.dapm_routes = audio_map_tx; + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx); } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL; goto asrc_fail; } + /* Format info from DT is optional. */ + daifmt = snd_soc_of_parse_daifmt(np, NULL, + &bitclkmaster, &framemaster); + daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; + if (bitclkmaster || framemaster) { + if (codec_np == bitclkmaster) + daifmt |= (codec_np == framemaster) ? + SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS; + else + daifmt |= (codec_np == framemaster) ? + SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS; + + /* Override dai_fmt with value from DT */ + priv->dai_fmt = daifmt; + } + + /* Change direction according to format */ + if (priv->dai_fmt & SND_SOC_DAIFMT_CBM_CFM) { + priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_IN; + priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_IN; + } + + of_node_put(bitclkmaster); + of_node_put(framemaster); + if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) { dev_err(&pdev->dev, "failed to find codec device\n"); ret = -EPROBE_DEFER; @@ -601,19 +717,17 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->cpu_priv.sysclk_id[0] = FSL_SAI_CLK_MAST1; } - snprintf(priv->name, sizeof(priv->name), "%s-audio", - fsl_asoc_card_is_ac97(priv) ? "ac97" : - codec_dev->name); - /* Initialize sound card */ priv->pdev = pdev; priv->card.dev = &pdev->dev; - priv->card.name = priv->name; + ret = snd_soc_of_parse_card_name(&priv->card, "model"); + if (ret) { + snprintf(priv->name, sizeof(priv->name), "%s-audio", + fsl_asoc_card_is_ac97(priv) ? "ac97" : codec_dev_name); + priv->card.name = priv->name; + } priv->card.dai_link = priv->dai_link; - priv->card.dapm_routes = fsl_asoc_card_is_ac97(priv) ? - audio_map_ac97 : audio_map; priv->card.late_probe = fsl_asoc_card_late_probe; - priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); priv->card.dapm_widgets = fsl_asoc_card_dapm_widgets; priv->card.num_dapm_widgets = ARRAY_SIZE(fsl_asoc_card_dapm_widgets); @@ -621,13 +735,12 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) if (!asrc_pdev) priv->card.num_dapm_routes /= 2; - memcpy(priv->dai_link, fsl_asoc_card_dai, - sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link)); - - ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing"); - if (ret) { - dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret); - goto asrc_fail; + if (of_property_read_bool(np, "audio-routing")) { + ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing"); + if (ret) { + dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret); + goto asrc_fail; + } } /* Normal DAI Link */ @@ -704,8 +817,37 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(&priv->card, priv); ret = devm_snd_soc_register_card(&pdev->dev, &priv->card); - if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + goto asrc_fail; + } + + /* + * Properties "hp-det-gpio" and "mic-det-gpio" are optional, and + * asoc_simple_init_jack uses these properties for creating + * Headphone Jack and Microphone Jack. + * + * The notifier is initialized in snd_soc_card_jack_new(), then + * snd_soc_jack_notifier_register can be called. + */ + if (of_property_read_bool(np, "hp-det-gpio")) { + ret = asoc_simple_init_jack(&priv->card, &priv->hp_jack, + 1, NULL, "Headphone Jack"); + if (ret) + goto asrc_fail; + + snd_soc_jack_notifier_register(&priv->hp_jack.jack, &hp_jack_nb); + } + + if (of_property_read_bool(np, "mic-det-gpio")) { + ret = asoc_simple_init_jack(&priv->card, &priv->mic_jack, + 0, NULL, "Mic Jack"); + if (ret) + goto asrc_fail; + + snd_soc_jack_notifier_register(&priv->mic_jack.jack, &mic_jack_nb); + } asrc_fail: of_node_put(asrc_np); @@ -724,6 +866,8 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = { { .compatible = "fsl,imx-audio-sgtl5000", }, { .compatible = "fsl,imx-audio-wm8962", }, { .compatible = "fsl,imx-audio-wm8960", }, + { .compatible = "fsl,imx-audio-mqs", }, + { .compatible = "fsl,imx-audio-wm8524", }, {} }; MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids); diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 95f6a9617b0b8a1e54ebb0864ad3812aad894f6f..02c81d2e34ad00f5437a46d5f264679552507a24 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -37,7 +37,7 @@ static struct snd_pcm_hw_constraint_list fsl_asrc_rate_constraints = { .list = supported_asrc_rate, }; -/** +/* * The following tables map the relationship between asrc_inclk/asrc_outclk in * fsl_asrc.h and the registers of ASRCSR */ @@ -68,7 +68,7 @@ static unsigned char output_clk_map_imx53[ASRC_CLK_MAP_LEN] = { 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, }; -/** +/* * i.MX8QM/i.MX8QXP uses the same map for input and output. * clk_map_imx8qm[0] is for i.MX8QM asrc0 * clk_map_imx8qm[1] is for i.MX8QM asrc1 @@ -102,16 +102,17 @@ static unsigned char clk_map_imx8qxp[2][ASRC_CLK_MAP_LEN] = { }; /** - * Select the pre-processing and post-processing options + * fsl_asrc_sel_proc - Select the pre-processing and post-processing options + * @inrate: input sample rate + * @outrate: output sample rate + * @pre_proc: return value for pre-processing option + * @post_proc: return value for post-processing option + * * Make sure to exclude following unsupported cases before * calling this function: * 1) inrate > 8.125 * outrate * 2) inrate > 16.125 * outrate * - * inrate: input sample rate - * outrate: output sample rate - * pre_proc: return value for pre-processing option - * post_proc: return value for post-processing option */ static void fsl_asrc_sel_proc(int inrate, int outrate, int *pre_proc, int *post_proc) @@ -148,7 +149,9 @@ static void fsl_asrc_sel_proc(int inrate, int outrate, } /** - * Request ASRC pair + * fsl_asrc_request_pair - Request ASRC pair + * @channels: number of channels + * @pair: pointer to pair * * It assigns pair by the order of A->C->B because allocation of pair B, * within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A @@ -193,7 +196,8 @@ static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair) } /** - * Release ASRC pair + * fsl_asrc_release_pair - Release ASRC pair + * @pair: pair to release * * It clears the resource from asrc and releases the occupied channels. */ @@ -217,7 +221,10 @@ static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair) } /** - * Configure input and output thresholds + * fsl_asrc_set_watermarks- configure input and output thresholds + * @pair: pointer to pair + * @in: input threshold + * @out: output threshold */ static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out) { @@ -234,7 +241,9 @@ static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out) } /** - * Calculate the total divisor between asrck clock rate and sample rate + * fsl_asrc_cal_asrck_divisor - Calculate the total divisor between asrck clock rate and sample rate + * @pair: pointer to pair + * @div: divider * * It follows the formula clk_rate = samplerate * (2 ^ prescaler) * divider */ @@ -250,7 +259,10 @@ static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair *pair, u32 div) } /** - * Calculate and set the ratio for Ideal Ratio mode only + * fsl_asrc_set_ideal_ratio - Calculate and set the ratio for Ideal Ratio mode only + * @pair: pointer to pair + * @inrate: input rate + * @outrate: output rate * * The ratio is a 32-bit fixed point value with 26 fractional bits. */ @@ -293,7 +305,9 @@ static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair, } /** - * Configure the assigned ASRC pair + * fsl_asrc_config_pair - Configure the assigned ASRC pair + * @pair: pointer to pair + * @use_ideal_rate: boolean configuration * * It configures those ASRC registers according to a configuration instance * of struct asrc_config which includes in/output sample rate, width, channel @@ -508,7 +522,8 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) } /** - * Start the assigned ASRC pair + * fsl_asrc_start_pair - Start the assigned ASRC pair + * @pair: pointer to pair * * It enables the assigned pair and makes it stopped at the stall level. */ @@ -539,7 +554,8 @@ static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair) } /** - * Stop the assigned ASRC pair + * fsl_asrc_stop_pair - Stop the assigned ASRC pair + * @pair: pointer to pair */ static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair) { @@ -552,7 +568,9 @@ static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair) } /** - * Get DMA channel according to the pair and direction. + * fsl_asrc_get_dma_channel- Get DMA channel according to the pair and direction. + * @pair: pointer to pair + * @dir: DMA direction */ static struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir) @@ -582,11 +600,51 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream, SNDRV_PCM_HW_PARAM_RATE, &fsl_asrc_rate_constraints); } +/* Select proper clock source for internal ratio mode */ +static void fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv, + struct fsl_asrc_pair *pair, + int in_rate, + int out_rate) +{ + struct fsl_asrc_pair_priv *pair_priv = pair->private; + struct asrc_config *config = pair_priv->config; + int rate[2], select_clk[2]; /* Array size 2 means IN and OUT */ + int clk_rate, clk_index; + int i = 0, j = 0; + + rate[IN] = in_rate; + rate[OUT] = out_rate; + + /* Select proper clock source for internal ratio mode */ + for (j = 0; j < 2; j++) { + for (i = 0; i < ASRC_CLK_MAP_LEN; i++) { + clk_index = asrc_priv->clk_map[j][i]; + clk_rate = clk_get_rate(asrc_priv->asrck_clk[clk_index]); + /* Only match a perfect clock source with no remainder */ + if (clk_rate != 0 && (clk_rate / rate[j]) <= 1024 && + (clk_rate % rate[j]) == 0) + break; + } + + select_clk[j] = i; + } + + /* Switch to ideal ratio mode if there is no proper clock source */ + if (select_clk[IN] == ASRC_CLK_MAP_LEN || select_clk[OUT] == ASRC_CLK_MAP_LEN) { + select_clk[IN] = INCLK_NONE; + select_clk[OUT] = OUTCLK_ASRCK1_CLK; + } + + config->inclk = select_clk[IN]; + config->outclk = select_clk[OUT]; +} + static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai); + struct fsl_asrc_priv *asrc_priv = asrc->private; struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_asrc_pair *pair = runtime->private_data; struct fsl_asrc_pair_priv *pair_priv = pair->private; @@ -605,8 +663,6 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, config.pair = pair->index; config.channel_num = channels; - config.inclk = INCLK_NONE; - config.outclk = OUTCLK_ASRCK1_CLK; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { config.input_format = params_format(params); @@ -620,6 +676,10 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, config.output_sample_rate = rate; } + fsl_asrc_select_clk(asrc_priv, pair, + config.input_sample_rate, + config.output_sample_rate); + ret = fsl_asrc_config_pair(pair, false); if (ret) { dev_err(dai->dev, "fail to config asrc pair\n"); @@ -854,7 +914,8 @@ static const struct regmap_config fsl_asrc_regmap_config = { }; /** - * Initialize ASRC registers with a default configurations + * fsl_asrc_init - Initialize ASRC registers with a default configuration + * @asrc: ASRC context */ static int fsl_asrc_init(struct fsl_asrc *asrc) { @@ -888,7 +949,9 @@ static int fsl_asrc_init(struct fsl_asrc *asrc) } /** - * Interrupt handler for ASRC + * fsl_asrc_isr- Interrupt handler for ASRC + * @irq: irq number + * @dev_id: ASRC context */ static irqreturn_t fsl_asrc_isr(int irq, void *dev_id) { diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index 5f01a58f422a8f2b4db39b1c786558bfa2a6c90d..29f91cdecbc33142ca1a0b7f8b1c132601c9a166 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -129,7 +129,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, struct snd_pcm_hw_params *params) { enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL; struct snd_dmaengine_dai_dma_data *dma_params_be = NULL; @@ -313,7 +313,7 @@ static int fsl_asrc_dma_startup(struct snd_soc_component *component, struct snd_pcm_substream *substream) { bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_dmaengine_dai_dma_data *dma_data; struct device *dev = component->dev; diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 8b9027f76d8a1a795c5f70a666ca59a284ca3e09..a447bafa00d2009512007553d8641768ba1220a1 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -116,13 +116,9 @@ static int fsl_audmix_put_mix_clk_src(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int *item = ucontrol->value.enumerated.item; unsigned int reg_val, val, mix_clk; - int ret; /* Get current state */ - ret = snd_soc_component_read(comp, FSL_AUDMIX_CTR, ®_val); - if (ret) - return ret; - + reg_val = snd_soc_component_read(comp, FSL_AUDMIX_CTR); mix_clk = ((reg_val & FSL_AUDMIX_CTR_MIXCLK_MASK) >> FSL_AUDMIX_CTR_MIXCLK_SHIFT); val = snd_soc_enum_item_to_val(e, item[0]); @@ -162,9 +158,7 @@ static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol, int ret; /* Get current state */ - ret = snd_soc_component_read(comp, FSL_AUDMIX_CTR, ®_val); - if (ret) - return ret; + reg_val = snd_soc_component_read(comp, FSL_AUDMIX_CTR); /* "From" state */ out_src = ((reg_val & FSL_AUDMIX_CTR_OUTSRC_MASK) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 13ae089c1911f2886edc186e4c77a40196d49252..be021250d6e9b0715ea882a4a8c5c55b1a0bc5e7 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -200,7 +200,7 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) { struct fsl_dma_private *dma_private = dev_id; struct snd_pcm_substream *substream = dma_private->substream; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct device *dev = rtd->dev; struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; irqreturn_t ret = IRQ_NONE; diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index c6b5eb2d2af7905e60de98e1a62501ad11080e1d..60951a8aabd309a36a0740caa0a19d023c3c27fe 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -79,11 +79,8 @@ static int fsl_easrc_get_reg(struct snd_kcontrol *kcontrol, struct soc_mreg_control *mc = (struct soc_mreg_control *)kcontrol->private_value; unsigned int regval; - int ret; - ret = snd_soc_component_read(component, mc->regbase, ®val); - if (ret < 0) - return ret; + regval = snd_soc_component_read(component, mc->regbase); ucontrol->value.integer.value[0] = regval; @@ -179,22 +176,21 @@ static int fsl_easrc_set_rs_ratio(struct fsl_asrc_pair *ctx) struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; unsigned int in_rate = ctx_priv->in_params.norm_rate; unsigned int out_rate = ctx_priv->out_params.norm_rate; - unsigned int int_bits; unsigned int frac_bits; u64 val; u32 *r; switch (easrc_priv->rs_num_taps) { case EASRC_RS_32_TAPS: - int_bits = 5; + /* integer bits = 5; */ frac_bits = 39; break; case EASRC_RS_64_TAPS: - int_bits = 6; + /* integer bits = 6; */ frac_bits = 38; break; case EASRC_RS_128_TAPS: - int_bits = 7; + /* integer bits = 7; */ frac_bits = 37; break; default: @@ -390,11 +386,11 @@ static int fsl_easrc_resampler_config(struct fsl_asrc *easrc) * For input int[16, 24, 32] -> output float32 * scale it by multiplying filter coefficients by 2^-15, 2^-23, 2^-31 * input: - * asrc: Structure pointer of fsl_asrc - * infilter : Pointer to non-scaled input filter - * shift: The multiply factor + * @easrc: Structure pointer of fsl_asrc + * @infilter : Pointer to non-scaled input filter + * @shift: The multiply factor * output: - * outfilter: scaled filter + * @outfilter: scaled filter */ static int fsl_easrc_normalize_filter(struct fsl_asrc *easrc, u64 *infilter, @@ -964,7 +960,7 @@ static int fsl_easrc_release_slot(struct fsl_asrc *easrc, unsigned int ctx_id) * * Configure the register relate with context. */ -int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id) +static int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id) { struct fsl_easrc_ctx_priv *ctx_priv; struct fsl_asrc_pair *ctx; @@ -1125,15 +1121,15 @@ static int fsl_easrc_process_format(struct fsl_asrc_pair *ctx, return 0; } -int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx, - snd_pcm_format_t *in_raw_format, - snd_pcm_format_t *out_raw_format) +static int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx, + snd_pcm_format_t *in_raw_format, + snd_pcm_format_t *out_raw_format) { struct fsl_asrc *easrc = ctx->asrc; struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; struct fsl_easrc_data_fmt *in_fmt = &ctx_priv->in_params.fmt; struct fsl_easrc_data_fmt *out_fmt = &ctx_priv->out_params.fmt; - int ret; + int ret = 0; /* Get the bitfield values for input data format */ if (in_raw_format && out_raw_format) { @@ -1198,10 +1194,9 @@ int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx, * to conform with this format. Interleaving parameters are accessed * through the ASRC_CTRL_IN_ACCESSa and ASRC_CTRL_OUT_ACCESSa registers */ -int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx) +static int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx) { struct fsl_easrc_ctx_priv *ctx_priv; - struct device *dev; struct fsl_asrc *easrc; if (!ctx) @@ -1209,7 +1204,6 @@ int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx) easrc = ctx->asrc; ctx_priv = ctx->private; - dev = &easrc->pdev->dev; /* input interleaving parameters */ regmap_update_bits(easrc->regmap, REG_EASRC_CIA(ctx->index), @@ -1242,7 +1236,7 @@ int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx) * Returns a negative number on error and >=0 as context id * on success */ -int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx) +static int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx) { enum asrc_pair_index index = ASRC_INVALID_PAIR; struct fsl_asrc *easrc = ctx->asrc; @@ -1287,17 +1281,15 @@ int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx) * * This funciton is mainly doing the revert thing in request context */ -void fsl_easrc_release_context(struct fsl_asrc_pair *ctx) +static void fsl_easrc_release_context(struct fsl_asrc_pair *ctx) { unsigned long lock_flags; struct fsl_asrc *easrc; - struct device *dev; if (!ctx) return; easrc = ctx->asrc; - dev = &easrc->pdev->dev; spin_lock_irqsave(&easrc->lock, lock_flags); @@ -1314,7 +1306,7 @@ void fsl_easrc_release_context(struct fsl_asrc_pair *ctx) * * Enable the DMA request and context */ -int fsl_easrc_start_context(struct fsl_asrc_pair *ctx) +static int fsl_easrc_start_context(struct fsl_asrc_pair *ctx) { struct fsl_asrc *easrc = ctx->asrc; @@ -1332,7 +1324,7 @@ int fsl_easrc_start_context(struct fsl_asrc_pair *ctx) * * Disable the DMA request and context */ -int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx) +static int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx) { struct fsl_asrc *easrc = ctx->asrc; int val, i; @@ -1379,8 +1371,8 @@ int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx) return 0; } -struct dma_chan *fsl_easrc_get_dma_channel(struct fsl_asrc_pair *ctx, - bool dir) +static struct dma_chan *fsl_easrc_get_dma_channel(struct fsl_asrc_pair *ctx, + bool dir) { struct fsl_asrc *easrc = ctx->asrc; enum asrc_pair_index index = ctx->index; @@ -1391,7 +1383,6 @@ struct dma_chan *fsl_easrc_get_dma_channel(struct fsl_asrc_pair *ctx, return dma_request_slave_channel(&easrc->pdev->dev, name); }; -EXPORT_SYMBOL_GPL(fsl_easrc_get_dma_channel); static const unsigned int easrc_rates[] = { 8000, 11025, 12000, 16000, diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index cbcb70d6f8c83b7e637b98ee2917f7f516b75ffb..4ae36099ae82f0d146c0cf927113703e4025c5bd 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -22,8 +22,7 @@ SNDRV_PCM_FMTBIT_S24_LE) /** - * fsl_esai_soc_data: soc specific data - * + * struct fsl_esai_soc_data - soc specific data * @imx: for imx platform * @reset_at_xrun: flags for enable reset operaton */ @@ -33,8 +32,7 @@ struct fsl_esai_soc_data { }; /** - * fsl_esai: ESAI private data - * + * struct fsl_esai - ESAI private data * @dma_params_rx: DMA parameters for receive channel * @dma_params_tx: DMA parameters for transmit channel * @pdev: platform device pointer @@ -49,6 +47,8 @@ struct fsl_esai_soc_data { * @fifo_depth: depth of tx/rx FIFO * @slot_width: width of each DAI slot * @slots: number of slots + * @tx_mask: slot mask for TX + * @rx_mask: slot mask for RX * @channels: channel num for tx or rx * @hck_rate: clock rate of desired HCKx clock * @sck_rate: clock rate of desired SCKx clock @@ -157,13 +157,15 @@ static irqreturn_t esai_isr(int irq, void *devid) } /** - * This function is used to calculate the divisors of psr, pm, fp and it is - * supposed to be called in set_dai_sysclk() and set_bclk(). + * fsl_esai_divisor_cal - This function is used to calculate the + * divisors of psr, pm, fp and it is supposed to be called in + * set_dai_sysclk() and set_bclk(). * + * @dai: pointer to DAI + * @tx: current setting is for playback or capture * @ratio: desired overall ratio for the paticipating dividers * @usefp: for HCK setting, there is no need to set fp divider * @fp: bypass other dividers by setting fp directly if fp != 0 - * @tx: current setting is for playback or capture */ static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio, bool usefp, u32 fp) @@ -250,13 +252,12 @@ out_fp: } /** - * This function mainly configures the clock frequency of MCLK (HCKT/HCKR) - * - * @Parameters: - * clk_id: The clock source of HCKT/HCKR + * fsl_esai_set_dai_sysclk - configure the clock frequency of MCLK (HCKT/HCKR) + * @dai: pointer to DAI + * @clk_id: The clock source of HCKT/HCKR * (Input from outside; output from inside, FSYS or EXTAL) - * freq: The required clock rate of HCKT/HCKR - * dir: The clock direction of HCKT/HCKR + * @freq: The required clock rate of HCKT/HCKR + * @dir: The clock direction of HCKT/HCKR * * Note: If the direction is input, we do not care about clk_id. */ @@ -358,7 +359,10 @@ out: } /** - * This function configures the related dividers according to the bclk rate + * fsl_esai_set_bclk - configure the related dividers according to the bclk rate + * @dai: pointer to DAI + * @tx: direction boolean + * @freq: bclk freq */ static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) { @@ -1008,7 +1012,7 @@ static int fsl_esai_probe(struct platform_device *pdev) if (irq < 0) return irq; - ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0, + ret = devm_request_irq(&pdev->dev, irq, esai_isr, IRQF_SHARED, esai_priv->name, esai_priv); if (ret) { dev_err(&pdev->dev, "failed to claim irq %u\n", irq); diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 9d436b0c5718a2531049e7e8ba7d025b6f1fe4c6..cdff739924e2e5c4dbb54d6fbd55c1e2fa4d010b 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -680,10 +680,11 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs), - FSL_SAI_CR1_RFW_MASK, + FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth), sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX); regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs), - FSL_SAI_CR1_RFW_MASK, FSL_SAI_MAXBURST_RX - 1); + FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth), + FSL_SAI_MAXBURST_RX - 1); snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, &sai->dma_params_rx); @@ -1016,6 +1017,7 @@ static int fsl_sai_probe(struct platform_device *pdev) platform_set_drvdata(pdev, sai); pm_runtime_enable(&pdev->dev); + regcache_cache_only(sai->regmap, true); ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, &fsl_sai_dai, 1); @@ -1107,7 +1109,6 @@ static int fsl_sai_runtime_suspend(struct device *dev) clk_disable_unprepare(sai->bus_clk); regcache_cache_only(sai->regmap, true); - regcache_mark_dirty(sai->regmap); return 0; } @@ -1137,6 +1138,7 @@ static int fsl_sai_runtime_resume(struct device *dev) } regcache_cache_only(sai->regmap, false); + regcache_mark_dirty(sai->regmap); regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR); regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR); usleep_range(1000, 2000); diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 76b15deea80c7afeec9a37276c37ba54033a8686..6aba7d28f5f344ab641dc3e247786ebd2a80510b 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -94,7 +94,7 @@ #define FSL_SAI_CSR_FRDE BIT(0) /* SAI Transmit and Receive Configuration 1 Register */ -#define FSL_SAI_CR1_RFW_MASK 0x1f +#define FSL_SAI_CR1_RFW_MASK(x) ((x) - 1) /* SAI Transmit and Receive Configuration 2 Register */ #define FSL_SAI_CR2_SYNC BIT(30) diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 1b2e516f9162fcf7e5e20eeb45bf1295aa067473..455f96908377cc748306bba5506acec29b7eacec 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,18 @@ static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb }; #define DEFAULT_RXCLK_SRC 1 +/** + * struct fsl_spdif_soc_data: soc specific data + * + * @imx: for imx platform + * @shared_root_clock: flag of sharing a clock source with others; + * so the driver shouldn't set root clock rate + */ +struct fsl_spdif_soc_data { + bool imx; + bool shared_root_clock; +}; + /* * SPDIF control structure * Defines channel status, subcode and Q sub @@ -68,8 +81,8 @@ struct spdif_mixer_control { }; /** - * fsl_spdif_priv: Freescale SPDIF private data - * + * struct fsl_spdif_priv - Freescale SPDIF private data + * @soc: SPDIF soc data * @fsl_spdif_control: SPDIF control data * @cpu_dai_drv: cpu dai driver * @pdev: platform device pointer @@ -87,8 +100,10 @@ struct spdif_mixer_control { * @spbaclk: SPBA clock (optional, depending on SoC design) * @dma_params_tx: DMA parameters for transmit channel * @dma_params_rx: DMA parameters for receive channel + * @regcache_srpc: regcache for SRPC */ struct fsl_spdif_priv { + const struct fsl_spdif_soc_data *soc; struct spdif_mixer_control fsl_spdif_control; struct snd_soc_dai_driver cpu_dai_drv; struct platform_device *pdev; @@ -110,6 +125,27 @@ struct fsl_spdif_priv { u32 regcache_srpc; }; +static struct fsl_spdif_soc_data fsl_spdif_vf610 = { + .imx = false, + .shared_root_clock = false, +}; + +static struct fsl_spdif_soc_data fsl_spdif_imx35 = { + .imx = true, + .shared_root_clock = false, +}; + +static struct fsl_spdif_soc_data fsl_spdif_imx6sx = { + .imx = true, + .shared_root_clock = true, +}; + +/* Check if clk is a root clock that does not share clock source with others */ +static inline bool fsl_spdif_can_set_clk_rate(struct fsl_spdif_priv *spdif, int clk) +{ + return (clk == STC_TXCLK_SPDIF_ROOT) && !spdif->soc->shared_root_clock; +} + /* DPLL locked and lock loss interrupt handler */ static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv) { @@ -369,7 +405,7 @@ static int spdif_set_rx_clksrc(struct fsl_spdif_priv *spdif_priv, static int spdif_set_sample_rate(struct snd_pcm_substream *substream, int sample_rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; struct regmap *regmap = spdif_priv->regmap; @@ -420,8 +456,7 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream, sysclk_df = spdif_priv->sysclk_df[rate]; - /* Don't mess up the clocks from other modules */ - if (clk != STC_TXCLK_SPDIF_ROOT) + if (!fsl_spdif_can_set_clk_rate(spdif_priv, clk)) goto clk_set_bypass; /* The S/PDIF block needs a clock of 64 * fs * txclk_df */ @@ -457,34 +492,19 @@ clk_set_bypass: static int fsl_spdif_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct platform_device *pdev = spdif_priv->pdev; struct regmap *regmap = spdif_priv->regmap; u32 scr, mask; - int i; int ret; /* Reset module and interrupts only for first initialization */ if (!snd_soc_dai_active(cpu_dai)) { - ret = clk_prepare_enable(spdif_priv->coreclk); - if (ret) { - dev_err(&pdev->dev, "failed to enable core clock\n"); - return ret; - } - - if (!IS_ERR(spdif_priv->spbaclk)) { - ret = clk_prepare_enable(spdif_priv->spbaclk); - if (ret) { - dev_err(&pdev->dev, "failed to enable spba clock\n"); - goto err_spbaclk; - } - } - ret = spdif_softreset(spdif_priv); if (ret) { dev_err(&pdev->dev, "failed to soft reset\n"); - goto err; + return ret; } /* Disable all the interrupts */ @@ -498,18 +518,10 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream, mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK | SCR_TXSEL_MASK | SCR_USRC_SEL_MASK | SCR_TXFIFO_FSEL_MASK; - for (i = 0; i < SPDIF_TXRATE_MAX; i++) { - ret = clk_prepare_enable(spdif_priv->txclk[i]); - if (ret) - goto disable_txclk; - } } else { scr = SCR_RXFIFO_FSEL_IF8 | SCR_RXFIFO_AUTOSYNC; mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK| SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK; - ret = clk_prepare_enable(spdif_priv->rxclk); - if (ret) - goto err; } regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr); @@ -517,39 +529,25 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream, regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_LOW_POWER, 0); return 0; - -disable_txclk: - for (i--; i >= 0; i--) - clk_disable_unprepare(spdif_priv->txclk[i]); -err: - if (!IS_ERR(spdif_priv->spbaclk)) - clk_disable_unprepare(spdif_priv->spbaclk); -err_spbaclk: - clk_disable_unprepare(spdif_priv->coreclk); - - return ret; } static void fsl_spdif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct regmap *regmap = spdif_priv->regmap; - u32 scr, mask, i; + u32 scr, mask; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { scr = 0; mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK | SCR_TXSEL_MASK | SCR_USRC_SEL_MASK | SCR_TXFIFO_FSEL_MASK; - for (i = 0; i < SPDIF_TXRATE_MAX; i++) - clk_disable_unprepare(spdif_priv->txclk[i]); } else { scr = SCR_RXFIFO_OFF | SCR_RXFIFO_CTL_ZERO; mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK| SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK; - clk_disable_unprepare(spdif_priv->rxclk); } regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr); @@ -558,9 +556,6 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream *substream, spdif_intr_status_clear(spdif_priv); regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_LOW_POWER, SCR_LOW_POWER); - if (!IS_ERR(spdif_priv->spbaclk)) - clk_disable_unprepare(spdif_priv->spbaclk); - clk_disable_unprepare(spdif_priv->coreclk); } } @@ -568,7 +563,7 @@ static int fsl_spdif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control; struct platform_device *pdev = spdif_priv->pdev; @@ -596,7 +591,7 @@ static int fsl_spdif_hw_params(struct snd_pcm_substream *substream, static int fsl_spdif_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct regmap *regmap = spdif_priv->regmap; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; @@ -781,8 +776,8 @@ static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol, } /* Get valid good bit from interrupt status register */ -static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int fsl_spdif_rx_vbit_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); @@ -796,6 +791,35 @@ static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol, return 0; } +static int fsl_spdif_tx_vbit_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); + struct regmap *regmap = spdif_priv->regmap; + u32 val; + + regmap_read(regmap, REG_SPDIF_SCR, &val); + val = (val & SCR_VAL_MASK) >> SCR_VAL_OFFSET; + val = 1 - val; + ucontrol->value.integer.value[0] = val; + + return 0; +} + +static int fsl_spdif_tx_vbit_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai); + struct regmap *regmap = spdif_priv->regmap; + u32 val = (1 - ucontrol->value.integer.value[0]) << SCR_VAL_OFFSET; + + regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_VAL_MASK, val); + + return 0; +} + /* DPLL lock information */ static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -953,11 +977,21 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = { /* Valid bit error controller */ { .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 V-Bit Errors", + .name = "IEC958 RX V-Bit Errors", .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = fsl_spdif_vbit_info, - .get = fsl_spdif_vbit_get, + .get = fsl_spdif_rx_vbit_get, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 TX V-Bit", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_WRITE | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = fsl_spdif_vbit_info, + .get = fsl_spdif_tx_vbit_get, + .put = fsl_spdif_tx_vbit_put, }, /* DPLL lock info get controller */ { @@ -990,6 +1024,10 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai) snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, ARRAY_SIZE(fsl_spdif_ctrls)); + /*Clear the val bit for Tx*/ + regmap_update_bits(spdif_private->regmap, REG_SPDIF_SCR, + SCR_VAL_MASK, SCR_VAL_CLEAR); + return 0; } @@ -1186,7 +1224,7 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, continue; ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index, - i == STC_TXCLK_SPDIF_ROOT); + fsl_spdif_can_set_clk_rate(spdif_priv, i)); if (savesub == ret) continue; @@ -1230,6 +1268,12 @@ static int fsl_spdif_probe(struct platform_device *pdev) spdif_priv->pdev = pdev; + spdif_priv->soc = of_device_get_match_data(&pdev->dev); + if (!spdif_priv->soc) { + dev_err(&pdev->dev, "failed to get soc data\n"); + return -ENODEV; + } + /* Initialize this copy of the CPU DAI driver structure */ memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); spdif_priv->cpu_dai_drv.name = dev_name(&pdev->dev); @@ -1311,6 +1355,8 @@ static int fsl_spdif_probe(struct platform_device *pdev) /* Register with ASoC */ dev_set_drvdata(&pdev->dev, spdif_priv); + pm_runtime_enable(&pdev->dev); + regcache_cache_only(spdif_priv->regmap, true); ret = devm_snd_soc_register_component(&pdev->dev, &fsl_spdif_component, &spdif_priv->cpu_dai_drv, 1); @@ -1326,41 +1372,96 @@ static int fsl_spdif_probe(struct platform_device *pdev) return ret; } -#ifdef CONFIG_PM_SLEEP -static int fsl_spdif_suspend(struct device *dev) +#ifdef CONFIG_PM +static int fsl_spdif_runtime_suspend(struct device *dev) { struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev); + int i; regmap_read(spdif_priv->regmap, REG_SPDIF_SRPC, &spdif_priv->regcache_srpc); - regcache_cache_only(spdif_priv->regmap, true); - regcache_mark_dirty(spdif_priv->regmap); + + clk_disable_unprepare(spdif_priv->rxclk); + + for (i = 0; i < SPDIF_TXRATE_MAX; i++) + clk_disable_unprepare(spdif_priv->txclk[i]); + + if (!IS_ERR(spdif_priv->spbaclk)) + clk_disable_unprepare(spdif_priv->spbaclk); + clk_disable_unprepare(spdif_priv->coreclk); return 0; } -static int fsl_spdif_resume(struct device *dev) +static int fsl_spdif_runtime_resume(struct device *dev) { struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev); + int ret; + int i; + + ret = clk_prepare_enable(spdif_priv->coreclk); + if (ret) { + dev_err(dev, "failed to enable core clock\n"); + return ret; + } + + if (!IS_ERR(spdif_priv->spbaclk)) { + ret = clk_prepare_enable(spdif_priv->spbaclk); + if (ret) { + dev_err(dev, "failed to enable spba clock\n"); + goto disable_core_clk; + } + } + + for (i = 0; i < SPDIF_TXRATE_MAX; i++) { + ret = clk_prepare_enable(spdif_priv->txclk[i]); + if (ret) + goto disable_tx_clk; + } + + ret = clk_prepare_enable(spdif_priv->rxclk); + if (ret) + goto disable_tx_clk; regcache_cache_only(spdif_priv->regmap, false); + regcache_mark_dirty(spdif_priv->regmap); regmap_update_bits(spdif_priv->regmap, REG_SPDIF_SRPC, SRPC_CLKSRC_SEL_MASK | SRPC_GAINSEL_MASK, spdif_priv->regcache_srpc); - return regcache_sync(spdif_priv->regmap); + ret = regcache_sync(spdif_priv->regmap); + if (ret) + goto disable_rx_clk; + + return 0; + +disable_rx_clk: + clk_disable_unprepare(spdif_priv->rxclk); +disable_tx_clk: + for (i--; i >= 0; i--) + clk_disable_unprepare(spdif_priv->txclk[i]); + if (!IS_ERR(spdif_priv->spbaclk)) + clk_disable_unprepare(spdif_priv->spbaclk); +disable_core_clk: + clk_disable_unprepare(spdif_priv->coreclk); + + return ret; } -#endif /* CONFIG_PM_SLEEP */ +#endif /* CONFIG_PM */ static const struct dev_pm_ops fsl_spdif_pm = { - SET_SYSTEM_SLEEP_PM_OPS(fsl_spdif_suspend, fsl_spdif_resume) + 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) }; static const struct of_device_id fsl_spdif_dt_ids[] = { - { .compatible = "fsl,imx35-spdif", }, - { .compatible = "fsl,vf610-spdif", }, + { .compatible = "fsl,imx35-spdif", .data = &fsl_spdif_imx35, }, + { .compatible = "fsl,vf610-spdif", .data = &fsl_spdif_vf610, }, + { .compatible = "fsl,imx6sx-spdif", .data = &fsl_spdif_imx6sx, }, {} }; MODULE_DEVICE_TABLE(of, fsl_spdif_dt_ids); diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 1a2fa7f181423b0edff239d5f46e7d5e0bfeb4d6..d8b9c6547142055a9815384183a58e120048dd01 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -203,12 +203,10 @@ struct fsl_ssi_soc_data { }; /** - * fsl_ssi: per-SSI private data - * + * struct fsl_ssi - per-SSI private data * @regs: Pointer to the regmap registers * @irq: IRQ of this SSI * @cpu_dai_drv: CPU DAI driver for this device - * * @dai_fmt: DAI configuration this device is currently used with * @streams: Mask of current active streams: BIT(TX) and BIT(RX) * @i2s_net: I2S and Network mode configurations of SCR register @@ -221,38 +219,29 @@ struct fsl_ssi_soc_data { * @slot_width: Width of each DAI slot * @slots: Number of slots * @regvals: Specific RX/TX register settings - * * @clk: Clock source to access register * @baudclk: Clock source to generate bit and frame-sync clocks * @baudclk_streams: Active streams that are using baudclk - * * @regcache_sfcsr: Cache sfcsr register value during suspend and resume * @regcache_sacnt: Cache sacnt register value during suspend and resume - * * @dma_params_tx: DMA transmit parameters * @dma_params_rx: DMA receive parameters * @ssi_phys: physical address of the SSI registers - * * @fiq_params: FIQ stream filtering parameters - * * @card_pdev: Platform_device pointer to register a sound card for PowerPC or * to register a CODEC platform device for AC97 * @card_name: Platform_device name to register a sound card for PowerPC or * to register a CODEC platform device for AC97 * @card_idx: The index of SSI to register a sound card for PowerPC or * to register a CODEC platform device for AC97 - * * @dbg_stats: Debugging statistics - * * @soc: SoC specific data * @dev: Pointer to &pdev->dev - * * @fifo_watermark: The FIFO watermark setting. Notifies DMA when there are * @fifo_watermark or fewer words in TX fifo or * @fifo_watermark or more empty words in RX fifo. * @dma_maxburst: Max number of words to transfer in one go. So far, * this is always the same as fifo_watermark. - * * @ac97_reg_lock: Mutex lock to serialize AC97 register access operations */ struct fsl_ssi { @@ -374,7 +363,9 @@ static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi *ssi) } /** - * Interrupt handler to gather states + * fsl_ssi_irq - Interrupt handler to gather states + * @irq: irq number + * @dev_id: context */ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) { @@ -395,7 +386,10 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) } /** - * Set SCR, SIER, STCR and SRCR registers with cached values in regvals + * fsl_ssi_config_enable - Set SCR, SIER, STCR and SRCR registers with + * cached values in regvals + * @ssi: SSI context + * @tx: direction * * Notes: * 1) For offline_config SoCs, enable all necessary bits of both streams @@ -474,7 +468,7 @@ enable_scr: ssi->streams |= BIT(dir); } -/** +/* * Exclude bits that are used by the opposite stream * * When both streams are active, disabling some bits for the current stream @@ -495,7 +489,10 @@ enable_scr: ((vals) & _ssi_xor_shared_bits(vals, avals, aactive)) /** - * Unset SCR, SIER, STCR and SRCR registers with cached values in regvals + * fsl_ssi_config_disable - Unset SCR, SIER, STCR and SRCR registers + * with cached values in regvals + * @ssi: SSI context + * @tx: direction * * Notes: * 1) For offline_config SoCs, to avoid online reconfigurations, disable all @@ -577,7 +574,9 @@ static void fsl_ssi_tx_ac97_saccst_setup(struct fsl_ssi *ssi) } /** - * Cache critical bits of SIER, SRCR, STCR and SCR to later set them safely + * fsl_ssi_setup_regvals - Cache critical bits of SIER, SRCR, STCR and + * SCR to later set them safely + * @ssi: SSI context */ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi) { @@ -630,7 +629,7 @@ static void fsl_ssi_setup_ac97(struct fsl_ssi *ssi) static int fsl_ssi_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); int ret; @@ -654,16 +653,19 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); clk_disable_unprepare(ssi->clk); } /** - * Configure Digital Audio Interface bit clock + * fsl_ssi_set_bclk - Configure Digital Audio Interface bit clock + * @substream: ASoC substream + * @dai: pointer to DAI + * @hw_params: pointers to hw_params * - * Note: This function can be only called when using SSI as DAI master + * Notes: This function can be only called when using SSI as DAI master * * Quick instruction for parameters: * freq: Output BCLK frequency = samplerate * slots * slot_width @@ -782,7 +784,10 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, } /** - * Configure SSI based on PCM hardware parameters + * fsl_ssi_hw_params - Configure SSI based on PCM hardware parameters + * @substream: ASoC substream + * @hw_params: pointers to hw_params + * @dai: pointer to DAI * * Notes: * 1) SxCCR.WL bits are critical bits that require SSI to be temporarily @@ -858,7 +863,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, static int fsl_ssi_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); if (fsl_ssi_is_i2s_master(ssi) && @@ -997,7 +1002,9 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt) } /** - * Configure Digital Audio Interface (DAI) Format + * fsl_ssi_set_dai_fmt - Configure Digital Audio Interface (DAI) Format + * @dai: pointer to DAI + * @fmt: format mask */ static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) { @@ -1011,7 +1018,12 @@ static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) } /** - * Set TDM slot number and slot width + * fsl_ssi_set_dai_tdm_slot - Set TDM slot number and slot width + * @dai: pointer to DAI + * @tx_mask: mask for TX + * @rx_mask: mask for RX + * @slots: number of slots + * @slot_width: number of bits per slot */ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mask, int slots, int slot_width) @@ -1055,7 +1067,10 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, } /** - * Start or stop SSI and corresponding DMA transaction. + * fsl_ssi_trigger - Start or stop SSI and corresponding DMA transaction. + * @substream: ASoC substream + * @cmd: trigger command + * @dai: pointer to DAI * * The DMA channel is in external master start and pause mode, which * means the SSI completely controls the flow of data. @@ -1063,7 +1078,7 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; @@ -1239,7 +1254,8 @@ static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = { }; /** - * Initialize SSI registers + * fsl_ssi_hw_init - Initialize SSI registers + * @ssi: SSI context */ static int fsl_ssi_hw_init(struct fsl_ssi *ssi) { @@ -1268,7 +1284,8 @@ static int fsl_ssi_hw_init(struct fsl_ssi *ssi) } /** - * Clear SSI registers + * fsl_ssi_hw_clean - Clear SSI registers + * @ssi: SSI context */ static void fsl_ssi_hw_clean(struct fsl_ssi *ssi) { @@ -1285,7 +1302,8 @@ static void fsl_ssi_hw_clean(struct fsl_ssi *ssi) regmap_update_bits(ssi->regs, REG_SSI_SCR, SSI_SCR_SSIEN, 0); } } -/** + +/* * Make every character in a string lower-case */ static void make_lowercase(char *s) diff --git a/sound/soc/fsl/fsl_ssi_dbg.c b/sound/soc/fsl/fsl_ssi_dbg.c index 2a20ee23dc52d19e62b2544df73d8cf755ee3d69..2c46c55f0a88290a1e9a42b7f664e49263d293a7 100644 --- a/sound/soc/fsl/fsl_ssi_dbg.c +++ b/sound/soc/fsl/fsl_ssi_dbg.c @@ -78,7 +78,7 @@ void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *dbg, u32 sisr) dbg->stats.tfe0++; } -/** +/* * Show the statistics of a flag only if its interrupt is enabled * * Compilers will optimize it to a no-op if the interrupt is disabled @@ -90,7 +90,7 @@ void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *dbg, u32 sisr) } while (0) -/** +/* * Display the statistics for the current SSI device * * To avoid confusion, only show those counts that are enabled diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index e09b45de0efd4b1e7623cfb00ca5e720f2a98316..202fb8950078f359b9f7e95df2aba567dc6797b0 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -6,8 +6,8 @@ * License. You may obtain a copy of the GNU General Public License * Version 2 or later at the following locations: * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * https://www.opensource.org/licenses/gpl-license.html + * https://www.gnu.org/copyleft/gpl.html */ #include @@ -44,7 +44,7 @@ static const struct snd_pcm_hw_constraint_list imx_audmix_rate_constraints = { static int imx_audmix_fe_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct imx_audmix *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_pcm_runtime *runtime = substream->runtime; struct device *dev = rtd->card->dev; @@ -73,7 +73,7 @@ static int imx_audmix_fe_startup(struct snd_pcm_substream *substream) static int imx_audmix_fe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct device *dev = rtd->card->dev; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; unsigned int fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF; @@ -112,7 +112,7 @@ static int imx_audmix_fe_hw_params(struct snd_pcm_substream *substream, static int imx_audmix_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct device *dev = rtd->card->dev; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; unsigned int fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF; diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 3ce85a43e08f23a0a5eae2fd833d54edab9eb247..25c18b9e348f60106c319b4a29e7d54f51f477d2 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -5,7 +5,7 @@ // Copyright 2009 Pengutronix, Sascha Hauer // // Initial development of this code was funded by -// Phytec Messtechnik GmbH, http://www.phytec.de +// Phytec Messtechnik GmbH, https://www.phytec.de #include #include diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c index fab2d6c56653ec9c900a8f858142867a9d85ea48..dd9c1ac81cf52d5ef9a7a7a7e33a9bad4f0cf9e4 100644 --- a/sound/soc/fsl/imx-mc13783.c +++ b/sound/soc/fsl/imx-mc13783.c @@ -26,7 +26,7 @@ static int imx_mc13783_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 3b8c796d7829f5c096e9337ee3d92aa9ad97442c..9e4f66b6b92b00f6da379c637f2d51bfde6aba1f 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -114,7 +114,7 @@ static int psc_dma_hw_free(struct snd_soc_component *component, static int psc_dma_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct snd_pcm_runtime *runtime = substream->runtime; struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); @@ -216,7 +216,7 @@ static int psc_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct psc_dma_stream *s; int rc; @@ -244,7 +244,7 @@ static int psc_dma_open(struct snd_soc_component *component, static int psc_dma_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct psc_dma_stream *s; @@ -270,7 +270,7 @@ static snd_pcm_uframes_t psc_dma_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct psc_dma_stream *s; dma_addr_t count; diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 1ab4fbda08cb029e5655ddeb57f9032c98efba07..3149d59ae968d2ce969178b9ee9c845cfef2d2b0 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -38,7 +38,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); u32 mode; diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index f7bd90051ce70b35f06b2b66cb95b6d53fd0d08f..eccc833390d422481e4abcac512bab9b4f023800 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -98,7 +98,7 @@ static int mpc8610_hpcd_machine_probe(struct snd_soc_card *card) */ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mpc8610_hpcd_data *machine_data = container_of(rtd->card, struct mpc8610_hpcd_data, card); struct device *dev = rtd->card->dev; @@ -426,9 +426,11 @@ static int __init mpc8610_hpcd_init(void) guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); if (of_address_to_resource(guts_np, 0, &res)) { pr_err("mpc8610-hpcd: missing/invalid global utilities node\n"); + of_node_put(guts_np); return -EINVAL; } guts_phys = res.start; + of_node_put(guts_np); return platform_driver_register(&mpc8610_hpcd_driver); } diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c index a36d4e8cd55cc33b9925c4a8cc858b5db93aa9bc..4ead537e090a72a19377de0d52cd4638587ba04d 100644 --- a/sound/soc/fsl/mx27vis-aic32x4.c +++ b/sound/soc/fsl/mx27vis-aic32x4.c @@ -36,7 +36,7 @@ static int mx27vis_amp_muter_gpio; static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index fe3091590f2075f4b20f74a93f144e11546c1b17..ac68d2238045dc4c0a47553f7a286ab98fbb0d76 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -121,7 +121,7 @@ static int p1022_ds_machine_probe(struct snd_soc_card *card) */ static int p1022_ds_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct machine_data *mdata = container_of(rtd->card, struct machine_data, card); struct device *dev = rtd->card->dev; diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c index f5374fe354abc509cd0f77ad895a2f98ff148a88..714515b8081feb073e1c8c54fef3bff9ac6c8ecf 100644 --- a/sound/soc/fsl/p1022_rdk.c +++ b/sound/soc/fsl/p1022_rdk.c @@ -127,7 +127,7 @@ static int p1022_rdk_machine_probe(struct snd_soc_card *card) */ static int p1022_rdk_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct machine_data *mdata = container_of(rtd->card, struct machine_data, card); struct device *dev = rtd->card->dev; diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c index 8b1551c55452bc12e19eed41af6691a80cb6d58f..99611a037adaca343434a4a98c3e0f259a94c800 100644 --- a/sound/soc/fsl/wm1133-ev1.c +++ b/sound/soc/fsl/wm1133-ev1.c @@ -75,7 +75,7 @@ static const struct _wm8350_audio wm8350_audio[] = { static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, found = 0; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 8c54dc6710fe56afb6f30411e6dd11e633e94af9..6cada4c1e283befe3c52848bda0340f082696a88 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -193,7 +193,7 @@ EXPORT_SYMBOL_GPL(asoc_simple_parse_clk); int asoc_simple_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num); int ret; @@ -212,7 +212,7 @@ EXPORT_SYMBOL_GPL(asoc_simple_startup); void asoc_simple_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); @@ -248,7 +248,7 @@ static int asoc_simple_set_clk_rate(struct asoc_simple_dai *simple_dai, int asoc_simple_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); @@ -540,7 +540,8 @@ EXPORT_SYMBOL_GPL(asoc_simple_parse_pin_switches); int asoc_simple_init_jack(struct snd_soc_card *card, struct asoc_simple_jack *sjack, - int is_hp, char *prefix) + int is_hp, char *prefix, + char *pin) { struct device *dev = card->dev; enum of_gpio_flags flags; @@ -557,12 +558,12 @@ int asoc_simple_init_jack(struct snd_soc_card *card, if (is_hp) { snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix); - pin_name = "Headphones"; + pin_name = pin ? pin : "Headphones"; gpio_name = "Headphone detection"; mask = SND_JACK_HEADPHONE; } else { snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix); - pin_name = "Mic Jack"; + pin_name = pin ? pin : "Mic Jack"; gpio_name = "Mic detection"; mask = SND_JACK_MICROPHONE; } diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c index e30b66b94bf67bb19bf960050291c6eca45e440e..0843235d73c91fbfd3334626ec8bf305e0e9a300 100644 --- a/sound/soc/img/img-i2s-in.c +++ b/sound/soc/img/img-i2s-in.c @@ -343,8 +343,10 @@ static int img_i2s_in_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) chan_control_mask = IMG_I2S_IN_CH_CTL_CLK_TRANS_MASK; ret = pm_runtime_get_sync(i2s->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(i2s->dev); return ret; + } for (i = 0; i < i2s->active_channels; i++) img_i2s_in_ch_disable(i2s, i); diff --git a/sound/soc/img/img-parallel-out.c b/sound/soc/img/img-parallel-out.c index 5ddbe3a31c2e9a964adaf6e98509ee99a5fbbeba..4da49a42e8547d0b12dc314b85a7bcf50677a01b 100644 --- a/sound/soc/img/img-parallel-out.c +++ b/sound/soc/img/img-parallel-out.c @@ -163,8 +163,10 @@ static int img_prl_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } ret = pm_runtime_get_sync(prl->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(prl->dev); return ret; + } reg = img_prl_out_readl(prl, IMG_PRL_OUT_CTL); reg = (reg & ~IMG_PRL_OUT_CTL_EDGE_MASK) | control_set; diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 36f547939f0a7edc0b700cdfd1a8c6bb7548f099..82805a8681e570accda66c1e2c4f20e31a42f8c5 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -240,6 +240,13 @@ config SND_SOC_ACPI_INTEL_MATCH endif ## SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL +config SND_SOC_INTEL_KEEMBAY + tristate "Keembay Platforms" + depends on ARM64 || COMPILE_TEST + depends on COMMON_CLK + help + If you have a Intel Keembay platform then enable this option + by saying Y or m. # ASoC codec drivers source "sound/soc/intel/boards/Kconfig" diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index e16d6dc4d4e60a0d4ea935b43965e941b65ffb9e..04ee48204fc9f76276757e6ef41ee70609449021 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/ obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += baytrail/ obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += atom/ obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += skylake/ +obj-$(CONFIG_SND_SOC_INTEL_KEEMBAY) += keembay/ # Machine support obj-$(CONFIG_SND_SOC) += boards/ diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index 69f3af4524abb104c634b8e06511c158a4de48e1..ff42f629b03538559fa9495c5235515503193efe 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -61,8 +61,13 @@ static int sst_fill_and_send_cmd_unlocked(struct sst_data *drv, /** * sst_fill_and_send_cmd - generate the IPC message and send it to the FW - * @ipc_msg: type of IPC (CMD, SET_PARAMS, GET_PARAMS) - * @cmd_data: the IPC payload + * @drv: sst_data + * @ipc_msg: type of IPC (CMD, SET_PARAMS, GET_PARAMS) + * @block: block index + * @task_id: task index + * @pipe_id: pipe index + * @cmd_data: the IPC payload + * @len: length of data to be sent */ static int sst_fill_and_send_cmd(struct sst_data *drv, u8 ipc_msg, u8 block, u8 task_id, u8 pipe_id, @@ -78,7 +83,7 @@ static int sst_fill_and_send_cmd(struct sst_data *drv, return ret; } -/** +/* * tx map value is a bitfield where each bit represents a FW channel * * 3 2 1 0 # 0 = codec0, 1 = codec1 @@ -90,7 +95,7 @@ static u8 sst_ssp_tx_map[SST_MAX_TDM_SLOTS] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, /* default rx map */ }; -/** +/* * rx map value is a bitfield where each bit represents a slot * * 76543210 # 0 = slot 0, 1 = slot 1 @@ -101,7 +106,7 @@ static u8 sst_ssp_rx_map[SST_MAX_TDM_SLOTS] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, /* default tx map */ }; -/** +/* * NOTE: this is invoked with lock held */ static int sst_send_slot_map(struct sst_data *drv) @@ -145,7 +150,8 @@ static int sst_slot_enum_info(struct snd_kcontrol *kcontrol, /** * sst_slot_get - get the status of the interleaver/deinterleaver control - * + * @kcontrol: control pointer + * @ucontrol: User data * Searches the map where the control status is stored, and gets the * channel/slot which is currently set for this enumerated control. Since it is * an enumerated control, there is only one possible value. @@ -197,7 +203,8 @@ static int sst_check_and_send_slot_map(struct sst_data *drv, struct snd_kcontrol /** * sst_slot_put - set the status of interleaver/deinterleaver control - * + * @kcontrol: control pointer + * @ucontrol: User data * (de)interleaver controls are defined in opposite sense to be user-friendly * * Instead of the enum value being the value written to the register, it is the @@ -280,7 +287,9 @@ static int sst_send_algo_cmd(struct sst_data *drv, /** * sst_find_and_send_pipe_algo - send all the algo parameters for a pipe - * + * @drv: sst_data + * @pipe: string identifier + * @ids: list of algorithms * The algos which are in each pipeline are sent to the firmware one by one * * Called with lock held @@ -379,11 +388,15 @@ static int sst_gain_ctl_info(struct snd_kcontrol *kcontrol, /** * sst_send_gain_cmd - send the gain algorithm IPC to the FW - * @gv: the stored value of gain (also contains rampduration) - * @mute: flag that indicates whether this was called from the - * digital_mute callback or directly. If called from the - * digital_mute callback, module will be muted/unmuted based on this - * flag. The flag is always 0 if called directly. + * @drv: sst_data + * @gv:the stored value of gain (also contains rampduration) + * @task_id: task index + * @loc_id: location/position index + * @module_id: module index + * @mute: flag that indicates whether this was called from the + * digital_mute callback or directly. If called from the + * digital_mute callback, module will be muted/unmuted based on this + * flag. The flag is always 0 if called directly. * * Called with sst_data.lock held * @@ -544,9 +557,12 @@ static const uint swm_mixer_input_ids[SST_SWM_INPUT_COUNT] = { /** * fill_swm_input - fill in the SWM input ids given the register + * @cmpnt: ASoC component + * @swm_input: array of swm_input_ids + * @reg: the register value is a bit-field inicated which mixer inputs are ON. * - * The register value is a bit-field inicated which mixer inputs are ON. Use the - * lookup table to get the input-id and fill it in the structure. + * Use the lookup table to get the input-id and fill it in the + * structure. */ static int fill_swm_input(struct snd_soc_component *cmpnt, struct swm_input_ids *swm_input, unsigned int reg) @@ -577,7 +593,7 @@ static int fill_swm_input(struct snd_soc_component *cmpnt, } -/** +/* * called with lock held */ static int sst_set_pipe_gain(struct sst_ids *ids, @@ -707,7 +723,7 @@ SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm2_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_sprot_l0_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l1_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l2_controls); -SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_voip_controls); +SST_SBA_DECLARE_MIX_CONTROLS(__maybe_unused sst_mix_voip_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec0_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec1_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_modem_controls); @@ -881,7 +897,7 @@ int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt) return 0; } -/** +/* * sst_ssp_config - contains SSP configuration for media UC * this can be overwritten by set_dai_xxx APIs */ @@ -1300,6 +1316,9 @@ static bool is_sst_dapm_widget(struct snd_soc_dapm_widget *w) /** * sst_send_pipe_gains - send gains for the front-end DAIs + * @dai: front-end dai + * @stream: direction + * @mute: boolean indicating mute status * * The gains in the pipes connected to the front-ends are muted/unmuted * automatically via the digital_mute() DAPM callback. This function sends the @@ -1357,7 +1376,9 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute) /** * sst_fill_module_list - populate the list of modules/gains for a pipe - * + * @kctl: kcontrol pointer + * @w: dapm widget + * @type: widget type * * Fills the widget pointer in the kcontrol private data, and also fills the * kcontrol pointer in the widget private data. @@ -1403,7 +1424,8 @@ static int sst_fill_module_list(struct snd_kcontrol *kctl, /** * sst_fill_widget_module_info - fill list of gains/algos for the pipe - * @widget: pipe modelled as a DAPM widget + * @w: pipe modeled as a DAPM widget + * @component: ASoC component * * Fill the list of gains/algos for the widget by looking at all the card * controls and comparing the name of the widget with the first part of control @@ -1463,6 +1485,8 @@ static int sst_fill_widget_module_info(struct snd_soc_dapm_widget *w, /** * sst_fill_linked_widgets - fill the parent pointer for the linked widget + * @component: ASoC component + * @ids: sst_ids array */ static void sst_fill_linked_widgets(struct snd_soc_component *component, struct sst_ids *ids) @@ -1480,6 +1504,7 @@ static void sst_fill_linked_widgets(struct snd_soc_component *component, /** * sst_map_modules_to_pipe - fill algo/gains list for all pipes + * @component: ASoC component */ static int sst_map_modules_to_pipe(struct snd_soc_component *component) { diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 8817eaae6bb7a8e03315091f1064fc67f0d86923..49b9f18472bcefe5c848b97c9b8a55c17d1e6147 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -274,7 +274,7 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) { struct sst_runtime_stream *stream = substream->runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret_val; dev_dbg(rtd->dev, "setting buffer ptr param\n"); @@ -582,7 +582,7 @@ static int sst_soc_trigger(struct snd_soc_component *component, int ret_val = 0, str_id; struct sst_runtime_stream *stream; int status; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); dev_dbg(rtd->dev, "%s called\n", __func__); if (substream->pcm->internal) @@ -630,7 +630,7 @@ static snd_pcm_uframes_t sst_soc_pointer(struct snd_soc_component *component, struct sst_runtime_stream *stream; int ret_val, status; struct pcm_stream_info *str_info; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); stream = substream->runtime->private_data; status = sst_get_stream_status(stream); diff --git a/sound/soc/intel/atom/sst/sst_loader.c b/sound/soc/intel/atom/sst/sst_loader.c index 9b0e3739c738cbf2d279686bc2eb1d9ec8c69ec4..fc91a304256b471f7b2f663a46851b4ac08383d2 100644 --- a/sound/soc/intel/atom/sst/sst_loader.c +++ b/sound/soc/intel/atom/sst/sst_loader.c @@ -49,6 +49,7 @@ void memcpy32_fromio(void *dst, const void __iomem *src, int count) /** * intel_sst_reset_dsp_mrfld - Resetting SST DSP + * @sst_drv_ctx: intel_sst_drv context pointer * * This resets DSP in case of MRFLD platfroms */ @@ -77,6 +78,7 @@ int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *sst_drv_ctx) /** * sst_start_merrifield - Start the SST DSP processor + * @sst_drv_ctx: intel_sst_drv context pointer * * This starts the DSP in MERRIFIELD platfroms */ @@ -274,12 +276,10 @@ void sst_memcpy_free_resources(struct intel_sst_drv *sst_drv_ctx) struct sst_memcpy_list *listnode, *tmplistnode; /* Free the list */ - if (!list_empty(&sst_drv_ctx->memcpy_list)) { - list_for_each_entry_safe(listnode, tmplistnode, - &sst_drv_ctx->memcpy_list, memcpylist) { - list_del(&listnode->memcpylist); - kfree(listnode); - } + list_for_each_entry_safe(listnode, tmplistnode, + &sst_drv_ctx->memcpy_list, memcpylist) { + list_del(&listnode->memcpylist); + kfree(listnode); } } @@ -387,6 +387,8 @@ void sst_post_download_mrfld(struct intel_sst_drv *ctx) /** * sst_load_fw - function to load FW into DSP + * @sst_drv_ctx: intel_sst_drv context pointer + * * Transfers the FW to DSP using dma/memcpy */ int sst_load_fw(struct intel_sst_drv *sst_drv_ctx) diff --git a/sound/soc/intel/atom/sst/sst_stream.c b/sound/soc/intel/atom/sst/sst_stream.c index ea09f4170201d4119f28ac368b148e10289d01e2..c0221e103e7967a955b33ed00b6c2df5cc4dc91d 100644 --- a/sound/soc/intel/atom/sst/sst_stream.c +++ b/sound/soc/intel/atom/sst/sst_stream.c @@ -92,8 +92,8 @@ int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params) /** * sst_realloc_stream - Send msg for (re-)allocating a stream using the - * @sst_drv_ctx intel_sst_drv context pointer - * @str_id: stream ID + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID * * Send a msg for (re-)allocating a stream using the parameters previously * passed to sst_alloc_stream_mrfld() for the same stream ID. @@ -142,12 +142,13 @@ out: } /** -* sst_start_stream - Send msg for a starting stream -* @str_id: stream ID -* -* This function is called by any function which wants to start -* a stream. -*/ + * sst_start_stream - Send msg for a starting stream + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID + * + * This function is called by any function which wants to start + * a stream. + */ int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) { int retval = 0; @@ -234,7 +235,8 @@ out: /** * sst_pause_stream - Send msg for a pausing stream - * @str_id: stream ID + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID * * This function is called by any function which wants to pause * an already running stream. @@ -278,7 +280,8 @@ int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) /** * sst_resume_stream - Send msg for resuming stream - * @str_id: stream ID + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID * * This function is called by any function which wants to resume * an already paused stream. @@ -345,7 +348,8 @@ int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) /** * sst_drop_stream - Send msg for stopping stream - * @str_id: stream ID + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID * * This function is called by any function which wants to stop * a stream. @@ -377,12 +381,14 @@ int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int str_id) } /** -* sst_drain_stream - Send msg for draining stream -* @str_id: stream ID -* -* This function is called by any function which wants to drain -* a stream. -*/ + * sst_drain_stream - Send msg for draining stream + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID + * @partial_drain: boolean indicating if a gapless transition is taking place + * + * This function is called by any function which wants to drain + * a stream. + */ int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx, int str_id, bool partial_drain) { @@ -415,7 +421,8 @@ int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx, /** * sst_free_stream - Frees a stream - * @str_id: stream ID + * @sst_drv_ctx: intel_sst_drv context pointer + * @str_id: stream ID * * This function is called by any function which wants to free * a stream. diff --git a/sound/soc/intel/baytrail/sst-baytrail-pcm.c b/sound/soc/intel/baytrail/sst-baytrail-pcm.c index 53383055c8dc68ae29c8be4174fe5e8d3eef25f6..54a66cc6db890234f0fa870300293abce64d7042 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-pcm.c +++ b/sound/soc/intel/baytrail/sst-baytrail-pcm.c @@ -62,7 +62,7 @@ static int sst_byt_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; struct sst_byt *byt = pdata->byt; @@ -121,7 +121,7 @@ static int sst_byt_pcm_hw_params(struct snd_soc_component *component, static int sst_byt_pcm_restore_stream_context(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; @@ -155,7 +155,7 @@ static void sst_byt_pcm_work(struct work_struct *work) static int sst_byt_pcm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; struct sst_byt *byt = pdata->byt; @@ -197,7 +197,7 @@ static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data) struct sst_byt_pcm_data *pcm_data = data; struct snd_pcm_substream *substream = pcm_data->substream; struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt *byt = pdata->byt; @@ -219,7 +219,7 @@ static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data) static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; @@ -232,7 +232,7 @@ static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_soc_component *component static int sst_byt_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; struct sst_byt *byt = pdata->byt; @@ -260,7 +260,7 @@ static int sst_byt_pcm_open(struct snd_soc_component *component, static int sst_byt_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; struct sst_byt *byt = pdata->byt; @@ -286,7 +286,7 @@ static int sst_byt_pcm_mmap(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct vm_area_struct *vma) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); dev_dbg(rtd->dev, "PCM: mmap\n"); return snd_pcm_lib_default_mmap(substream, vma); diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 5dc489a794542d1a75a7bea8ed29e5f99f3e8222..d96fc13134347ada8bb6d9846cc4ff728d3f9986 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -288,6 +288,7 @@ config SND_SOC_INTEL_DA7219_MAX98357A_GENERIC tristate select SND_SOC_DA7219 select SND_SOC_MAX98357A + select SND_SOC_MAX98390 select SND_SOC_DMIC select SND_SOC_HDAC_HDMI @@ -298,14 +299,14 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON if SND_SOC_INTEL_APL config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH - tristate "Broxton with DA7219 and MAX98357A in I2S Mode" + tristate "Broxton with DA7219 and MAX98357A/MAX98390 in I2S Mode" depends on I2C && ACPI && GPIOLIB depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON help This adds support for ASoC machine driver for Broxton-P platforms - with DA7219 + MAX98357A I2S audio codec. + with DA7219 + MAX98357A/MAX98390 I2S audio codec. Say Y or m if you have such a device. This is a recommended option. If unsure select "N". @@ -389,7 +390,7 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_DA7219 select SND_SOC_MAX98927 - select SND_SOC_MAX98373 + select SND_SOC_MAX98373_I2C select SND_SOC_DMIC select SND_SOC_HDAC_HDMI help @@ -466,7 +467,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH depends on ((SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC) &&\ (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ (SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST)) - select SND_SOC_MAX98373 + select SND_SOC_MAX98373_I2C select SND_SOC_RT1015 select SND_SOC_RT5682_I2C select SND_SOC_DMIC @@ -530,7 +531,7 @@ config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_DA7219 - select SND_SOC_MAX98373 + select SND_SOC_MAX98373_I2C select SND_SOC_DMIC help This adds support for ASoC machine driver for SOF platforms @@ -564,6 +565,8 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST depends on SOUNDWIRE depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC + select SND_SOC_MAX98373_I2C + select SND_SOC_MAX98373_SDW select SND_SOC_RT700_SDW select SND_SOC_RT711_SDW select SND_SOC_RT1308_SDW @@ -573,7 +576,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH select SND_SOC_DMIC help Add support for Intel SoundWire-based platforms connected to - RT700, RT711, RT1308 and RT715 + MAX98373, RT700, RT711, RT1308 and RT715 If unsure select "N". endif diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 15684610f8c6be711ec00a2d34fb37b9b32a4722..dc04acb911b651993939cf80b8c22172b5d39262 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -34,9 +34,11 @@ snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o snd-soc-sof_da7219_max98373-objs := sof_da7219_max98373.o hda_dsp_common.o snd-soc-ehl-rt5660-objs := ehl_rt5660.o hda_dsp_common.o snd-soc-sof-sdw-objs += sof_sdw.o \ + sof_sdw_max98373.o \ sof_sdw_rt711.o sof_sdw_rt700.o \ sof_sdw_rt1308.o sof_sdw_rt715.o \ sof_sdw_rt5682.o \ + sof_maxim_common.o \ sof_sdw_dmic.o sof_sdw_hdmi.o hda_dsp_common.o obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c index a97e912adf4b3dfb845d0018e90d3ee3bbfcdd63..ce7320916b22b797ccf85ebbab25f921ecbb97ae 100644 --- a/sound/soc/intel/boards/bdw-rt5650.c +++ b/sound/soc/intel/boards/bdw-rt5650.c @@ -106,7 +106,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, static int bdw_rt5650_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -297,9 +297,19 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bdw rt5650" /* card name will be 'sof-bdw rt5650' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bdw-rt5650" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* ASoC machine driver for Broadwell DSP + RT5650 */ static struct snd_soc_card bdw_rt5650_card = { - .name = "bdw-rt5650", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = bdw_rt5650_dais, .num_links = ARRAY_SIZE(bdw_rt5650_dais), diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index bed4d5f73d9cffe6887ae74aa718dd03e7d3d084..86e427e3822f74645eac234735f54c5c7f538d4f 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -156,7 +156,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, static int bdw_rt5677_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -173,7 +173,7 @@ static int bdw_rt5677_hw_params(struct snd_pcm_substream *substream, static int bdw_rt5677_dsp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -272,8 +272,8 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) RT5677_CLK_SEL_SYS2); /* Request rt5677 GPIO for headphone amp control */ - bdw_rt5677->gpio_hp_en = devm_gpiod_get(component->dev, "headphone-enable", - GPIOD_OUT_LOW); + bdw_rt5677->gpio_hp_en = gpiod_get(component->dev, "headphone-enable", + GPIOD_OUT_LOW); if (IS_ERR(bdw_rt5677->gpio_hp_en)) { dev_err(component->dev, "Can't find HP_AMP_SHDN_L gpio\n"); return PTR_ERR(bdw_rt5677->gpio_hp_en); @@ -307,6 +307,19 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) return 0; } +static void bdw_rt5677_exit(struct snd_soc_pcm_runtime *rtd) +{ + struct bdw_rt5677_priv *bdw_rt5677 = + 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(bdw_rt5677->gpio_hp_en)) + gpiod_put(bdw_rt5677->gpio_hp_en); +} + /* broadwell digital audio interface glue - connects codec <--> CPU */ SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); @@ -373,6 +386,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .init = bdw_rt5677_init, + .exit = bdw_rt5677_exit, #if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) SND_SOC_DAILINK_REG(dummy, be, dummy), #else @@ -405,9 +419,19 @@ static int bdw_rt5677_resume_post(struct snd_soc_card *card) return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bdw rt5677" /* card name will be 'sof-bdw rt5677' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bdw-rt5677" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* ASoC machine driver for Broadwell DSP + RT5677 */ static struct snd_soc_card bdw_rt5677_card = { - .name = "bdw-rt5677", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = bdw_rt5677_dais, .num_links = ARRAY_SIZE(bdw_rt5677_dais), diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index 42f8723beef20aa5864aa6308ce6e0eb4bcbfde0..f6399077d29195e9a0bb4dfa22d9dcbaca76e297 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -103,7 +103,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, static int broadwell_rt286_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -291,9 +291,19 @@ static int broadwell_resume(struct snd_soc_card *card){ return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bdw rt286" /* card name will be 'sof-bdw rt286' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "broadwell-rt286" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* broadwell audio machine driver for WPT + RT286S */ static struct snd_soc_card broadwell_rt286 = { - .name = "broadwell-rt286", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = broadwell_rt286_dais, .num_links = ARRAY_SIZE(broadwell_rt286_dais), diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 44016c16f25e2e83c00ad586a5434d147b25d3dc..0c0a717823c40779e066278128c2416c932311d8 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -25,9 +25,14 @@ #define BXT_DIALOG_CODEC_DAI "da7219-hifi" #define BXT_MAXIM_CODEC_DAI "HiFi" +#define MAX98390_DEV0_NAME "i2c-MX98390:00" +#define MAX98390_DEV1_NAME "i2c-MX98390:01" #define DUAL_CHANNEL 2 #define QUAD_CHANNEL 4 +#define SPKAMP_MAX98357A 1 +#define SPKAMP_MAX98390 2 + static struct snd_soc_jack broxton_headset; static struct snd_soc_jack broxton_hdmi[3]; @@ -40,6 +45,7 @@ struct bxt_hdmi_pcm { struct bxt_card_private { struct list_head hdmi_pcm_list; bool common_hdmi_codec_drv; + int spkamp; }; enum { @@ -85,13 +91,20 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, static const struct snd_kcontrol_new broxton_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static const struct snd_kcontrol_new max98357a_controls[] = { SOC_DAPM_PIN_SWITCH("Spk"), }; +static const struct snd_kcontrol_new max98390_controls[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right 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_SPK("Spk", NULL), SND_SOC_DAPM_MIC("SoC DMIC", NULL), SND_SOC_DAPM_SPK("HDMI1", NULL), SND_SOC_DAPM_SPK("HDMI2", NULL), @@ -100,14 +113,20 @@ static const struct snd_soc_dapm_widget broxton_widgets[] = { platform_clock_control, SND_SOC_DAPM_POST_PMD|SND_SOC_DAPM_PRE_PMU), }; +static const struct snd_soc_dapm_widget max98357a_widgets[] = { + SND_SOC_DAPM_SPK("Spk", NULL), +}; + +static const struct snd_soc_dapm_widget max98390_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right 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"}, - /* speaker */ - {"Spk", NULL, "Speaker"}, - /* other jacks */ {"MIC", NULL, "Headset Mic"}, @@ -134,6 +153,17 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Headset Mic", NULL, "Platform Clock" }, }; +static const struct snd_soc_dapm_route max98357a_routes[] = { + /* speaker */ + {"Spk", NULL, "Speaker"}, +}; + +static const struct snd_soc_dapm_route max98390_routes[] = { + /* Speaker */ + {"Left Spk", NULL, "Left BE_OUT"}, + {"Right Spk", NULL, "Right BE_OUT"}, +}; + static const struct snd_soc_dapm_route broxton_map[] = { {"HiFi Playback", NULL, "ssp5 Tx"}, {"ssp5 Tx", NULL, "codec0_out"}, @@ -404,6 +434,10 @@ SND_SOC_DAILINK_DEF(ssp5_pin, SND_SOC_DAILINK_DEF(ssp5_codec, DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", BXT_MAXIM_CODEC_DAI))); +SND_SOC_DAILINK_DEF(max98390_codec, + DAILINK_COMP_ARRAY( + /* Left */ COMP_CODEC(MAX98390_DEV0_NAME, "max98390-aif1"), + /* Right */ COMP_CODEC(MAX98390_DEV1_NAME, "max98390-aif1"))); SND_SOC_DAILINK_DEF(ssp1_pin, DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); @@ -601,15 +635,69 @@ static struct snd_soc_dai_link broxton_dais[] = { }, }; +static struct snd_soc_codec_conf max98390_codec_confs[] = { + { + .dlc = COMP_CODEC_CONF(MAX98390_DEV0_NAME), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF(MAX98390_DEV1_NAME), + .name_prefix = "Right", + }, +}; + #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; + const struct snd_kcontrol_new *controls; + const struct snd_soc_dapm_widget *widgets; + const struct snd_soc_dapm_route *routes; + int num_controls, num_widgets, num_routes, err, i = 0; char jack_name[NAME_SIZE]; + switch (ctx->spkamp) { + case SPKAMP_MAX98357A: + controls = max98357a_controls; + num_controls = ARRAY_SIZE(max98357a_controls); + widgets = max98357a_widgets; + num_widgets = ARRAY_SIZE(max98357a_widgets); + routes = max98357a_routes; + num_routes = ARRAY_SIZE(max98357a_routes); + break; + case SPKAMP_MAX98390: + controls = max98390_controls; + num_controls = ARRAY_SIZE(max98390_controls); + widgets = max98390_widgets; + num_widgets = ARRAY_SIZE(max98390_widgets); + routes = max98390_routes; + num_routes = ARRAY_SIZE(max98390_routes); + break; + default: + dev_err(card->dev, "Invalid speaker amplifier %d\n", ctx->spkamp); + return -EINVAL; + } + + err = snd_soc_dapm_new_controls(&card->dapm, widgets, num_widgets); + if (err) { + dev_err(card->dev, "Fail to new widgets\n"); + return err; + } + + err = snd_soc_add_card_controls(card, controls, num_controls); + if (err) { + dev_err(card->dev, "Fail to add controls\n"); + return err; + } + + err = snd_soc_dapm_add_routes(&card->dapm, routes, num_routes); + if (err) { + dev_err(card->dev, "Fail to add routes\n"); + return err; + } + if (soc_intel_is_glk()) snd_soc_dapm_add_routes(&card->dapm, gemini_map, ARRAY_SIZE(gemini_map)); @@ -678,6 +766,11 @@ static int broxton_audio_probe(struct platform_device *pdev) INIT_LIST_HEAD(&ctx->hdmi_pcm_list); + if (acpi_dev_present("MX98390", NULL, -1)) + ctx->spkamp = SPKAMP_MAX98390; + else + ctx->spkamp = SPKAMP_MAX98357A; + broxton_audio_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&broxton_audio_card, ctx); if (soc_intel_is_glk()) { @@ -702,7 +795,13 @@ static int broxton_audio_probe(struct platform_device *pdev) } else if (soc_intel_is_cml()) { unsigned int i; - broxton_audio_card.name = "cmlda7219max"; + if (ctx->spkamp == SPKAMP_MAX98390) { + broxton_audio_card.name = "cml_max98390_da7219"; + + broxton_audio_card.codec_conf = max98390_codec_confs; + broxton_audio_card.num_configs = ARRAY_SIZE(max98390_codec_confs); + } else + broxton_audio_card.name = "cmlda7219max"; for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) { /* MAXIM_CODEC is connected to SSP1. */ @@ -710,6 +809,11 @@ static int broxton_audio_probe(struct platform_device *pdev) BXT_MAXIM_CODEC_DAI)) { broxton_dais[i].name = "SSP1-Codec"; broxton_dais[i].cpus->dai_name = "SSP1 Pin"; + + if (ctx->spkamp == SPKAMP_MAX98390) { + broxton_dais[i].codecs = max98390_codec; + broxton_dais[i].num_codecs = ARRAY_SIZE(max98390_codec); + } } /* DIALOG_CODEC is connected to SSP0 */ else if (!strcmp(broxton_dais[i].codecs->dai_name, @@ -759,6 +863,7 @@ 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_ALIAS("platform:bxt_da7219_max98357a"); MODULE_ALIAS("platform:glk_da7219_max98357a"); diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 7a4decf341918e65c3b39841cda1efc1b15875ed..0f3157dfa8384cea4a18af161c6b6e399f8d0952 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -224,7 +224,7 @@ static int broxton_ssp5_fixup(struct snd_soc_pcm_runtime *rtd, static int broxton_rt298_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -565,6 +565,7 @@ static int bxt_card_late_probe(struct snd_soc_card *card) /* 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, @@ -580,6 +581,7 @@ static struct snd_soc_card broxton_rt298 = { 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, diff --git a/sound/soc/intel/boards/byt-rt5640.c b/sound/soc/intel/boards/byt-rt5640.c index ace232f8aed659dc54eee231cac0fad4bdf8bf0c..8851949f38e229c65d7a24d20a56f7e47f9bb2fc 100644 --- a/sound/soc/intel/boards/byt-rt5640.c +++ b/sound/soc/intel/boards/byt-rt5640.c @@ -72,7 +72,7 @@ static const struct snd_kcontrol_new byt_rt5640_controls[] = { static int byt_rt5640_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index fad937610494431b2ab788b22ba4a26138aa9de9..9cb42ba40c07a5a93b1f57d1187845330a17a25e 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -205,9 +205,19 @@ static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht cx2072x" /* card name will be 'sof-bytcht cx2072x' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bytcht-cx2072x" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card byt_cht_cx2072x_card = { - .name = "bytcht-cx2072x", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = byt_cht_cx2072x_dais, .num_links = ARRAY_SIZE(byt_cht_cx2072x_dais), diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c index f3791ff2bad1c1374cf74bfb5b80ebcd4ceb0466..e1e46b4bbac54f7302f718de1f3eb30bc506b022 100644 --- a/sound/soc/intel/boards/bytcht_da7213.c +++ b/sound/soc/intel/boards/bytcht_da7213.c @@ -105,7 +105,7 @@ static int aif1_startup(struct snd_pcm_substream *substream) static int aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -126,7 +126,7 @@ static int aif1_hw_params(struct snd_pcm_substream *substream, static int aif1_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -205,9 +205,19 @@ static struct snd_soc_dai_link dailink[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht da7213" /* card name will be 'sof-bytcht da7213' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bytcht-da7213" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card bytcht_da7213_card = { - .name = "bytcht-da7213", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = dailink, .num_links = ARRAY_SIZE(dailink), diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index ecbc58e8a37f5cb292f951ba62f725c2c41d6800..414ae4bb5224a96d58d2586c2d2d092395ebe988 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -407,8 +407,18 @@ static int byt_cht_es8316_resume(struct snd_soc_card *card) return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht es8316" /* card name will be 'sof-bytcht es8316' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bytcht-es8316" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + static struct snd_soc_card byt_cht_es8316_card = { - .name = "bytcht-es8316", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = byt_cht_es8316_dais, .num_links = ARRAY_SIZE(byt_cht_es8316_dais), @@ -515,9 +525,8 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) BYT_CHT_ES8316_MONO_SPEAKER; } if (quirk_override != -1) { - dev_info(dev, "Overriding quirk 0x%x => 0x%x\n", - (unsigned int)quirk, - quirk_override); + dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n", + quirk, quirk_override); quirk = quirk_override; } log_quirks(dev); diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 1fdb70b9e478865919f04a56c35c1e1a41317485..479992f4e97a35c91d0e2118e809fdb3c2482e8b 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -380,7 +380,7 @@ static struct snd_soc_jack_pin rt5640_pins[] = { static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); return byt_rt5640_prepare_and_enable_pll1(dai, params_rate(params)); @@ -1127,8 +1127,18 @@ static int byt_rt5640_resume(struct snd_soc_card *card) return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht rt5640" /* card name will be 'sof-bytcht rt5640' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bytcr-rt5640" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + static struct snd_soc_card byt_rt5640_card = { - .name = "bytcr-rt5640", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = byt_rt5640_dais, .num_links = ARRAY_SIZE(byt_rt5640_dais), @@ -1255,8 +1265,8 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) if (dmi_id) byt_rt5640_quirk = (unsigned long)dmi_id->driver_data; if (quirk_override != -1) { - dev_info(&pdev->dev, "Overriding quirk 0x%x => 0x%x\n", - (unsigned int)byt_rt5640_quirk, quirk_override); + dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", + byt_rt5640_quirk, quirk_override); byt_rt5640_quirk = quirk_override; } diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 520e916e329cdd81521c2db87a79e178899693de..4e2897596cea317814e0d7d8d47032f16216e56f 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -347,7 +347,7 @@ static struct snd_soc_jack_pin bytcr_jack_pins[] = { static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); snd_pcm_format_t format = params_format(params); int rate = params_rate(params); @@ -827,8 +827,18 @@ static int byt_rt5651_resume(struct snd_soc_card *card) return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht rt5651" /* card name will be 'sof-bytcht rt5651' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "bytcr-rt5651" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + static struct snd_soc_card byt_rt5651_card = { - .name = "bytcr-rt5651", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = byt_rt5651_dais, .num_links = ARRAY_SIZE(byt_rt5651_dais), @@ -967,8 +977,8 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) dmi_check_system(byt_rt5651_quirk_table); if (quirk_override != -1) { - dev_info(&pdev->dev, "Overriding quirk 0x%x => 0x%x\n", - (unsigned int)byt_rt5651_quirk, quirk_override); + dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", + byt_rt5651_quirk, quirk_override); byt_rt5651_quirk = quirk_override; } diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 767ac2ae03e225a4afd425acb7fb6f2a3eff4c92..835e9bd6b52d3c63eacbcc9d754dafa552bb22ca 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -112,7 +112,7 @@ static const struct snd_kcontrol_new cht_mc_controls[] = { static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -382,9 +382,19 @@ static struct snd_soc_dai_link cht_dailink[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht max98090" /* card name will be 'sof-bytcht max98090 */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "chtmax98090" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card snd_soc_card_cht = { - .name = "chtmax98090", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = cht_dailink, .num_links = ARRAY_SIZE(cht_dailink), diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c index 2f7c94d335c1cea1107f897190a6f59b17994d65..3e12bff15fedb313f75737fc3e159f2ba6eb2f10 100644 --- a/sound/soc/intel/boards/cht_bsw_nau8824.c +++ b/sound/soc/intel/boards/cht_bsw_nau8824.c @@ -72,7 +72,7 @@ static const struct snd_kcontrol_new cht_mc_controls[] = { static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -231,9 +231,19 @@ static struct snd_soc_dai_link cht_dailink[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht nau8824" /* card name will be 'sof-bytcht nau8824 */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "chtnau8824" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card snd_soc_card_cht = { - .name = "chtnau8824", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = cht_dailink, .num_links = ARRAY_SIZE(cht_dailink), diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 22de138ffa3379ca3d7af44bc6aee4cac5ade3de..b53c02481749498aa661a347924d46f6647b7b07 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -207,7 +207,7 @@ static struct snd_soc_jack_pin cht_bsw_jack_pins[] = { static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -479,9 +479,21 @@ static struct snd_soc_dai_link cht_dailink[] = { }, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_RT5645_NAME "bytcht rt5645" /* card name 'sof-bytcht rt5645' */ +#define CARD_RT5650_NAME "bytcht rt5650" /* card name 'sof-bytcht rt5650' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_RT5645_NAME "chtrt5645" +#define CARD_RT5650_NAME "chtrt5650" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card snd_soc_card_chtrt5645 = { - .name = "chtrt5645", + .name = CARD_RT5645_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = cht_dailink, .num_links = ARRAY_SIZE(cht_dailink), @@ -494,7 +506,8 @@ static struct snd_soc_card snd_soc_card_chtrt5645 = { }; static struct snd_soc_card snd_soc_card_chtrt5650 = { - .name = "chtrt5650", + .name = CARD_RT5650_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = cht_dailink, .num_links = ARRAY_SIZE(cht_dailink), diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 22e432768edb3e9702aba9e6ce6d45b65438d898..8442be93eb1c6bf8ecb47f05893c8e0b7a8b5346 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -143,7 +143,7 @@ static const struct snd_kcontrol_new cht_mc_controls[] = { static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -253,13 +253,17 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); /* - * Default mode for SSP configuration is TDM 4 slot. One board/design, - * the Lenovo Miix 2 10 uses not 1 but 2 codecs connected to SSP2. The - * second piggy-backed, output-only codec is inside the keyboard-dock - * (which has extra speakers). Unlike the main rt5672 codec, we cannot - * configure this codec, it is hard coded to use 2 channel 24 bit I2S. - * Since we only support 2 channels anyways, there is no need for TDM - * on any cht-bsw-rt5672 designs. So we simply use I2S 2ch everywhere. + * The default mode for the cpu-dai is TDM 4 slot. The default mode + * for the codec-dai is I2S. So we need to either set the cpu-dai to + * I2S mode to match the codec-dai, or set the codec-dai to TDM 4 slot + * (or program both to yet another mode). + * One board, the Lenovo Miix 2 10, uses not 1 but 2 codecs connected + * to SSP2. The second piggy-backed, output-only codec is inside the + * keyboard-dock (which has extra speakers). Unlike the main rt5672 + * codec, we cannot configure this codec, it is hard coded to use + * 2 channel 24 bit I2S. For this to work we must use I2S mode on this + * board. Since we only support 2 channels anyways, there is no need + * for TDM on any cht-bsw-rt5672 designs. So we use I2S 2ch everywhere. */ ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | @@ -378,9 +382,19 @@ static int cht_resume_post(struct snd_soc_card *card) return 0; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +/* use space before codec name to simplify card ID, and simplify driver name */ +#define CARD_NAME "bytcht rt5672" /* card name will be 'sof-bytcht rt5672' */ +#define DRIVER_NAME "SOF" +#else +#define CARD_NAME "cht-bsw-rt5672" +#define DRIVER_NAME NULL /* card name will be used for driver name */ +#endif + /* SoC card */ static struct snd_soc_card snd_soc_card_cht = { - .name = "cht-bsw-rt5672", + .name = CARD_NAME, + .driver_name = DRIVER_NAME, .owner = THIS_MODULE, .dai_link = cht_dailink, .num_links = ARRAY_SIZE(cht_dailink), diff --git a/sound/soc/intel/boards/cml_rt1011_rt5682.c b/sound/soc/intel/boards/cml_rt1011_rt5682.c index 68eff29daf8f8f2f972ccffba64da5740de822dc..14813beb33d168ae6d71ce77521cd5412d1f47a2 100644 --- a/sound/soc/intel/boards/cml_rt1011_rt5682.c +++ b/sound/soc/intel/boards/cml_rt1011_rt5682.c @@ -34,7 +34,6 @@ #define SOF_RT1011_SPEAKER_WR BIT(1) #define SOF_RT1011_SPEAKER_TL BIT(2) #define SOF_RT1011_SPEAKER_TR BIT(3) -#define SPK_CH 4 /* Default: Woofer speakers */ static unsigned long sof_rt1011_quirk = SOF_RT1011_SPEAKER_WL | @@ -161,6 +160,13 @@ static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; }; +static void cml_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; + + snd_soc_component_set_jack(component, NULL, NULL); +} + static int cml_rt1011_spk_init(struct snd_soc_pcm_runtime *rtd) { int ret = 0; @@ -193,7 +199,7 @@ static int cml_rt1011_spk_init(struct snd_soc_pcm_runtime *rtd) static int cml_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int clk_id, clk_freq, pll_out, ret; @@ -226,7 +232,7 @@ static int cml_rt5682_hw_params(struct snd_pcm_substream *substream, static int cml_rt1011_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; struct snd_soc_card *card = rtd->card; int srate, i, ret = 0; @@ -376,10 +382,17 @@ SND_SOC_DAILINK_DEF(ssp0_codec, SND_SOC_DAILINK_DEF(ssp1_pin, DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); -SND_SOC_DAILINK_DEF(ssp1_codec, +SND_SOC_DAILINK_DEF(ssp1_codec_2spk, DAILINK_COMP_ARRAY( /* WL */ COMP_CODEC("i2c-10EC1011:00", CML_RT1011_CODEC_DAI), /* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI))); +SND_SOC_DAILINK_DEF(ssp1_codec_4spk, + DAILINK_COMP_ARRAY( + /* WL */ COMP_CODEC("i2c-10EC1011:00", CML_RT1011_CODEC_DAI), + /* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI), + /* TL */ COMP_CODEC("i2c-10EC1011:02", CML_RT1011_CODEC_DAI), + /* TR */ COMP_CODEC("i2c-10EC1011:03", CML_RT1011_CODEC_DAI))); + SND_SOC_DAILINK_DEF(dmic_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); @@ -415,6 +428,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { .name = "SSP0-Codec", .id = 0, .init = cml_rt5682_codec_init, + .exit = cml_rt5682_codec_exit, .ignore_pmdown_time = 1, .ops = &cml_rt5682_ops, .dpcm_playback = 1, @@ -475,7 +489,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { .no_pcm = 1, .init = cml_rt1011_spk_init, .ops = &cml_rt1011_ops, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec_2spk, platform), }, }; @@ -488,11 +502,21 @@ static struct snd_soc_codec_conf rt1011_conf[] = { .dlc = COMP_CODEC_CONF("i2c-10EC1011:01"), .name_prefix = "WR", }, + /* single configuration structure for 2 and 4 channels */ + { + .dlc = COMP_CODEC_CONF("i2c-10EC1011:02"), + .name_prefix = "TL", + }, + { + .dlc = COMP_CODEC_CONF("i2c-10EC1011:03"), + .name_prefix = "TR", + }, }; /* Cometlake audio machine driver for RT1011 and RT5682 */ static struct snd_soc_card snd_soc_card_cml = { .name = "cml_rt1011_rt5682", + .owner = THIS_MODULE, .dai_link = cml_rt1011_rt5682_dailink, .num_links = ARRAY_SIZE(cml_rt1011_rt5682_dailink), .codec_conf = rt1011_conf, @@ -509,8 +533,7 @@ static struct snd_soc_card snd_soc_card_cml = { static int snd_cml_rt1011_probe(struct platform_device *pdev) { - struct snd_soc_dai_link_component *rt1011_dais_components; - struct snd_soc_codec_conf *rt1011_dais_confs; + struct snd_soc_dai_link *dai_link; struct card_private *ctx; struct snd_soc_acpi_mach *mach; const char *platform_name; @@ -527,67 +550,16 @@ static int snd_cml_rt1011_probe(struct platform_device *pdev) dmi_check_system(sof_rt1011_quirk_table); - dev_info(&pdev->dev, "sof_rt1011_quirk = %lx\n", sof_rt1011_quirk); + dev_dbg(&pdev->dev, "sof_rt1011_quirk = %lx\n", sof_rt1011_quirk); + /* when 4 speaker is available, update codec config */ if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL | SOF_RT1011_SPEAKER_TR)) { - rt1011_dais_confs = devm_kzalloc(&pdev->dev, - sizeof(struct snd_soc_codec_conf) * - SPK_CH, GFP_KERNEL); - - if (!rt1011_dais_confs) - return -ENOMEM; - - rt1011_dais_components = devm_kzalloc(&pdev->dev, - sizeof(struct snd_soc_dai_link_component) * - SPK_CH, GFP_KERNEL); - - if (!rt1011_dais_components) - return -ENOMEM; - - for (i = 0; i < SPK_CH; i++) { - rt1011_dais_confs[i].dlc.name = devm_kasprintf(&pdev->dev, - GFP_KERNEL, - "i2c-10EC1011:0%d", - i); - - if (!rt1011_dais_confs[i].dlc.name) - return -ENOMEM; - - switch (i) { - case 0: - rt1011_dais_confs[i].name_prefix = "WL"; - break; - case 1: - rt1011_dais_confs[i].name_prefix = "WR"; - break; - case 2: - rt1011_dais_confs[i].name_prefix = "TL"; - break; - case 3: - rt1011_dais_confs[i].name_prefix = "TR"; - break; - default: - return -EINVAL; - } - rt1011_dais_components[i].name = devm_kasprintf(&pdev->dev, - GFP_KERNEL, - "i2c-10EC1011:0%d", - i); - if (!rt1011_dais_components[i].name) - return -ENOMEM; - - rt1011_dais_components[i].dai_name = CML_RT1011_CODEC_DAI; - } - - snd_soc_card_cml.codec_conf = rt1011_dais_confs; - snd_soc_card_cml.num_configs = SPK_CH; - - for (i = 0; i < ARRAY_SIZE(cml_rt1011_rt5682_dailink); i++) { - if (!strcmp(cml_rt1011_rt5682_dailink[i].codecs->dai_name, - CML_RT1011_CODEC_DAI)) { - cml_rt1011_rt5682_dailink[i].codecs = rt1011_dais_components; - cml_rt1011_rt5682_dailink[i].num_codecs = SPK_CH; + for_each_card_prelinks(&snd_soc_card_cml, i, dai_link) { + if (!strcmp(dai_link->codecs[0].dai_name, + CML_RT1011_CODEC_DAI)) { + dai_link->codecs = ssp1_codec_4spk; + dai_link->num_codecs = ARRAY_SIZE(ssp1_codec_4spk); } } } diff --git a/sound/soc/intel/boards/ehl_rt5660.c b/sound/soc/intel/boards/ehl_rt5660.c index 78160e3b16158e12dd54d76415fd46fb9075a9b2..7c0d4e9154067ea945d3dc26a956b57cb67b4bc5 100644 --- a/sound/soc/intel/boards/ehl_rt5660.c +++ b/sound/soc/intel/boards/ehl_rt5660.c @@ -109,7 +109,7 @@ static int card_late_probe(struct snd_soc_card *card) static int rt5660_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c index 954ab01f695b8f8a117ca4674dcdabd480f81576..62cca511522eaa13874c632bff7adc51008937e1 100644 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c @@ -187,7 +187,7 @@ static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) static int geminilake_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index 74af090f2657e8d029087418c55ebf7a2b87de50..744b7b5b8106b09eb5dbf2899fb3a4795ac8c959 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c @@ -55,7 +55,7 @@ static int haswell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, static int haswell_rt5640_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index e29c31ffd241f1d1adf255ca2a1863d5d9dfb902..cc9a2509ace292620d23db78f6555fc77b70b9f4 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -175,7 +175,7 @@ static const struct snd_soc_dapm_route kabylake_ssp1_map[] = { static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *runtime = substream->private_data; + struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int ret, j; @@ -220,7 +220,7 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, static int kabylake_ssp0_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int j, ret; @@ -455,7 +455,7 @@ static struct snd_pcm_hw_constraint_list constraints_channels_quad = { static int kbl_fe_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_rt = substream->private_data; + struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream); /* * On this platform for PCM device we support, @@ -512,7 +512,7 @@ static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, static int kabylake_dmic_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_rt = substream->private_data; + struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream); runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c index d2a0784547842c9092fca2a79c2fdcc884c8ce61..3a9f91b58e113ac07235ae610db1c0929f526ffe 100644 --- a/sound/soc/intel/boards/kbl_rt5660.c +++ b/sound/soc/intel/boards/kbl_rt5660.c @@ -165,8 +165,8 @@ static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd) dev_warn(component->dev, "Failed to add driver gpios\n"); /* Request rt5660 GPIO for lineout mute control, return if fails */ - ctx->gpio_lo_mute = devm_gpiod_get(component->dev, "lineout-mute", - GPIOD_OUT_HIGH); + 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); @@ -207,6 +207,18 @@ static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd) 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); @@ -243,7 +255,7 @@ static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) static int kabylake_rt5660_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -421,6 +433,7 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { .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_CBS_CFS, diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 09ba55fc36d5180630ca2b99e73fe94c24cf32c1..3ea4602dfb3ee0c1e2a59de237b7258915810fc4 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -430,7 +430,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -468,7 +468,7 @@ static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int ret = 0, j; diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index b34cf6cf11395832c23b6ec4a3b6dc37380cfab6..922cd0176e1ff184e1cfec19685c0792fdd80e90 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -336,22 +336,45 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, 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 = container_of( - params, struct snd_soc_dpcm, hw_params); - struct snd_soc_dai_link *fe_dai_link = dpcm->fe->dai_link; - struct snd_soc_dai_link *be_dai_link = dpcm->be->dai_link; + 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(fe_dai_link->name, "Kbl Audio Port") || - !strcmp(fe_dai_link->name, "Kbl Audio Headset Playback") || - !strcmp(fe_dai_link->name, "Kbl Audio Capture Port")) { + 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(fe_dai_link->name, "Kbl Audio DMIC cap")) { + } 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; @@ -362,7 +385,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, * The speaker on the SSP0 supports S16_LE and not S24_LE. * thus changing the mask here */ - if (!strcmp(be_dai_link->name, "SSP0-Codec")) + if (!strcmp(rtd_dpcm->be->dai_link->name, "SSP0-Codec")) snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); return 0; @@ -371,7 +394,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; @@ -395,7 +418,7 @@ static struct snd_soc_ops kabylake_rt5663_ops = { static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int ret = 0, j; diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h index 507750ef67f300f8101da7a681076618a217597f..4b0b3959182e5532c7049e1410132a7e0ebb5b5e 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.h +++ b/sound/soc/intel/boards/skl_hda_dsp_common.h @@ -33,6 +33,7 @@ struct skl_hda_private { int dai_index; const char *platform_name; bool common_hdmi_codec_drv; + bool idisp_codec; }; extern struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS]; diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 79c8947f840b9c8fa26262c6969b89c693f7be4f..ca4900036ead960694d6ec8d2f1d98e638d64eaf 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -79,6 +79,9 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link) link->platforms->name = ctx->platform_name; link->nonatomic = 1; + if (!ctx->idisp_codec) + return 0; + if (strstr(link->name, "HDMI")) { ret = skl_hda_hdmi_add_pcm(card, ctx->pcm_count); @@ -118,19 +121,20 @@ static char hda_soc_components[30]; static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) { struct snd_soc_card *card = &hda_soc_card; + struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_dai_link *dai_link; - u32 codec_count, codec_mask, idisp_mask; + u32 codec_count, codec_mask; int i, num_links, num_route; codec_mask = mach_params->codec_mask; codec_count = hweight_long(codec_mask); - idisp_mask = codec_mask & IDISP_CODEC_MASK; + ctx->idisp_codec = !!(codec_mask & IDISP_CODEC_MASK); if (!codec_count || codec_count > 2 || - (codec_count == 2 && !idisp_mask)) + (codec_count == 2 && !ctx->idisp_codec)) return -EINVAL; - if (codec_mask == idisp_mask) { + if (codec_mask == IDISP_CODEC_MASK) { /* topology with iDisp as the only HDA codec */ num_links = IDISP_DAI_COUNT + DMIC_DAI_COUNT; num_route = IDISP_ROUTE_COUNT; @@ -152,7 +156,7 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) num_route = ARRAY_SIZE(skl_hda_map); card->dapm_widgets = skl_hda_widgets; card->num_dapm_widgets = ARRAY_SIZE(skl_hda_widgets); - if (!idisp_mask) { + if (!ctx->idisp_codec) { for (i = 0; i < IDISP_DAI_COUNT; i++) { skl_hda_be_dai_links[i].codecs = dummy_codec; skl_hda_be_dai_links[i].num_codecs = @@ -211,6 +215,8 @@ static int skl_hda_audio_probe(struct platform_device *pdev) if (!mach) return -EINVAL; + snd_soc_card_set_drvdata(&hda_soc_card, ctx); + ret = skl_hda_fill_card_info(&mach->mach_params); if (ret < 0) { dev_err(&pdev->dev, "Unsupported HDAudio/iDisp configuration found\n"); @@ -223,7 +229,6 @@ static int skl_hda_audio_probe(struct platform_device *pdev) ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; hda_soc_card.dev = &pdev->dev; - snd_soc_card_set_drvdata(&hda_soc_card, ctx); if (mach->mach_params.dmic_num > 0) { snprintf(hda_soc_components, sizeof(hda_soc_components), diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index d7b8154c43a4b83ef78c7f21d7a14bd2150a61f6..55802900069a21192b2fe6d80a5101f9bb269fcf 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -295,7 +295,7 @@ static const struct snd_soc_ops skylake_nau8825_fe_ops = { static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index 4b317bcf6ea0a2c5e20e80be5c3251f684ef0b22..0c734f3a9364ddd6e7f95d0f8c6bd9fc16e43305 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -347,7 +347,7 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 903ae1b28ec96ec6907555860f4d8aa19418ea58..5a0c64a83146541cf4cb65445cd745178ca6f85d 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -228,7 +228,7 @@ static int skylake_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, static int skylake_rt286_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/intel/boards/sof_da7219_max98373.c b/sound/soc/intel/boards/sof_da7219_max98373.c index 7037038585955a5c477fe125c81361a5a5ea74f4..f3cb0773e70ee8829848c8ba202d8ba82b990aab 100644 --- a/sound/soc/intel/boards/sof_da7219_max98373.c +++ b/sound/soc/intel/boards/sof_da7219_max98373.c @@ -179,7 +179,7 @@ static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd) static int ssp1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *runtime = substream->private_data; + struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); int ret, j; for (j = 0; j < runtime->num_codecs; j++) { diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index 1a549b32d1c904518b7864ef6d4fbc423f2bab35..1a696159202971465bd5b18ca6aca98b1105d6d8 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -9,7 +9,9 @@ #include #include "sof_maxim_common.h" -static const struct snd_soc_dapm_route max_98373_dapm_routes[] = { +#define MAX_98373_PIN_NAME 16 + +const struct snd_soc_dapm_route max_98373_dapm_routes[] = { /* speaker */ { "Left Spk", NULL, "Left BE_OUT" }, { "Right Spk", NULL, "Right BE_OUT" }, @@ -27,11 +29,11 @@ static struct snd_soc_codec_conf max_98373_codec_conf[] = { }; struct snd_soc_dai_link_component max_98373_components[] = { - { /* For Left */ + { /* For Right */ .name = MAX_98373_DEV0_NAME, .dai_name = MAX_98373_CODEC_DAI, }, - { /* For Right */ + { /* For Left */ .name = MAX_98373_DEV1_NAME, .dai_name = MAX_98373_CODEC_DAI, }, @@ -40,25 +42,68 @@ struct snd_soc_dai_link_component max_98373_components[] = { static int max98373_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int j; for_each_rtd_codec_dais(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name, MAX_98373_DEV0_NAME)) { /* DEV0 tdm slot configuration */ - snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); + snd_soc_dai_set_tdm_slot(codec_dai, 0x03, 3, 8, 24); } if (!strcmp(codec_dai->component->name, MAX_98373_DEV1_NAME)) { /* DEV1 tdm slot configuration */ - snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16); + snd_soc_dai_set_tdm_slot(codec_dai, 0x0C, 3, 8, 24); } } return 0; } +int max98373_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai; + int j; + int ret = 0; + + for_each_rtd_codec_dais(rtd, j, codec_dai) { + struct snd_soc_component *component = codec_dai->component; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char pin_name[MAX_98373_PIN_NAME]; + + 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) + snd_soc_dapm_sync(dapm); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + /* Make sure no streams are active before disable pin */ + if (snd_soc_dai_active(codec_dai) != 1) + break; + ret = snd_soc_dapm_disable_pin(dapm, pin_name); + if (!ret) + snd_soc_dapm_sync(dapm); + break; + default: + break; + } + } + + return ret; +} + struct snd_soc_ops max_98373_ops = { .hw_params = max98373_hw_params, + .trigger = max98373_trigger, }; int max98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd) diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h index 785b3433536817d64f9a71ce6f58294592d84d2b..5240b1c9d379b99c9b096b56a9360f48e7579363 100644 --- a/sound/soc/intel/boards/sof_maxim_common.h +++ b/sound/soc/intel/boards/sof_maxim_common.h @@ -18,7 +18,10 @@ extern struct snd_soc_dai_link_component max_98373_components[2]; extern struct snd_soc_ops max_98373_ops; +extern const struct snd_soc_dapm_route max_98373_dapm_routes[]; int max98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd); void sof_max98373_codec_conf(struct snd_soc_card *card); +int max98373_trigger(struct snd_pcm_substream *substream, int cmd); + #endif /* __SOF_MAXIM_COMMON_H */ diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c index 9fa8a49112769254d294ea87cb6c057e0e7bfea3..d2b0456236c72c0b119a692f9c57f0f4b4da7f71 100644 --- a/sound/soc/intel/boards/sof_pcm512x.c +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -96,7 +96,7 @@ static int sof_pcm512x_codec_init(struct snd_soc_pcm_runtime *rtd) static int aif1_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *codec = asoc_rtd_to_codec(rtd, 0)->component; snd_soc_component_update_bits(codec, PCM512x_GPIO_CONTROL_1, @@ -107,7 +107,7 @@ static int aif1_startup(struct snd_pcm_substream *substream) static void aif1_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *codec = asoc_rtd_to_codec(rtd, 0)->component; snd_soc_component_update_bits(codec, PCM512x_GPIO_CONTROL_1, diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 13a48b0c35aef326a4225149387aee6bee3a0a3a..0129d23694ed5be695a92b7bf460436cee1cfa4f 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -43,6 +43,7 @@ ((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK) #define SOF_RT1015_SPEAKER_AMP_PRESENT BIT(13) #define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(14) +#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(15) /* Default: MCLK on, MCLK 19.2M, SSP0 */ static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | @@ -206,10 +207,17 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; }; +static void sof_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; + + snd_soc_component_set_jack(component, NULL, NULL); +} + static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int clk_id, clk_freq, pll_out, ret; @@ -267,7 +275,7 @@ static struct snd_soc_ops sof_rt5682_ops = { static int sof_rt1015_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *codec_dai; int i, ret; @@ -276,8 +284,15 @@ static int sof_rt1015_hw_params(struct snd_pcm_substream *substream, return 0; for_each_rtd_codec_dais(rtd, i, codec_dai) { + /* Set tdm/i2s1 master bclk ratio */ + ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (ret < 0) { + dev_err(card->dev, "failed to set bclk ratio\n"); + return ret; + } + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, - params_rate(params) * 50, + params_rate(params) * 64, params_rate(params) * 256); if (ret < 0) { dev_err(card->dev, "failed to set pll\n"); @@ -311,6 +326,7 @@ static int sof_card_late_probe(struct snd_soc_card *card) { struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_component *component = NULL; + struct snd_soc_dapm_context *dapm = &card->dapm; char jack_name[NAME_SIZE]; struct sof_hdmi_pcm *pcm; int err; @@ -349,6 +365,14 @@ static int sof_card_late_probe(struct snd_soc_card *card) i++; } + if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) { + /* Disable Left and Right Spk pin after boot */ + snd_soc_dapm_disable_pin(dapm, "Left Spk"); + snd_soc_dapm_disable_pin(dapm, "Right Spk"); + err = snd_soc_dapm_sync(dapm); + if (err < 0) + return err; + } return hdac_hdmi_jack_port_init(component, &card->dapm); } @@ -484,6 +508,13 @@ static struct snd_soc_dai_link_component max98357a_component[] = { } }; +static struct snd_soc_dai_link_component max98360a_component[] = { + { + .name = "MX98360A:00", + .dai_name = "HiFi", + } +}; + static struct snd_soc_dai_link_component rt1015_components[] = { { .name = "i2c-10EC1015:00", @@ -525,6 +556,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].platforms = platform_component; links[id].num_platforms = ARRAY_SIZE(platform_component); links[id].init = sof_rt5682_codec_init; + links[id].exit = sof_rt5682_codec_exit; links[id].ops = &sof_rt5682_ops; links[id].nonatomic = true; links[id].dpcm_playback = 1; @@ -645,6 +677,11 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].num_codecs = ARRAY_SIZE(max_98373_components); links[id].init = max98373_spk_codec_init; links[id].ops = &max_98373_ops; + } else if (sof_rt5682_quirk & + SOF_MAX98360A_SPEAKER_AMP_PRESENT) { + links[id].codecs = max98360a_component; + links[id].num_codecs = ARRAY_SIZE(max98360a_component); + links[id].init = speaker_codec_init; } else { links[id].codecs = max98357a_component; links[id].num_codecs = ARRAY_SIZE(max98357a_component); @@ -786,21 +823,6 @@ static int sof_audio_probe(struct platform_device *pdev) &sof_audio_card_rt5682); } -static int sof_rt5682_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - struct snd_soc_component *component = NULL; - - for_each_card_components(card, component) { - if (!strcmp(component->name, rt5682_component[0].name)) { - snd_soc_component_set_jack(component, NULL, NULL); - break; - } - } - - return 0; -} - static const struct platform_device_id board_ids[] = { { .name = "sof_rt5682", @@ -831,12 +853,20 @@ static const struct platform_device_id board_ids[] = { SOF_RT5682_SSP_AMP(1) | SOF_RT5682_NUM_HDMIDEV(4)), }, + { + .name = "jsl_rt5682_max98360a", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_RT5682_MCLK_24MHZ | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_MAX98360A_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(1)), + }, { } }; static struct platform_driver sof_audio = { .probe = sof_audio_probe, - .remove = sof_rt5682_remove, .driver = { .name = "sof_rt5682", .pm = &snd_soc_pm_ops, @@ -854,3 +884,4 @@ MODULE_ALIAS("platform:sof_rt5682"); MODULE_ALIAS("platform:tgl_max98357a_rt5682"); MODULE_ALIAS("platform:jsl_rt5682_rt1015"); MODULE_ALIAS("platform:tgl_max98373_rt5682"); +MODULE_ALIAS("platform:jsl_rt5682_max98360a"); diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index e1c1a8ba78e6215075729df32acb7ac63b4cffcf..2463d432bf4dcafd43dcae8f7d0c828acd75cf4b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -15,9 +15,32 @@ #include "sof_sdw_common.h" unsigned long sof_sdw_quirk = SOF_RT711_JD_SRC_JD1; +static int quirk_override = -1; +module_param_named(quirk, quirk_override, int, 0444); +MODULE_PARM_DESC(quirk, "Board-specific quirk override"); #define INC_ID(BE, CPU, LINK) do { (BE)++; (CPU)++; (LINK)++; } while (0) +static void log_quirks(struct device *dev) +{ + if (SOF_RT711_JDSRC(sof_sdw_quirk)) + dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", + SOF_RT711_JDSRC(sof_sdw_quirk)); + if (sof_sdw_quirk & SOF_SDW_FOUR_SPK) + dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n"); + if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) + dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n"); + if (sof_sdw_quirk & SOF_SDW_PCH_DMIC) + dev_dbg(dev, "quirk SOF_SDW_PCH_DMIC enabled\n"); + if (SOF_SSP_GET_PORT(sof_sdw_quirk)) + dev_dbg(dev, "SSP port %ld\n", + SOF_SSP_GET_PORT(sof_sdw_quirk)); + if (sof_sdw_quirk & SOF_RT715_DAI_ID_FIX) + dev_dbg(dev, "quirk SOF_RT715_DAI_ID_FIX enabled\n"); + if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION) + dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n"); +} + static int sof_sdw_quirk_cb(const struct dmi_system_id *id) { sof_sdw_quirk = (unsigned long)id->driver_data; @@ -97,7 +120,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Google"), DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"), }, - .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC), + .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | + SOF_SDW_FOUR_SPK), }, {} @@ -136,6 +160,15 @@ static struct snd_soc_codec_conf codec_conf[] = { .dlc = COMP_CODEC_CONF("sdw:3:25d:715:0"), .name_prefix = "rt715", }, + /* two MAX98373s on link1 with different unique id */ + { + .dlc = COMP_CODEC_CONF("sdw:1:19f:8373:0:3"), + .name_prefix = "Right", + }, + { + .dlc = COMP_CODEC_CONF("sdw:1:19f:8373:0:7"), + .name_prefix = "Left", + }, { .dlc = COMP_CODEC_CONF("sdw:0:25d:5682:0"), .name_prefix = "rt5682", @@ -157,12 +190,12 @@ static struct snd_soc_dai_link_component platform_component[] = { }; /* these wrappers are only needed to avoid typecast compilation errors */ -static int sdw_startup(struct snd_pcm_substream *substream) +int sdw_startup(struct snd_pcm_substream *substream) { return sdw_startup_stream(substream); } -static void sdw_shutdown(struct snd_pcm_substream *substream) +void sdw_shutdown(struct snd_pcm_substream *substream) { sdw_shutdown_stream(substream); } @@ -184,6 +217,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .direction = {true, true}, .dai_name = "rt711-aif1", .init = sof_sdw_rt711_init, + .exit = sof_sdw_rt711_exit, }, { .id = 0x1308, @@ -199,6 +233,13 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt715-aif2", .init = sof_sdw_rt715_init, }, + { + .id = 0x8373, + .direction = {true, true}, + .dai_name = "max98373-aif1", + .init = sof_sdw_mx8373_init, + .codec_card_late_probe = sof_sdw_mx8373_late_probe, + }, { .id = 0x5682, .direction = {true, true}, @@ -658,11 +699,14 @@ static inline int get_next_be_id(struct snd_soc_dai_link *links, return links[be_id - 1].id + 1; } +#define IDISP_CODEC_MASK 0x4 + static int sof_card_dai_links_create(struct device *dev, struct snd_soc_acpi_mach *mach, struct snd_soc_card *card) { int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_dai_link_component *idisp_components; struct snd_soc_dai_link_component *ssp_components; struct snd_soc_acpi_mach_params *mach_params; @@ -706,12 +750,15 @@ static int sof_card_dai_links_create(struct device *dev, return ret; } + if (mach_params->codec_mask & IDISP_CODEC_MASK) + ctx->idisp_codec = true; + /* enable dmic01 & dmic16k */ dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC) ? 2 : 0; comp_num += dmic_num; dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num, - dmic_num, hdmi_num); + dmic_num, ctx->idisp_codec ? hdmi_num : 0); /* allocate BE dailinks */ num_links = comp_num + sdw_be_num; @@ -860,13 +907,18 @@ DMIC: if (!name) return -ENOMEM; - idisp_components[i].name = "ehdaudio0D2"; - idisp_components[i].dai_name = devm_kasprintf(dev, - GFP_KERNEL, - "intel-hdmi-hifi%d", - i + 1); - if (!idisp_components[i].dai_name) - return -ENOMEM; + if (ctx->idisp_codec) { + idisp_components[i].name = "ehdaudio0D2"; + idisp_components[i].dai_name = devm_kasprintf(dev, + GFP_KERNEL, + "intel-hdmi-hifi%d", + i + 1); + if (!idisp_components[i].dai_name) + return -ENOMEM; + } else { + idisp_components[i].name = "snd-soc-dummy"; + idisp_components[i].dai_name = "snd-soc-dummy-dai"; + } cpu_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); @@ -888,12 +940,29 @@ DMIC: return 0; } +static int sof_sdw_card_late_probe(struct snd_soc_card *card) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { + if (!codec_info_list[i].late_probe) + continue; + + ret = codec_info_list[i].codec_card_late_probe(card); + if (ret < 0) + return ret; + } + + return sof_sdw_hdmi_card_late_probe(card); +} + /* SoC card */ static const char sdw_card_long_name[] = "Intel Soundwire SOF"; static struct snd_soc_card card_sof_sdw = { .name = "soundwire", - .late_probe = sof_sdw_hdmi_card_late_probe, + .owner = THIS_MODULE, + .late_probe = sof_sdw_card_late_probe, .codec_conf = codec_conf, .num_configs = ARRAY_SIZE(codec_conf), }; @@ -914,9 +983,17 @@ static int mc_probe(struct platform_device *pdev) dmi_check_system(sof_sdw_quirk_table); + if (quirk_override != -1) { + dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", + sof_sdw_quirk, quirk_override); + sof_sdw_quirk = quirk_override; + } + log_quirks(&pdev->dev); + INIT_LIST_HEAD(&ctx->hdmi_pcm_list); card->dev = &pdev->dev; + snd_soc_card_set_drvdata(card, ctx); mach = pdev->dev.platform_data; ret = sof_card_dai_links_create(&pdev->dev, mach, @@ -926,8 +1003,6 @@ static int mc_probe(struct platform_device *pdev) ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; - snd_soc_card_set_drvdata(card, ctx); - /* * the default amp_num is zero for each codec and * amp_num will only be increased for active amp diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 69b363b8a6869672a56737057244dca9e130aad2..12e32439ba46deb3d8656bdcf28706b6e4bb8edd 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -11,6 +11,7 @@ #include #include +#include #define MAX_NO_PROPS 2 #define MAX_HDMI_NUM 4 @@ -61,16 +62,23 @@ struct sof_sdw_codec_info { struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); + + bool late_probe; + int (*codec_card_late_probe)(struct snd_soc_card *card); }; struct mc_private { struct list_head hdmi_pcm_list; bool common_hdmi_codec_drv; + bool idisp_codec; struct snd_soc_jack sdw_headset; }; extern unsigned long sof_sdw_quirk; +int sdw_startup(struct snd_pcm_substream *substream); +void sdw_shutdown(struct snd_pcm_substream *substream); + /* generic HDMI support */ int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd); @@ -84,6 +92,7 @@ int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); +int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link); /* RT700 support */ int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link, @@ -105,6 +114,14 @@ int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link, struct sof_sdw_codec_info *info, bool playback); +/* MAX98373 support */ +int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + +int sof_sdw_mx8373_late_probe(struct snd_soc_card *card); + /* RT5682 support */ int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, diff --git a/sound/soc/intel/boards/sof_sdw_hdmi.c b/sound/soc/intel/boards/sof_sdw_hdmi.c index 0654b38a7e0d3dc7a8108decd4ea41b2a0c85156..99b04bb2f3a05d38a018f079dda1e3b1fed2666d 100644 --- a/sound/soc/intel/boards/sof_sdw_hdmi.c +++ b/sound/soc/intel/boards/sof_sdw_hdmi.c @@ -52,6 +52,12 @@ int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card) int err, i = 0; char jack_name[NAME_SIZE]; + if (!ctx->idisp_codec) + return 0; + + if (list_empty(&ctx->hdmi_pcm_list)) + return -EINVAL; + pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm, head); component = pcm->codec_dai->component; diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c new file mode 100644 index 0000000000000000000000000000000000000000..6437872a9b3d469d19ff0730fdd862f0bb9d9ff3 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_max98373.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2020 Intel Corporation +// +// sof_sdw_max98373 - Helpers to handle 2x MAX98373 +// codec devices from generic machine driver + +#include +#include +#include +#include +#include "sof_sdw_common.h" +#include "sof_maxim_common.h" + +static const struct snd_soc_dapm_widget mx8373_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_kcontrol_new mx8373_controls[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), +}; + +static int spk_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s spk:mx8373", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_add_card_controls(card, mx8373_controls, + ARRAY_SIZE(mx8373_controls)); + if (ret) { + dev_err(card->dev, "mx8373 ctrls addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, mx8373_widgets, + ARRAY_SIZE(mx8373_widgets)); + if (ret) { + dev_err(card->dev, "mx8373 widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes, 2); + if (ret) + dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); + + return ret; +} + +static const struct snd_soc_ops max_98373_sdw_ops = { + .startup = sdw_startup, + .trigger = max98373_trigger, + .shutdown = sdw_shutdown, +}; + +int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + info->amp_num++; + if (info->amp_num == 2) + dai_links->init = spk_init; + + info->late_probe = true; + + dai_links->ops = &max_98373_sdw_ops; + + return 0; +} + +int sof_sdw_mx8373_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_dapm_context *dapm = &card->dapm; + + /* Disable Left and Right Spk pin after boot */ + snd_soc_dapm_disable_pin(dapm, "Left Spk"); + snd_soc_dapm_disable_pin(dapm, "Right Spk"); + return snd_soc_dapm_sync(dapm); +} diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c index 177cc781ada6792f9cbfec050bd423b8c072a3d6..3655e890acecce5cdd8b180b9075fd95ecc9d0f6 100644 --- a/sound/soc/intel/boards/sof_sdw_rt1308.c +++ b/sound/soc/intel/boards/sof_sdw_rt1308.c @@ -91,7 +91,7 @@ static int all_spk_init(struct snd_soc_pcm_runtime *rtd) static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int clk_id, clk_freq, pll_out; diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index d4d75c8dc6b78612c63498d690b6e2c52e627153..606009fa390107662f4a0ed5a240bd6a6732be33 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -133,6 +133,21 @@ static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } +int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link) +{ + struct device *sdw_dev; + + sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, + dai_link->codecs[0].name); + if (!sdw_dev) + return -EINVAL; + + device_remove_properties(sdw_dev); + put_device(sdw_dev); + + return 0; +} + int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, @@ -147,7 +162,7 @@ int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, if (!playback) return 0; - ret = rt711_add_codec_device_props("sdw:0:25d:711:0"); + ret = rt711_add_codec_device_props(dai_links->codecs[0].name); if (ret < 0) return ret; diff --git a/sound/soc/intel/boards/sof_wm8804.c b/sound/soc/intel/boards/sof_wm8804.c index c13fd20da559371e35214108fc34f49b03db4103..a46ba13e8eb0cfa5712312dc5868b8bfecb0688b 100644 --- a/sound/soc/intel/boards/sof_wm8804.c +++ b/sound/soc/intel/boards/sof_wm8804.c @@ -49,7 +49,7 @@ static const struct dmi_system_id sof_wm8804_quirk_table[] = { static int sof_wm8804_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_component *codec = codec_dai->component; diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c index cdea0c09fe0aed290e81de2e31845680eaa82e6e..dee1f0fa998b5bbd902dff4d03d618293c12beb1 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c @@ -19,6 +19,11 @@ static struct snd_soc_acpi_codecs max98357a_spk_codecs = { .codecs = {"MX98357A"} }; +static struct snd_soc_acpi_codecs max98390_spk_codecs = { + .num_codecs = 1, + .codecs = {"MX98390"} +}; + /* * The order of the three entries with .id = "10EC5682" matters * here, because DSDT tables expose an ACPI HID for the MAX98357A @@ -55,6 +60,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = { .sof_fw_filename = "sof-cml.ri", .sof_tplg_filename = "sof-cml-da7219-max98357a.tplg", }, + { + .id = "DLGS7219", + .drv_name = "cml_da7219_max98357a", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &max98390_spk_codecs, + .sof_fw_filename = "sof-cml.ri", + .sof_tplg_filename = "sof-cml-da7219-max98357a.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines); 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 45e07d8860137c0f7464da975170bd567fce8be3..badafc1d54d20f49aa3fdc52909d65cc53e20dd0 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c @@ -12,7 +12,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[] = { { - .id = "INTC1027", + .id = "10EC5660", .drv_name = "ehl_rt5660", .sof_fw_filename = "sof-ehl.ri", .sof_tplg_filename = "sof-ehl-rt5660.tplg", diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c index 859f8a1bd914494424f109b4daa86131f147d877..34f5fcad5701f841f0e7e10a4c5a2e287aa8cbe6 100644 --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c @@ -19,6 +19,11 @@ static struct snd_soc_acpi_codecs rt1015_spk = { .codecs = {"10EC1015"} }; +static struct snd_soc_acpi_codecs mx98360a_spk = { + .num_codecs = 1, + .codecs = {"MX98360A"} +}; + /* * When adding new entry to the snd_soc_acpi_intel_jsl_machines array, * use .quirk_data member to distinguish different machine driver, @@ -47,6 +52,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = { .quirk_data = &rt1015_spk, .sof_tplg_filename = "sof-jsl-rt5682-rt1015.tplg", }, + { + .id = "10EC5682", + .drv_name = "jsl_rt5682_max98360a", + .sof_fw_filename = "sof-jsl.ri", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &mx98360a_spk, + .sof_tplg_filename = "sof-jsl-rt5682-mx98360a.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines); diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 5a56f43594799c1898ff195361ef25668fd324d2..2ffa608d987dd0b3c06d7695f00b2d03ceef2c72 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -56,6 +56,19 @@ static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = { } }; +static const struct snd_soc_acpi_adr_device mx8373_1_adr[] = { + { + .adr = 0x000123019F837300, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + }, + { + .adr = 0x000127019F837300, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + } +}; + static const struct snd_soc_acpi_adr_device rt5682_0_adr[] = { { .adr = 0x000021025D568200, @@ -93,6 +106,11 @@ static const struct snd_soc_acpi_link_adr tgl_chromebook_base[] = { .num_adr = ARRAY_SIZE(rt5682_0_adr), .adr_d = rt5682_0_adr, }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(mx8373_1_adr), + .adr_d = mx8373_1_adr, + }, {} }; @@ -139,6 +157,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { .sof_fw_filename = "sof-tgl.ri", .sof_tplg_filename = "sof-tgl-rt711-rt1308.tplg", }, + { + .link_mask = 0x3, /* rt5682 on link0 & 2xmax98373 on link 1 */ + .links = tgl_chromebook_base, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-tgl.ri", + .sof_tplg_filename = "sof-tgl-sdw-max98373-rt5682.tplg", + }, { .link_mask = 0x1, /* this will only enable rt5682 for now */ .links = tgl_chromebook_base, diff --git a/sound/soc/intel/haswell/sst-haswell-pcm.c b/sound/soc/intel/haswell/sst-haswell-pcm.c index 16ac16f5a641fe67199fd0983aa72193212024a0..b8d86c74c53d4342b2c606543d79d2d6ced4b0b8 100644 --- a/sound/soc/intel/haswell/sst-haswell-pcm.c +++ b/sound/soc/intel/haswell/sst-haswell-pcm.c @@ -462,7 +462,7 @@ static int hsw_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct hsw_pcm_data *pcm_data; @@ -652,7 +652,7 @@ static int hsw_pcm_hw_params(struct snd_soc_component *component, static int hsw_pcm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct hsw_pcm_data *pcm_data; struct sst_hsw_stream *sst_stream; @@ -695,7 +695,7 @@ static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data) struct hsw_pcm_data *pcm_data = data; struct snd_pcm_substream *substream = pcm_data->substream; struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct sst_hsw *hsw = pdata->hsw; @@ -760,7 +760,7 @@ static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data) static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct hsw_pcm_data *pcm_data; @@ -785,7 +785,7 @@ static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_soc_component *component, static int hsw_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct hsw_pcm_data *pcm_data; struct sst_hsw *hsw = pdata->hsw; @@ -818,7 +818,7 @@ static int hsw_pcm_open(struct snd_soc_component *component, static int hsw_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component); struct hsw_pcm_data *pcm_data; struct sst_hsw *hsw = pdata->hsw; diff --git a/sound/soc/intel/keembay/Makefile b/sound/soc/intel/keembay/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9084e8c6385451ae9533524712432f27dd24ebf8 --- /dev/null +++ b/sound/soc/intel/keembay/Makefile @@ -0,0 +1,4 @@ +snd-soc-kmb_platform-objs := \ + kmb_platform.o + +obj-$(CONFIG_SND_SOC_INTEL_KEEMBAY) += snd-soc-kmb_platform.o diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..16f9fc4c663d1e24e75bc513e06fb423329d6cb7 --- /dev/null +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -0,0 +1,668 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (C) 2020 Intel Corporation. +// +// Intel KeemBay Platform driver. +// + +#include +#include +#include +#include +#include +#include +#include "kmb_platform.h" + +#define PERIODS_MIN 2 +#define PERIODS_MAX 48 +#define PERIOD_BYTES_MIN 4096 +#define BUFFER_BYTES_MAX (PERIODS_MAX * PERIOD_BYTES_MIN) +#define TDM_OPERATION 1 +#define I2S_OPERATION 0 +#define DATA_WIDTH_CONFIG_BIT 6 +#define TDM_CHANNEL_CONFIG_BIT 3 + +static const struct snd_pcm_hardware kmb_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH | + SNDRV_PCM_INFO_BLOCK_TRANSFER, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000, + .rate_min = 8000, + .rate_max = 48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = BUFFER_BYTES_MAX, + .period_bytes_min = PERIOD_BYTES_MIN, + .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN, + .periods_min = PERIODS_MIN, + .periods_max = PERIODS_MAX, + .fifo_size = 16, +}; + +static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s, + struct snd_pcm_runtime *runtime, + unsigned int tx_ptr, bool *period_elapsed) +{ + unsigned int period_pos = tx_ptr % runtime->period_size; + void __iomem *i2s_base = kmb_i2s->i2s_base; + void *buf = runtime->dma_area; + int i; + + /* KMB i2s uses two separate L/R FIFO */ + for (i = 0; i < kmb_i2s->fifo_th; i++) { + if (kmb_i2s->config.data_width == 16) { + writel(((u16(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0)); + writel(((u16(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0)); + } else { + writel(((u32(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0)); + writel(((u32(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0)); + } + + period_pos++; + + if (++tx_ptr >= runtime->buffer_size) + tx_ptr = 0; + } + + *period_elapsed = period_pos >= runtime->period_size; + + return tx_ptr; +} + +static unsigned int kmb_pcm_rx_fn(struct kmb_i2s_info *kmb_i2s, + struct snd_pcm_runtime *runtime, + unsigned int rx_ptr, bool *period_elapsed) +{ + unsigned int period_pos = rx_ptr % runtime->period_size; + void __iomem *i2s_base = kmb_i2s->i2s_base; + void *buf = runtime->dma_area; + int i; + + /* KMB i2s uses two separate L/R FIFO */ + for (i = 0; i < kmb_i2s->fifo_th; i++) { + if (kmb_i2s->config.data_width == 16) { + ((u16(*)[2])buf)[rx_ptr][0] = readl(i2s_base + LRBR_LTHR(0)); + ((u16(*)[2])buf)[rx_ptr][1] = readl(i2s_base + RRBR_RTHR(0)); + } else { + ((u32(*)[2])buf)[rx_ptr][0] = readl(i2s_base + LRBR_LTHR(0)); + ((u32(*)[2])buf)[rx_ptr][1] = readl(i2s_base + RRBR_RTHR(0)); + } + + period_pos++; + + if (++rx_ptr >= runtime->buffer_size) + rx_ptr = 0; + } + + *period_elapsed = period_pos >= runtime->period_size; + + return rx_ptr; +} + +static inline void kmb_i2s_disable_channels(struct kmb_i2s_info *kmb_i2s, + u32 stream) +{ + u32 i; + + /* Disable all channels regardless of configuration*/ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + for (i = 0; i < MAX_ISR; i++) + writel(0, kmb_i2s->i2s_base + TER(i)); + } else { + for (i = 0; i < MAX_ISR; i++) + writel(0, kmb_i2s->i2s_base + RER(i)); + } +} + +static inline void kmb_i2s_clear_irqs(struct kmb_i2s_info *kmb_i2s, u32 stream) +{ + struct i2s_clk_config_data *config = &kmb_i2s->config; + u32 i; + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + for (i = 0; i < config->chan_nr / 2; i++) + readl(kmb_i2s->i2s_base + TOR(i)); + } else { + for (i = 0; i < config->chan_nr / 2; i++) + readl(kmb_i2s->i2s_base + ROR(i)); + } +} + +static inline void kmb_i2s_irq_trigger(struct kmb_i2s_info *kmb_i2s, + u32 stream, int chan_nr, bool trigger) +{ + u32 i, irq; + u32 flag; + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + flag = TX_INT_FLAG; + else + flag = RX_INT_FLAG; + + for (i = 0; i < chan_nr / 2; i++) { + irq = readl(kmb_i2s->i2s_base + IMR(i)); + + if (trigger) + irq = irq & ~flag; + else + irq = irq | flag; + + writel(irq, kmb_i2s->i2s_base + IMR(i)); + } +} + +static void kmb_pcm_operation(struct kmb_i2s_info *kmb_i2s, bool playback) +{ + struct snd_pcm_substream *substream; + bool period_elapsed; + unsigned int new_ptr; + unsigned int ptr; + + if (playback) + substream = kmb_i2s->tx_substream; + else + substream = kmb_i2s->rx_substream; + + if (!substream || !snd_pcm_running(substream)) + return; + + if (playback) { + ptr = kmb_i2s->tx_ptr; + new_ptr = kmb_pcm_tx_fn(kmb_i2s, substream->runtime, + ptr, &period_elapsed); + cmpxchg(&kmb_i2s->tx_ptr, ptr, new_ptr); + } else { + ptr = kmb_i2s->rx_ptr; + new_ptr = kmb_pcm_rx_fn(kmb_i2s, substream->runtime, + ptr, &period_elapsed); + cmpxchg(&kmb_i2s->rx_ptr, ptr, new_ptr); + } + + if (period_elapsed) + snd_pcm_period_elapsed(substream); +} + +static int kmb_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct kmb_i2s_info *kmb_i2s; + + kmb_i2s = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); + snd_soc_set_runtime_hwparams(substream, &kmb_pcm_hardware); + snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + runtime->private_data = kmb_i2s; + + return 0; +} + +static int kmb_pcm_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct kmb_i2s_info *kmb_i2s = runtime->private_data; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + kmb_i2s->tx_ptr = 0; + kmb_i2s->tx_substream = substream; + } else { + kmb_i2s->rx_ptr = 0; + kmb_i2s->rx_substream = substream; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + kmb_i2s->tx_substream = NULL; + else + kmb_i2s->rx_substream = NULL; + break; + default: + return -EINVAL; + } + + return 0; +} + +static irqreturn_t kmb_i2s_irq_handler(int irq, void *dev_id) +{ + struct kmb_i2s_info *kmb_i2s = dev_id; + struct i2s_clk_config_data *config = &kmb_i2s->config; + irqreturn_t ret = IRQ_NONE; + u32 isr[4]; + int i; + + for (i = 0; i < config->chan_nr / 2; i++) + isr[i] = readl(kmb_i2s->i2s_base + ISR(i)); + + kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_PLAYBACK); + kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_CAPTURE); + + for (i = 0; i < config->chan_nr / 2; i++) { + /* + * Check if TX fifo is empty. If empty fill FIFO with samples + */ + if ((isr[i] & ISR_TXFE)) { + kmb_pcm_operation(kmb_i2s, true); + ret = IRQ_HANDLED; + } + /* + * Data available. Retrieve samples from FIFO + */ + if ((isr[i] & ISR_RXDA)) { + kmb_pcm_operation(kmb_i2s, false); + ret = IRQ_HANDLED; + } + /* Error Handling: TX */ + if (isr[i] & ISR_TXFO) { + dev_dbg(kmb_i2s->dev, "TX overrun (ch_id=%d)\n", i); + ret = IRQ_HANDLED; + } + /* Error Handling: RX */ + if (isr[i] & ISR_RXFO) { + dev_dbg(kmb_i2s->dev, "RX overrun (ch_id=%d)\n", i); + ret = IRQ_HANDLED; + } + } + + return ret; +} + +static int kmb_platform_pcm_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *soc_runtime) +{ + size_t size = kmb_pcm_hardware.buffer_bytes_max; + /* Use SNDRV_DMA_TYPE_CONTINUOUS as KMB doesn't use PCI sg buffer */ + snd_pcm_set_managed_buffer_all(soc_runtime->pcm, + SNDRV_DMA_TYPE_CONTINUOUS, + NULL, size, size); + return 0; +} + +static snd_pcm_uframes_t kmb_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct kmb_i2s_info *kmb_i2s = runtime->private_data; + snd_pcm_uframes_t pos; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + pos = kmb_i2s->tx_ptr; + else + pos = kmb_i2s->rx_ptr; + + return pos < runtime->buffer_size ? pos : 0; +} + +static const struct snd_soc_component_driver kmb_component = { + .name = "kmb", + .pcm_construct = kmb_platform_pcm_new, + .open = kmb_pcm_open, + .trigger = kmb_pcm_trigger, + .pointer = kmb_pcm_pointer, +}; + +static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s, + struct snd_pcm_substream *substream) +{ + struct i2s_clk_config_data *config = &kmb_i2s->config; + + /* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */ + writel(1, kmb_i2s->i2s_base + IER); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + writel(1, kmb_i2s->i2s_base + ITER); + else + writel(1, kmb_i2s->i2s_base + IRER); + + kmb_i2s_irq_trigger(kmb_i2s, substream->stream, config->chan_nr, true); + + if (kmb_i2s->master) + writel(1, kmb_i2s->i2s_base + CER); + else + writel(0, kmb_i2s->i2s_base + CER); +} + +static void kmb_i2s_stop(struct kmb_i2s_info *kmb_i2s, + struct snd_pcm_substream *substream) +{ + /* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */ + kmb_i2s_clear_irqs(kmb_i2s, substream->stream); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + writel(0, kmb_i2s->i2s_base + ITER); + else + writel(0, kmb_i2s->i2s_base + IRER); + + kmb_i2s_irq_trigger(kmb_i2s, substream->stream, 8, false); + + if (!kmb_i2s->active) { + writel(0, kmb_i2s->i2s_base + CER); + writel(0, kmb_i2s->i2s_base + IER); + } +} + +static void kmb_disable_clk(void *clk) +{ + clk_disable_unprepare(clk); +} + +static int kmb_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + int ret; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + kmb_i2s->master = false; + ret = 0; + break; + case SND_SOC_DAIFMT_CBS_CFS: + writel(MASTER_MODE, kmb_i2s->pss_base + I2S_GEN_CFG_0); + + ret = clk_prepare_enable(kmb_i2s->clk_i2s); + if (ret < 0) + return ret; + + ret = devm_add_action_or_reset(kmb_i2s->dev, kmb_disable_clk, + kmb_i2s->clk_i2s); + if (ret) + return ret; + + kmb_i2s->master = true; + break; + default: + return -EINVAL; + } + + return ret; +} + +static int kmb_dai_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + /* Keep track of i2s activity before turn off + * the i2s interface + */ + kmb_i2s->active++; + kmb_i2s_start(kmb_i2s, substream); + break; + case SNDRV_PCM_TRIGGER_STOP: + kmb_i2s->active--; + kmb_i2s_stop(kmb_i2s, substream); + break; + default: + return -EINVAL; + } + + return 0; +} + +static void kmb_i2s_config(struct kmb_i2s_info *kmb_i2s, int stream) +{ + struct i2s_clk_config_data *config = &kmb_i2s->config; + u32 ch_reg; + + kmb_i2s_disable_channels(kmb_i2s, stream); + + for (ch_reg = 0; ch_reg < config->chan_nr / 2; ch_reg++) { + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + writel(kmb_i2s->xfer_resolution, + kmb_i2s->i2s_base + TCR(ch_reg)); + + writel(kmb_i2s->fifo_th - 1, + kmb_i2s->i2s_base + TFCR(ch_reg)); + + writel(1, kmb_i2s->i2s_base + TER(ch_reg)); + } else { + writel(kmb_i2s->xfer_resolution, + kmb_i2s->i2s_base + RCR(ch_reg)); + + writel(kmb_i2s->fifo_th - 1, + kmb_i2s->i2s_base + RFCR(ch_reg)); + + writel(1, kmb_i2s->i2s_base + RER(ch_reg)); + } + } +} + +static int kmb_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params, + struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + struct i2s_clk_config_data *config = &kmb_i2s->config; + u32 register_val, write_val; + int ret; + + switch (params_format(hw_params)) { + case SNDRV_PCM_FORMAT_S16_LE: + config->data_width = 16; + kmb_i2s->ccr = 0x00; + kmb_i2s->xfer_resolution = 0x02; + break; + case SNDRV_PCM_FORMAT_S24_LE: + config->data_width = 24; + kmb_i2s->ccr = 0x08; + kmb_i2s->xfer_resolution = 0x04; + break; + case SNDRV_PCM_FORMAT_S32_LE: + config->data_width = 32; + kmb_i2s->ccr = 0x10; + kmb_i2s->xfer_resolution = 0x05; + break; + default: + dev_err(kmb_i2s->dev, "kmb: unsupported PCM fmt"); + return -EINVAL; + } + + config->chan_nr = params_channels(hw_params); + + switch (config->chan_nr) { + /* TODO: This switch case will handle up to TDM8 in the near future */ + case TWO_CHANNEL_SUPPORT: + write_val = ((config->chan_nr / 2) << TDM_CHANNEL_CONFIG_BIT) | + (config->data_width << DATA_WIDTH_CONFIG_BIT) | + MASTER_MODE | I2S_OPERATION; + + writel(write_val, kmb_i2s->pss_base + I2S_GEN_CFG_0); + + register_val = readl(kmb_i2s->pss_base + I2S_GEN_CFG_0); + dev_dbg(kmb_i2s->dev, "pss register = 0x%X", register_val); + break; + default: + dev_dbg(kmb_i2s->dev, "channel not supported\n"); + return -EINVAL; + } + + kmb_i2s_config(kmb_i2s, substream->stream); + + writel(kmb_i2s->ccr, kmb_i2s->i2s_base + CCR); + + config->sample_rate = params_rate(hw_params); + + if (kmb_i2s->master) { + /* Only 2 ch supported in Master mode */ + u32 bitclk = config->sample_rate * config->data_width * 2; + + ret = clk_set_rate(kmb_i2s->clk_i2s, bitclk); + if (ret) { + dev_err(kmb_i2s->dev, + "Can't set I2S clock rate: %d\n", ret); + return ret; + } + } + + return 0; +} + +static int kmb_dai_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + writel(1, kmb_i2s->i2s_base + TXFFR); + else + writel(1, kmb_i2s->i2s_base + RXFFR); + + return 0; +} + +static struct snd_soc_dai_ops kmb_dai_ops = { + .trigger = kmb_dai_trigger, + .hw_params = kmb_dai_hw_params, + .prepare = kmb_dai_prepare, + .set_fmt = kmb_set_dai_fmt, +}; + +static struct snd_soc_dai_driver intel_kmb_platform_dai[] = { + { + .name = "kmb-plat-dai", + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000, + .rate_min = 8000, + .rate_max = 48000, + .formats = (SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S16_LE), + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + /* + * .channels_max will be overwritten + * if provided by Device Tree + */ + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000, + .rate_min = 8000, + .rate_max = 48000, + .formats = (SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S16_LE), + }, + .ops = &kmb_dai_ops, + }, +}; + +static int kmb_plat_dai_probe(struct platform_device *pdev) +{ + struct snd_soc_dai_driver *kmb_i2s_dai; + struct device *dev = &pdev->dev; + struct kmb_i2s_info *kmb_i2s; + int ret, irq; + u32 comp1_reg; + + kmb_i2s = devm_kzalloc(dev, sizeof(*kmb_i2s), GFP_KERNEL); + if (!kmb_i2s) + return -ENOMEM; + + kmb_i2s_dai = devm_kzalloc(dev, sizeof(*kmb_i2s_dai), GFP_KERNEL); + if (!kmb_i2s_dai) + return -ENOMEM; + + kmb_i2s_dai->ops = &kmb_dai_ops; + + /* Prepare the related clocks */ + kmb_i2s->clk_apb = devm_clk_get(dev, "apb_clk"); + if (IS_ERR(kmb_i2s->clk_apb)) { + dev_err(dev, "Failed to get apb clock\n"); + return PTR_ERR(kmb_i2s->clk_apb); + } + + ret = clk_prepare_enable(kmb_i2s->clk_apb); + if (ret < 0) + return ret; + + ret = devm_add_action_or_reset(dev, kmb_disable_clk, kmb_i2s->clk_apb); + if (ret) { + dev_err(dev, "Failed to add clk_apb reset action\n"); + return ret; + } + + kmb_i2s->clk_i2s = devm_clk_get(dev, "osc"); + if (IS_ERR(kmb_i2s->clk_i2s)) { + dev_err(dev, "Failed to get osc clock\n"); + return PTR_ERR(kmb_i2s->clk_i2s); + } + + kmb_i2s->i2s_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(kmb_i2s->i2s_base)) + return PTR_ERR(kmb_i2s->i2s_base); + + kmb_i2s->pss_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(kmb_i2s->pss_base)) + return PTR_ERR(kmb_i2s->pss_base); + + kmb_i2s->dev = &pdev->dev; + + irq = platform_get_irq_optional(pdev, 0); + if (irq > 0) { + ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0, + pdev->name, kmb_i2s); + if (ret < 0) { + dev_err(dev, "failed to request irq\n"); + return ret; + } + } + + comp1_reg = readl(kmb_i2s->i2s_base + I2S_COMP_PARAM_1); + + kmb_i2s->fifo_th = (1 << COMP1_FIFO_DEPTH(comp1_reg)) / 2; + + ret = devm_snd_soc_register_component(dev, &kmb_component, + intel_kmb_platform_dai, + ARRAY_SIZE(intel_kmb_platform_dai)); + if (ret) { + dev_err(dev, "not able to register dai\n"); + return ret; + } + + /* To ensure none of the channels are enabled at boot up */ + kmb_i2s_disable_channels(kmb_i2s, SNDRV_PCM_STREAM_PLAYBACK); + kmb_i2s_disable_channels(kmb_i2s, SNDRV_PCM_STREAM_CAPTURE); + + dev_set_drvdata(dev, kmb_i2s); + + return ret; +} + +static const struct of_device_id kmb_plat_of_match[] = { + { .compatible = "intel,keembay-i2s", }, + {} +}; + +static struct platform_driver kmb_plat_dai_driver = { + .driver = { + .name = "kmb-plat-dai", + .of_match_table = kmb_plat_of_match, + }, + .probe = kmb_plat_dai_probe, +}; + +module_platform_driver(kmb_plat_dai_driver); + +MODULE_DESCRIPTION("ASoC Intel KeemBay Platform driver"); +MODULE_AUTHOR("Sia Jee Heng "); +MODULE_AUTHOR("Sit, Michael Wei Hong "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:kmb_platform"); diff --git a/sound/soc/intel/keembay/kmb_platform.h b/sound/soc/intel/keembay/kmb_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..9756b132c12ff12fa648bf84ad336c3ddd4d3f1b --- /dev/null +++ b/sound/soc/intel/keembay/kmb_platform.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Intel KeemBay Platform driver + * + * Copyright (C) 2020 Intel Corporation. + * + */ + +#ifndef KMB_PLATFORM_H_ +#define KMB_PLATFORM_H_ + +#include +#include +#include + +/* Register values with reference to KMB databook v1.1 */ +/* common register for all channel */ +#define IER 0x000 +#define IRER 0x004 +#define ITER 0x008 +#define CER 0x00C +#define CCR 0x010 +#define RXFFR 0x014 +#define TXFFR 0x018 + +/* Interrupt status register fields */ +#define ISR_TXFO BIT(5) +#define ISR_TXFE BIT(4) +#define ISR_RXFO BIT(1) +#define ISR_RXDA BIT(0) + +/* I2S Tx Rx Registers for all channels */ +#define LRBR_LTHR(x) (0x40 * (x) + 0x020) +#define RRBR_RTHR(x) (0x40 * (x) + 0x024) +#define RER(x) (0x40 * (x) + 0x028) +#define TER(x) (0x40 * (x) + 0x02C) +#define RCR(x) (0x40 * (x) + 0x030) +#define TCR(x) (0x40 * (x) + 0x034) +#define ISR(x) (0x40 * (x) + 0x038) +#define IMR(x) (0x40 * (x) + 0x03C) +#define ROR(x) (0x40 * (x) + 0x040) +#define TOR(x) (0x40 * (x) + 0x044) +#define RFCR(x) (0x40 * (x) + 0x048) +#define TFCR(x) (0x40 * (x) + 0x04C) +#define RFF(x) (0x40 * (x) + 0x050) +#define TFF(x) (0x40 * (x) + 0x054) + +/* I2S COMP Registers */ +#define I2S_COMP_PARAM_2 0x01F0 +#define I2S_COMP_PARAM_1 0x01F4 +#define I2S_COMP_VERSION 0x01F8 +#define I2S_COMP_TYPE 0x01FC + +/* PSS_GEN_CTRL_I2S_GEN_CFG_0 Registers */ +#define I2S_GEN_CFG_0 0x000 +#define PSS_CPR_RST_EN 0x010 +#define PSS_CPR_RST_SET 0x014 +#define PSS_CPR_CLK_CLR 0x000 +#define PSS_CPR_AUX_RST_EN 0x070 + +#define MASTER_MODE BIT(13) + +/* Interrupt Flag */ +#define TX_INT_FLAG GENMASK(5, 4) +#define RX_INT_FLAG GENMASK(1, 0) +/* + * Component parameter register fields - define the I2S block's + * configuration. + */ +#define COMP1_TX_WORDSIZE_3(r) FIELD_GET(GENMASK(27, 25), (r)) +#define COMP1_TX_WORDSIZE_2(r) FIELD_GET(GENMASK(24, 22), (r)) +#define COMP1_TX_WORDSIZE_1(r) FIELD_GET(GENMASK(21, 19), (r)) +#define COMP1_TX_WORDSIZE_0(r) FIELD_GET(GENMASK(18, 16), (r)) +#define COMP1_RX_ENABLED(r) FIELD_GET(BIT(6), (r)) +#define COMP1_TX_ENABLED(r) FIELD_GET(BIT(5), (r)) +#define COMP1_MODE_EN(r) FIELD_GET(BIT(4), (r)) +#define COMP1_APB_DATA_WIDTH(r) FIELD_GET(GENMASK(1, 0), (r)) +#define COMP2_RX_WORDSIZE_3(r) FIELD_GET(GENMASK(12, 10), (r)) +#define COMP2_RX_WORDSIZE_2(r) FIELD_GET(GENMASK(9, 7), (r)) +#define COMP2_RX_WORDSIZE_1(r) FIELD_GET(GENMASK(5, 3), (r)) +#define COMP2_RX_WORDSIZE_0(r) FIELD_GET(GENMASK(2, 0), (r)) + +/* Add 1 to the below registers to indicate the actual size */ +#define COMP1_TX_CHANNELS(r) (FIELD_GET(GENMASK(10, 9), (r)) + 1) +#define COMP1_RX_CHANNELS(r) (FIELD_GET(GENMASK(8, 7), (r)) + 1) +#define COMP1_FIFO_DEPTH(r) (FIELD_GET(GENMASK(3, 2), (r)) + 1) + +/* Number of entries in WORDSIZE and DATA_WIDTH parameter registers */ +#define COMP_MAX_WORDSIZE 8 /* 3 bits register width */ + +#define MAX_CHANNEL_NUM 8 +#define MIN_CHANNEL_NUM 2 +#define MAX_ISR 4 + +#define TWO_CHANNEL_SUPPORT 2 /* up to 2.0 */ +#define FOUR_CHANNEL_SUPPORT 4 /* up to 3.1 */ +#define SIX_CHANNEL_SUPPORT 6 /* up to 5.1 */ +#define EIGHT_CHANNEL_SUPPORT 8 /* up to 7.1 */ + +#define DWC_I2S_PLAY BIT(0) +#define DWC_I2S_RECORD BIT(1) +#define DW_I2S_SLAVE BIT(2) +#define DW_I2S_MASTER BIT(3) + +#define I2S_RXDMA 0x01C0 +#define I2S_TXDMA 0x01C8 + +/* + * struct i2s_clk_config_data - represent i2s clk configuration data + * @chan_nr: number of channel + * @data_width: number of bits per sample (8/16/24/32 bit) + * @sample_rate: sampling frequency (8Khz, 16Khz, 48Khz) + */ +struct i2s_clk_config_data { + int chan_nr; + u32 data_width; + u32 sample_rate; +}; + +struct kmb_i2s_info { + void __iomem *i2s_base; + void __iomem *pss_base; + struct clk *clk_i2s; + struct clk *clk_apb; + int active; + unsigned int capability; + unsigned int i2s_reg_comp1; + unsigned int i2s_reg_comp2; + struct device *dev; + u32 ccr; + u32 xfer_resolution; + u32 fifo_th; + bool master; + + struct i2s_clk_config_data config; + int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); + + /* data related to PIO transfers */ + bool use_pio; + struct snd_pcm_substream *tx_substream; + struct snd_pcm_substream *rx_substream; + unsigned int tx_ptr; + unsigned int rx_ptr; +}; + +#endif /* KMB_PLATFORM_H_ */ diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 89dcccdfb1cdce6958684874ea3acffec0661640..5dee55e9546bbd936260eaad2d7b986715e511d2 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -544,7 +544,7 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, { struct hdac_bus *bus = dev_get_drvdata(dai->dev); struct hdac_ext_stream *link_dev; - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct skl_pipe_params p_params = {0}; struct hdac_ext_link *link; @@ -634,7 +634,7 @@ 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_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct hdac_ext_stream *link_dev = snd_soc_dai_get_dma_data(dai, substream); struct hdac_ext_link *link; @@ -1071,7 +1071,7 @@ int skl_dai_load(struct snd_soc_component *cmp, int index, static int skl_platform_soc_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai_link *dai_link = rtd->dai_link; dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "In %s:%s\n", __func__, @@ -1225,7 +1225,7 @@ static int skl_platform_soc_mmap(struct snd_soc_component *component, static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream, u64 nsec) { - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); u64 codec_frames, codec_nsecs; @@ -1509,11 +1509,9 @@ int skl_platform_unregister(struct device *dev) struct skl_dev *skl = bus_to_skl(bus); struct skl_module_deferred_bind *modules, *tmp; - if (!list_empty(&skl->bind_list)) { - list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { - list_del(&modules->node); - kfree(modules); - } + list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { + list_del(&modules->node); + kfree(modules); } kfree(skl->dais); diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index b9aab47d1202fca08ee166dcee0d2a73903ca2b2..b7d2d97d12a7314d7d016a17e2942e13e28d4e56 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -3773,9 +3773,8 @@ 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; - if (!list_empty(&skl->ppl_list)) - list_for_each_entry_safe(ppl, tmp, &skl->ppl_list, node) - list_del(&ppl->node); + list_for_each_entry_safe(ppl, tmp, &skl->ppl_list, node) + list_del(&ppl->node); /* clean up topology */ snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 9889f728752cde88f4bffcd414e5e58151d99703..5e93ad85e06dec737d10f16746470b2ca0586044 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -97,7 +97,7 @@ struct skl_audio_data_format { u8 number_of_channels; u8 valid_bit_depth; u8 sample_type; - u8 reserved[1]; + u8 reserved; } __packed; struct skl_base_cfg { diff --git a/sound/soc/kirkwood/armada-370-db.c b/sound/soc/kirkwood/armada-370-db.c index 4f66b011f1b4de30890c7443e2f38f793d5fec78..8e44ae37ad1ee7f40c54036c315b0afbc66a3f0d 100644 --- a/sound/soc/kirkwood/armada-370-db.c +++ b/sound/soc/kirkwood/armada-370-db.c @@ -18,7 +18,7 @@ static int a370db_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int freq; diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index a656d20141270e51854176e3429feb6008b847f5..f7bc007bbdec6ff3387124376184c44640188acf 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -118,30 +118,34 @@ config SND_SOC_MT8183 If unsure select "N". config SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A - tristate "ASoC Audio driver for MT8183 with MT6358 TS3A227E MAX98357A codec" + tristate "ASoC Audio driver for MT8183 with MT6358 TS3A227E MAX98357A RT1015 codec" depends on I2C depends on SND_SOC_MT8183 select SND_SOC_MT6358 select SND_SOC_MAX98357A + select SND_SOC_RT1015 select SND_SOC_BT_SCO select SND_SOC_TS3A227E select SND_SOC_CROS_EC_CODEC if CROS_EC + select SND_SOC_HDMI_CODEC help This adds ASoC driver for Mediatek MT8183 boards - with the MT6358 TS3A227E MAX98357A audio codec. + with the MT6358 TS3A227E MAX98357A RT1015 audio codec. Select Y if you have such device. If unsure select "N". config SND_SOC_MT8183_DA7219_MAX98357A - tristate "ASoC Audio driver for MT8183 with DA7219 MAX98357A codec" + tristate "ASoC Audio driver for MT8183 with DA7219 MAX98357A RT1015 codec" depends on SND_SOC_MT8183 && I2C select SND_SOC_MT6358 select SND_SOC_MAX98357A + select SND_SOC_RT1015 select SND_SOC_DA7219 select SND_SOC_BT_SCO + select SND_SOC_HDMI_CODEC help This adds ASoC driver for Mediatek MT8183 boards - with the DA7219 MAX98357A audio codec. + with the DA7219 MAX98357A RT1015 audio codec. Select Y if you have such device. If unsure select "N". diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c index 375e3b492922efd2c11bcda0ac826ec20b2dce83..882cdf86c8bf893fafb4eb6dc99730d1303855eb 100644 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c @@ -37,7 +37,7 @@ static int mtk_regmap_write(struct regmap *map, int reg, unsigned int val) int mtk_afe_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct snd_pcm_runtime *runtime = substream->runtime; int memif_num = asoc_rtd_to_cpu(rtd, 0)->id; @@ -98,7 +98,7 @@ EXPORT_SYMBOL_GPL(mtk_afe_fe_startup); void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mtk_base_afe_memif *memif = &afe->memif[asoc_rtd_to_cpu(rtd, 0)->id]; int irq_id; @@ -120,7 +120,7 @@ int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = asoc_rtd_to_cpu(rtd, 0)->id; struct mtk_base_afe_memif *memif = &afe->memif[id]; @@ -196,7 +196,7 @@ EXPORT_SYMBOL_GPL(mtk_afe_fe_hw_free); int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime * const runtime = substream->runtime; struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = asoc_rtd_to_cpu(rtd, 0)->id; @@ -263,7 +263,7 @@ EXPORT_SYMBOL_GPL(mtk_afe_fe_trigger); int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = asoc_rtd_to_cpu(rtd, 0)->id; int pbuf_size; @@ -505,7 +505,7 @@ EXPORT_SYMBOL_GPL(mtk_memif_set_rate); int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream, int id, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.c b/sound/soc/mediatek/common/mtk-afe-platform-driver.c index 0a1a65c86f0e8a62323a4029d70ee8ab573cd91c..01501d5747a7c0fb67b8d962ecb91aad6a591c06 100644 --- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c +++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c @@ -80,7 +80,7 @@ EXPORT_SYMBOL_GPL(mtk_afe_add_sub_dai_control); snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); struct mtk_base_afe_memif *memif = &afe->memif[asoc_rtd_to_cpu(rtd, 0)->id]; const struct mtk_base_memif_data *memif_data = memif->data; diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index f0250b0dd734cef307d06f5e3b9dfd1092586be0..df29641c74aaaa693e50874e05fc178a12a61fcf 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c @@ -494,7 +494,7 @@ static int mt2701_dlm_fe_trigger(struct snd_pcm_substream *substream, static int mt2701_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int fs; if (asoc_rtd_to_cpu(rtd, 0)->id != MT2701_MEMIF_ULBT) diff --git a/sound/soc/mediatek/mt2701/mt2701-cs42448.c b/sound/soc/mediatek/mt2701/mt2701-cs42448.c index c47af9b6949b318cb20ea1ab2b00ca100d00ab93..44a8d5cfb0aae51420b30308f4d548b6ad9e63ad 100644 --- a/sound/soc/mediatek/mt2701/mt2701-cs42448.c +++ b/sound/soc/mediatek/mt2701/mt2701-cs42448.c @@ -127,7 +127,7 @@ static const struct snd_soc_ops mt2701_cs42448_48k_fe_ops = { static int mt2701_cs42448_be_ops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int mclk_rate; diff --git a/sound/soc/mediatek/mt2701/mt2701-wm8960.c b/sound/soc/mediatek/mt2701/mt2701-wm8960.c index 0122e7df067f57c0bea37b549568a1cb23425bbf..414e422c0eba0a14b4bdc0739799d08f8b156399 100644 --- a/sound/soc/mediatek/mt2701/mt2701-wm8960.c +++ b/sound/soc/mediatek/mt2701/mt2701-wm8960.c @@ -24,7 +24,7 @@ static const struct snd_kcontrol_new mt2701_wm8960_controls[] = { static int mt2701_wm8960_be_ops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int mclk_rate; diff --git a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c index 7f3ac04b942592f238c4330b8c419dded85bec77..3d68e4726ea246f655eb1b2e8db9794632631b70 100644 --- a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c +++ b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c @@ -139,7 +139,7 @@ static const struct snd_pcm_hardware mt6797_afe_hardware = { static int mt6797_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); @@ -150,7 +150,7 @@ static int mt6797_memif_fs(struct snd_pcm_substream *substream, static int mt6797_irq_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index 1cc044425a9e52e99859180c3cc0fa95593004d0..7e7bda70d12e90eb6c7677b01686585039905947 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -482,7 +482,7 @@ static int mt8173_afe_hdmi_trigger(struct snd_pcm_substream *substream, int cmd, static int mt8173_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); struct mtk_base_afe_memif *memif = &afe->memif[asoc_rtd_to_cpu(rtd, 0)->id]; diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c index 37693d354e66ee94d348a8255e238d3cee2fa02c..fc94314bfc02ffd40dd9863fe29dc80419f5e04b 100644 --- a/sound/soc/mediatek/mt8173/mt8173-max98090.c +++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c @@ -52,7 +52,7 @@ static const struct snd_kcontrol_new mt8173_max98090_controls[] = { static int mt8173_max98090_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); return snd_soc_dai_set_sysclk(codec_dai, 0, params_rate(params) * 256, diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c index 51009a1727778ba865e9d96e281a0cfeb01383d8..0f28dc2217c091e174f8fbe132d51dac25c03ba7 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c @@ -43,7 +43,7 @@ static const struct snd_kcontrol_new mt8173_rt5650_rt5514_controls[] = { static int mt8173_rt5650_rt5514_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int i, ret; diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c index 247ac7690805a7a1fe170d871bdb8d21df839042..077c6ee0678067c3ac2a2a6836a4b40625c9f5e4 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c @@ -47,7 +47,7 @@ static const struct snd_kcontrol_new mt8173_rt5650_rt5676_controls[] = { static int mt8173_rt5650_rt5676_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int i, ret; diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c index 2065c94dbf99dea431ef5212d86b8c96d8166c66..347b095d478d722a5acd6fc2a74b42d0c11baf0a 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c @@ -58,7 +58,7 @@ static const struct snd_kcontrol_new mt8173_rt5650_controls[] = { static int mt8173_rt5650_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int mclk_clock; struct snd_soc_dai *codec_dai; int i, ret; diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index e0c4714da92cb60d426e92c953b46503b4d74162..c4a598cbbdaa14fb39d1ea1978e3a522b70381b6 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -142,7 +142,7 @@ static const struct snd_pcm_hardware mt8183_afe_hardware = { static int mt8183_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); @@ -153,7 +153,7 @@ static int mt8183_memif_fs(struct snd_pcm_substream *substream, static int mt8183_irq_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index ffd7c931e7bb0f46366952a885ebdc13eed33fc3..06d0a4f80fc1769729df95d74378f8f02e2fcb28 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -8,23 +8,32 @@ #include #include +#include #include +#include #include #include #include -#include "mt8183-afe-common.h" #include "../../codecs/da7219-aad.h" #include "../../codecs/da7219.h" +#include "../../codecs/rt1015.h" +#include "mt8183-afe-common.h" + +#define DA7219_CODEC_DAI "da7219-hifi" +#define DA7219_DEV_NAME "da7219.5-001a" +#define RT1015_CODEC_DAI "rt1015-aif" +#define RT1015_DEV0_NAME "rt1015.6-0028" +#define RT1015_DEV1_NAME "rt1015.6-0029" struct mt8183_da7219_max98357_priv { - struct snd_soc_jack headset_jack; + struct snd_soc_jack headset_jack, hdmi_jack; }; static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int rate = params_rate(params); unsigned int mclk_fs_ratio = 128; unsigned int mclk_fs = rate * mclk_fs_ratio; @@ -40,7 +49,7 @@ static const struct snd_soc_ops mt8183_mt6358_i2s_ops = { static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; unsigned int rate = params_rate(params); unsigned int mclk_fs_ratio = 256; @@ -54,8 +63,7 @@ static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream, dev_err(rtd->dev, "failed to set cpu dai sysclk\n"); for_each_rtd_codec_dais(rtd, j, codec_dai) { - - if (!strcmp(codec_dai->component->name, "da7219.5-001a")) { + if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) { ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, mclk_fs, @@ -82,13 +90,12 @@ static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream, static int mt8183_da7219_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_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, "da7219.5-001a")) { + if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) { ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0); if (ret < 0) { @@ -107,6 +114,51 @@ static const struct snd_soc_ops mt8183_da7219_i2s_ops = { .hw_free = mt8183_da7219_hw_free, }; +static int +mt8183_da7219_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + unsigned int rate = params_rate(params); + struct snd_soc_dai *codec_dai; + int ret = 0, i; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + if (!strcmp(codec_dai->component->name, RT1015_DEV0_NAME) || + !strcmp(codec_dai->component->name, RT1015_DEV1_NAME)) { + ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (ret) { + dev_err(rtd->dev, "failed to set bclk ratio\n"); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, 0, + RT1015_PLL_S_BCLK, + rate * 64, rate * 256); + if (ret) { + dev_err(rtd->dev, "failed to set pll\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, + RT1015_SCLK_S_PLL, + rate * 256, + SND_SOC_CLOCK_IN); + if (ret) { + dev_err(rtd->dev, "failed to set sysclk\n"); + return ret; + } + } + } + + return mt8183_da7219_i2s_hw_params(substream, params); +} + +static const struct snd_soc_ops mt8183_da7219_rt1015_i2s_ops = { + .hw_params = mt8183_da7219_rt1015_i2s_hw_params, + .hw_free = mt8183_da7219_hw_free, +}; + static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -119,6 +171,58 @@ static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + /* fix BE i2s format to 32bit, clean param mask first */ + snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), + 0, SNDRV_PCM_FORMAT_LAST); + + params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); + + return 0; +} + +static int +mt8183_da7219_max98357_startup( + struct snd_pcm_substream *substream) +{ + 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, + }; + + struct snd_pcm_runtime *runtime = substream->runtime; + + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); + 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); + + return 0; +} + +static const struct snd_soc_ops mt8183_da7219_max98357_ops = { + .startup = mt8183_da7219_max98357_startup, +}; + static int mt8183_da7219_max98357_bt_sco_startup( struct snd_pcm_substream *substream) @@ -228,13 +332,20 @@ SND_SOC_DAILINK_DEFS(i2s1, SND_SOC_DAILINK_DEFS(i2s2, DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), - DAILINK_COMP_ARRAY(COMP_CODEC("da7219.5-001a", "da7219-hifi")), + DAILINK_COMP_ARRAY(COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)), DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(i2s3, +SND_SOC_DAILINK_DEFS(i2s3_max98357a, DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi"), - COMP_CODEC("da7219.5-001a", "da7219-hifi")), + COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s3_rt1015, + DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), + DAILINK_COMP_ARRAY(COMP_CODEC(RT1015_DEV0_NAME, RT1015_CODEC_DAI), + COMP_CODEC(RT1015_DEV1_NAME, RT1015_CODEC_DAI), + COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)), DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(i2s5, @@ -244,10 +355,25 @@ SND_SOC_DAILINK_DEFS(i2s5, SND_SOC_DAILINK_DEFS(tdm, DAILINK_COMP_ARRAY(COMP_CPU("TDM")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), DAILINK_COMP_ARRAY(COMP_EMPTY())); -static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { +static int mt8183_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mt8183_da7219_max98357_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + int ret; + + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + &priv->hdmi_jack, NULL, 0); + if (ret) + return ret; + + return hdmi_codec_set_jack_detect(asoc_rtd_to_codec(rtd, 0)->component, + &priv->hdmi_jack); +} + +static struct snd_soc_dai_link mt8183_da7219_dai_links[] = { /* FE */ { .name = "Playback_1", @@ -256,6 +382,7 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + .ops = &mt8183_da7219_max98357_ops, SND_SOC_DAILINK_REG(playback1), }, { @@ -303,6 +430,7 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + .ops = &mt8183_da7219_max98357_ops, SND_SOC_DAILINK_REG(capture3), }, { @@ -380,9 +508,6 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, - .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, - .ops = &mt8183_da7219_i2s_ops, - SND_SOC_DAILINK_REG(i2s3), }, { .name = "I2S5", @@ -402,12 +527,42 @@ static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = { .dpcm_playback = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, + .init = mt8183_da7219_max98357_hdmi_init, SND_SOC_DAILINK_REG(tdm), }, }; static int -mt8183_da7219_max98357_headset_init(struct snd_soc_component *component); +mt8183_da7219_max98357_headset_init(struct snd_soc_component *component) +{ + int ret; + struct mt8183_da7219_max98357_priv *priv = + snd_soc_card_get_drvdata(component->card); + + /* Enable Headset and 4 Buttons Jack detection */ + ret = snd_soc_card_jack_new(component->card, + "Headset Jack", + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &priv->headset_jack, + NULL, 0); + if (ret) + return ret; + + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key( + priv->headset_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + + da7219_aad_jack_det(component, &priv->headset_jack); + + return 0; +} static struct snd_soc_aux_dev mt8183_da7219_max98357_headset_dev = { .dlc = COMP_EMPTY(), @@ -446,57 +601,56 @@ static struct snd_soc_card mt8183_da7219_max98357_card = { .num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets), .dapm_routes = mt8183_da7219_max98357_dapm_routes, .num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes), - .dai_link = mt8183_da7219_max98357_dai_links, - .num_links = ARRAY_SIZE(mt8183_da7219_max98357_dai_links), + .dai_link = mt8183_da7219_dai_links, + .num_links = ARRAY_SIZE(mt8183_da7219_dai_links), .aux_dev = &mt8183_da7219_max98357_headset_dev, .num_aux_devs = 1, .codec_conf = mt6358_codec_conf, .num_configs = ARRAY_SIZE(mt6358_codec_conf), }; -static int -mt8183_da7219_max98357_headset_init(struct snd_soc_component *component) -{ - int ret; - struct mt8183_da7219_max98357_priv *priv = - snd_soc_card_get_drvdata(component->card); - - /* Enable Headset and 4 Buttons Jack detection */ - ret = snd_soc_card_jack_new(&mt8183_da7219_max98357_card, - "Headset Jack", - SND_JACK_HEADSET | - SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3, - &priv->headset_jack, - NULL, 0); - if (ret) - return ret; - - snd_jack_set_key( - priv->headset_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key( - priv->headset_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); - snd_jack_set_key( - priv->headset_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); - snd_jack_set_key( - priv->headset_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); - - da7219_aad_jack_det(component, &priv->headset_jack); +static struct snd_soc_codec_conf mt8183_da7219_rt1015_codec_conf[] = { + { + .dlc = COMP_CODEC_CONF("mt6358-sound"), + .name_prefix = "Mt6358", + }, + { + .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME), + .name_prefix = "Right", + }, +}; - return 0; -} +static struct snd_soc_card mt8183_da7219_rt1015_card = { + .name = "mt8183_da7219_rt1015", + .owner = THIS_MODULE, + .controls = mt8183_da7219_max98357_snd_controls, + .num_controls = ARRAY_SIZE(mt8183_da7219_max98357_snd_controls), + .dapm_widgets = mt8183_da7219_max98357_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets), + .dapm_routes = mt8183_da7219_max98357_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes), + .dai_link = mt8183_da7219_dai_links, + .num_links = ARRAY_SIZE(mt8183_da7219_dai_links), + .aux_dev = &mt8183_da7219_max98357_headset_dev, + .num_aux_devs = 1, + .codec_conf = mt8183_da7219_rt1015_codec_conf, + .num_configs = ARRAY_SIZE(mt8183_da7219_rt1015_codec_conf), +}; static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) { - struct snd_soc_card *card = &mt8183_da7219_max98357_card; - struct device_node *platform_node; + struct snd_soc_card *card; + struct device_node *platform_node, *hdmi_codec; struct snd_soc_dai_link *dai_link; struct mt8183_da7219_max98357_priv *priv; struct pinctrl *pinctrl; + const struct of_device_id *match; int ret, i; - card->dev = &pdev->dev; - platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); if (!platform_node) { @@ -504,10 +658,52 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) return -EINVAL; } + match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev); + if (!match || !match->data) + return -EINVAL; + + card = (struct snd_soc_card *)match->data; + card->dev = &pdev->dev; + + hdmi_codec = of_parse_phandle(pdev->dev.of_node, + "mediatek,hdmi-codec", 0); + for_each_card_prelinks(card, i, dai_link) { - if (dai_link->platforms->name) - continue; - dai_link->platforms->of_node = platform_node; + if (strcmp(dai_link->name, "I2S3") == 0) { + if (card == &mt8183_da7219_max98357_card) { + dai_link->be_hw_params_fixup = + mt8183_i2s_hw_params_fixup; + dai_link->ops = &mt8183_mt6358_i2s_ops; + dai_link->cpus = i2s3_max98357a_cpus; + dai_link->num_cpus = + ARRAY_SIZE(i2s3_max98357a_cpus); + dai_link->codecs = i2s3_max98357a_codecs; + dai_link->num_codecs = + ARRAY_SIZE(i2s3_max98357a_codecs); + dai_link->platforms = i2s3_max98357a_platforms; + dai_link->num_platforms = + ARRAY_SIZE(i2s3_max98357a_platforms); + } else if (card == &mt8183_da7219_rt1015_card) { + dai_link->be_hw_params_fixup = + mt8183_rt1015_i2s_hw_params_fixup; + dai_link->ops = &mt8183_da7219_rt1015_i2s_ops; + dai_link->cpus = i2s3_rt1015_cpus; + dai_link->num_cpus = + ARRAY_SIZE(i2s3_rt1015_cpus); + dai_link->codecs = i2s3_rt1015_codecs; + dai_link->num_codecs = + ARRAY_SIZE(i2s3_rt1015_codecs); + dai_link->platforms = i2s3_rt1015_platforms; + dai_link->num_platforms = + ARRAY_SIZE(i2s3_rt1015_platforms); + } + } + + if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) + dai_link->codecs->of_node = hdmi_codec; + + if (!dai_link->platforms->name) + dai_link->platforms->of_node = platform_node; } mt8183_da7219_max98357_headset_dev.dlc.of_node = @@ -538,14 +734,21 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id mt8183_da7219_max98357_dt_match[] = { - {.compatible = "mediatek,mt8183_da7219_max98357",}, + { + .compatible = "mediatek,mt8183_da7219_max98357", + .data = &mt8183_da7219_max98357_card, + }, + { + .compatible = "mediatek,mt8183_da7219_rt1015", + .data = &mt8183_da7219_rt1015_card, + }, {} }; #endif static struct platform_driver mt8183_da7219_max98357_driver = { .driver = { - .name = "mt8183_da7219_max98357", + .name = "mt8183_da7219", #ifdef CONFIG_OF .of_match_table = mt8183_da7219_max98357_dt_match, #endif diff --git a/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c index 777e93d70beabb8493509531ad6d951999fcf500..138591d71ebda11ddbcfc9d09fcc31beaccbadd0 100644 --- a/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c +++ b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c @@ -49,6 +49,8 @@ struct mtk_afe_i2s_priv { int mclk_id; int mclk_rate; int mclk_apll; + + int use_eiaj; }; static unsigned int get_i2s_wlen(snd_pcm_format_t format) @@ -711,7 +713,7 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe, unsigned int rate_reg = mt8183_rate_transform(afe->dev, rate, i2s_id); snd_pcm_format_t format = params_format(params); - unsigned int i2s_con = 0; + unsigned int i2s_con = 0, fmt_con = I2S_FMT_I2S << I2S_FMT_SFT; int ret = 0; dev_info(afe->dev, "%s(), id %d, rate %d, format %d\n", @@ -719,17 +721,21 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe, i2s_id, rate, format); - if (i2s_priv) + if (i2s_priv) { i2s_priv->rate = rate; - else + + if (i2s_priv->use_eiaj) + fmt_con = I2S_FMT_EIAJ << I2S_FMT_SFT; + } else { dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__); + } switch (i2s_id) { case MT8183_DAI_I2S_0: regmap_update_bits(afe->regmap, AFE_DAC_CON1, I2S_MODE_MASK_SFT, rate_reg << I2S_MODE_SFT); i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT; - i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT; + i2s_con |= fmt_con; i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT; regmap_update_bits(afe->regmap, AFE_I2S_CON, 0xffffeffe, i2s_con); @@ -737,7 +743,7 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe, case MT8183_DAI_I2S_1: i2s_con = I2S1_SEL_O28_O29 << I2S2_SEL_O03_O04_SFT; i2s_con |= rate_reg << I2S2_OUT_MODE_SFT; - i2s_con |= I2S_FMT_I2S << I2S2_FMT_SFT; + i2s_con |= fmt_con; i2s_con |= get_i2s_wlen(format) << I2S2_WLEN_SFT; regmap_update_bits(afe->regmap, AFE_I2S_CON1, 0xffffeffe, i2s_con); @@ -745,21 +751,21 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe, case MT8183_DAI_I2S_2: i2s_con = 8 << I2S3_UPDATE_WORD_SFT; i2s_con |= rate_reg << I2S3_OUT_MODE_SFT; - i2s_con |= I2S_FMT_I2S << I2S3_FMT_SFT; + i2s_con |= fmt_con; i2s_con |= get_i2s_wlen(format) << I2S3_WLEN_SFT; regmap_update_bits(afe->regmap, AFE_I2S_CON2, 0xffffeffe, i2s_con); break; case MT8183_DAI_I2S_3: i2s_con = rate_reg << I2S4_OUT_MODE_SFT; - i2s_con |= I2S_FMT_I2S << I2S4_FMT_SFT; + i2s_con |= fmt_con; i2s_con |= get_i2s_wlen(format) << I2S4_WLEN_SFT; regmap_update_bits(afe->regmap, AFE_I2S_CON3, 0xffffeffe, i2s_con); break; case MT8183_DAI_I2S_5: i2s_con = rate_reg << I2S5_OUT_MODE_SFT; - i2s_con |= I2S_FMT_I2S << I2S5_FMT_SFT; + i2s_con |= fmt_con; i2s_con |= get_i2s_wlen(format) << I2S5_WLEN_SFT; regmap_update_bits(afe->regmap, AFE_I2S_CON4, 0xffffeffe, i2s_con); @@ -841,9 +847,46 @@ static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai, return 0; } +static int mtk_dai_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8183_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_priv; + + switch (dai->id) { + case MT8183_DAI_I2S_0: + case MT8183_DAI_I2S_1: + case MT8183_DAI_I2S_2: + case MT8183_DAI_I2S_3: + case MT8183_DAI_I2S_5: + break; + default: + dev_warn(afe->dev, "%s(), id %d not support\n", + __func__, dai->id); + return -EINVAL; + } + i2s_priv = afe_priv->dai_priv[dai->id]; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_LEFT_J: + i2s_priv->use_eiaj = 1; + break; + case SND_SOC_DAIFMT_I2S: + i2s_priv->use_eiaj = 0; + break; + default: + dev_warn(afe->dev, "%s(), DAI format %d not support\n", + __func__, fmt & SND_SOC_DAIFMT_FORMAT_MASK); + return -EINVAL; + } + + return 0; +} + static const struct snd_soc_dai_ops mtk_dai_i2s_ops = { .hw_params = mtk_dai_i2s_hw_params, .set_sysclk = mtk_dai_i2s_set_sysclk, + .set_fmt = mtk_dai_i2s_set_fmt, }; /* dai driver */ diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 1fca8df109b42f8e494fad37e31ba65a2e42eb70..07410d7afaa9048362c06d1f83dbda1867111e54 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -7,13 +7,20 @@ // Author: Shunli Wang #include +#include +#include +#include +#include #include #include -#include -#include -#include "mt8183-afe-common.h" +#include "../../codecs/rt1015.h" #include "../../codecs/ts3a227e.h" +#include "mt8183-afe-common.h" + +#define RT1015_CODEC_DAI "rt1015-aif" +#define RT1015_DEV0_NAME "rt1015.6-0028" +#define RT1015_DEV1_NAME "rt1015.6-0029" enum PINCTRL_PIN_STATE { PIN_STATE_DEFAULT = 0, @@ -30,13 +37,13 @@ static const char * const mt8183_pin_str[PIN_STATE_MAX] = { struct mt8183_mt6358_ts3a227_max98357_priv { struct pinctrl *pinctrl; struct pinctrl_state *pin_states[PIN_STATE_MAX]; - struct snd_soc_jack headset_jack; + struct snd_soc_jack headset_jack, hdmi_jack; }; static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int rate = params_rate(params); unsigned int mclk_fs_ratio = 128; unsigned int mclk_fs = rate * mclk_fs_ratio; @@ -49,6 +56,48 @@ static const struct snd_soc_ops mt8183_mt6358_i2s_ops = { .hw_params = mt8183_mt6358_i2s_hw_params, }; +static int +mt8183_mt6358_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + unsigned int rate = params_rate(params); + unsigned int mclk_fs_ratio = 128; + unsigned int mclk_fs = rate * mclk_fs_ratio; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai; + int ret, i; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); + if (ret < 0) { + dev_err(card->dev, "failed to set bclk ratio\n"); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, + rate * 64, rate * 256); + if (ret < 0) { + dev_err(card->dev, "failed to set pll\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL, + rate * 256, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "failed to set sysclk\n"); + return ret; + } + } + + return snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), + 0, mclk_fs, SND_SOC_CLOCK_OUT); +} + +static const struct snd_soc_ops mt8183_mt6358_rt1015_i2s_ops = { + .hw_params = mt8183_mt6358_rt1015_i2s_hw_params, +}; + static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -62,6 +111,19 @@ static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + dev_dbg(rtd->dev, "%s(), fix format to 32bit\n", __func__); + + /* fix BE i2s format to 32bit, clean param mask first */ + snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), + 0, SNDRV_PCM_FORMAT_LAST); + + params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); + return 0; +} + static int mt8183_mt6358_ts3a227_max98357_bt_sco_startup( struct snd_pcm_substream *substream) @@ -179,11 +241,17 @@ SND_SOC_DAILINK_DEFS(i2s2, DAILINK_COMP_ARRAY(COMP_DUMMY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(i2s3, +SND_SOC_DAILINK_DEFS(i2s3_max98357a, DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi")), DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s3_rt1015, + DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), + DAILINK_COMP_ARRAY(COMP_CODEC(RT1015_DEV0_NAME, RT1015_CODEC_DAI), + COMP_CODEC(RT1015_DEV1_NAME, RT1015_CODEC_DAI)), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + SND_SOC_DAILINK_DEFS(i2s5, DAILINK_COMP_ARRAY(COMP_CPU("I2S5")), DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), @@ -191,12 +259,12 @@ SND_SOC_DAILINK_DEFS(i2s5, SND_SOC_DAILINK_DEFS(tdm, DAILINK_COMP_ARRAY(COMP_CPU("TDM")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), DAILINK_COMP_ARRAY(COMP_EMPTY())); static int mt8183_mt6358_tdm_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mt8183_mt6358_ts3a227_max98357_priv *priv = snd_soc_card_get_drvdata(rtd->card); int ret; @@ -215,7 +283,7 @@ static int mt8183_mt6358_tdm_startup(struct snd_pcm_substream *substream) static void mt8183_mt6358_tdm_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct mt8183_mt6358_ts3a227_max98357_priv *priv = snd_soc_card_get_drvdata(rtd->card); int ret; @@ -239,7 +307,7 @@ static int mt8183_mt6358_ts3a227_max98357_wov_startup( struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct mt8183_mt6358_ts3a227_max98357_priv *priv = snd_soc_card_get_drvdata(card); @@ -252,7 +320,7 @@ static void mt8183_mt6358_ts3a227_max98357_wov_shutdown( struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct mt8183_mt6358_ts3a227_max98357_priv *priv = snd_soc_card_get_drvdata(card); @@ -270,8 +338,23 @@ static const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_wov_ops = { .shutdown = mt8183_mt6358_ts3a227_max98357_wov_shutdown, }; -static struct snd_soc_dai_link -mt8183_mt6358_ts3a227_max98357_dai_links[] = { +static int +mt8183_mt6358_ts3a227_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mt8183_mt6358_ts3a227_max98357_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + int ret; + + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + &priv->hdmi_jack, NULL, 0); + if (ret) + return ret; + + return hdmi_codec_set_jack_detect(asoc_rtd_to_codec(rtd, 0)->component, + &priv->hdmi_jack); +} + +static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = { /* FE */ { .name = "Playback_1", @@ -413,9 +496,6 @@ mt8183_mt6358_ts3a227_max98357_dai_links[] = { .no_pcm = 1, .dpcm_playback = 1, .ignore_suspend = 1, - .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, - .ops = &mt8183_mt6358_i2s_ops, - SND_SOC_DAILINK_REG(i2s3), }, { .name = "I2S5", @@ -436,6 +516,7 @@ mt8183_mt6358_ts3a227_max98357_dai_links[] = { .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, .ops = &mt8183_mt6358_tdm_ops, + .init = mt8183_mt6358_ts3a227_max98357_hdmi_init, SND_SOC_DAILINK_REG(tdm), }, }; @@ -443,8 +524,35 @@ mt8183_mt6358_ts3a227_max98357_dai_links[] = { static struct snd_soc_card mt8183_mt6358_ts3a227_max98357_card = { .name = "mt8183_mt6358_ts3a227_max98357", .owner = THIS_MODULE, - .dai_link = mt8183_mt6358_ts3a227_max98357_dai_links, - .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_dai_links), + .dai_link = mt8183_mt6358_ts3a227_dai_links, + .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), +}; + +static struct snd_soc_card mt8183_mt6358_ts3a227_max98357b_card = { + .name = "mt8183_mt6358_ts3a227_max98357b", + .owner = THIS_MODULE, + .dai_link = mt8183_mt6358_ts3a227_dai_links, + .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), +}; + +static struct snd_soc_codec_conf mt8183_mt6358_ts3a227_rt1015_amp_conf[] = { + { + .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME), + .name_prefix = "Right", + }, +}; + +static struct snd_soc_card mt8183_mt6358_ts3a227_rt1015_card = { + .name = "mt8183_mt6358_ts3a227_rt1015", + .owner = THIS_MODULE, + .dai_link = mt8183_mt6358_ts3a227_dai_links, + .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), + .codec_conf = mt8183_mt6358_ts3a227_rt1015_amp_conf, + .num_configs = ARRAY_SIZE(mt8183_mt6358_ts3a227_rt1015_amp_conf), }; static int @@ -455,7 +563,7 @@ mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *component) snd_soc_card_get_drvdata(component->card); /* Enable Headset and 4 Buttons Jack detection */ - ret = snd_soc_card_jack_new(&mt8183_mt6358_ts3a227_max98357_card, + ret = snd_soc_card_jack_new(component->card, "Headset Jack", SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | @@ -478,14 +586,12 @@ static struct snd_soc_aux_dev mt8183_mt6358_ts3a227_max98357_headset_dev = { static int mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) { - struct snd_soc_card *card = &mt8183_mt6358_ts3a227_max98357_card; - struct device_node *platform_node, *ec_codec; + struct snd_soc_card *card; + struct device_node *platform_node, *ec_codec, *hdmi_codec; struct snd_soc_dai_link *dai_link; struct mt8183_mt6358_ts3a227_max98357_priv *priv; - int ret; - int i; - - card->dev = &pdev->dev; + const struct of_device_id *match; + int ret, i; platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); @@ -494,12 +600,18 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) return -EINVAL; } + match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev); + if (!match || !match->data) + return -EINVAL; + + card = (struct snd_soc_card *)match->data; + card->dev = &pdev->dev; + ec_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,ec-codec", 0); + hdmi_codec = of_parse_phandle(pdev->dev.of_node, + "mediatek,hdmi-codec", 0); for_each_card_prelinks(card, i, dai_link) { - if (dai_link->platforms->name) - continue; - if (ec_codec && strcmp(dai_link->name, "Wake on Voice") == 0) { dai_link->cpus[0].name = NULL; dai_link->cpus[0].of_node = ec_codec; @@ -509,9 +621,52 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) dai_link->codecs[0].dai_name = "Wake on Voice"; dai_link->platforms[0].of_node = ec_codec; dai_link->ignore = 0; - } else { - dai_link->platforms->of_node = platform_node; } + + if (strcmp(dai_link->name, "I2S3") == 0) { + if (card == &mt8183_mt6358_ts3a227_max98357_card || + card == &mt8183_mt6358_ts3a227_max98357b_card) { + dai_link->be_hw_params_fixup = + mt8183_i2s_hw_params_fixup; + dai_link->ops = &mt8183_mt6358_i2s_ops; + dai_link->cpus = i2s3_max98357a_cpus; + dai_link->num_cpus = + ARRAY_SIZE(i2s3_max98357a_cpus); + dai_link->codecs = i2s3_max98357a_codecs; + dai_link->num_codecs = + ARRAY_SIZE(i2s3_max98357a_codecs); + dai_link->platforms = i2s3_max98357a_platforms; + dai_link->num_platforms = + ARRAY_SIZE(i2s3_max98357a_platforms); + } else if (card == &mt8183_mt6358_ts3a227_rt1015_card) { + dai_link->be_hw_params_fixup = + mt8183_rt1015_i2s_hw_params_fixup; + dai_link->ops = &mt8183_mt6358_rt1015_i2s_ops; + dai_link->cpus = i2s3_rt1015_cpus; + dai_link->num_cpus = + ARRAY_SIZE(i2s3_rt1015_cpus); + dai_link->codecs = i2s3_rt1015_codecs; + dai_link->num_codecs = + ARRAY_SIZE(i2s3_rt1015_codecs); + dai_link->platforms = i2s3_rt1015_platforms; + dai_link->num_platforms = + ARRAY_SIZE(i2s3_rt1015_platforms); + } + } + + if (card == &mt8183_mt6358_ts3a227_max98357b_card) { + if (strcmp(dai_link->name, "I2S2") == 0 || + strcmp(dai_link->name, "I2S3") == 0) + dai_link->dai_fmt = SND_SOC_DAIFMT_LEFT_J | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM; + } + + if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) + dai_link->codecs->of_node = hdmi_codec; + + if (!dai_link->platforms->name) + dai_link->platforms->of_node = platform_node; } mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node = @@ -568,14 +723,25 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id mt8183_mt6358_ts3a227_max98357_dt_match[] = { - {.compatible = "mediatek,mt8183_mt6358_ts3a227_max98357",}, + { + .compatible = "mediatek,mt8183_mt6358_ts3a227_max98357", + .data = &mt8183_mt6358_ts3a227_max98357_card, + }, + { + .compatible = "mediatek,mt8183_mt6358_ts3a227_max98357b", + .data = &mt8183_mt6358_ts3a227_max98357b_card, + }, + { + .compatible = "mediatek,mt8183_mt6358_ts3a227_rt1015", + .data = &mt8183_mt6358_ts3a227_rt1015_card, + }, {} }; #endif static struct platform_driver mt8183_mt6358_ts3a227_max98357_driver = { .driver = { - .name = "mt8183_mt6358_ts3a227_max98357", + .name = "mt8183_mt6358_ts3a227", #ifdef CONFIG_OF .of_match_table = mt8183_mt6358_ts3a227_max98357_dt_match, #endif diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 8b6295283989dcae6cf4afce2c3dfed9ed84277b..363dc3b1bbe470325ce74f554978b3274d9b762a 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -68,6 +68,7 @@ config SND_MESON_AXG_SOUND_CARD imply SND_MESON_AXG_SPDIFOUT imply SND_MESON_AXG_SPDIFIN imply SND_MESON_AXG_PDM + imply SND_MESON_G12A_TOACODEC imply SND_MESON_G12A_TOHDMITX if DRM_MESON_DW_HDMI help Select Y or M to add support for the AXG SoC sound card diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c index 832e22d275fe086add4b317ca03114e0ff7195d6..9322245521463712fccb693448f0fa416aa7e12d 100644 --- a/sound/soc/meson/aiu-encoder-i2s.c +++ b/sound/soc/meson/aiu-encoder-i2s.c @@ -72,11 +72,10 @@ static int aiu_encoder_i2s_setup_desc(struct snd_soc_component *component, { /* Always operate in split (classic interleaved) mode */ unsigned int desc = AIU_I2S_SOURCE_DESC_MODE_SPLIT; - unsigned int val; /* Reset required to update the pipeline */ snd_soc_component_write(component, AIU_RST_SOFT, AIU_RST_SOFT_I2S_FAST); - snd_soc_component_read(component, AIU_I2S_SYNC, &val); + snd_soc_component_read(component, AIU_I2S_SYNC); switch (params_physical_width(params)) { case 16: /* Nothing to do */ diff --git a/sound/soc/meson/aiu-fifo-i2s.c b/sound/soc/meson/aiu-fifo-i2s.c index 9a5271ce80fe38546ed53b0f24a1833447217d27..d91b0d874342fbfa80f8f741f98c7137ecb17de2 100644 --- a/sound/soc/meson/aiu-fifo-i2s.c +++ b/sound/soc/meson/aiu-fifo-i2s.c @@ -46,7 +46,6 @@ static int aiu_fifo_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; - unsigned int val; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -54,7 +53,7 @@ static int aiu_fifo_i2s_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_soc_component_write(component, AIU_RST_SOFT, AIU_RST_SOFT_I2S_FAST); - snd_soc_component_read(component, AIU_I2S_SYNC, &val); + snd_soc_component_read(component, AIU_I2S_SYNC); break; } diff --git a/sound/soc/meson/aiu-fifo.c b/sound/soc/meson/aiu-fifo.c index d9cede4c33ffc692d07ceceb44e885e9b3545463..aa88aae8e517dc7c2f566bff3f75aee7e25aaa0e 100644 --- a/sound/soc/meson/aiu-fifo.c +++ b/sound/soc/meson/aiu-fifo.c @@ -37,8 +37,7 @@ snd_pcm_uframes_t aiu_fifo_pointer(struct snd_soc_component *component, struct snd_pcm_runtime *runtime = substream->runtime; unsigned int addr; - snd_soc_component_read(component, fifo->mem_offset + AIU_MEM_RD, - &addr); + addr = snd_soc_component_read(component, fifo->mem_offset + AIU_MEM_RD); return bytes_to_frames(runtime, addr - (unsigned int)runtime->dma_addr); } diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 89f7f64747cd0a562e3915fbf3918947b37d671e..2b77010c2c5ce8398c330e8c8e13cc9248daa828 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -40,7 +40,7 @@ static const struct snd_soc_pcm_stream codec_params = { static int axg_card_tdm_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); struct axg_dai_link_tdm_data *be = (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; @@ -116,7 +116,7 @@ static int axg_card_add_tdm_loopback(struct snd_soc_card *card, lb = &card->dai_link[*index + 1]; - lb->name = kasprintf(GFP_KERNEL, "%s-lb", pad->name); + lb->name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-lb", pad->name); if (!lb->name) return -ENOMEM; @@ -327,20 +327,22 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, return ret; if (axg_card_cpu_is_playback_fe(dai_link->cpus->of_node)) - ret = meson_card_set_fe_link(card, dai_link, np, true); + return meson_card_set_fe_link(card, dai_link, np, true); else if (axg_card_cpu_is_capture_fe(dai_link->cpus->of_node)) - ret = meson_card_set_fe_link(card, dai_link, np, false); - else - ret = meson_card_set_be_link(card, dai_link, np); + return meson_card_set_fe_link(card, dai_link, np, false); + + ret = meson_card_set_be_link(card, dai_link, np); if (ret) return ret; - if (axg_card_cpu_is_tdm_iface(dai_link->cpus->of_node)) - ret = axg_card_parse_tdm(card, np, index); - else if (axg_card_cpu_is_codec(dai_link->cpus->of_node)) { + if (axg_card_cpu_is_codec(dai_link->cpus->of_node)) { dai_link->params = &codec_params; - dai_link->no_pcm = 0; /* link is not a DPCM BE */ + } else { + dai_link->no_pcm = 1; + snd_soc_dai_link_set_capabilities(dai_link); + if (axg_card_cpu_is_tdm_iface(dai_link->cpus->of_node)) + ret = axg_card_parse_tdm(card, np, index); } return ret; diff --git a/sound/soc/meson/axg-spdifout.c b/sound/soc/meson/axg-spdifout.c index 7ce6aa97ddf7aab674fe1386562fd26c32cd273a..e769a5ee6e27e6a9be7091f7e2d31745fb1d1ba0 100644 --- a/sound/soc/meson/axg-spdifout.c +++ b/sound/soc/meson/axg-spdifout.c @@ -108,7 +108,7 @@ static int axg_spdifout_trigger(struct snd_pcm_substream *substream, int cmd, } } -static int axg_spdifout_digital_mute(struct snd_soc_dai *dai, int mute) +static int axg_spdifout_mute(struct snd_soc_dai *dai, int mute, int direction) { struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai); @@ -285,10 +285,11 @@ static void axg_spdifout_shutdown(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops axg_spdifout_ops = { .trigger = axg_spdifout_trigger, - .digital_mute = axg_spdifout_digital_mute, + .mute_stream = axg_spdifout_mute, .hw_params = axg_spdifout_hw_params, .startup = axg_spdifout_startup, .shutdown = axg_spdifout_shutdown, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver axg_spdifout_dai_drv[] = { diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c index 358c8c0d861cd79dc3af06a8f89d972cd8d8c93f..f7e8e9da68a06bbd9e951be45ea9a12880259d16 100644 --- a/sound/soc/meson/axg-tdm-formatter.c +++ b/sound/soc/meson/axg-tdm-formatter.c @@ -70,7 +70,7 @@ EXPORT_SYMBOL_GPL(axg_tdm_formatter_set_channel_masks); static int axg_tdm_formatter_enable(struct axg_tdm_formatter *formatter) { struct axg_tdm_stream *ts = formatter->stream; - bool invert = formatter->drv->quirks->invert_sclk; + bool invert; int ret; /* Do nothing if the formatter is already enabled */ @@ -96,11 +96,12 @@ static int axg_tdm_formatter_enable(struct axg_tdm_formatter *formatter) return ret; /* - * If sclk is inverted, invert it back and provide the inversion - * required by the formatter + * If sclk is inverted, it means the bit should latched on the + * rising edge which is what our HW expects. If not, we need to + * invert it before the formatter. */ - invert ^= axg_tdm_sclk_invert(ts->iface->fmt); - ret = clk_set_phase(formatter->sclk, invert ? 180 : 0); + invert = axg_tdm_sclk_invert(ts->iface->fmt); + ret = clk_set_phase(formatter->sclk, invert ? 0 : 180); if (ret) return ret; diff --git a/sound/soc/meson/axg-tdm-formatter.h b/sound/soc/meson/axg-tdm-formatter.h index 9ef98e955cb2744450e75006b432a2043aa13593..a1f0dcc0ff134c7e5fd021958c2fa342e05a9dac 100644 --- a/sound/soc/meson/axg-tdm-formatter.h +++ b/sound/soc/meson/axg-tdm-formatter.h @@ -16,7 +16,6 @@ struct snd_kcontrol; struct axg_tdm_formatter_hw { unsigned int skew_offset; - bool invert_sclk; }; struct axg_tdm_formatter_ops { diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index 6de27238e9dff447a86349472f0c2dce72665b11..36df30915378cca26e80c93ef235f9ac669d1378 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -119,18 +119,25 @@ static int axg_tdm_iface_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); - /* These modes are not supported */ - if (fmt & (SND_SOC_DAIFMT_CBS_CFM | SND_SOC_DAIFMT_CBM_CFS)) { + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + if (!iface->mclk) { + dev_err(dai->dev, "cpu clock master: mclk missing\n"); + return -ENODEV; + } + break; + + case SND_SOC_DAIFMT_CBM_CFM: + break; + + case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBM_CFS: dev_err(dai->dev, "only CBS_CFS and CBM_CFM are supported\n"); + /* Fall-through */ + default: return -EINVAL; } - /* If the TDM interface is the clock master, it requires mclk */ - if (!iface->mclk && (fmt & SND_SOC_DAIFMT_CBS_CFS)) { - dev_err(dai->dev, "cpu clock master: mclk missing\n"); - return -ENODEV; - } - iface->fmt = fmt; return 0; } @@ -319,7 +326,8 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream, if (ret) return ret; - if (iface->fmt & SND_SOC_DAIFMT_CBS_CFS) { + if ((iface->fmt & SND_SOC_DAIFMT_MASTER_MASK) == + SND_SOC_DAIFMT_CBS_CFS) { ret = axg_tdm_iface_set_sclk(dai, params); if (ret) return ret; diff --git a/sound/soc/meson/axg-tdmin.c b/sound/soc/meson/axg-tdmin.c index 973d4c02ef8db02de0f0a8f211cdcc254b04f573..88ed95ae886bb506cda8c8ac74dae2babcd568c0 100644 --- a/sound/soc/meson/axg-tdmin.c +++ b/sound/soc/meson/axg-tdmin.c @@ -228,15 +228,29 @@ static const struct axg_tdm_formatter_driver axg_tdmin_drv = { .regmap_cfg = &axg_tdmin_regmap_cfg, .ops = &axg_tdmin_ops, .quirks = &(const struct axg_tdm_formatter_hw) { - .invert_sclk = false, .skew_offset = 2, }, }; +static const struct axg_tdm_formatter_driver g12a_tdmin_drv = { + .component_drv = &axg_tdmin_component_drv, + .regmap_cfg = &axg_tdmin_regmap_cfg, + .ops = &axg_tdmin_ops, + .quirks = &(const struct axg_tdm_formatter_hw) { + .skew_offset = 3, + }, +}; + static const struct of_device_id axg_tdmin_of_match[] = { { .compatible = "amlogic,axg-tdmin", .data = &axg_tdmin_drv, + }, { + .compatible = "amlogic,g12a-tdmin", + .data = &g12a_tdmin_drv, + }, { + .compatible = "amlogic,sm1-tdmin", + .data = &g12a_tdmin_drv, }, {} }; MODULE_DEVICE_TABLE(of, axg_tdmin_of_match); diff --git a/sound/soc/meson/axg-tdmout.c b/sound/soc/meson/axg-tdmout.c index 418ec314b37d452e390b59501219b32f750bb88a..3ceabddae629ec19cd7f81e31aeb2866d8977fd3 100644 --- a/sound/soc/meson/axg-tdmout.c +++ b/sound/soc/meson/axg-tdmout.c @@ -238,7 +238,6 @@ static const struct axg_tdm_formatter_driver axg_tdmout_drv = { .regmap_cfg = &axg_tdmout_regmap_cfg, .ops = &axg_tdmout_ops, .quirks = &(const struct axg_tdm_formatter_hw) { - .invert_sclk = true, .skew_offset = 1, }, }; @@ -248,7 +247,6 @@ static const struct axg_tdm_formatter_driver g12a_tdmout_drv = { .regmap_cfg = &axg_tdmout_regmap_cfg, .ops = &axg_tdmout_ops, .quirks = &(const struct axg_tdm_formatter_hw) { - .invert_sclk = true, .skew_offset = 2, }, }; @@ -309,7 +307,6 @@ static const struct axg_tdm_formatter_driver sm1_tdmout_drv = { .regmap_cfg = &axg_tdmout_regmap_cfg, .ops = &axg_tdmout_ops, .quirks = &(const struct axg_tdm_formatter_hw) { - .invert_sclk = true, .skew_offset = 2, }, }; diff --git a/sound/soc/meson/gx-card.c b/sound/soc/meson/gx-card.c index 4abf7efb7eacc54442ad7c3a662050d427086bbc..5119434a81c4283ba69559bf44fa21b87ca72d58 100644 --- a/sound/soc/meson/gx-card.c +++ b/sound/soc/meson/gx-card.c @@ -29,7 +29,7 @@ static const struct snd_soc_pcm_stream codec_params = { static int gx_card_i2s_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct meson_card *priv = snd_soc_card_get_drvdata(rtd->card); struct gx_dai_link_i2s_data *be = (struct gx_dai_link_i2s_data *)priv->link_data[rtd->num]; @@ -96,21 +96,21 @@ static int gx_card_add_link(struct snd_soc_card *card, struct device_node *np, return ret; if (gx_card_cpu_identify(dai_link->cpus, "FIFO")) - ret = meson_card_set_fe_link(card, dai_link, np, true); - else - ret = meson_card_set_be_link(card, dai_link, np); + return meson_card_set_fe_link(card, dai_link, np, true); + ret = meson_card_set_be_link(card, dai_link, np); if (ret) return ret; - /* Check if the cpu is the i2s encoder and parse i2s data */ - if (gx_card_cpu_identify(dai_link->cpus, "I2S Encoder")) - ret = gx_card_parse_i2s(card, np, index); - /* Or apply codec to codec params if necessary */ - else if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL")) { + if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL")) { dai_link->params = &codec_params; - dai_link->no_pcm = 0; /* link is not a DPCM BE */ + } else { + dai_link->no_pcm = 1; + snd_soc_dai_link_set_capabilities(dai_link); + /* Check if the cpu is the i2s encoder and parse i2s data */ + if (gx_card_cpu_identify(dai_link->cpus, "I2S Encoder")) + ret = gx_card_parse_i2s(card, np, index); } return ret; diff --git a/sound/soc/meson/meson-card-utils.c b/sound/soc/meson/meson-card-utils.c index 5a4a91c887347f5b37574cff2f9ada7c40ba0b5b..6a64ac01b5ca6a15fef48b6b6ec6db7b8367b9bd 100644 --- a/sound/soc/meson/meson-card-utils.c +++ b/sound/soc/meson/meson-card-utils.c @@ -13,7 +13,7 @@ int meson_card_i2s_set_sysclk(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, unsigned int mclk_fs) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; unsigned int mclk; int ret, i; @@ -119,7 +119,7 @@ unsigned int meson_card_parse_daifmt(struct device_node *node, struct device_node *framemaster = NULL; unsigned int daifmt; - daifmt = snd_soc_of_parse_daifmt(node, DT_PREFIX, + daifmt = snd_soc_of_parse_daifmt(node, "", &bitclkmaster, &framemaster); daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; @@ -147,10 +147,6 @@ int meson_card_set_be_link(struct snd_soc_card *card, struct device_node *np; int ret, num_codecs; - link->no_pcm = 1; - link->dpcm_playback = 1; - link->dpcm_capture = 1; - num_codecs = of_get_child_count(node); if (!num_codecs) { dev_err(card->dev, "be link %s has no codec\n", diff --git a/sound/soc/meson/meson-codec-glue.c b/sound/soc/meson/meson-codec-glue.c index 524a33472337388666f83ebf9026a71a2ad6d5fb..d07270d17cee7b3cf2f28527ee56b87bfad25a22 100644 --- a/sound/soc/meson/meson-codec-glue.c +++ b/sound/soc/meson/meson-codec-glue.c @@ -98,7 +98,7 @@ EXPORT_SYMBOL_GPL(meson_codec_glue_input_set_fmt); int meson_codec_glue_output_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct meson_codec_glue_input *in_data = meson_codec_glue_output_get_input_data(dai->capture_widget); diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index f46d7aca8cf6b735968881b733bcc8d8a04633f5..a6407f4388de7de3fde2ebb8cb9ec032f6c09eaa 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -19,7 +19,7 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int rate = params_rate(params); diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c index 016a91199485150345bcde36b663b303bd141f58..f310a8e91bbf0e14a14b99e2496175f46ad3b1da 100644 --- a/sound/soc/pxa/brownstone.c +++ b/sound/soc/pxa/brownstone.c @@ -43,7 +43,7 @@ static const struct snd_soc_dapm_route brownstone_audio_map[] = { static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int freq_out, sspa_mclk, sysclk; diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 6fbef9a0afa730cedd4e0503a6bc73c83eb9a4e8..8ee2dea25a8d0263a94432952a39c06fe7a947ee 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -96,7 +96,7 @@ static void corgi_ext_control(struct snd_soc_dapm_context *dapm) static int corgi_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* check the jack status at stream startup */ corgi_ext_control(&rtd->card->dapm); @@ -115,7 +115,7 @@ static void corgi_shutdown(struct snd_pcm_substream *substream) static int corgi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c index b4da9a9a65210e784f6fedd1841b167ebe96fa48..7334fac758defe778cb14fcefca7014dad269006 100644 --- a/sound/soc/pxa/hx4700.c +++ b/sound/soc/pxa/hx4700.c @@ -53,7 +53,7 @@ static struct snd_soc_jack_gpio hs_jack_gpio = { static int hx4700_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret = 0; diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c index 3014e8244ab4666d571f2621488a518fa7f67308..a575676508b35a0812f0ecd661c7ee6b9123b708 100644 --- a/sound/soc/pxa/imote2.c +++ b/sound/soc/pxa/imote2.c @@ -11,7 +11,7 @@ static int imote2_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index e4c818f4cd62b34ad9f3d7e1fcce3c217541992b..a5f326c97af23e5fbf03e39e3b08ba0b9659c2e9 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -68,7 +68,7 @@ static void magician_ext_control(struct snd_soc_dapm_context *dapm) static int magician_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* check the jack status at stream startup */ magician_ext_control(&rtd->card->dapm); @@ -82,7 +82,7 @@ static int magician_startup(struct snd_pcm_substream *substream) static int magician_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int width; @@ -120,7 +120,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream, static int magician_capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret = 0; diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index bf27b277c01f9e6b4aa27c50d3c8bd52003f76ef..763db7bbd9bb30592a09b5c37c682cc4e2abcb7a 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -51,14 +51,14 @@ static int rear_amp_power(struct snd_soc_component *component, int power) unsigned short reg; if (power) { - reg = snd_soc_component_read32(component, AC97_GPIO_CFG); + reg = snd_soc_component_read(component, AC97_GPIO_CFG); snd_soc_component_write(component, AC97_GPIO_CFG, reg | 0x0100); - reg = snd_soc_component_read32(component, AC97_GPIO_PULL); + reg = snd_soc_component_read(component, AC97_GPIO_PULL); snd_soc_component_write(component, AC97_GPIO_PULL, reg | (1<<15)); } else { - reg = snd_soc_component_read32(component, AC97_GPIO_CFG); + reg = snd_soc_component_read(component, AC97_GPIO_CFG); snd_soc_component_write(component, AC97_GPIO_CFG, reg & ~0x0100); - reg = snd_soc_component_read32(component, AC97_GPIO_PULL); + reg = snd_soc_component_read(component, AC97_GPIO_PULL); snd_soc_component_write(component, AC97_GPIO_PULL, reg & ~(1<<15)); } diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c index 3fe6c4c5a3ab24ebac10c8759373fe852890c85e..53fc49e32fbc8e8da8b41ecae53664bd5cb2d92e 100644 --- a/sound/soc/pxa/mmp-pcm.c +++ b/sound/soc/pxa/mmp-pcm.c @@ -110,7 +110,7 @@ static bool filter(struct dma_chan *chan, void *param) static int mmp_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct platform_device *pdev = to_platform_device(component->dev); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct mmp_dma_data dma_data; diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 287984a564c8197788dcab5e73185336a04b68ac..323ba3e23039ddf6158d7c23902aed42e13f288d 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -68,7 +68,7 @@ static void poodle_ext_control(struct snd_soc_dapm_context *dapm) static int poodle_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* check the jack status at stream startup */ poodle_ext_control(&rtd->card->dapm); @@ -89,7 +89,7 @@ static void poodle_shutdown(struct snd_pcm_substream *substream) static int poodle_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 6a72cc1665b7c45db50ae4670bb58c473a4c0d3f..d1e09ade0190d67404cf796f12a6e1d0a0413cf2 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -178,7 +178,7 @@ static int pxa_ssp_resume(struct snd_soc_component *component) #define pxa_ssp_resume NULL #endif -/** +/* * ssp_set_clkdiv - set SSP clock divider * @div: serial clock rate divider */ diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 03102e938ba138a1aaf839186b4471caf6d9fc9a..5301859a8453c7000641fea3bf0d39c65567b3da 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -95,7 +95,7 @@ static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_in = { static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); if (IS_ERR(clk_i2s)) diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 6d8174f629358097dfe5ed6af518473e86cd1ce7..7c1384a869ca482f9cac29925510cb80f6ac6aa8 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -105,7 +105,7 @@ static void spitz_ext_control(struct snd_soc_dapm_context *dapm) static int spitz_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* check the jack status at stream startup */ spitz_ext_control(&rtd->card->dapm); @@ -116,7 +116,7 @@ static int spitz_startup(struct snd_pcm_substream *substream) static int spitz_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index b429db25f88418e5f3e47ad90962fa4a4cdbd479..3b40b5fa5de7e2bb8cef493e0923f4964eb98bcd 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -72,7 +72,7 @@ static void tosa_ext_control(struct snd_soc_dapm_context *dapm) static int tosa_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* check the jack status at stream startup */ tosa_ext_control(&rtd->card->dapm); diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index 6eee1aefc89a864be35ae87be845d8bc1d1f6521..edf2b9eec5b8b4f92baae3f3bb486690cbfa733b 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c @@ -33,7 +33,7 @@ static struct snd_soc_card snd_soc_z2; static int z2_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 447b59b8bd33ccf11e598b86d0ac806ab474025b..bb89a53f4ab10a2189beaf60c0b20e8d6da608c1 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -75,7 +75,7 @@ static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd) static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int wm9713_div = 0; diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index cfca0f730c61e431880c2b0afdc1a83385306418..5d6b2466a2f2c70a3f2b3ad0ff25e2c44b3d8da1 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -37,6 +37,7 @@ config SND_SOC_APQ8016_SBC tristate "SoC Audio support for APQ8016 SBC platforms" depends on SND_SOC_QCOM select SND_SOC_LPASS_APQ8016 + select SND_SOC_QCOM_COMMON help Support for Qualcomm Technologies LPASS audio block in APQ8016 SOC-based systems. diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 2ef090f4af9e92bbbc39d724eed34543a07ed7c6..083413abc2f694bedc98237bc6d3e45ebe0958ca 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -16,13 +16,14 @@ #include #include #include +#include "common.h" struct apq8016_sbc_data { + struct snd_soc_card card; void __iomem *mic_iomux; void __iomem *spkr_iomux; struct snd_soc_jack jack; bool jack_setup; - struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ }; #define MIC_CTRL_TER_WS_SLAVE_SEL BIT(21) @@ -110,107 +111,13 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd) return 0; } -static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) +static void apq8016_sbc_add_ops(struct snd_soc_card *card) { - struct device *dev = card->dev; struct snd_soc_dai_link *link; - struct device_node *np, *codec, *cpu, *node = dev->of_node; - struct apq8016_sbc_data *data; - struct snd_soc_dai_link_component *dlc; - int ret, num_links; - - ret = snd_soc_of_parse_card_name(card, "qcom,model"); - if (ret) { - dev_err(dev, "Error parsing card name: %d\n", ret); - return ERR_PTR(ret); - } - - /* DAPM routes */ - if (of_property_read_bool(node, "qcom,audio-routing")) { - ret = snd_soc_of_parse_audio_routing(card, - "qcom,audio-routing"); - if (ret) - return ERR_PTR(ret); - } - - - /* Populate links */ - num_links = of_get_child_count(node); - - /* Allocate the private data and the DAI link array */ - data = devm_kzalloc(dev, - struct_size(data, dai_link, num_links), - GFP_KERNEL); - if (!data) - return ERR_PTR(-ENOMEM); - - card->dai_link = &data->dai_link[0]; - card->num_links = num_links; - - link = data->dai_link; - - for_each_child_of_node(node, np) { - dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); - if (!dlc) - return ERR_PTR(-ENOMEM); - - link->cpus = &dlc[0]; - link->platforms = &dlc[1]; - - link->num_cpus = 1; - link->num_platforms = 1; - - cpu = of_get_child_by_name(np, "cpu"); - codec = of_get_child_by_name(np, "codec"); - - if (!cpu || !codec) { - dev_err(dev, "Can't find cpu/codec DT node\n"); - ret = -EINVAL; - goto error; - } + int i; - link->cpus->of_node = of_parse_phandle(cpu, "sound-dai", 0); - if (!link->cpus->of_node) { - dev_err(card->dev, "error getting cpu phandle\n"); - ret = -EINVAL; - goto error; - } - - ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name); - if (ret) { - dev_err(card->dev, "error getting cpu dai name\n"); - goto error; - } - - ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); - - if (ret < 0) { - dev_err(card->dev, "error getting codec dai name\n"); - goto error; - } - - link->platforms->of_node = link->cpus->of_node; - ret = of_property_read_string(np, "link-name", &link->name); - if (ret) { - dev_err(card->dev, "error getting codec dai_link name\n"); - goto error; - } - - link->stream_name = link->name; + for_each_card_prelinks(card, i, link) link->init = apq8016_sbc_dai_init; - link++; - - of_node_put(cpu); - of_node_put(codec); - } - - return data; - - error: - of_node_put(np); - of_node_put(cpu); - of_node_put(codec); - return ERR_PTR(ret); } static const struct snd_soc_dapm_widget apq8016_sbc_dapm_widgets[] = { @@ -228,20 +135,20 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev) struct snd_soc_card *card; struct apq8016_sbc_data *data; struct resource *res; + int ret; - card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); - if (!card) + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) return -ENOMEM; + card = &data->card; card->dev = dev; card->dapm_widgets = apq8016_sbc_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(apq8016_sbc_dapm_widgets); - data = apq8016_sbc_parse_of(card); - if (IS_ERR(data)) { - dev_err(&pdev->dev, "Error resolving dai links: %ld\n", - PTR_ERR(data)); - return PTR_ERR(data); - } + + ret = qcom_snd_parse_of(card); + if (ret) + return ret; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mic-iomux"); data->mic_iomux = devm_ioremap_resource(dev, res); @@ -255,6 +162,7 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(card, data); + apq8016_sbc_add_ops(card); return devm_snd_soc_register_card(&pdev->dev, card); } diff --git a/sound/soc/qcom/apq8096.c b/sound/soc/qcom/apq8096.c index 287ad2aa27f373154733b7de83a2a69af7050068..253549600c5a3f8ee98de0ad225dd38097e7fd62 100644 --- a/sound/soc/qcom/apq8096.c +++ b/sound/soc/qcom/apq8096.c @@ -30,7 +30,7 @@ static int apq8096_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static int msm_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS]; @@ -109,7 +109,7 @@ static int apq8096_platform_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int ret; - card = kzalloc(sizeof(*card), GFP_KERNEL); + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; @@ -117,31 +117,10 @@ static int apq8096_platform_probe(struct platform_device *pdev) dev_set_drvdata(dev, card); ret = qcom_snd_parse_of(card); if (ret) - goto err; + return ret; apq8096_add_be_ops(card); - ret = snd_soc_register_card(card); - if (ret) - goto err_card_register; - - return 0; - -err_card_register: - kfree(card->dai_link); -err: - kfree(card); - return ret; -} - -static int apq8096_platform_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = dev_get_drvdata(&pdev->dev); - - snd_soc_unregister_card(card); - kfree(card->dai_link); - kfree(card); - - return 0; + return devm_snd_soc_register_card(dev, card); } static const struct of_device_id msm_snd_apq8096_dt_match[] = { @@ -153,7 +132,6 @@ MODULE_DEVICE_TABLE(of, msm_snd_apq8096_dt_match); static struct platform_driver msm_snd_apq8096_driver = { .probe = apq8096_platform_probe, - .remove = apq8096_platform_remove, .driver = { .name = "msm-snd-apq8096", .of_match_table = msm_snd_apq8096_dt_match, diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 8ada4ecba847269266a19486d823432b6964924b..5194d90ddb96467ca8190c4f61fb59156a448b63 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -4,7 +4,6 @@ #include #include "common.h" -#include "qdsp6/q6afe.h" int qcom_snd_parse_of(struct snd_soc_card *card) { @@ -19,6 +18,9 @@ int qcom_snd_parse_of(struct snd_soc_card *card) int ret, num_links; ret = snd_soc_of_parse_card_name(card, "model"); + if (ret == 0 && !card->name) + /* Deprecated, only for compatibility with old device trees */ + ret = snd_soc_of_parse_card_name(card, "qcom,model"); if (ret) { dev_err(dev, "Error parsing card name: %d\n", ret); return ret; @@ -26,8 +28,13 @@ int qcom_snd_parse_of(struct snd_soc_card *card) /* DAPM routes */ if (of_property_read_bool(dev->of_node, "audio-routing")) { - ret = snd_soc_of_parse_audio_routing(card, - "audio-routing"); + ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); + if (ret) + return ret; + } + /* Deprecated, only for compatibility with old device trees */ + if (of_property_read_bool(dev->of_node, "qcom,audio-routing")) { + ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing"); if (ret) return ret; } @@ -36,7 +43,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card) num_links = of_get_child_count(dev->of_node); /* Allocate the DAI link array */ - card->dai_link = kcalloc(num_links, sizeof(*link), GFP_KERNEL); + card->dai_link = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL); if (!card->dai_link) return -ENOMEM; @@ -81,11 +88,13 @@ int qcom_snd_parse_of(struct snd_soc_card *card) ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name); if (ret) { - dev_err(card->dev, "%s: error getting cpu dai name\n", link->name); + if (ret != -EPROBE_DEFER) + dev_err(card->dev, "%s: error getting cpu dai name: %d\n", + link->name, ret); goto err; } - if (codec && platform) { + if (platform) { link->platforms->of_node = of_parse_phandle(platform, "sound-dai", 0); @@ -94,24 +103,26 @@ int qcom_snd_parse_of(struct snd_soc_card *card) ret = -EINVAL; goto err; } + } else { + link->platforms->of_node = link->cpus->of_node; + } + if (codec) { ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); if (ret < 0) { - dev_err(card->dev, "%s: codec dai not found\n", link->name); + if (ret != -EPROBE_DEFER) + dev_err(card->dev, "%s: codec dai not found: %d\n", + link->name, ret); goto err; } - link->no_pcm = 1; - link->ignore_pmdown_time = 1; - - if (q6afe_is_rx_port(link->id)) { - link->dpcm_playback = 1; - link->dpcm_capture = 0; - } else { - link->dpcm_playback = 0; - link->dpcm_capture = 1; - } + if (platform) { + /* DPCM backend */ + link->no_pcm = 1; + link->ignore_pmdown_time = 1; + } } else { + /* DPCM frontend */ dlc = devm_kzalloc(dev, sizeof(*dlc), GFP_KERNEL); if (!dlc) return -ENOMEM; @@ -119,16 +130,18 @@ int qcom_snd_parse_of(struct snd_soc_card *card) link->codecs = dlc; link->num_codecs = 1; - link->platforms->of_node = link->cpus->of_node; link->codecs->dai_name = "snd-soc-dummy-dai"; link->codecs->name = "snd-soc-dummy"; link->dynamic = 1; - link->dpcm_playback = 1; - link->dpcm_capture = 1; } - link->ignore_suspend = 1; - link->nonatomic = 1; + if (platform || !codec) { + /* DPCM */ + snd_soc_dai_link_set_capabilities(link); + link->ignore_suspend = 1; + link->nonatomic = 1; + } + link->stream_name = link->name; link++; @@ -143,7 +156,6 @@ err: of_node_put(cpu); of_node_put(codec); of_node_put(platform); - kfree(card->dai_link); return ret; } EXPORT_SYMBOL(qcom_snd_parse_of); diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 34f7fd1bab1cfbffdc88c9d3c202eab65771010b..01179bc0e5e572d793f85e1cfd363013d9b6551b 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -54,7 +54,7 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct lpass_variant *v = drvdata->variant; @@ -125,7 +125,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; @@ -218,7 +218,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component, static int lpass_platform_pcmops_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; @@ -239,7 +239,7 @@ static int lpass_platform_pcmops_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; @@ -291,7 +291,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; @@ -365,7 +365,7 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; @@ -410,7 +410,7 @@ static irqreturn_t lpass_dma_interrupt_handler( struct lpass_data *drvdata, int chan, u32 interrupts) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct lpass_variant *v = drvdata->variant; irqreturn_t ret = IRQ_NONE; int rv; diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c index da242515e14679f8deebfb44e5bfb1e88440990d..2f3ea6beb066a58377a5d463559fe000ccaaf4ca 100644 --- a/sound/soc/qcom/qdsp6/q6adm.c +++ b/sound/soc/qcom/qdsp6/q6adm.c @@ -403,7 +403,7 @@ struct q6copp *q6adm_open(struct device *dev, int port_id, int path, int rate, spin_lock_irqsave(&adm->copps_list_lock, flags); copp = q6adm_alloc_copp(adm, port_id); - if (IS_ERR_OR_NULL(copp)) { + if (IS_ERR(copp)) { spin_unlock_irqrestore(&adm->copps_list_lock, flags); return ERR_CAST(copp); } @@ -419,7 +419,6 @@ struct q6copp *q6adm_open(struct device *dev, int port_id, int path, int rate, copp->bit_width = bit_width; copp->app_type = app_type; - ret = q6adm_device_open(adm, copp, port_id, path, topology, channel_mode, bit_width, rate); if (ret < 0) { @@ -588,12 +587,12 @@ static int q6adm_probe(struct apr_device *adev) struct device *dev = &adev->dev; struct q6adm *adm; - adm = devm_kzalloc(&adev->dev, sizeof(*adm), GFP_KERNEL); + adm = devm_kzalloc(dev, sizeof(*adm), GFP_KERNEL); if (!adm) return -ENOMEM; adm->apr = adev; - dev_set_drvdata(&adev->dev, adm); + dev_set_drvdata(dev, adm); adm->dev = dev; q6core_get_svc_api_info(adev->svc_id, &adm->ainfo); mutex_init(&adm->lock); diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index 0ce4eb60f9848ff6406c953da694d4e10e7b1577..e0945f7a58c816e5c6b7dda7cc7073aeb8aa3bb6 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -800,14 +800,6 @@ int q6afe_get_port_id(int index) } EXPORT_SYMBOL_GPL(q6afe_get_port_id); -int q6afe_is_rx_port(int index) -{ - if (index < 0 || index >= AFE_PORT_MAX) - return -EINVAL; - - return port_maps[index].is_rx; -} -EXPORT_SYMBOL_GPL(q6afe_is_rx_port); static int afe_apr_send_pkt(struct q6afe *afe, struct apr_pkt *pkt, struct q6afe_port *port) { diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h index 1a0f80a14afeaf087d692fc6171f6d2643ebccc8..c7ed5422baffd3bb73fc7eef091130da2b700779 100644 --- a/sound/soc/qcom/qdsp6/q6afe.h +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -198,7 +198,6 @@ int q6afe_port_start(struct q6afe_port *port); int q6afe_port_stop(struct q6afe_port *port); void q6afe_port_put(struct q6afe_port *port); int q6afe_get_port_id(int index); -int q6afe_is_rx_port(int index); void q6afe_hdmi_port_prepare(struct q6afe_port *port, struct q6afe_hdmi_cfg *cfg); void q6afe_slim_port_prepare(struct q6afe_port *port, diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index aff57052a735585708e05add7c09eb6a625df5bb..9b7b218f2a20b5925afb4d2b31c966375ca98ed0 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -37,9 +37,6 @@ #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024) #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4) #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4) -#define Q6ASM_DAI_TX_RX 0 -#define Q6ASM_DAI_TX 1 -#define Q6ASM_DAI_RX 2 #define ALAC_CH_LAYOUT_MONO ((101 << 16) | 1) #define ALAC_CH_LAYOUT_STEREO ((101 << 16) | 2) @@ -215,9 +212,10 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; + struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream); struct q6asm_dai_rtd *prtd = runtime->private_data; struct q6asm_dai_data *pdata; + struct device *dev = component->dev; int ret, i; pdata = snd_soc_component_get_drvdata(component); @@ -225,7 +223,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, return -EINVAL; if (!prtd || !prtd->audio_client) { - pr_err("%s: private data null or audio client freed\n", + dev_err(dev, "%s: private data null or audio client freed\n", __func__); return -EINVAL; } @@ -248,7 +246,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, prtd->periods); if (ret < 0) { - pr_err("Audio Start: Buffer Allocation failed rc = %d\n", + dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret); return -ENOMEM; } @@ -262,7 +260,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, } if (ret < 0) { - pr_err("%s: q6asm_open_write failed\n", __func__); + dev_err(dev, "%s: q6asm_open_write failed\n", __func__); q6asm_audio_client_free(prtd->audio_client); prtd->audio_client = NULL; return -ENOMEM; @@ -272,7 +270,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE, prtd->session_id, substream->stream); if (ret) { - pr_err("%s: stream reg failed ret:%d\n", __func__, ret); + dev_err(dev, "%s: stream reg failed ret:%d\n", __func__, ret); return ret; } @@ -292,7 +290,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, } if (ret < 0) - pr_info("%s: CMD Format block failed\n", __func__); + dev_info(dev, "%s: CMD Format block failed\n", __func__); prtd->state = Q6ASM_STREAM_RUNNING; @@ -332,7 +330,7 @@ static int q6asm_dai_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; + struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_prtd, 0); struct q6asm_dai_rtd *prtd; struct q6asm_dai_data *pdata; @@ -344,7 +342,7 @@ static int q6asm_dai_open(struct snd_soc_component *component, pdata = snd_soc_component_get_drvdata(component); if (!pdata) { - pr_err("Drv data not found ..\n"); + dev_err(dev, "Drv data not found ..\n"); return -EINVAL; } @@ -357,7 +355,7 @@ static int q6asm_dai_open(struct snd_soc_component *component, (q6asm_cb)event_handler, prtd, stream_id, LEGACY_PCM_MODE); if (IS_ERR(prtd->audio_client)) { - pr_info("%s: Could not allocate memory\n", __func__); + dev_info(dev, "%s: Could not allocate memory\n", __func__); ret = PTR_ERR(prtd->audio_client); kfree(prtd); return ret; @@ -372,12 +370,12 @@ static int q6asm_dai_open(struct snd_soc_component *component, SNDRV_PCM_HW_PARAM_RATE, &constraints_sample_rates); if (ret < 0) - pr_info("snd_pcm_hw_constraint_list failed\n"); + dev_info(dev, "snd_pcm_hw_constraint_list failed\n"); /* Ensure that buffer size is a multiple of period size */ ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) - pr_info("snd_pcm_hw_constraint_integer failed\n"); + dev_info(dev, "snd_pcm_hw_constraint_integer failed\n"); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ret = snd_pcm_hw_constraint_minmax(runtime, @@ -385,21 +383,21 @@ static int q6asm_dai_open(struct snd_soc_component *component, PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE, PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE); if (ret < 0) { - pr_err("constraint for buffer bytes min max ret = %d\n", - ret); + dev_err(dev, "constraint for buffer bytes min max ret = %d\n", + ret); } } ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); if (ret < 0) { - pr_err("constraint for period bytes step ret = %d\n", + dev_err(dev, "constraint for period bytes step ret = %d\n", ret); } ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); if (ret < 0) { - pr_err("constraint for buffer bytes step ret = %d\n", + dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret); } @@ -424,7 +422,7 @@ static int q6asm_dai_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; + struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream); struct q6asm_dai_rtd *prtd = runtime->private_data; if (prtd->audio_client) { diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c index ae4b2cabdf2d6cc69ffc33fdf5cab45e61ff5c36..755062eadcc85ef9ca53e507ec91f0b9a518086c 100644 --- a/sound/soc/qcom/qdsp6/q6asm.c +++ b/sound/soc/qcom/qdsp6/q6asm.c @@ -311,7 +311,7 @@ static int q6asm_apr_send_session_pkt(struct q6asm *a, struct audio_client *ac, 5 * HZ); if (!rc) { - dev_err(a->dev, "CMD timeout\n"); + dev_err(a->dev, "CMD %x timeout\n", hdr->opcode); rc = -ETIMEDOUT; } else if (ac->result.status > 0) { dev_err(a->dev, "DSP returned error[%x]\n", @@ -891,7 +891,7 @@ static int q6asm_ac_send_cmd_sync(struct audio_client *ac, struct apr_pkt *pkt) rc = wait_event_timeout(ac->cmd_wait, (ac->result.opcode == hdr->opcode), 5 * HZ); if (!rc) { - dev_err(ac->dev, "CMD timeout\n"); + dev_err(ac->dev, "CMD %x timeout\n", hdr->opcode); rc = -ETIMEDOUT; goto err; } @@ -912,9 +912,9 @@ err: /** * q6asm_open_write() - Open audio client for writing - * * @ac: audio client pointer * @format: audio sample format + * @codec_profile: compressed format profile * @bits_per_sample: bits per sample * * Return: Will be an negative value on error or zero on success diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index 46e50612b92c10e2fde503983bad1dbf6e70d566..eaa95b5a7b6633dcd8262dea53be99617dfc8143 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -924,7 +924,7 @@ static int routing_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct msm_routing_data *data = dev_get_drvdata(component->dev); unsigned int be_id = asoc_rtd_to_cpu(rtd, 0)->id; struct session_data *session; diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c index 68e9388ff46f1b8b9b7d7995b0e6bcdb880fb2d2..0d10fba53945e69c833de4ab1a7bd8c11b1cc1e0 100644 --- a/sound/soc/qcom/sdm845.c +++ b/sound/soc/qcom/sdm845.c @@ -45,7 +45,7 @@ static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28}; static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai; struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); @@ -85,7 +85,7 @@ static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream, static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai; int ret = 0, j; @@ -170,7 +170,7 @@ end: static int sdm845_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret = 0; @@ -301,7 +301,7 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream) { unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); @@ -391,7 +391,7 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream) static void sdm845_snd_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); @@ -437,7 +437,7 @@ static void sdm845_snd_shutdown(struct snd_pcm_substream *substream) static int sdm845_snd_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; @@ -476,7 +476,7 @@ static int sdm845_snd_prepare(struct snd_pcm_substream *substream) static int sdm845_snd_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; @@ -543,16 +543,14 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int ret; - card = kzalloc(sizeof(*card), GFP_KERNEL); + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; /* Allocate the private data */ - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto data_alloc_fail; - } + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; card->dapm_widgets = sdm845_snd_widgets; card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets); @@ -560,38 +558,13 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev) dev_set_drvdata(dev, card); ret = qcom_snd_parse_of(card); if (ret) - goto parse_dt_fail; + return ret; data->card = card; snd_soc_card_set_drvdata(card, data); sdm845_add_ops(card); - ret = snd_soc_register_card(card); - if (ret) { - dev_err(dev, "Sound card registration failed\n"); - goto register_card_fail; - } - return ret; - -register_card_fail: - kfree(card->dai_link); -parse_dt_fail: - kfree(data); -data_alloc_fail: - kfree(card); - return ret; -} - -static int sdm845_snd_platform_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = dev_get_drvdata(&pdev->dev); - struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card); - - snd_soc_unregister_card(card); - kfree(card->dai_link); - kfree(data); - kfree(card); - return 0; + return devm_snd_soc_register_card(dev, card); } static const struct of_device_id sdm845_snd_device_id[] = { @@ -604,7 +577,6 @@ MODULE_DEVICE_TABLE(of, sdm845_snd_device_id); static struct platform_driver sdm845_snd_driver = { .probe = sdm845_snd_platform_probe, - .remove = sdm845_snd_platform_remove, .driver = { .name = "msm-snd-sdm845", .of_match_table = sdm845_snd_device_id, diff --git a/sound/soc/qcom/storm.c b/sound/soc/qcom/storm.c index 3a6e18709b9e249e89017d6c0484e21a3d547e8a..c0c388d4db82912df343c5b6eac87b2bfcfddcef 100644 --- a/sound/soc/qcom/storm.c +++ b/sound/soc/qcom/storm.c @@ -19,7 +19,7 @@ static int storm_ops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); struct snd_soc_card *card = soc_runtime->card; snd_pcm_format_t format = params_format(params); unsigned int rate = params_rate(params); diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c b/sound/soc/rockchip/rk3288_hdmi_analog.c index 01078155a914866713583b5d84d15b610297d247..33a00774746d607a6382fc11a20b686d588c6344 100644 --- a/sound/soc/rockchip/rk3288_hdmi_analog.c +++ b/sound/soc/rockchip/rk3288_hdmi_analog.c @@ -66,7 +66,7 @@ static int rk_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int mclk; diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 9539b0d024fed224577fb000a8077fda874a74f3..e2d52d8d0ff99f68976b4317a13192510a598974 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -32,6 +32,19 @@ static unsigned int dmic_wakeup_delay; static struct snd_soc_jack rockchip_sound_jack; +/* Headset jack detection DAPM pins */ +static struct snd_soc_jack_pin rockchip_sound_jack_pins[] = { + { + .pin = "Headphones", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, + +}; + static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphones", NULL), SND_SOC_DAPM_SPK("Speakers", NULL), @@ -51,7 +64,7 @@ static const struct snd_kcontrol_new rockchip_controls[] = { static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int mclk; int ret; @@ -70,7 +83,7 @@ static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substrea static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int mclk; @@ -102,7 +115,7 @@ static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream, static int rockchip_sound_da7219_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int mclk, ret; @@ -176,7 +189,9 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) SND_JACK_HEADSET | SND_JACK_LINEOUT | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3, - &rockchip_sound_jack, NULL, 0); + &rockchip_sound_jack, + rockchip_sound_jack_pins, + ARRAY_SIZE(rockchip_sound_jack_pins)); if (ret) { dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret); @@ -200,7 +215,7 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int mclk; int ret; diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 61c984f10d8e61199b7c02e287532039c6f3d9ed..d1438753edb45e35b6a230f1e7fd52c164b1c7b4 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -272,7 +272,7 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct rk_i2s_dev *i2s = to_info(dai); - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int val = 0; unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck; diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index 1f527d3763ce12619c60fc7394b9518afe0fc214..9acfd024aa5df78b050e948181691cd23e60e486 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -145,7 +145,7 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int mclk; diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c index 0617ccf4e42c154884259d9aec87548d7bc7e7ce..16ca2ad9242648436ee5a0e2ca40d67e5e47deaf 100644 --- a/sound/soc/rockchip/rockchip_rt5645.c +++ b/sound/soc/rockchip/rockchip_rt5645.c @@ -55,7 +55,7 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int mclk; diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c index 6635145a26c4d0ba4a0aef11313becb2450f1750..674810851fbc6f8f3eaf6c1877703d40cf62c3f5 100644 --- a/sound/soc/rockchip/rockchip_spdif.c +++ b/sound/soc/rockchip/rockchip_spdif.c @@ -306,44 +306,22 @@ static int rk_spdif_probe(struct platform_device *pdev) return -ENOMEM; spdif->hclk = devm_clk_get(&pdev->dev, "hclk"); - if (IS_ERR(spdif->hclk)) { - dev_err(&pdev->dev, "Can't retrieve rk_spdif bus clock\n"); + if (IS_ERR(spdif->hclk)) return PTR_ERR(spdif->hclk); - } - ret = clk_prepare_enable(spdif->hclk); - if (ret) { - dev_err(spdif->dev, "hclock enable failed %d\n", ret); - return ret; - } spdif->mclk = devm_clk_get(&pdev->dev, "mclk"); - if (IS_ERR(spdif->mclk)) { - dev_err(&pdev->dev, "Can't retrieve rk_spdif master clock\n"); - ret = PTR_ERR(spdif->mclk); - goto err_disable_hclk; - } - - ret = clk_prepare_enable(spdif->mclk); - if (ret) { - dev_err(spdif->dev, "clock enable failed %d\n", ret); - goto err_disable_clocks; - } + if (IS_ERR(spdif->mclk)) + return PTR_ERR(spdif->mclk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(regs)) { - ret = PTR_ERR(regs); - goto err_disable_clocks; - } + if (IS_ERR(regs)) + return PTR_ERR(regs); spdif->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "hclk", regs, &rk_spdif_regmap_config); - if (IS_ERR(spdif->regmap)) { - dev_err(&pdev->dev, - "Failed to initialise managed register map\n"); - ret = PTR_ERR(spdif->regmap); - goto err_disable_clocks; - } + if (IS_ERR(spdif->regmap)) + return PTR_ERR(spdif->regmap); spdif->playback_dma_data.addr = res->start + SPDIF_SMPDR; spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -352,47 +330,44 @@ static int rk_spdif_probe(struct platform_device *pdev) spdif->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, spdif); - pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - pm_request_idle(&pdev->dev); + if (!pm_runtime_enabled(&pdev->dev)) { + ret = rk_spdif_runtime_resume(&pdev->dev); + if (ret) + goto err_pm_runtime; + } ret = devm_snd_soc_register_component(&pdev->dev, &rk_spdif_component, &rk_spdif_dai, 1); if (ret) { dev_err(&pdev->dev, "Could not register DAI\n"); - goto err_pm_runtime; + goto err_pm_suspend; } ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); if (ret) { dev_err(&pdev->dev, "Could not register PCM\n"); - goto err_pm_runtime; + goto err_pm_suspend; } return 0; +err_pm_suspend: + if (!pm_runtime_status_suspended(&pdev->dev)) + rk_spdif_runtime_suspend(&pdev->dev); err_pm_runtime: pm_runtime_disable(&pdev->dev); -err_disable_clocks: - clk_disable_unprepare(spdif->mclk); -err_disable_hclk: - clk_disable_unprepare(spdif->hclk); return ret; } static int rk_spdif_remove(struct platform_device *pdev) { - struct rk_spdif_dev *spdif = dev_get_drvdata(&pdev->dev); - pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) rk_spdif_runtime_suspend(&pdev->dev); - clk_disable_unprepare(spdif->mclk); - clk_disable_unprepare(spdif->hclk); - return 0; } diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 99a49248e9663765ee3e4c171cb891e7307a6ba8..1431be4ed054ebb4cb58a05aa62f2ef53653f958 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -77,7 +77,7 @@ config SND_SOC_SAMSUNG_S3C24XX_UDA134X config SND_SOC_SAMSUNG_SIMTEC tristate help - Internal node for common S3C24XX/Simtec suppor + Internal node for common S3C24XX/Simtec support. config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23 tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" @@ -212,4 +212,25 @@ config SND_SOC_SAMSUNG_TM2_WM5110 help Say Y if you want to add support for SoC audio on the TM2 board. +config SND_SOC_SAMSUNG_ARIES_WM8994 + tristate "SoC I2S Audio support for WM8994 on Aries" + depends on SND_SOC_SAMSUNG && MFD_WM8994 && IIO && EXTCON + select SND_SOC_BT_SCO + select SND_SOC_WM8994 + select SND_SAMSUNG_I2S + help + Say Y if you want to add support for SoC audio on Aries boards, + which has a WM8994 codec connected to a BT codec, a cellular + modem, and the Samsung I2S controller. Jack detection is done + via ADC, GPIOs, and an extcon device. Switching between the Mic + and TV-Out path is also handled. + +config SND_SOC_SAMSUNG_MIDAS_WM1811 + tristate "SoC I2S Audio support for Midas boards" + depends on SND_SOC_SAMSUNG + select SND_SAMSUNG_I2S + select SND_SOC_WM8994 + help + Say Y if you want to add support for SoC audio on the Midas boards. + endif #SND_SOC_SAMSUNG diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 8f5dfe20b9f14bbf8f2ad0f77970d26dd9ffa004..398e843f388cce8fe6f784071a517a30c1bacde1 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -41,6 +41,8 @@ snd-soc-bells-objs := bells.o snd-soc-odroid-objs := odroid.o snd-soc-arndale-objs := arndale.o snd-soc-tm2-wm5110-objs := tm2_wm5110.o +snd-soc-aries-wm8994-objs := aries_wm8994.o +snd-soc-midas-wm1811-objs := midas_wm1811.o obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o @@ -64,3 +66,5 @@ obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o obj-$(CONFIG_SND_SOC_ODROID) += snd-soc-odroid.o obj-$(CONFIG_SND_SOC_ARNDALE) += snd-soc-arndale.o obj-$(CONFIG_SND_SOC_SAMSUNG_TM2_WM5110) += snd-soc-tm2-wm5110.o +obj-$(CONFIG_SND_SOC_SAMSUNG_ARIES_WM8994) += snd-soc-aries-wm8994.o +obj-$(CONFIG_SND_SOC_SAMSUNG_MIDAS_WM1811) += snd-soc-midas-wm1811.o diff --git a/sound/soc/samsung/aries_wm8994.c b/sound/soc/samsung/aries_wm8994.c new file mode 100644 index 0000000000000000000000000000000000000000..0ac5956ba270d7360109d3f9dd9086c3301dfc5c --- /dev/null +++ b/sound/soc/samsung/aries_wm8994.c @@ -0,0 +1,695 @@ +// SPDX-License-Identifier: GPL-2.0+ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i2s.h" +#include "../codecs/wm8994.h" + +#define ARIES_MCLK1_FREQ 24000000 + +struct aries_wm8994_variant { + unsigned int modem_dai_fmt; + bool has_fm_radio; +}; + +struct aries_wm8994_data { + struct extcon_dev *usb_extcon; + struct regulator *reg_main_micbias; + struct regulator *reg_headset_micbias; + struct gpio_desc *gpio_headset_detect; + struct gpio_desc *gpio_headset_key; + struct gpio_desc *gpio_earpath_sel; + struct iio_channel *adc; + const struct aries_wm8994_variant *variant; +}; + +/* USB dock */ +static struct snd_soc_jack aries_dock; + +static struct snd_soc_jack_pin dock_pins[] = { + { + .pin = "LINE", + .mask = SND_JACK_LINEOUT, + }, +}; + +static int aries_extcon_notifier(struct notifier_block *this, + unsigned long connected, void *_cmd) +{ + if (connected) + snd_soc_jack_report(&aries_dock, SND_JACK_LINEOUT, + SND_JACK_LINEOUT); + else + snd_soc_jack_report(&aries_dock, 0, SND_JACK_LINEOUT); + + return NOTIFY_DONE; +} + +static struct notifier_block aries_extcon_notifier_block = { + .notifier_call = aries_extcon_notifier, +}; + +/* Headset jack */ +static struct snd_soc_jack aries_headset; + +static struct snd_soc_jack_pin jack_pins[] = { + { + .pin = "HP", + .mask = SND_JACK_HEADPHONE, + }, { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static struct snd_soc_jack_zone headset_zones[] = { + { + .min_mv = 0, + .max_mv = 241, + .jack_type = SND_JACK_HEADPHONE, + }, { + .min_mv = 242, + .max_mv = 2980, + .jack_type = SND_JACK_HEADSET, + }, { + .min_mv = 2981, + .max_mv = UINT_MAX, + .jack_type = SND_JACK_HEADPHONE, + }, +}; + +static irqreturn_t headset_det_irq_thread(int irq, void *data) +{ + struct aries_wm8994_data *priv = (struct aries_wm8994_data *) data; + int ret = 0; + int time_left_ms = 300; + int adc; + + while (time_left_ms > 0) { + if (!gpiod_get_value(priv->gpio_headset_detect)) { + snd_soc_jack_report(&aries_headset, 0, + SND_JACK_HEADSET); + gpiod_set_value(priv->gpio_earpath_sel, 0); + return IRQ_HANDLED; + } + msleep(20); + time_left_ms -= 20; + } + + /* Temporarily enable micbias and earpath selector */ + ret = regulator_enable(priv->reg_headset_micbias); + if (ret) + pr_err("%s failed to enable micbias: %d", __func__, ret); + + gpiod_set_value(priv->gpio_earpath_sel, 1); + + ret = iio_read_channel_processed(priv->adc, &adc); + if (ret < 0) { + /* failed to read ADC, so assume headphone */ + pr_err("%s failed to read ADC, assuming headphones", __func__); + snd_soc_jack_report(&aries_headset, SND_JACK_HEADPHONE, + SND_JACK_HEADSET); + } else { + snd_soc_jack_report(&aries_headset, + snd_soc_jack_get_type(&aries_headset, adc), + SND_JACK_HEADSET); + } + + ret = regulator_disable(priv->reg_headset_micbias); + if (ret) + pr_err("%s failed disable micbias: %d", __func__, ret); + + /* Disable earpath selector when no mic connected */ + if (!(aries_headset.status & SND_JACK_MICROPHONE)) + gpiod_set_value(priv->gpio_earpath_sel, 0); + + return IRQ_HANDLED; +} + +static int headset_button_check(void *data) +{ + struct aries_wm8994_data *priv = (struct aries_wm8994_data *) data; + + /* Filter out keypresses when 4 pole jack not detected */ + if (gpiod_get_value_cansleep(priv->gpio_headset_key) && + aries_headset.status & SND_JACK_MICROPHONE) + return SND_JACK_BTN_0; + + return 0; +} + +static struct snd_soc_jack_gpio headset_button_gpio[] = { + { + .name = "Media Button", + .report = SND_JACK_BTN_0, + .debounce_time = 30, + .jack_status_check = headset_button_check, + }, +}; + +static int aries_spk_cfg(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct snd_soc_pcm_runtime *rtd; + struct snd_soc_component *component; + int ret = 0; + + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]); + component = asoc_rtd_to_codec(rtd, 0)->component; + + /** + * We have an odd setup - the SPKMODE pin is pulled up so + * we only have access to the left side SPK configs, + * but SPKOUTR isn't bridged so when playing back in + * stereo, we only get the left hand channel. The only + * option we're left with is to force the AIF into mono + * mode. + */ + switch (event) { + case SND_SOC_DAPM_POST_PMU: + ret = snd_soc_component_update_bits(component, + WM8994_AIF1_DAC1_FILTERS_1, + WM8994_AIF1DAC1_MONO, WM8994_AIF1DAC1_MONO); + break; + case SND_SOC_DAPM_PRE_PMD: + ret = snd_soc_component_update_bits(component, + WM8994_AIF1_DAC1_FILTERS_1, + WM8994_AIF1DAC1_MONO, 0); + break; + } + + return ret; +} + +static int aries_main_bias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct aries_wm8994_data *priv = snd_soc_card_get_drvdata(card); + int ret = 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = regulator_enable(priv->reg_main_micbias); + break; + case SND_SOC_DAPM_POST_PMD: + ret = regulator_disable(priv->reg_main_micbias); + break; + } + + return ret; +} + +static int aries_headset_bias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct aries_wm8994_data *priv = snd_soc_card_get_drvdata(card); + int ret = 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = regulator_enable(priv->reg_headset_micbias); + break; + case SND_SOC_DAPM_POST_PMD: + ret = regulator_disable(priv->reg_headset_micbias); + break; + } + + return ret; +} + +static const struct snd_kcontrol_new aries_controls[] = { + SOC_DAPM_PIN_SWITCH("Modem In"), + SOC_DAPM_PIN_SWITCH("Modem Out"), +}; + +static const struct snd_soc_dapm_widget aries_dapm_widgets[] = { + SND_SOC_DAPM_HP("HP", NULL), + + SND_SOC_DAPM_SPK("SPK", aries_spk_cfg), + SND_SOC_DAPM_SPK("RCV", NULL), + + SND_SOC_DAPM_LINE("LINE", NULL), + + SND_SOC_DAPM_MIC("Main Mic", aries_main_bias), + SND_SOC_DAPM_MIC("Headset Mic", aries_headset_bias), + + SND_SOC_DAPM_MIC("Bluetooth Mic", NULL), + SND_SOC_DAPM_SPK("Bluetooth SPK", NULL), + + SND_SOC_DAPM_LINE("Modem In", NULL), + SND_SOC_DAPM_LINE("Modem Out", NULL), + + /* This must be last as it is conditionally not used */ + SND_SOC_DAPM_LINE("FM In", NULL), +}; + +static int aries_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + unsigned int pll_out; + int ret; + + /* AIF1CLK should be >=3MHz for optimal performance */ + if (params_width(params) == 24) + pll_out = params_rate(params) * 384; + else if (params_rate(params) == 8000 || params_rate(params) == 11025) + pll_out = params_rate(params) * 512; + else + pll_out = params_rate(params) * 256; + + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, + ARIES_MCLK1_FREQ, pll_out); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, + pll_out, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static int aries_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + int ret; + + /* Switch sysclk to MCLK1 */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1, + ARIES_MCLK1_FREQ, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + /* Stop PLL */ + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, + ARIES_MCLK1_FREQ, 0); + if (ret < 0) + return ret; + + return 0; +} + +/* + * Main DAI operations + */ +static struct snd_soc_ops aries_ops = { + .hw_params = aries_hw_params, + .hw_free = aries_hw_free, +}; + +static int aries_baseband_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + unsigned int pll_out; + int ret; + + pll_out = 8000 * 512; + + /* Set the codec FLL */ + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, WM8994_FLL_SRC_MCLK1, + ARIES_MCLK1_FREQ, pll_out); + if (ret < 0) + return ret; + + /* Set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, + pll_out, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static int aries_late_probe(struct snd_soc_card *card) +{ + struct aries_wm8994_data *priv = snd_soc_card_get_drvdata(card); + int ret, irq; + + ret = snd_soc_card_jack_new(card, "Dock", SND_JACK_LINEOUT, + &aries_dock, dock_pins, ARRAY_SIZE(dock_pins)); + if (ret) + return ret; + + ret = devm_extcon_register_notifier(card->dev, + priv->usb_extcon, EXTCON_JACK_LINE_OUT, + &aries_extcon_notifier_block); + if (ret) + return ret; + + if (extcon_get_state(priv->usb_extcon, + EXTCON_JACK_LINE_OUT) > 0) + snd_soc_jack_report(&aries_dock, SND_JACK_LINEOUT, + SND_JACK_LINEOUT); + else + snd_soc_jack_report(&aries_dock, 0, SND_JACK_LINEOUT); + + ret = snd_soc_card_jack_new(card, "Headset", + SND_JACK_HEADSET | SND_JACK_BTN_0, + &aries_headset, + jack_pins, ARRAY_SIZE(jack_pins)); + if (ret) + return ret; + + ret = snd_soc_jack_add_zones(&aries_headset, ARRAY_SIZE(headset_zones), + headset_zones); + if (ret) + return ret; + + irq = gpiod_to_irq(priv->gpio_headset_detect); + if (irq < 0) { + dev_err(card->dev, "Failed to map headset detect gpio to irq"); + return -EINVAL; + } + + ret = devm_request_threaded_irq(card->dev, irq, NULL, + headset_det_irq_thread, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, "headset_detect", priv); + if (ret) { + dev_err(card->dev, "Failed to request headset detect irq"); + return ret; + } + + headset_button_gpio[0].data = priv; + headset_button_gpio[0].desc = priv->gpio_headset_key; + + snd_jack_set_key(aries_headset.jack, SND_JACK_BTN_0, KEY_MEDIA); + + return snd_soc_jack_add_gpios(&aries_headset, + ARRAY_SIZE(headset_button_gpio), headset_button_gpio); +} + +static const struct snd_soc_pcm_stream baseband_params = { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 8000, + .channels_min = 1, + .channels_max = 1, +}; + +static const struct snd_soc_pcm_stream bluetooth_params = { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 8000, + .channels_min = 1, + .channels_max = 2, +}; + +static const struct snd_soc_dapm_widget aries_modem_widgets[] = { + SND_SOC_DAPM_INPUT("Modem RX"), + SND_SOC_DAPM_OUTPUT("Modem TX"), +}; + +static const struct snd_soc_dapm_route aries_modem_routes[] = { + { "Modem Capture", NULL, "Modem RX" }, + { "Modem TX", NULL, "Modem Playback" }, +}; + +static const struct snd_soc_component_driver aries_component = { + .name = "aries-audio", + .dapm_widgets = aries_modem_widgets, + .num_dapm_widgets = ARRAY_SIZE(aries_modem_widgets), + .dapm_routes = aries_modem_routes, + .num_dapm_routes = ARRAY_SIZE(aries_modem_routes), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static struct snd_soc_dai_driver aries_ext_dai[] = { + { + .name = "Voice call", + .playback = { + .stream_name = "Modem Playback", + .channels_min = 1, + .channels_max = 1, + .rate_min = 8000, + .rate_max = 8000, + .rates = SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .stream_name = "Modem Capture", + .channels_min = 1, + .channels_max = 1, + .rate_min = 8000, + .rate_max = 8000, + .rates = SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, +}; + +SND_SOC_DAILINK_DEFS(aif1, + DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(baseband, + DAILINK_COMP_ARRAY(COMP_CPU("Voice call")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif2"))); + +SND_SOC_DAILINK_DEFS(bluetooth, + DAILINK_COMP_ARRAY(COMP_CPU("bt-sco-pcm")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif3"))); + +static struct snd_soc_dai_link aries_dai[] = { + { + .name = "WM8994 AIF1", + .stream_name = "HiFi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, + .ops = &aries_ops, + SND_SOC_DAILINK_REG(aif1), + }, + { + .name = "WM8994 AIF2", + .stream_name = "Baseband", + .init = &aries_baseband_init, + .params = &baseband_params, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(baseband), + }, + { + .name = "WM8994 AIF3", + .stream_name = "Bluetooth", + .params = &bluetooth_params, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(bluetooth), + }, +}; + +static struct snd_soc_card aries_card = { + .name = "ARIES", + .owner = THIS_MODULE, + .dai_link = aries_dai, + .num_links = ARRAY_SIZE(aries_dai), + .controls = aries_controls, + .num_controls = ARRAY_SIZE(aries_controls), + .dapm_widgets = aries_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aries_dapm_widgets), + .late_probe = aries_late_probe, +}; + +static const struct aries_wm8994_variant fascinate4g_variant = { + .modem_dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS + | SND_SOC_DAIFMT_IB_NF, + .has_fm_radio = false, +}; + +static const struct aries_wm8994_variant aries_variant = { + .modem_dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM + | SND_SOC_DAIFMT_IB_NF, + .has_fm_radio = true, +}; + +static const struct of_device_id samsung_wm8994_of_match[] = { + { + .compatible = "samsung,fascinate4g-wm8994", + .data = &fascinate4g_variant, + }, + { + .compatible = "samsung,aries-wm8994", + .data = &aries_variant, + }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match); + +static int aries_audio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *cpu, *codec, *extcon_np; + struct device *dev = &pdev->dev; + struct snd_soc_card *card = &aries_card; + struct aries_wm8994_data *priv; + struct snd_soc_dai_link *dai_link; + const struct of_device_id *match; + int ret, i; + + if (!np) + return -EINVAL; + + card->dev = dev; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + snd_soc_card_set_drvdata(card, priv); + + match = of_match_node(samsung_wm8994_of_match, np); + priv->variant = match->data; + + /* Remove FM widget if not present */ + if (!priv->variant->has_fm_radio) + card->num_dapm_widgets--; + + priv->reg_main_micbias = devm_regulator_get(dev, "main-micbias"); + if (IS_ERR(priv->reg_main_micbias)) { + dev_err(dev, "Failed to get main micbias regulator\n"); + return PTR_ERR(priv->reg_main_micbias); + } + + priv->reg_headset_micbias = devm_regulator_get(dev, "headset-micbias"); + if (IS_ERR(priv->reg_headset_micbias)) { + dev_err(dev, "Failed to get headset micbias regulator\n"); + return PTR_ERR(priv->reg_headset_micbias); + } + + priv->gpio_earpath_sel = devm_gpiod_get(dev, "earpath-sel", + GPIOD_OUT_LOW); + if (IS_ERR(priv->gpio_earpath_sel)) { + dev_err(dev, "Failed to get earpath selector gpio"); + return PTR_ERR(priv->gpio_earpath_sel); + } + + extcon_np = of_parse_phandle(np, "extcon", 0); + priv->usb_extcon = extcon_find_edev_by_node(extcon_np); + if (IS_ERR(priv->usb_extcon)) { + if (PTR_ERR(priv->usb_extcon) != -EPROBE_DEFER) + dev_err(dev, "Failed to get extcon device"); + return PTR_ERR(priv->usb_extcon); + } + of_node_put(extcon_np); + + priv->adc = devm_iio_channel_get(dev, "headset-detect"); + if (IS_ERR(priv->adc)) { + if (PTR_ERR(priv->adc) != -EPROBE_DEFER) + dev_err(dev, "Failed to get ADC channel"); + return PTR_ERR(priv->adc); + } + if (priv->adc->channel->type != IIO_VOLTAGE) + return -EINVAL; + + priv->gpio_headset_key = devm_gpiod_get(dev, "headset-key", + GPIOD_IN); + if (IS_ERR(priv->gpio_headset_key)) { + dev_err(dev, "Failed to get headset key gpio"); + return PTR_ERR(priv->gpio_headset_key); + } + + priv->gpio_headset_detect = devm_gpiod_get(dev, + "headset-detect", GPIOD_IN); + if (IS_ERR(priv->gpio_headset_detect)) { + dev_err(dev, "Failed to get headset detect gpio"); + return PTR_ERR(priv->gpio_headset_detect); + } + + /* Update card-name if provided through DT, else use default name */ + snd_soc_of_parse_card_name(card, "model"); + + ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); + if (ret < 0) { + dev_err(dev, "Audio routing invalid/unspecified\n"); + return ret; + } + + aries_dai[1].dai_fmt = priv->variant->modem_dai_fmt; + + cpu = of_get_child_by_name(dev->of_node, "cpu"); + if (!cpu) + return -EINVAL; + + codec = of_get_child_by_name(dev->of_node, "codec"); + if (!codec) + return -EINVAL; + + for_each_card_prelinks(card, i, dai_link) { + dai_link->codecs->of_node = of_parse_phandle(codec, + "sound-dai", 0); + if (!dai_link->codecs->of_node) { + ret = -EINVAL; + goto out; + } + } + + /* Set CPU and platform of_node for main DAI */ + aries_dai[0].cpus->of_node = of_parse_phandle(cpu, + "sound-dai", 0); + if (!aries_dai[0].cpus->of_node) { + ret = -EINVAL; + goto out; + } + + aries_dai[0].platforms->of_node = aries_dai[0].cpus->of_node; + + /* Set CPU of_node for BT DAI */ + aries_dai[2].cpus->of_node = of_parse_phandle(cpu, + "sound-dai", 1); + if (!aries_dai[2].cpus->of_node) { + ret = -EINVAL; + goto out; + } + + ret = devm_snd_soc_register_component(dev, &aries_component, + aries_ext_dai, ARRAY_SIZE(aries_ext_dai)); + if (ret < 0) { + dev_err(dev, "Failed to register component: %d\n", ret); + goto out; + } + + ret = devm_snd_soc_register_card(dev, card); + if (ret) + dev_err(dev, "snd_soc_register_card() failed:%d\n", ret); + +out: + of_node_put(cpu); + of_node_put(codec); + + return ret; +} + +static struct platform_driver aries_audio_driver = { + .driver = { + .name = "aries-audio-wm8994", + .of_match_table = of_match_ptr(samsung_wm8994_of_match), + .pm = &snd_soc_pm_ops, + }, + .probe = aries_audio_probe, +}; + +module_platform_driver(aries_audio_driver); + +MODULE_DESCRIPTION("ALSA SoC ARIES WM8994"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:aries-audio-wm8994"); diff --git a/sound/soc/samsung/arndale.c b/sound/soc/samsung/arndale.c index c81ece78e0360f699336c276853f5f9753ec7e80..28587375813ac9a8cd4209b20ec6c74d86f363d8 100644 --- a/sound/soc/samsung/arndale.c +++ b/sound/soc/samsung/arndale.c @@ -20,7 +20,7 @@ static int arndale_rt5631_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int rfs, ret; @@ -55,7 +55,7 @@ static struct snd_soc_ops arndale_rt5631_ops = { static int arndale_wm1811_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int rfs, rclk; diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index 9139a1e7e2006293a48f7f8cd3dbb95b204b6768..b8f0057a0510501e098fbc27f2ea920b4a67b503 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -67,7 +67,7 @@ static int h1940_startup(struct snd_pcm_substream *substream) static int h1940_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int div; int ret; diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index f86e3028b402402bf6a3ec4628588f0bbe4884ef..80ecb5c7fed0c1a03110a9a16c73d853ae154bc9 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -931,7 +931,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream, { struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct i2s_dai *i2s = to_info(asoc_rtd_to_cpu(rtd, 0)); unsigned long flags; diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c index 30899016cf08a5177446c78909868c0ecd1c50bd..40a85f539509a363f3e6057d2ecec99871d54a0b 100644 --- a/sound/soc/samsung/jive_wm8750.c +++ b/sound/soc/samsung/jive_wm8750.c @@ -32,7 +32,7 @@ static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = { static int jive_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct s3c_i2sv2_rate_calc div; diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index f4375c49f7f49dd6771bb153a1208dd768320a4a..a1ff1400857ed715fcd973781bb83f5085f396dc 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c @@ -104,7 +104,7 @@ static int littlemill_set_bias_level_post(struct snd_soc_card *card, static int littlemill_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; diff --git a/sound/soc/samsung/midas_wm1811.c b/sound/soc/samsung/midas_wm1811.c new file mode 100644 index 0000000000000000000000000000000000000000..d03340ce49a2495a49210e649db0dbcc628f0d05 --- /dev/null +++ b/sound/soc/samsung/midas_wm1811.c @@ -0,0 +1,543 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Midas audio support +// +// Copyright (C) 2018 Simon Shields +// Copyright (C) 2020 Samsung Electronics Co., Ltd. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i2s.h" +#include "../codecs/wm8994.h" + +/* + * The MCLK1 clock source is XCLKOUT with its mux set to the external fixed rate + * oscillator (XXTI). + */ +#define MCLK1_RATE 24000000U +#define MCLK2_RATE 32768U +#define DEFAULT_FLL1_RATE 11289600U + +struct midas_priv { + struct regulator *reg_mic_bias; + struct regulator *reg_submic_bias; + struct gpio_desc *gpio_fm_sel; + struct gpio_desc *gpio_lineout_sel; + unsigned int fll1_rate; + + struct snd_soc_jack headset_jack; +}; + +static int midas_start_fll1(struct snd_soc_pcm_runtime *rtd, unsigned int rate) +{ + struct snd_soc_card *card = rtd->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + int ret; + + if (!rate) + rate = priv->fll1_rate; + /* + * If no new rate is requested, set FLL1 to a sane default for jack + * detection. + */ + if (!rate) + rate = DEFAULT_FLL1_RATE; + + if (rate != priv->fll1_rate && priv->fll1_rate) { + /* while reconfiguring, switch to MCLK2 for SYSCLK */ + ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, + MCLK2_RATE, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret); + return ret; + } + } + + ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, + MCLK1_RATE, rate); + if (ret < 0) { + dev_err(card->dev, "Failed to set FLL1 rate: %d\n", ret); + return ret; + } + priv->fll1_rate = rate; + + ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_FLL1, + priv->fll1_rate, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "Failed to set SYSCLK source: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK, 0, + SAMSUNG_I2S_OPCLK_PCLK); + if (ret < 0) { + dev_err(card->dev, "Failed to set OPCLK source: %d\n", ret); + return ret; + } + + return 0; +} + +static int midas_stop_fll1(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0); + int ret; + + ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, + MCLK2_RATE, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, 0, 0, 0); + if (ret < 0) { + dev_err(card->dev, "Unable to stop FLL1: %d\n", ret); + return ret; + } + + priv->fll1_rate = 0; + + return 0; +} + +static int midas_aif1_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + unsigned int pll_out; + + /* AIF1CLK should be at least 3MHz for "optimal performance" */ + if (params_rate(params) == 8000 || params_rate(params) == 11025) + pll_out = params_rate(params) * 512; + else + pll_out = params_rate(params) * 256; + + return midas_start_fll1(rtd, pll_out); +} + +static struct snd_soc_ops midas_aif1_ops = { + .hw_params = midas_aif1_hw_params, +}; + +/* + * We only have a single external speaker, so mix stereo data + * to a single mono stream. + */ +static int midas_ext_spkmode(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm); + int ret = 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS, + WM8994_SPKMIXR_TO_SPKOUTL_MASK, + WM8994_SPKMIXR_TO_SPKOUTL); + break; + case SND_SOC_DAPM_POST_PMD: + ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS, + WM8994_SPKMIXR_TO_SPKOUTL_MASK, + 0); + break; + } + + return ret; +} + +static int midas_mic_bias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + return regulator_enable(priv->reg_mic_bias); + case SND_SOC_DAPM_POST_PMD: + return regulator_disable(priv->reg_mic_bias); + } + + return 0; +} + +static int midas_submic_bias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + return regulator_enable(priv->reg_submic_bias); + case SND_SOC_DAPM_POST_PMD: + return regulator_disable(priv->reg_submic_bias); + } + + return 0; +} + +static int midas_fm_set(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + + if (!priv->gpio_fm_sel) + return 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + gpiod_set_value_cansleep(priv->gpio_fm_sel, 1); + break; + case SND_SOC_DAPM_POST_PMD: + gpiod_set_value_cansleep(priv->gpio_fm_sel, 0); + break; + } + + return 0; +} + +static int midas_line_set(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + + if (!priv->gpio_lineout_sel) + return 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + gpiod_set_value_cansleep(priv->gpio_lineout_sel, 1); + break; + case SND_SOC_DAPM_POST_PMD: + gpiod_set_value_cansleep(priv->gpio_lineout_sel, 0); + break; + } + + return 0; +} + +static const struct snd_kcontrol_new midas_controls[] = { + SOC_DAPM_PIN_SWITCH("HP"), + + SOC_DAPM_PIN_SWITCH("SPK"), + SOC_DAPM_PIN_SWITCH("RCV"), + + SOC_DAPM_PIN_SWITCH("LINE"), + SOC_DAPM_PIN_SWITCH("HDMI"), + + SOC_DAPM_PIN_SWITCH("Main Mic"), + SOC_DAPM_PIN_SWITCH("Sub Mic"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + + SOC_DAPM_PIN_SWITCH("FM In"), +}; + +static const struct snd_soc_dapm_widget midas_dapm_widgets[] = { + SND_SOC_DAPM_HP("HP", NULL), + + SND_SOC_DAPM_SPK("SPK", midas_ext_spkmode), + SND_SOC_DAPM_SPK("RCV", NULL), + + /* FIXME: toggle MAX77693 on i9300/i9305 */ + SND_SOC_DAPM_LINE("LINE", midas_line_set), + SND_SOC_DAPM_LINE("HDMI", NULL), + SND_SOC_DAPM_LINE("FM In", midas_fm_set), + + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Main Mic", midas_mic_bias), + SND_SOC_DAPM_MIC("Sub Mic", midas_submic_bias), +}; + +static int midas_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card, + &card->dai_link[0]); + struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0); + + if (dapm->dev != aif1_dai->dev) + return 0; + + switch (level) { + case SND_SOC_BIAS_STANDBY: + return midas_stop_fll1(rtd); + case SND_SOC_BIAS_PREPARE: + return midas_start_fll1(rtd, 0); + default: + break; + } + + return 0; +} + +static int midas_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card, + &card->dai_link[0]); + struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0); + struct midas_priv *priv = snd_soc_card_get_drvdata(card); + int ret; + + /* Use MCLK2 as SYSCLK for boot */ + ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, MCLK2_RATE, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(aif1_dai->dev, "Failed to switch to MCLK2: %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new(card, "Headset", + SND_JACK_HEADSET | SND_JACK_MECHANICAL | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5, + &priv->headset_jack, NULL, 0); + if (ret) + return ret; + + wm8958_mic_detect(aif1_dai->component, &priv->headset_jack, + NULL, NULL, NULL, NULL); + return 0; +} + +static struct snd_soc_dai_driver midas_ext_dai[] = { + { + .name = "Voice call", + .playback = { + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 16000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 16000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, + { + .name = "Bluetooth", + .playback = { + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 16000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 16000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, +}; + +static const struct snd_soc_component_driver midas_component = { + .name = "midas-audio", +}; + +SND_SOC_DAILINK_DEFS(wm1811_hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(wm1811_voice, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif2")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(wm1811_bt, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif3")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +static struct snd_soc_dai_link midas_dai[] = { + { + .name = "WM8994 AIF1", + .stream_name = "HiFi Primary", + .ops = &midas_aif1_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(wm1811_hifi), + }, { + .name = "WM1811 Voice", + .stream_name = "Voice call", + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(wm1811_voice), + }, { + .name = "WM1811 BT", + .stream_name = "Bluetooth", + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(wm1811_bt), + }, +}; + +static struct snd_soc_card midas_card = { + .name = "Midas WM1811", + .owner = THIS_MODULE, + + .dai_link = midas_dai, + .num_links = ARRAY_SIZE(midas_dai), + .controls = midas_controls, + .num_controls = ARRAY_SIZE(midas_controls), + .dapm_widgets = midas_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(midas_dapm_widgets), + + .set_bias_level = midas_set_bias_level, + .late_probe = midas_late_probe, +}; + +static int midas_probe(struct platform_device *pdev) +{ + struct device_node *cpu_dai_node = NULL, *codec_dai_node = NULL; + struct device_node *cpu = NULL, *codec = NULL; + struct snd_soc_card *card = &midas_card; + struct device *dev = &pdev->dev; + static struct snd_soc_dai_link *dai_link; + struct midas_priv *priv; + int ret, i; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + snd_soc_card_set_drvdata(card, priv); + card->dev = dev; + + priv->reg_mic_bias = devm_regulator_get(dev, "mic-bias"); + if (IS_ERR(priv->reg_mic_bias)) { + dev_err(dev, "Failed to get mic bias regulator\n"); + return PTR_ERR(priv->reg_mic_bias); + } + + priv->reg_submic_bias = devm_regulator_get(dev, "submic-bias"); + if (IS_ERR(priv->reg_submic_bias)) { + dev_err(dev, "Failed to get submic bias regulator\n"); + return PTR_ERR(priv->reg_submic_bias); + } + + priv->gpio_fm_sel = devm_gpiod_get_optional(dev, "fm-sel", GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpio_fm_sel)) { + dev_err(dev, "Failed to get FM selection GPIO\n"); + return PTR_ERR(priv->gpio_fm_sel); + } + + priv->gpio_lineout_sel = devm_gpiod_get_optional(dev, "lineout-sel", + GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpio_lineout_sel)) { + dev_err(dev, "Failed to get line out selection GPIO\n"); + return PTR_ERR(priv->gpio_lineout_sel); + } + + ret = snd_soc_of_parse_card_name(card, "model"); + if (ret < 0) { + dev_err(dev, "Card name is not specified\n"); + return ret; + } + + ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); + if (ret < 0) { + dev_err(dev, "Audio routing invalid/unspecified\n"); + return ret; + } + + cpu = of_get_child_by_name(dev->of_node, "cpu"); + if (!cpu) + return -EINVAL; + + codec = of_get_child_by_name(dev->of_node, "codec"); + if (!codec) { + of_node_put(cpu); + return -EINVAL; + } + + cpu_dai_node = of_parse_phandle(cpu, "sound-dai", 0); + of_node_put(cpu); + if (!cpu_dai_node) { + dev_err(dev, "parsing cpu/sound-dai failed\n"); + of_node_put(codec); + return -EINVAL; + } + + codec_dai_node = of_parse_phandle(codec, "sound-dai", 0); + of_node_put(codec); + if (!codec_dai_node) { + dev_err(dev, "audio-codec property invalid/missing\n"); + ret = -EINVAL; + goto put_cpu_dai_node; + } + + for_each_card_prelinks(card, i, dai_link) { + dai_link->codecs->of_node = codec_dai_node; + dai_link->cpus->of_node = cpu_dai_node; + dai_link->platforms->of_node = cpu_dai_node; + } + + ret = devm_snd_soc_register_component(dev, &midas_component, + midas_ext_dai, ARRAY_SIZE(midas_ext_dai)); + if (ret < 0) { + dev_err(dev, "Failed to register component: %d\n", ret); + goto put_codec_dai_node; + } + + ret = devm_snd_soc_register_card(dev, card); + if (ret < 0) { + dev_err(dev, "Failed to register card: %d\n", ret); + goto put_codec_dai_node; + } + + return 0; + +put_codec_dai_node: + of_node_put(codec_dai_node); +put_cpu_dai_node: + of_node_put(cpu_dai_node); + return ret; +} + +static const struct of_device_id midas_of_match[] = { + { .compatible = "samsung,midas-audio" }, + { }, +}; +MODULE_DEVICE_TABLE(of, midas_of_match); + +static struct platform_driver midas_driver = { + .driver = { + .name = "midas-audio", + .of_match_table = midas_of_match, + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + }, + .probe = midas_probe, +}; +module_platform_driver(midas_driver); + +MODULE_AUTHOR("Simon Shields "); +MODULE_DESCRIPTION("ASoC support for Midas"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index b7ce1da854cee03b4f2d9f19560abd0cf56362eb..54317e0f68f8eae8ed8e0a6c6753619875e9222b 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -25,7 +25,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int pll_out = 0, bclk = 0; @@ -99,7 +99,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); /* disable the PLL */ @@ -117,7 +117,7 @@ static struct snd_soc_ops neo1973_hifi_ops = { static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int pcmdiv = 0; int ret = 0; @@ -154,7 +154,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); /* disable the PLL */ diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index 6eda5af989fe38a8f07a5c2d28fadb147cd4b8d6..ca643a488c3caa02154ad2382dc91a7d867c65c1 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -35,7 +35,7 @@ static int odroid_card_fe_startup(struct snd_pcm_substream *substream) static int odroid_card_fe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); unsigned long flags; int ret = 0; @@ -56,7 +56,7 @@ static const struct snd_soc_ops odroid_card_fe_ops = { static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); unsigned int pll_freq, rclk_freq, rfs; unsigned long flags; @@ -115,7 +115,7 @@ static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, static int odroid_card_be_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); unsigned long flags; diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index a5b1a12b349660e6b727a48a078d1e91baeca1a1..6f50c7b4732606274e91b341867dc1228a84b9c7 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -104,8 +104,13 @@ /** * struct s3c_pcm_info - S3C PCM Controller information + * @lock: Spin lock * @dev: The parent device passed to use from the probe. * @regs: The pointer to the device register block. + * @sclk_per_fs: number of sclk per frame sync + * @idleclk: Whether to keep PCMSCLK enabled even when idle (no active xfer) + * @pclk: the PCLK_PCM (pcm) clock pointer + * @cclk: the SCLK_AUDIO (audio-bus) clock pointer * @dma_playback: DMA information for playback channel. * @dma_capture: DMA information for capture channel. */ @@ -211,7 +216,7 @@ static void s3c_pcm_snd_rxctrl(struct s3c_pcm_info *pcm, int on) static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); unsigned long flags; @@ -255,7 +260,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); void __iomem *regs = pcm->regs; struct clk *clk; diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 3afe63c0923ebd8abc2d1fca68dd61476fc5a2d9..08f7c82aedb6238906a704533d55900bc1748edf 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c @@ -148,7 +148,7 @@ static int rx1950_spk_power(struct snd_soc_dapm_widget *w, static int rx1950_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int div; int ret; diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 5e95c30fb2bacc936c9e3c25ac9588f5e8ac2f81..ed21786104a1c983c0b6f2b698c3aea4332b328b 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -379,7 +379,7 @@ static int s3c_i2sv2_set_sysclk(struct snd_soc_dai *cpu_dai, static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct s3c_i2sv2_info *i2s = to_info(asoc_rtd_to_cpu(rtd, 0)); int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); unsigned long irqs; diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c index fd2a4da086f3084bed37955b5d2f085b5707b01f..3cddd11344ac5f72140d09e14e9ada84ab21096b 100644 --- a/sound/soc/samsung/s3c24xx_simtec.c +++ b/sound/soc/samsung/s3c24xx_simtec.c @@ -159,7 +159,7 @@ EXPORT_SYMBOL_GPL(simtec_audio_init); static int simtec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index abb5c4713c534e6f1b50ff141625a8e451f4508c..6272070dcd92be68227c5713b8466f79b87f1007 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c @@ -49,7 +49,7 @@ static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct s3c24xx_uda134x *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret = 0; @@ -101,7 +101,7 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct s3c24xx_uda134x *priv = snd_soc_card_get_drvdata(rtd->card); mutex_lock(&priv->clk_lock); @@ -118,7 +118,7 @@ static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream) static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c index 36bef136d57f818c7e9ba8282d861dfd144ee9fe..c95629becbc342f9edd77fa48a95958ef21cd642 100644 --- a/sound/soc/samsung/smartq_wm8987.c +++ b/sound/soc/samsung/smartq_wm8987.c @@ -24,7 +24,7 @@ static struct snd_soc_card snd_soc_smartq; static int smartq_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int clk = 0; diff --git a/sound/soc/samsung/smdk_spdif.c b/sound/soc/samsung/smdk_spdif.c index 776a270261bf1b397cfe5361e2fac16aaa449c98..6f3eeb7bc834b5844748bdaa98da9ac11c28be78 100644 --- a/sound/soc/samsung/smdk_spdif.c +++ b/sound/soc/samsung/smdk_spdif.c @@ -100,7 +100,7 @@ static int set_audio_clock_rate(unsigned long epll_rate, static int smdk_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned long pll_out, rclk_rate; int ret, ratio; diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c index 02074c34a2b2e16f7986410506114886e82b3fe1..ed753a2f202e0ccc192f6eb0cb8d2a429139535b 100644 --- a/sound/soc/samsung/smdk_wm8580.c +++ b/sound/soc/samsung/smdk_wm8580.c @@ -22,7 +22,7 @@ static int smdk_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int pll_out; int rfs, ret; diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index a9f345f19a8a1cd019c34172d65ad8f26fa00922..64a1a64656abaf11304d4e4b1140cc968521a292 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -44,7 +44,7 @@ static struct smdk_wm8994_data smdk_board_data = { static int smdk_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); unsigned int pll_out; int ret; diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c index 746930dde5d7917587be324de45327520d219236..a01640576f71d677618af9131b857f5fca741e1d 100644 --- a/sound/soc/samsung/smdk_wm8994pcm.c +++ b/sound/soc/samsung/smdk_wm8994pcm.c @@ -43,7 +43,7 @@ static int smdk_wm8994_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned long mclk_freq; diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 40c5de8df0ffe7b81ff373536b29a302e85376fb..07163f07c6d561cb69a980584a5dd3e52963dc49 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -30,7 +30,7 @@ static int snow_card_hw_params(struct snd_pcm_substream *substream, static const unsigned int pll_rate[] = { 73728000U, 67737602U, 49152000U, 45158401U, 32768001U }; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snow_priv *priv = snd_soc_card_get_drvdata(rtd->card); int bfs, psr, rfs, bitwidth; unsigned long int rclk; diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index 759fc66443298a8b6f2b792130f008a0dd6123af..226c359892e9ff29ca0b50e74191a53526102d22 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c @@ -70,9 +70,9 @@ * @clk_rate: Current clock rate for calcurate ratio. * @pclk: The peri-clock pointer for spdif master operation. * @sclk: The source clock pointer for making sync signals. - * @save_clkcon: Backup clkcon reg. in suspend. - * @save_con: Backup con reg. in suspend. - * @save_cstas: Backup cstas reg. in suspend. + * @saved_clkcon: Backup clkcon reg. in suspend. + * @saved_con: Backup con reg. in suspend. + * @saved_cstas: Backup cstas reg. in suspend. * @dma_playback: DMA information for playback channel. */ struct samsung_spdif_info { @@ -141,7 +141,7 @@ static int spdif_set_sysclk(struct snd_soc_dai *cpu_dai, static int spdif_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct samsung_spdif_info *spdif = to_info(asoc_rtd_to_cpu(rtd, 0)); unsigned long flags; @@ -177,7 +177,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct samsung_spdif_info *spdif = to_info(asoc_rtd_to_cpu(rtd, 0)); void __iomem *regs = spdif->regs; struct snd_dmaengine_dai_dma_data *dma_data; @@ -279,7 +279,7 @@ err: static void spdif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct samsung_spdif_info *spdif = to_info(asoc_rtd_to_cpu(rtd, 0)); void __iomem *regs = spdif->regs; u32 con, clkcon; diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index 6dfd540e2d743a0951d11c544616fa766f00a55c..9300fef9bf26985d503bc919c3706e8e80cbf361 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -92,7 +92,7 @@ static int tm2_stop_sysclk(struct snd_soc_card *card) static int tm2_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(rtd->card); @@ -133,7 +133,7 @@ static struct snd_soc_ops tm2_aif1_ops = { static int tm2_aif2_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; unsigned int asyncclk_rate; int ret; @@ -187,7 +187,7 @@ static int tm2_aif2_hw_params(struct snd_pcm_substream *substream, static int tm2_aif2_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; int ret; @@ -208,7 +208,7 @@ static struct snd_soc_ops tm2_aif2_ops = { static int tm2_hdmi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); unsigned int bfs; int bitwidth, ret; diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index dc20f0f7080a091e6f695d75a82c8bd6283bb343..ef8a29b9f641c6e9455eec7958cff9cd4c9336be 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -30,8 +30,8 @@ config SND_SOC_SH4_FSI config SND_SOC_SH4_SIU tristate depends on ARCH_SHMOBILE && HAVE_CLK + depends on DMADEVICES select DMA_ENGINE - select DMADEVICES select SH_DMAE select FW_LOADER diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index a35de78f14a9cce0da9e2362c76f6ed5cd57937b..b70068dd5a06ffa107f82130b11742882119e979 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c @@ -118,7 +118,7 @@ static void camelot_rxdma(void *data) static int camelot_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; int ret, dmairq; @@ -152,7 +152,7 @@ static int camelot_pcm_open(struct snd_soc_component *component, static int camelot_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; int dmairq; @@ -174,7 +174,7 @@ static int camelot_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; int ret; @@ -193,7 +193,7 @@ static int camelot_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; pr_debug("PCM data: addr 0x%08lx len %d\n", @@ -241,7 +241,7 @@ static inline void dmabrg_rec_dma_stop(struct camelot_pcm *cam) static int camelot_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; @@ -269,7 +269,7 @@ static snd_pcm_uframes_t camelot_pos(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; unsigned long pos; diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 1c3c4fdc9befdfe071c33a7ad40d1c84dc20afa9..3c574792231bc5c376d201838f497bd3cb063744 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -406,7 +406,7 @@ static int fsi_is_play(struct snd_pcm_substream *substream) static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); return asoc_rtd_to_cpu(rtd, 0); } @@ -1632,12 +1632,12 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); int ret; - /* set master/slave audio interface */ + /* set clock master audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: break; case SND_SOC_DAIFMT_CBS_CFS: - fsi->clk_master = 1; /* codec is slave, cpu is master */ + fsi->clk_master = 1; /* cpu is master */ break; default: return -EINVAL; diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index d5702fbf176beaa7b6d1d602d15302a691360b90..7082c12d3bf23870b4eae05a6caebb96aaf0c91a 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c @@ -45,7 +45,7 @@ static struct clk_lookup *siumckb_lookup; static int migor_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; unsigned int rate = params_rate(params); @@ -78,7 +78,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream, static int migor_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); if (use_count) { diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 4349f2fb823ff18fa50b6b15ce85037d8cc2e21e..6e670b3e92a002171ba0e83742a544873cad3694 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -694,7 +694,7 @@ static void rsnd_dai_stream_quit(struct rsnd_dai_stream *io) static struct snd_soc_dai *rsnd_substream_to_dai(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); return asoc_rtd_to_cpu(rtd, 0); } @@ -759,13 +759,13 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); - /* set master/slave audio interface */ + /* set clock master for audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: rdai->clk_master = 0; break; case SND_SOC_DAIFMT_CBS_CFS: - rdai->clk_master = 1; /* codec is slave, cpu is master */ + rdai->clk_master = 1; /* cpu is master */ break; default: return -EINVAL; @@ -1399,7 +1399,7 @@ static int rsnd_hw_params(struct snd_soc_component *component, struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); /* * rsnd assumes that it might be used under DPCM if user want to use diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index d47608ff5facc37981bdf8f3cce960c85c5aafe0..6b519370fd644904cfcdea26b1b6b82899166ce1 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -775,7 +775,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv); void rsnd_ssi_remove(struct rsnd_priv *priv); struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); int rsnd_ssi_use_busif(struct rsnd_dai_stream *io); -u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io); +u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io); #define rsnd_ssi_is_pin_sharing(io) \ __rsnd_ssi_is_pin_sharing(rsnd_io_to_mod_ssi(io)) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 47d5ddb526f2116e0755f4a6238c62abb02e7811..d0ded427a83638de28022cb158f7abccd10ff43b 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -111,8 +111,8 @@ struct rsnd_ssi { #define rsnd_ssi_nr(priv) ((priv)->ssi_nr) #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) #define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io)) -#define rsnd_ssi_is_multi_slave(mod, io) \ - (rsnd_ssi_multi_slaves(io) & (1 << rsnd_mod_id(mod))) +#define rsnd_ssi_is_multi_secondary(mod, io) \ + (rsnd_ssi_multi_secondaries(io) & (1 << rsnd_mod_id(mod))) #define rsnd_ssi_is_run_mods(mod, io) \ (rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod))) #define rsnd_ssi_can_output_clk(mod) (!__rsnd_ssi_is_pin_sharing(mod)) @@ -165,7 +165,7 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod, dev_warn(dev, "%s status check failed\n", rsnd_mod_name(mod)); } -static u32 rsnd_ssi_multi_slaves(struct rsnd_dai_stream *io) +static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io) { struct rsnd_mod *mod; enum rsnd_mod_type types[] = { @@ -193,7 +193,7 @@ static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io) struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io); u32 mods; - mods = rsnd_ssi_multi_slaves_runtime(io) | + mods = rsnd_ssi_multi_secondaries_runtime(io) | 1 << rsnd_mod_id(ssi_mod); if (ssi_parent_mod) @@ -202,10 +202,10 @@ static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io) return mods; } -u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io) +u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io) { if (rsnd_runtime_is_multi_ssi(io)) - return rsnd_ssi_multi_slaves(io); + return rsnd_ssi_multi_secondaries(io); return 0; } @@ -283,7 +283,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, if (!rsnd_ssi_can_output_clk(mod)) return 0; - if (rsnd_ssi_is_multi_slave(mod, io)) + if (rsnd_ssi_is_multi_secondary(mod, io)) return 0; if (rsnd_runtime_is_tdm_split(io)) @@ -626,7 +626,7 @@ static int rsnd_ssi_start(struct rsnd_mod *mod, * EN will be set via SSIU :: SSI_CONTROL * if Multi channel mode */ - if (rsnd_ssi_multi_slaves_runtime(io)) + if (rsnd_ssi_multi_secondaries_runtime(io)) return 0; /* @@ -675,7 +675,7 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod, /* In multi-SSI mode, stop is performed by setting ssi0129 in * SSI_CONTROL to 0 (in rsnd_ssio_stop_gen2). Do nothing here. */ - if (rsnd_ssi_multi_slaves_runtime(io)) + if (rsnd_ssi_multi_secondaries_runtime(io)) return 0; /* @@ -888,7 +888,7 @@ static void rsnd_ssi_parent_attach(struct rsnd_mod *mod, if (!rsnd_rdai_is_clk_master(rdai)) return; - if (rsnd_ssi_is_multi_slave(mod, io)) + if (rsnd_ssi_is_multi_secondary(mod, io)) return; switch (rsnd_mod_id(mod)) { @@ -930,9 +930,9 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod, /* * SSIP/SSIU/IRQ are not needed on - * SSI Multi slaves + * SSI Multi secondaries */ - if (rsnd_ssi_is_multi_slave(mod, io)) + if (rsnd_ssi_is_multi_secondary(mod, io)) return 0; /* @@ -1091,9 +1091,9 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, /* * SSIP/SSIU/IRQ/DMA are not needed on - * SSI Multi slaves + * SSI Multi secondaries */ - if (rsnd_ssi_is_multi_slave(mod, io)) + if (rsnd_ssi_is_multi_secondary(mod, io)) return 0; ret = rsnd_ssi_common_probe(mod, io, priv); diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 9c7c3e7539c9347e2a045cad6ca167003524449e..f29bd72f3a26533353bfc18239ee91375fd23dbe 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -60,7 +60,7 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_dai *rdai = rsnd_io_to_rdai(io); - u32 ssis = rsnd_ssi_multi_slaves_runtime(io); + u32 ssis = rsnd_ssi_multi_secondaries_runtime(io); int use_busif = rsnd_ssi_use_busif(io); int id = rsnd_mod_id(mod); int is_clk_master = rsnd_rdai_is_clk_master(rdai); @@ -246,7 +246,7 @@ static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod, rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4)); - if (rsnd_ssi_multi_slaves_runtime(io)) + if (rsnd_ssi_multi_secondaries_runtime(io)) rsnd_mod_write(mod, SSI_CONTROL, 0x1); return 0; @@ -267,7 +267,7 @@ static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod, if (--ssiu->usrcnt) return 0; - if (rsnd_ssi_multi_slaves_runtime(io)) + if (rsnd_ssi_multi_secondaries_runtime(io)) rsnd_mod_write(mod, SSI_CONTROL, 0); return 0; diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 6a6ffd6d31925072c8a9a2c0cc6c71ca3bd809d7..bd9de77c35f3eac318af8af78d1d394f91749d86 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -281,11 +281,11 @@ static int siu_pcm_stmread_stop(struct siu_port *port_info) return 0; } -static bool filter(struct dma_chan *chan, void *slave) +static bool filter(struct dma_chan *chan, void *secondary) { - struct sh_dmae_slave *param = slave; + struct sh_dmae_slave *param = secondary; - pr_debug("%s: slave ID %d\n", __func__, param->shdma_slave.slave_id); + pr_debug("%s: secondary ID %d\n", __func__, param->shdma_slave.slave_id); chan->private = ¶m->shdma_slave; return true; diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c index 8125fa3840b60f6b20480215d43bda1401e5f6e3..15b01bcefca5c025ea26b119f08ca6ab0566b148 100644 --- a/sound/soc/sh/ssi.c +++ b/sound/soc/sh/ssi.c @@ -304,7 +304,7 @@ static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ssicr |= CR_SWS_MASTER | CR_SCK_MASTER; break; default: - pr_debug("ssi: invalid master/slave configuration\n"); + pr_debug("ssi: invalid master/secondary configuration\n"); return -EINVAL; } diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index c086786e4471cfcfdd43cf2268689f6c77ebe62f..65db083e242b36f547887c731237dc32dd0e5aea 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -82,13 +82,12 @@ static int snd_soc_ac97_gpio_get(struct gpio_chip *chip, unsigned offset) struct snd_soc_component *component = gpio_to_component(chip); int ret; - if (snd_soc_component_read(component, AC97_GPIO_STATUS, &ret) < 0) - ret = -1; + ret = snd_soc_component_read(component, AC97_GPIO_STATUS); dev_dbg(component->dev, "get gpio %d : %d\n", offset, - ret < 0 ? ret : ret & (1 << offset)); + ret & (1 << offset)); - return ret < 0 ? ret : !!(ret & (1 << offset)); + return !!(ret & (1 << offset)); } static void snd_soc_ac97_gpio_set(struct gpio_chip *chip, unsigned offset, @@ -394,6 +393,8 @@ EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); /** * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions + * @ops: bus ops + * @pdev: platform device * * This function sets the reset and warm_reset properties of ops and parses * the device node of pdev to get pinctrl states and gpio numbers to use. diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 785a0385cc7f5da3f0e83d6b963cfeacdb98c718..f0b4f4bc44a45117c98d9f9e402c32c44c0c618d 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -2,12 +2,53 @@ // // soc-component.c // +// Copyright 2009-2011 Wolfson Microelectronics PLC. // Copyright (C) 2019 Renesas Electronics Corp. +// +// Mark Brown // Kuninori Morimoto // #include #include +#define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret) +static inline int _soc_component_ret(struct snd_soc_component *component, + const char *func, int ret) +{ + /* Positive/Zero values are not errors */ + if (ret >= 0) + return ret; + + /* Negative values might be errors */ + switch (ret) { + case -EPROBE_DEFER: + case -ENOTSUPP: + break; + default: + dev_err(component->dev, + "ASoC: error at %s on %s: %d\n", + func, component->name, ret); + } + + return ret; +} + +void snd_soc_component_set_aux(struct snd_soc_component *component, + struct snd_soc_aux_dev *aux) +{ + component->init = (aux) ? aux->init : NULL; +} + +int snd_soc_component_init(struct snd_soc_component *component) +{ + int ret = 0; + + if (component->init) + ret = component->init(component); + + return soc_component_ret(component, ret); +} + /** * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. * @component: COMPONENT @@ -22,11 +63,13 @@ int snd_soc_component_set_sysclk(struct snd_soc_component *component, int clk_id, int source, unsigned int freq, int dir) { + int ret = -ENOTSUPP; + if (component->driver->set_sysclk) - return component->driver->set_sysclk(component, clk_id, source, + ret = component->driver->set_sysclk(component, clk_id, source, freq, dir); - return -ENOTSUPP; + return soc_component_ret(component, ret); } EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); @@ -44,11 +87,13 @@ int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { + int ret = -EINVAL; + if (component->driver->set_pll) - return component->driver->set_pll(component, pll_id, source, + ret = component->driver->set_pll(component, pll_id, source, freq_in, freq_out); - return -EINVAL; + return soc_component_ret(component, ret); } EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); @@ -62,194 +107,105 @@ void snd_soc_component_seq_notifier(struct snd_soc_component *component, int snd_soc_component_stream_event(struct snd_soc_component *component, int event) { + int ret = 0; + if (component->driver->stream_event) - return component->driver->stream_event(component, event); + ret = component->driver->stream_event(component, event); - return 0; + return soc_component_ret(component, ret); } int snd_soc_component_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { + int ret = 0; + if (component->driver->set_bias_level) - return component->driver->set_bias_level(component, level); + ret = component->driver->set_bias_level(component, level); - return 0; + return soc_component_ret(component, ret); } -int snd_soc_component_enable_pin(struct snd_soc_component *component, - const char *pin) +static int soc_component_pin(struct snd_soc_component *component, + const char *pin, + int (*pin_func)(struct snd_soc_dapm_context *dapm, + const char *pin)) { struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); char *full_name; int ret; - if (!component->name_prefix) - return snd_soc_dapm_enable_pin(dapm, pin); + if (!component->name_prefix) { + ret = pin_func(dapm, pin); + goto end; + } full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; + if (!full_name) { + ret = -ENOMEM; + goto end; + } - ret = snd_soc_dapm_enable_pin(dapm, full_name); + ret = pin_func(dapm, full_name); kfree(full_name); +end: + return soc_component_ret(component, ret); +} - return ret; +int snd_soc_component_enable_pin(struct snd_soc_component *component, + const char *pin) +{ + return soc_component_pin(component, pin, snd_soc_dapm_enable_pin); } EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin); int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_enable_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_enable_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked); } EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked); int snd_soc_component_disable_pin(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_disable_pin(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_disable_pin(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_disable_pin); } EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin); int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_disable_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_disable_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_disable_pin_unlocked); } EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked); int snd_soc_component_nc_pin(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_nc_pin(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_nc_pin(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_nc_pin); } EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin); int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_nc_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_nc_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_nc_pin_unlocked); } EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked); int snd_soc_component_get_pin_status(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_get_pin_status(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_get_pin_status(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status); } EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status); int snd_soc_component_force_enable_pin(struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_force_enable_pin(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_force_enable_pin(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin); } EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin); @@ -257,22 +213,7 @@ int snd_soc_component_force_enable_pin_unlocked( struct snd_soc_component *component, const char *pin) { - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char *full_name; - int ret; - - if (!component->name_prefix) - return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin); - - full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); - if (!full_name) - return -ENOMEM; - - ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, full_name); - kfree(full_name); - - return ret; + return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked); } EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); @@ -287,21 +228,25 @@ EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); int snd_soc_component_set_jack(struct snd_soc_component *component, struct snd_soc_jack *jack, void *data) { + int ret = -ENOTSUPP; + if (component->driver->set_jack) - return component->driver->set_jack(component, jack, data); + ret = component->driver->set_jack(component, jack, data); - return -ENOTSUPP; + return soc_component_ret(component, ret); } EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); int snd_soc_component_module_get(struct snd_soc_component *component, int upon_open) { + int ret = 0; + if (component->driver->module_get_upon_open == !!upon_open && !try_module_get(component->dev->driver->owner)) - return -ENODEV; + ret = -ENODEV; - return 0; + return soc_component_ret(component, ret); } void snd_soc_component_module_put(struct snd_soc_component *component, @@ -314,52 +259,23 @@ void snd_soc_component_module_put(struct snd_soc_component *component, int snd_soc_component_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { + int ret = 0; + if (component->driver->open) - return component->driver->open(component, substream); - return 0; + ret = component->driver->open(component, substream); + + return soc_component_ret(component, ret); } int snd_soc_component_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - if (component->driver->close) - return component->driver->close(component, substream); - return 0; -} + int ret = 0; -int snd_soc_component_prepare(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - if (component->driver->prepare) - return component->driver->prepare(component, substream); - return 0; -} - -int snd_soc_component_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - if (component->driver->hw_params) - return component->driver->hw_params(component, - substream, params); - return 0; -} - -int snd_soc_component_hw_free(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - if (component->driver->hw_free) - return component->driver->hw_free(component, substream); - return 0; -} + if (component->driver->close) + ret = component->driver->close(component, substream); -int snd_soc_component_trigger(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - int cmd) -{ - if (component->driver->trigger) - return component->driver->trigger(component, substream, cmd); - return 0; + return soc_component_ret(component, ret); } void snd_soc_component_suspend(struct snd_soc_component *component) @@ -383,10 +299,12 @@ int snd_soc_component_is_suspended(struct snd_soc_component *component) int snd_soc_component_probe(struct snd_soc_component *component) { + int ret = 0; + if (component->driver->probe) - return component->driver->probe(component); + ret = component->driver->probe(component); - return 0; + return soc_component_ret(component, ret); } void snd_soc_component_remove(struct snd_soc_component *component) @@ -398,10 +316,12 @@ void snd_soc_component_remove(struct snd_soc_component *component) int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, struct device_node *ep) { + int ret = -ENOTSUPP; + if (component->driver->of_xlate_dai_id) - return component->driver->of_xlate_dai_id(component, ep); + ret = component->driver->of_xlate_dai_id(component, ep); - return -ENOTSUPP; + return soc_component_ret(component, ret); } int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, @@ -410,13 +330,269 @@ int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, { if (component->driver->of_xlate_dai_name) return component->driver->of_xlate_dai_name(component, - args, dai_name); + args, dai_name); + /* + * Don't use soc_component_ret here because we may not want to report + * the error just yet. If a device has more than one component, the + * first may not match and we don't want spam the log with this. + */ return -ENOTSUPP; } +void snd_soc_component_setup_regmap(struct snd_soc_component *component) +{ + int val_bytes = regmap_get_val_bytes(component->regmap); + + /* Errors are legitimate for non-integer byte multiples */ + if (val_bytes > 0) + component->val_bytes = val_bytes; +} + +#ifdef CONFIG_REGMAP + +/** + * snd_soc_component_init_regmap() - Initialize regmap instance for the + * component + * @component: The component for which to initialize the regmap instance + * @regmap: The regmap instance that should be used by the component + * + * This function allows deferred assignment of the regmap instance that is + * associated with the component. Only use this if the regmap instance is not + * yet ready when the component is registered. The function must also be called + * before the first IO attempt of the component. + */ +void snd_soc_component_init_regmap(struct snd_soc_component *component, + struct regmap *regmap) +{ + component->regmap = regmap; + snd_soc_component_setup_regmap(component); +} +EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); + +/** + * snd_soc_component_exit_regmap() - De-initialize regmap instance for the + * component + * @component: The component for which to de-initialize the regmap instance + * + * Calls regmap_exit() on the regmap instance associated to the component and + * removes the regmap instance from the component. + * + * This function should only be used if snd_soc_component_init_regmap() was used + * to initialize the regmap instance. + */ +void snd_soc_component_exit_regmap(struct snd_soc_component *component) +{ + regmap_exit(component->regmap); + component->regmap = NULL; +} +EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); + +#endif + +static unsigned int soc_component_read_no_lock( + struct snd_soc_component *component, + unsigned int reg) +{ + int ret; + unsigned int val = 0; + + if (component->regmap) + ret = regmap_read(component->regmap, reg, &val); + else if (component->driver->read) { + ret = 0; + val = component->driver->read(component, reg); + } + else + ret = -EIO; + + if (ret < 0) + soc_component_ret(component, ret); + + return val; +} + +/** + * snd_soc_component_read() - Read register value + * @component: Component to read from + * @reg: Register to read + * + * Return: read value + */ +unsigned int snd_soc_component_read(struct snd_soc_component *component, + unsigned int reg) +{ + unsigned int val; + + mutex_lock(&component->io_mutex); + val = soc_component_read_no_lock(component, reg); + mutex_unlock(&component->io_mutex); + + return val; +} +EXPORT_SYMBOL_GPL(snd_soc_component_read); + +static int soc_component_write_no_lock( + struct snd_soc_component *component, + unsigned int reg, unsigned int val) +{ + int ret = -EIO; + + if (component->regmap) + ret = regmap_write(component->regmap, reg, val); + else if (component->driver->write) + ret = component->driver->write(component, reg, val); + + return soc_component_ret(component, ret); +} + +/** + * snd_soc_component_write() - Write register value + * @component: Component to write to + * @reg: Register to write + * @val: Value to write to the register + * + * Return: 0 on success, a negative error code otherwise. + */ +int snd_soc_component_write(struct snd_soc_component *component, + unsigned int reg, unsigned int val) +{ + int ret; + + mutex_lock(&component->io_mutex); + ret = soc_component_write_no_lock(component, reg, val); + mutex_unlock(&component->io_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_component_write); + +static int snd_soc_component_update_bits_legacy( + struct snd_soc_component *component, unsigned int reg, + unsigned int mask, unsigned int val, bool *change) +{ + unsigned int old, new; + int ret = 0; + + mutex_lock(&component->io_mutex); + + old = soc_component_read_no_lock(component, reg); + + new = (old & ~mask) | (val & mask); + *change = old != new; + if (*change) + ret = soc_component_write_no_lock(component, reg, new); + + mutex_unlock(&component->io_mutex); + + return soc_component_ret(component, ret); +} + +/** + * snd_soc_component_update_bits() - Perform read/modify/write cycle + * @component: Component to update + * @reg: Register to update + * @mask: Mask that specifies which bits to update + * @val: New value for the bits specified by mask + * + * Return: 1 if the operation was successful and the value of the register + * changed, 0 if the operation was successful, but the value did not change. + * Returns a negative error code otherwise. + */ +int snd_soc_component_update_bits(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, unsigned int val) +{ + bool change; + int ret; + + if (component->regmap) + ret = regmap_update_bits_check(component->regmap, reg, mask, + val, &change); + else + ret = snd_soc_component_update_bits_legacy(component, reg, + mask, val, &change); + + if (ret < 0) + return soc_component_ret(component, ret); + return change; +} +EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); + +/** + * snd_soc_component_update_bits_async() - Perform asynchronous + * read/modify/write cycle + * @component: Component to update + * @reg: Register to update + * @mask: Mask that specifies which bits to update + * @val: New value for the bits specified by mask + * + * This function is similar to snd_soc_component_update_bits(), but the update + * operation is scheduled asynchronously. This means it may not be completed + * when the function returns. To make sure that all scheduled updates have been + * completed snd_soc_component_async_complete() must be called. + * + * Return: 1 if the operation was successful and the value of the register + * changed, 0 if the operation was successful, but the value did not change. + * Returns a negative error code otherwise. + */ +int snd_soc_component_update_bits_async(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, unsigned int val) +{ + bool change; + int ret; + + if (component->regmap) + ret = regmap_update_bits_check_async(component->regmap, reg, + mask, val, &change); + else + ret = snd_soc_component_update_bits_legacy(component, reg, + mask, val, &change); + + if (ret < 0) + return soc_component_ret(component, ret); + return change; +} +EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); + +/** + * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed + * @component: Component for which to wait + * + * This function blocks until all asynchronous I/O which has previously been + * scheduled using snd_soc_component_update_bits_async() has completed. + */ +void snd_soc_component_async_complete(struct snd_soc_component *component) +{ + if (component->regmap) + regmap_async_complete(component->regmap); +} +EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); + +/** + * snd_soc_component_test_bits - Test register for change + * @component: component + * @reg: Register to test + * @mask: Mask that specifies which bits to test + * @value: Value to test against + * + * Tests a register with a new value and checks if the new value is + * different from the old value. + * + * Return: 1 for change, otherwise 0. + */ +int snd_soc_component_test_bits(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, unsigned int value) +{ + unsigned int old, new; + + old = snd_soc_component_read(component, reg); + new = (old & ~mask) | value; + return old != new; +} +EXPORT_SYMBOL_GPL(snd_soc_component_test_bits); + int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i; @@ -431,22 +607,24 @@ int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i; /* FIXME: use 1st ioctl */ for_each_rtd_components(rtd, i, component) if (component->driver->ioctl) - return component->driver->ioctl(component, substream, - cmd, arg); + return soc_component_ret( + component, + component->driver->ioctl(component, + substream, cmd, arg)); return snd_pcm_lib_ioctl(substream, cmd, arg); } int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i, ret; @@ -455,7 +633,7 @@ int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream) ret = component->driver->sync_stop(component, substream); if (ret < 0) - return ret; + return soc_component_ret(component, ret); } } @@ -466,15 +644,18 @@ int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, int channel, unsigned long pos, void __user *buf, unsigned long bytes) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i; /* FIXME. it returns 1st copy now */ for_each_rtd_components(rtd, i, component) if (component->driver->copy_user) - return component->driver->copy_user( - component, substream, channel, pos, buf, bytes); + return soc_component_ret( + component, + component->driver->copy_user( + component, substream, channel, + pos, buf, bytes)); return -EINVAL; } @@ -482,7 +663,7 @@ int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, unsigned long offset) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; struct page *page; int i; @@ -503,15 +684,17 @@ struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i; /* FIXME. it returns 1st mmap now */ for_each_rtd_components(rtd, i, component) if (component->driver->mmap) - return component->driver->mmap(component, - substream, vma); + return soc_component_ret( + component, + component->driver->mmap(component, + substream, vma)); return -EINVAL; } @@ -526,7 +709,7 @@ int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd) if (component->driver->pcm_construct) { ret = component->driver->pcm_construct(component, rtd); if (ret < 0) - return ret; + return soc_component_ret(component, ret); } } @@ -545,3 +728,80 @@ void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd) if (component->driver->pcm_destruct) component->driver->pcm_destruct(component, rtd->pcm); } + +int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *component; + int i, ret; + + for_each_rtd_components(rtd, i, component) { + if (component->driver->prepare) { + ret = component->driver->prepare(component, substream); + if (ret < 0) + return soc_component_ret(component, ret); + } + } + + return 0; +} + +int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_component **last) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *component; + int i, ret; + + for_each_rtd_components(rtd, i, component) { + if (component->driver->hw_params) { + ret = component->driver->hw_params(component, + substream, params); + if (ret < 0) { + *last = component; + return soc_component_ret(component, ret); + } + } + } + + *last = NULL; + return 0; +} + +void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_component *last) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *component; + int i, ret; + + for_each_rtd_components(rtd, i, component) { + if (component == last) + break; + + if (component->driver->hw_free) { + ret = component->driver->hw_free(component, substream); + if (ret < 0) + soc_component_ret(component, ret); + } + } +} + +int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream, + int cmd) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *component; + int i, ret; + + for_each_rtd_components(rtd, i, component) { + if (component->driver->trigger) { + ret = component->driver->trigger(component, substream, cmd); + if (ret < 0) + return soc_component_ret(component, ret); + } + } + + return 0; +} diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 4984b6a2c3708789b0646bf3f6cd77b270ced1b7..415510909a827b713300beb6e7e7cd7578338659 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -867,8 +867,8 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) rtd->compr = compr; compr->private_data = rtd; - dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n", - codec_dai->name, cpu_dai->name); + dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n", + codec_dai->name, cpu_dai->name); return 0; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6eb6826eb4c6dca7e1682a249273a5c5927a6982..fc65dcf6bdc2254e6f9f168bab3b294d3fdbb048 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -446,7 +446,6 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( dev->parent = card->dev; dev->release = soc_release_rtd_dev; - dev->groups = soc_dev_attr_groups; dev_set_name(dev, "%s", dai_link->name); @@ -503,6 +502,10 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( /* see for_each_card_rtds */ list_add_tail(&rtd->list, &card->rtd_list); + ret = device_add_groups(dev, soc_dev_attr_groups); + if (ret < 0) + goto free_rtd; + return rtd; free_rtd: @@ -548,7 +551,7 @@ int snd_soc_suspend(struct device *dev) if (rtd->dai_link->ignore_suspend) continue; - for_each_rtd_codec_dais(rtd, i, dai) { + for_each_rtd_dais(rtd, i, dai) { if (snd_soc_dai_stream_active(dai, playback)) snd_soc_dai_digital_mute(dai, 1, playback); } @@ -687,7 +690,7 @@ static void soc_resume_deferred(struct work_struct *work) if (rtd->dai_link->ignore_suspend) continue; - for_each_rtd_codec_dais(rtd, i, dai) { + for_each_rtd_dais(rtd, i, dai) { if (snd_soc_dai_stream_active(dai, playback)) snd_soc_dai_digital_mute(dai, 0, playback); } @@ -945,6 +948,9 @@ void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, { lockdep_assert_held(&client_mutex); + /* release machine specific resources */ + snd_soc_link_exit(rtd); + /* * Notify the machine driver for extra destruction */ @@ -1208,15 +1214,14 @@ static int soc_probe_component(struct snd_soc_card *card, component->name); probed = 1; - /* machine specific init */ - if (component->init) { - ret = component->init(component); - if (ret < 0) { - dev_err(component->dev, - "Failed to do machine specific init %d\n", ret); - goto err_probe; - } - } + /* + * machine specific init + * see + * snd_soc_component_set_aux() + */ + ret = snd_soc_component_init(component); + if (ret < 0) + goto err_probe; ret = snd_soc_add_component_controls(component, component->driver->controls, @@ -1330,7 +1335,8 @@ static void soc_unbind_aux_dev(struct snd_soc_card *card) struct snd_soc_component *component, *_component; for_each_card_auxs_safe(card, component, _component) { - component->init = NULL; + /* for snd_soc_component_init() */ + snd_soc_component_set_aux(component, NULL); list_del(&component->card_aux_list); } } @@ -1347,7 +1353,8 @@ static int soc_bind_aux_dev(struct snd_soc_card *card) if (!component) return -EPROBE_DEFER; - component->init = aux->init; + /* for snd_soc_component_init() */ + snd_soc_component_set_aux(component, aux); /* see for_each_card_auxs */ list_add(&component->card_aux_list, &card->aux_comp_list); } @@ -1638,8 +1645,8 @@ match: continue; } - dev_info(card->dev, "info: override BE DAI link %s\n", - card->dai_link[i].name); + dev_dbg(card->dev, "info: override BE DAI link %s\n", + card->dai_link[i].name); /* override platform component */ if (!dai_link->platforms) { @@ -2378,76 +2385,6 @@ err: return ret; } -static int snd_soc_component_initialize(struct snd_soc_component *component, - const struct snd_soc_component_driver *driver, struct device *dev) -{ - INIT_LIST_HEAD(&component->dai_list); - INIT_LIST_HEAD(&component->dobj_list); - INIT_LIST_HEAD(&component->card_list); - mutex_init(&component->io_mutex); - - component->name = fmt_single_name(dev, &component->id); - if (!component->name) { - dev_err(dev, "ASoC: Failed to allocate name\n"); - return -ENOMEM; - } - - component->dev = dev; - component->driver = driver; - - return 0; -} - -static void snd_soc_component_setup_regmap(struct snd_soc_component *component) -{ - int val_bytes = regmap_get_val_bytes(component->regmap); - - /* Errors are legitimate for non-integer byte multiples */ - if (val_bytes > 0) - component->val_bytes = val_bytes; -} - -#ifdef CONFIG_REGMAP - -/** - * snd_soc_component_init_regmap() - Initialize regmap instance for the - * component - * @component: The component for which to initialize the regmap instance - * @regmap: The regmap instance that should be used by the component - * - * This function allows deferred assignment of the regmap instance that is - * associated with the component. Only use this if the regmap instance is not - * yet ready when the component is registered. The function must also be called - * before the first IO attempt of the component. - */ -void snd_soc_component_init_regmap(struct snd_soc_component *component, - struct regmap *regmap) -{ - component->regmap = regmap; - snd_soc_component_setup_regmap(component); -} -EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); - -/** - * snd_soc_component_exit_regmap() - De-initialize regmap instance for the - * component - * @component: The component for which to de-initialize the regmap instance - * - * Calls regmap_exit() on the regmap instance associated to the component and - * removes the regmap instance from the component. - * - * This function should only be used if snd_soc_component_init_regmap() was used - * to initialize the regmap instance. - */ -void snd_soc_component_exit_regmap(struct snd_soc_component *component) -{ - regmap_exit(component->regmap); - component->regmap = NULL; -} -EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); - -#endif - #define ENDIANNESS_MAP(name) \ (SNDRV_PCM_FMTBIT_##name##LE | SNDRV_PCM_FMTBIT_##name##BE) static u64 endianness_format_map[] = { @@ -2504,22 +2441,38 @@ static void snd_soc_del_component_unlocked(struct snd_soc_component *component) list_del(&component->list); } -int snd_soc_add_component(struct device *dev, - struct snd_soc_component *component, - const struct snd_soc_component_driver *component_driver, - struct snd_soc_dai_driver *dai_drv, - int num_dai) +int snd_soc_component_initialize(struct snd_soc_component *component, + const struct snd_soc_component_driver *driver, + struct device *dev) +{ + INIT_LIST_HEAD(&component->dai_list); + INIT_LIST_HEAD(&component->dobj_list); + INIT_LIST_HEAD(&component->card_list); + mutex_init(&component->io_mutex); + + component->name = fmt_single_name(dev, &component->id); + if (!component->name) { + dev_err(dev, "ASoC: Failed to allocate name\n"); + return -ENOMEM; + } + + component->dev = dev; + component->driver = driver; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_component_initialize); + +int snd_soc_add_component(struct snd_soc_component *component, + struct snd_soc_dai_driver *dai_drv, + int num_dai) { int ret; int i; mutex_lock(&client_mutex); - ret = snd_soc_component_initialize(component, component_driver, dev); - if (ret) - goto err_free; - - if (component_driver->endianness) { + if (component->driver->endianness) { for (i = 0; i < num_dai; i++) { convert_endianness_formats(&dai_drv[i].playback); convert_endianness_formats(&dai_drv[i].capture); @@ -2528,7 +2481,8 @@ int snd_soc_add_component(struct device *dev, ret = snd_soc_register_dais(component, dai_drv, num_dai); if (ret < 0) { - dev_err(dev, "ASoC: Failed to register DAIs: %d\n", ret); + dev_err(component->dev, "ASoC: Failed to register DAIs: %d\n", + ret); goto err_cleanup; } @@ -2546,7 +2500,7 @@ int snd_soc_add_component(struct device *dev, err_cleanup: if (ret < 0) snd_soc_del_component_unlocked(component); -err_free: + mutex_unlock(&client_mutex); if (ret == 0) @@ -2562,13 +2516,17 @@ int snd_soc_register_component(struct device *dev, int num_dai) { struct snd_soc_component *component; + int ret; component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL); if (!component) return -ENOMEM; - return snd_soc_add_component(dev, component, component_driver, - dai_drv, num_dai); + ret = snd_soc_component_initialize(component, component_driver, dev); + if (ret < 0) + return ret; + + return snd_soc_add_component(component, dai_drv, num_dai); } EXPORT_SYMBOL_GPL(snd_soc_register_component); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 457159975b01a22237e81810855940e4b955618c..91a2551e4cefef822bec350c591d19c600d8ab16 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -298,13 +298,15 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, { int ret = -ENOTSUPP; + /* + * ignore if direction was CAPTURE + * and it had .no_capture_mute flag + */ if (dai->driver->ops && - dai->driver->ops->mute_stream) + dai->driver->ops->mute_stream && + (direction == SNDRV_PCM_STREAM_PLAYBACK || + !dai->driver->ops->no_capture_mute)) ret = dai->driver->ops->mute_stream(dai, mute, direction); - else if (direction == SNDRV_PCM_STREAM_PLAYBACK && - dai->driver->ops && - dai->driver->ops->digital_mute) - ret = dai->driver->ops->digital_mute(dai, mute); return soc_dai_ret(dai, ret); } @@ -314,7 +316,7 @@ int snd_soc_dai_hw_params(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret = 0; /* perform any topology hw_params fixups before DAI */ @@ -400,28 +402,30 @@ void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link) struct snd_soc_dai_link_component *codec; struct snd_soc_dai *dai; bool supported[SNDRV_PCM_STREAM_LAST + 1]; + bool supported_cpu; + bool supported_codec; int direction; int i; for_each_pcm_streams(direction) { - supported[direction] = true; + supported_cpu = false; + supported_codec = false; for_each_link_cpus(dai_link, i, cpu) { dai = snd_soc_find_dai(cpu); - if (!dai || !snd_soc_dai_stream_valid(dai, direction)) { - supported[direction] = false; + if (dai && snd_soc_dai_stream_valid(dai, direction)) { + supported_cpu = true; break; } } - if (!supported[direction]) - continue; for_each_link_codecs(dai_link, i, codec) { dai = snd_soc_find_dai(codec); - if (!dai || !snd_soc_dai_stream_valid(dai, direction)) { - supported[direction] = false; + if (dai && snd_soc_dai_stream_valid(dai, direction)) { + supported_codec = true; break; } } + supported[direction] = supported_cpu && supported_codec; } dai_link->dpcm_playback = supported[SNDRV_PCM_STREAM_PLAYBACK]; @@ -514,7 +518,7 @@ int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; int i, ret; @@ -533,7 +537,7 @@ int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; int i, ret; @@ -552,7 +556,7 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; int i, ret; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 2491e1ce16d32358500eb019cf4021314ae70496..3273161e27875a7c0641aab3c07e278173ef09c1 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -616,12 +616,11 @@ static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm) return dapm->component->name_prefix; } -static int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg, - unsigned int *value) +static unsigned int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg) { if (!dapm->component) return -EIO; - return snd_soc_component_read(dapm->component, reg, value); + return snd_soc_component_read(dapm->component, reg); } static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm, @@ -753,7 +752,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, int i; if (e->reg != SND_SOC_NOPM) { - soc_dapm_read(dapm, e->reg, &val); + val = soc_dapm_read(dapm, e->reg); val = (val >> e->shift_l) & e->mask; item = snd_soc_enum_val_to_item(e, val); } else { @@ -790,7 +789,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i, unsigned int val; if (reg != SND_SOC_NOPM) { - soc_dapm_read(p->sink->dapm, reg, &val); + val = soc_dapm_read(p->sink->dapm, reg); /* * The nth_path argument allows this function to know * which path of a kcontrol it is setting the initial @@ -805,7 +804,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i, */ if (snd_soc_volsw_is_stereo(mc) && nth_path > 0) { if (reg != mc->rreg) - soc_dapm_read(p->sink->dapm, mc->rreg, &val); + val = soc_dapm_read(p->sink->dapm, mc->rreg); val = (val >> mc->rshift) & mask; } else { val = (val >> shift) & mask; @@ -1799,7 +1798,7 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie) /* If we're off and we're not supposed to go into STANDBY */ if (d->bias_level == SND_SOC_BIAS_OFF && d->target_bias_level != SND_SOC_BIAS_OFF) { - if (d->dev) + if (d->dev && cookie) pm_runtime_get_sync(d->dev); ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY); @@ -1846,7 +1845,7 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie) dev_err(d->dev, "ASoC: Failed to turn off bias: %d\n", ret); - if (d->dev) + if (d->dev && cookie) pm_runtime_put(d->dev); } @@ -2674,7 +2673,7 @@ int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; mutex_lock_nested(&rtd->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); @@ -3246,7 +3245,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) /* Read the initial power state from the device */ if (w->reg >= 0) { - soc_dapm_read(w->dapm, w->reg, &val); + val = soc_dapm_read(w->dapm, w->reg); val = val >> w->shift; val &= w->mask; if (val == w->on_val) @@ -3288,15 +3287,14 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; unsigned int reg_val, val, rval = 0; - int ret = 0; mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) { - ret = soc_dapm_read(dapm, reg, ®_val); + reg_val = soc_dapm_read(dapm, reg); val = (reg_val >> shift) & mask; - if (ret == 0 && reg != mc->rreg) - ret = soc_dapm_read(dapm, mc->rreg, ®_val); + if (reg != mc->rreg) + reg_val = soc_dapm_read(dapm, mc->rreg); if (snd_soc_volsw_is_stereo(mc)) rval = (reg_val >> mc->rshift) & mask; @@ -3309,9 +3307,6 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, } mutex_unlock(&card->dapm_mutex); - if (ret) - return ret; - if (invert) ucontrol->value.integer.value[0] = max - val; else @@ -3324,7 +3319,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[1] = rval; } - return ret; + return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); @@ -3439,11 +3434,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); if (e->reg != SND_SOC_NOPM && dapm_kcontrol_is_powered(kcontrol)) { - int ret = soc_dapm_read(dapm, e->reg, ®_val); - if (ret) { - mutex_unlock(&card->dapm_mutex); - return ret; - } + reg_val = soc_dapm_read(dapm, e->reg); } else { reg_val = dapm_kcontrol_get_value(kcontrol); } @@ -3804,7 +3795,7 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, { struct snd_soc_dapm_path *path; struct snd_soc_dai *source, *sink; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_hw_params *params = NULL; const struct snd_soc_pcm_stream *config = NULL; struct snd_pcm_runtime *runtime = NULL; @@ -4126,7 +4117,7 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_pcm_substream *substream, char *id) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dapm_widget template; struct snd_soc_dapm_widget *w; const char **w_param_text; diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 61844403f1817fd2bdc7c781f0d1c545e5f16f97..fb95c1464e66d4e21da00173ec77fbdcf2046128 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -46,7 +46,7 @@ static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm, int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_dmaengine_dai_dma_data *dma_data; int ret; @@ -105,7 +105,7 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct dmaengine_pcm *pcm = soc_component_to_pcm(component); struct device *dma_dev = dmaengine_dma_dev(pcm, substream); struct dma_chan *chan = pcm->chan[substream->stream]; @@ -424,6 +424,7 @@ static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) int snd_dmaengine_pcm_register(struct device *dev, const struct snd_dmaengine_pcm_config *config, unsigned int flags) { + const struct snd_soc_component_driver *driver; struct dmaengine_pcm *pcm; int ret; @@ -442,12 +443,15 @@ int snd_dmaengine_pcm_register(struct device *dev, goto err_free_dma; if (config && config->process) - ret = snd_soc_add_component(dev, &pcm->component, - &dmaengine_pcm_component_process, - NULL, 0); + driver = &dmaengine_pcm_component_process; else - ret = snd_soc_add_component(dev, &pcm->component, - &dmaengine_pcm_component, NULL, 0); + driver = &dmaengine_pcm_component; + + ret = snd_soc_component_initialize(&pcm->component, driver, dev); + if (ret) + goto err_free_dma; + + ret = snd_soc_add_component(&pcm->component, NULL, 0); if (ret) goto err_free_dma; diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c deleted file mode 100644 index 1ff9175e9d5e614d6b01af0fa4c16f3009b538a7..0000000000000000000000000000000000000000 --- a/sound/soc/soc-io.c +++ /dev/null @@ -1,202 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -// -// soc-io.c -- ASoC register I/O helpers -// -// Copyright 2009-2011 Wolfson Microelectronics PLC. -// -// Author: Mark Brown - -#include -#include -#include -#include -#include - -/** - * snd_soc_component_read() - Read register value - * @component: Component to read from - * @reg: Register to read - * @val: Pointer to where the read value is stored - * - * Return: 0 on success, a negative error code otherwise. - */ -int snd_soc_component_read(struct snd_soc_component *component, - unsigned int reg, unsigned int *val) -{ - int ret; - - if (component->regmap) - ret = regmap_read(component->regmap, reg, val); - else if (component->driver->read) { - *val = component->driver->read(component, reg); - ret = 0; - } - else - ret = -EIO; - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_component_read); - -unsigned int snd_soc_component_read32(struct snd_soc_component *component, - unsigned int reg) -{ - unsigned int val; - int ret; - - ret = snd_soc_component_read(component, reg, &val); - if (ret < 0) - return -1; - - return val; -} -EXPORT_SYMBOL_GPL(snd_soc_component_read32); - -/** - * snd_soc_component_write() - Write register value - * @component: Component to write to - * @reg: Register to write - * @val: Value to write to the register - * - * Return: 0 on success, a negative error code otherwise. - */ -int snd_soc_component_write(struct snd_soc_component *component, - unsigned int reg, unsigned int val) -{ - if (component->regmap) - return regmap_write(component->regmap, reg, val); - else if (component->driver->write) - return component->driver->write(component, reg, val); - else - return -EIO; -} -EXPORT_SYMBOL_GPL(snd_soc_component_write); - -static int snd_soc_component_update_bits_legacy( - struct snd_soc_component *component, unsigned int reg, - unsigned int mask, unsigned int val, bool *change) -{ - unsigned int old, new; - int ret; - - mutex_lock(&component->io_mutex); - - ret = snd_soc_component_read(component, reg, &old); - if (ret < 0) - goto out_unlock; - - new = (old & ~mask) | (val & mask); - *change = old != new; - if (*change) - ret = snd_soc_component_write(component, reg, new); -out_unlock: - mutex_unlock(&component->io_mutex); - - return ret; -} - -/** - * snd_soc_component_update_bits() - Perform read/modify/write cycle - * @component: Component to update - * @reg: Register to update - * @mask: Mask that specifies which bits to update - * @val: New value for the bits specified by mask - * - * Return: 1 if the operation was successful and the value of the register - * changed, 0 if the operation was successful, but the value did not change. - * Returns a negative error code otherwise. - */ -int snd_soc_component_update_bits(struct snd_soc_component *component, - unsigned int reg, unsigned int mask, unsigned int val) -{ - bool change; - int ret; - - if (component->regmap) - ret = regmap_update_bits_check(component->regmap, reg, mask, - val, &change); - else - ret = snd_soc_component_update_bits_legacy(component, reg, - mask, val, &change); - - if (ret < 0) - return ret; - return change; -} -EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); - -/** - * snd_soc_component_update_bits_async() - Perform asynchronous - * read/modify/write cycle - * @component: Component to update - * @reg: Register to update - * @mask: Mask that specifies which bits to update - * @val: New value for the bits specified by mask - * - * This function is similar to snd_soc_component_update_bits(), but the update - * operation is scheduled asynchronously. This means it may not be completed - * when the function returns. To make sure that all scheduled updates have been - * completed snd_soc_component_async_complete() must be called. - * - * Return: 1 if the operation was successful and the value of the register - * changed, 0 if the operation was successful, but the value did not change. - * Returns a negative error code otherwise. - */ -int snd_soc_component_update_bits_async(struct snd_soc_component *component, - unsigned int reg, unsigned int mask, unsigned int val) -{ - bool change; - int ret; - - if (component->regmap) - ret = regmap_update_bits_check_async(component->regmap, reg, - mask, val, &change); - else - ret = snd_soc_component_update_bits_legacy(component, reg, - mask, val, &change); - - if (ret < 0) - return ret; - return change; -} -EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); - -/** - * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed - * @component: Component for which to wait - * - * This function blocks until all asynchronous I/O which has previously been - * scheduled using snd_soc_component_update_bits_async() has completed. - */ -void snd_soc_component_async_complete(struct snd_soc_component *component) -{ - if (component->regmap) - regmap_async_complete(component->regmap); -} -EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); - -/** - * snd_soc_component_test_bits - Test register for change - * @component: component - * @reg: Register to test - * @mask: Mask that specifies which bits to test - * @value: Value to test against - * - * Tests a register with a new value and checks if the new value is - * different from the old value. - * - * Return: 1 for change, otherwise 0. - */ -int snd_soc_component_test_bits(struct snd_soc_component *component, - unsigned int reg, unsigned int mask, unsigned int value) -{ - unsigned int old, new; - int ret; - - ret = snd_soc_component_read(component, reg, &old); - if (ret < 0) - return ret; - new = (old & ~mask) | value; - return old != new; -} -EXPORT_SYMBOL_GPL(snd_soc_component_test_bits); diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index f849278beba0899f603df67ba9aa12e140851c08..cec70b19863e21bd73f0455ba21de5a64d635e5d 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -40,6 +40,12 @@ int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) return soc_link_ret(rtd, ret); } +void snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd) +{ + if (rtd->dai_link->exit) + rtd->dai_link->exit(rtd); +} + int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -53,7 +59,7 @@ int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, int snd_soc_link_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret = 0; if (rtd->dai_link->ops && @@ -65,7 +71,7 @@ int snd_soc_link_startup(struct snd_pcm_substream *substream) void snd_soc_link_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) @@ -74,7 +80,7 @@ void snd_soc_link_shutdown(struct snd_pcm_substream *substream) int snd_soc_link_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret = 0; if (rtd->dai_link->ops && @@ -87,7 +93,7 @@ int snd_soc_link_prepare(struct snd_pcm_substream *substream) int snd_soc_link_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret = 0; if (rtd->dai_link->ops && @@ -99,7 +105,7 @@ int snd_soc_link_hw_params(struct snd_pcm_substream *substream, void snd_soc_link_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) @@ -108,7 +114,7 @@ void snd_soc_link_hw_free(struct snd_pcm_substream *substream) int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret = 0; if (rtd->dai_link->ops && diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 55ffb34be95e1b1020dc684aac0eaa6f587ffed4..10f48827bb0e0fee2a6a7d7565d97114f4f06963 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -63,11 +63,8 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val, item; unsigned int reg_val; - int ret; - ret = snd_soc_component_read(component, e->reg, ®_val); - if (ret) - return ret; + reg_val = snd_soc_component_read(component, e->reg); val = (reg_val >> e->shift_l) & e->mask; item = snd_soc_enum_val_to_item(e, val); ucontrol->value.enumerated.item[0] = item; @@ -136,10 +133,7 @@ static int snd_soc_read_signed(struct snd_soc_component *component, int ret; unsigned int val; - ret = snd_soc_component_read(component, reg, &val); - if (ret < 0) - return ret; - + val = snd_soc_component_read(component, reg); val = (val >> shift) & mask; if (!sign_bit) { @@ -375,19 +369,12 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, int min = mc->min; unsigned int mask = (1U << (fls(min + max) - 1)) - 1; unsigned int val; - int ret; - - ret = snd_soc_component_read(component, reg, &val); - if (ret < 0) - return ret; + val = snd_soc_component_read(component, reg); ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask; if (snd_soc_volsw_is_stereo(mc)) { - ret = snd_soc_component_read(component, reg2, &val); - if (ret < 0) - return ret; - + val = snd_soc_component_read(component, reg2); val = ((val >> rshift) - min) & mask; ucontrol->value.integer.value[1] = val; } @@ -548,12 +535,8 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; unsigned int val; - int ret; - - ret = snd_soc_component_read(component, reg, &val); - if (ret) - return ret; + val = snd_soc_component_read(component, reg); ucontrol->value.integer.value[0] = (val >> shift) & mask; if (invert) ucontrol->value.integer.value[0] = @@ -563,10 +546,7 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] - min; if (snd_soc_volsw_is_stereo(mc)) { - ret = snd_soc_component_read(component, rreg, &val); - if (ret) - return ret; - + val = snd_soc_component_read(component, rreg); ucontrol->value.integer.value[1] = (val >> shift) & mask; if (invert) ucontrol->value.integer.value[1] = @@ -833,12 +813,9 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, long val = 0; unsigned int regval; unsigned int i; - int ret; for (i = 0; i < regcount; i++) { - ret = snd_soc_component_read(component, regbase+i, ®val); - if (ret) - return ret; + regval = snd_soc_component_read(component, regbase+i); val |= (regval & regwmask) << (regwshift*(regcount-i-1)); } val &= mask; @@ -918,12 +895,8 @@ int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, unsigned int mask = 1 << shift; unsigned int invert = mc->invert != 0; unsigned int val; - int ret; - - ret = snd_soc_component_read(component, reg, &val); - if (ret) - return ret; + val = snd_soc_component_read(component, reg); val &= mask; if (shift != 0 && val != 0) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b82d8fd277119a7e3526d8487fc69d6ad8b4cf32..20a45b2ca16b58e6c810f1f5c3c22b4cfe42479e 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -208,6 +208,7 @@ static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm) * PCM runtime components * @rtd: ASoC PCM runtime that is activated * @stream: Direction of the PCM stream + * @action: Activate stream if 1. Deactivate if -1. * * Increments/Decrements the active count for all the DAIs and components * attached to a PCM runtime. @@ -303,7 +304,7 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, struct snd_soc_dai *soc_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; if (soc_dai->rate && (soc_dai->driver->symmetric_rates || @@ -360,7 +361,7 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; struct snd_soc_dai *cpu_dai; unsigned int rate, channels, sample_bits, symmetry, i; @@ -422,7 +423,7 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai_link *link = rtd->dai_link; struct snd_soc_dai *dai; unsigned int symmetry, i; @@ -442,7 +443,7 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; if (!bits) @@ -456,7 +457,7 @@ static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits) static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; struct snd_soc_pcm_stream *pcm_codec, *pcm_cpu; @@ -591,7 +592,7 @@ EXPORT_SYMBOL_GPL(snd_soc_runtime_calc_hw); static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) { struct snd_pcm_hardware *hw = &substream->runtime->hw; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); u64 formats = hw->formats; /* @@ -607,7 +608,7 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) static int soc_pcm_components_open(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *last = NULL; struct snd_soc_component *component; int i, ret = 0; @@ -649,7 +650,7 @@ static int soc_pcm_components_open(struct snd_pcm_substream *substream) static int soc_pcm_components_close(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; int i, r, ret = 0; @@ -671,7 +672,7 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream) */ static int soc_pcm_close(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; struct snd_soc_dai *dai; int i; @@ -710,7 +711,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) */ static int soc_pcm_open(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_component *component; struct snd_soc_dai *dai; @@ -849,8 +850,7 @@ static void codec2codec_close_delayed_work(struct snd_soc_pcm_runtime *rtd) */ static int soc_pcm_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; int i, ret = 0; @@ -860,14 +860,9 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) if (ret < 0) goto out; - for_each_rtd_components(rtd, i, component) { - ret = snd_soc_component_prepare(component, substream); - if (ret < 0) { - dev_err(component->dev, - "ASoC: platform prepare error: %d\n", ret); - goto out; - } - } + ret = snd_soc_pcm_component_prepare(substream); + if (ret < 0) + goto out; ret = snd_soc_pcm_dai_prepare(substream); if (ret < 0) { @@ -904,25 +899,6 @@ static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params, interval->max = channels; } -static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_component *last) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component; - int i, r, ret = 0; - - for_each_rtd_components(rtd, i, component) { - if (component == last) - break; - - r = snd_soc_component_hw_free(component, substream); - if (r < 0) - ret = r; /* use last ret */ - } - - return ret; -} - /* * Called by ALSA when the hardware params are set by application. This * function can also be called multiple times and can allocate buffers @@ -931,7 +907,7 @@ static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream, static int soc_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; @@ -1024,23 +1000,16 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, snd_soc_dapm_update_dai(substream, params, cpu_dai); } - for_each_rtd_components(rtd, i, component) { - ret = snd_soc_component_hw_params(component, substream, params); - if (ret < 0) { - dev_err(component->dev, - "ASoC: %s hw params failed: %d\n", - component->name, ret); - goto component_err; - } - } - component = NULL; + ret = snd_soc_pcm_component_hw_params(substream, params, &component); + if (ret < 0) + goto component_err; out: mutex_unlock(&rtd->card->pcm_mutex); return ret; component_err: - soc_pcm_components_hw_free(substream, component); + snd_soc_pcm_component_hw_free(substream, component); i = rtd->num_cpus; @@ -1075,7 +1044,7 @@ codec_err: */ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *dai; int i; @@ -1099,7 +1068,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) snd_soc_link_hw_free(substream); /* free any component resources */ - soc_pcm_components_hw_free(substream, NULL); + snd_soc_pcm_component_hw_free(substream, NULL); /* now free hw params for the DAIs */ for_each_rtd_dais(rtd, i, dai) { @@ -1113,65 +1082,37 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) return 0; } -static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component; - int i, ret; - - ret = snd_soc_link_trigger(substream, cmd); - if (ret < 0) - return ret; - - for_each_rtd_components(rtd, i, component) { - ret = snd_soc_component_trigger(component, substream, cmd); - if (ret < 0) - return ret; - } - - return snd_soc_pcm_dai_trigger(substream, cmd); -} - -static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component; - int i, ret; - - ret = snd_soc_pcm_dai_trigger(substream, cmd); - if (ret < 0) - return ret; - - for_each_rtd_components(rtd, i, component) { - ret = snd_soc_component_trigger(component, substream, cmd); - if (ret < 0) - return ret; - } - - ret = snd_soc_link_trigger(substream, cmd); - if (ret < 0) - return ret; - - return 0; -} - static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { - int ret; + int ret = -EINVAL; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ret = soc_pcm_trigger_start(substream, cmd); + ret = snd_soc_link_trigger(substream, cmd); + if (ret < 0) + break; + + ret = snd_soc_pcm_component_trigger(substream, cmd); + if (ret < 0) + break; + + ret = snd_soc_pcm_dai_trigger(substream, cmd); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = soc_pcm_trigger_stop(substream, cmd); + ret = snd_soc_pcm_dai_trigger(substream, cmd); + if (ret < 0) + break; + + ret = snd_soc_pcm_component_trigger(substream, cmd); + if (ret < 0) + break; + + ret = snd_soc_link_trigger(substream, cmd); break; - default: - return -EINVAL; } return ret; @@ -1184,7 +1125,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) */ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; struct snd_pcm_runtime *runtime = substream->runtime; @@ -1662,7 +1603,7 @@ static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, u64 *formats) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); struct snd_soc_dpcm *dpcm; struct snd_soc_dai *dai; int stream = substream->stream; @@ -1699,7 +1640,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, unsigned int *channels_min, unsigned int *channels_max) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); struct snd_soc_dpcm *dpcm; int stream = substream->stream; @@ -1754,7 +1695,7 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, unsigned int *rate_min, unsigned int *rate_max) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); struct snd_soc_dpcm *dpcm; int stream = substream->stream; @@ -1792,7 +1733,7 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai; int i; @@ -1843,7 +1784,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, int stream) { struct snd_soc_dpcm *dpcm; - struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); struct snd_soc_dai *fe_cpu_dai; int err; int i; @@ -1874,7 +1815,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, if (!be_substream) continue; - rtd = be_substream->private_data; + rtd = asoc_substream_to_rtd(be_substream); if (rtd->dai_link->be_hw_params_fixup) continue; @@ -1896,7 +1837,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) { - struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); struct snd_pcm_runtime *runtime = fe_substream->runtime; int stream = fe_substream->stream, ret = 0; @@ -1977,7 +1918,7 @@ int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream) static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int stream = substream->stream; dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); @@ -2043,7 +1984,7 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int err, stream = substream->stream; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); @@ -2148,7 +2089,7 @@ unwind: static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int ret, stream = substream->stream; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); @@ -2294,7 +2235,7 @@ EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger); static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream, int cmd, bool fe_first) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int ret; /* call trigger on the frontend before the backend. */ @@ -2325,7 +2266,7 @@ static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream, static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int stream = substream->stream; int ret = 0; enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; @@ -2410,7 +2351,7 @@ out: static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int stream = substream->stream; /* if FE's runtime_update is already set, we're in race; @@ -2463,7 +2404,7 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); int stream = substream->stream, ret = 0; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); @@ -2730,7 +2671,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dpcm_runtime_update); static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream) { - struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); struct snd_soc_dpcm *dpcm; int stream = fe_substream->stream; @@ -2745,7 +2686,7 @@ static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream) static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) { - struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); int ret; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); @@ -2759,7 +2700,7 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) { - struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); struct snd_soc_dapm_widget_list *list; int ret; int stream = fe_substream->stream; @@ -2811,30 +2752,36 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (rtd->dai_link->dpcm_playback) { stream = SNDRV_PCM_STREAM_PLAYBACK; - for_each_rtd_cpu_dais(rtd, i, cpu_dai) - if (!snd_soc_dai_stream_valid(cpu_dai, - stream)) { - dev_err(rtd->card->dev, - "CPU DAI %s for rtd %s does not support playback\n", - cpu_dai->name, - rtd->dai_link->stream_name); - return -EINVAL; + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { + if (snd_soc_dai_stream_valid(cpu_dai, stream)) { + playback = 1; + break; } - playback = 1; + } + + if (!playback) { + dev_err(rtd->card->dev, + "No CPU DAIs support playback for stream %s\n", + rtd->dai_link->stream_name); + return -EINVAL; + } } if (rtd->dai_link->dpcm_capture) { stream = SNDRV_PCM_STREAM_CAPTURE; - for_each_rtd_cpu_dais(rtd, i, cpu_dai) - if (!snd_soc_dai_stream_valid(cpu_dai, - stream)) { - dev_err(rtd->card->dev, - "CPU DAI %s for rtd %s does not support capture\n", - cpu_dai->name, - rtd->dai_link->stream_name); - return -EINVAL; + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { + if (snd_soc_dai_stream_valid(cpu_dai, stream)) { + capture = 1; + break; } - capture = 1; + } + + if (!capture) { + dev_err(rtd->card->dev, + "No CPU DAIs support capture for stream %s\n", + rtd->dai_link->stream_name); + return -EINVAL; + } } } else { /* Adapt stream for codec2codec links */ @@ -2900,8 +2847,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) capture, &pcm); } if (ret < 0) { - dev_err(rtd->card->dev, "ASoC: can't create pcm for %s\n", - rtd->dai_link->name); + dev_err(rtd->card->dev, "ASoC: can't create pcm %s for dailink %s: %d\n", + new_name, rtd->dai_link->name, ret); return ret; } dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name); @@ -2966,15 +2913,16 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) ret = snd_soc_pcm_component_new(rtd); if (ret < 0) { - dev_err(rtd->dev, "ASoC: pcm constructor failed: %d\n", ret); + dev_err(rtd->dev, "ASoC: pcm %s constructor failed for dailink %s: %d\n", + new_name, rtd->dai_link->name, ret); return ret; } pcm->no_device_suspend = true; out: - dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", - (rtd->num_codecs > 1) ? "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, - (rtd->num_cpus > 1) ? "multicpu" : asoc_rtd_to_cpu(rtd, 0)->name); + dev_dbg(rtd->card->dev, "%s <-> %s mapping ok\n", + (rtd->num_codecs > 1) ? "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, + (rtd->num_cpus > 1) ? "multicpu" : asoc_rtd_to_cpu(rtd, 0)->name); return ret; } diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 6eaa00c210117265e778fa6ccb528d530e7f556f..cee99867131879620d292045b9837950e0c03a0d 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -741,7 +741,8 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, struct snd_soc_tplg_bytes_control *be; struct soc_bytes_ext *sbe; struct snd_kcontrol_new kc; - int i, err; + int i; + int err = 0; if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_bytes_control), count, @@ -786,7 +787,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, if (err) { soc_control_err(tplg, &be->hdr, be->hdr.name); kfree(sbe); - continue; + break; } /* pass control to driver for optional further init */ @@ -796,7 +797,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, dev_err(tplg->dev, "ASoC: failed to init %s\n", be->hdr.name); kfree(sbe); - continue; + break; } /* register control here */ @@ -806,12 +807,12 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, dev_err(tplg->dev, "ASoC: failed to add %s\n", be->hdr.name); kfree(sbe); - continue; + break; } list_add(&sbe->dobj.list, &tplg->comp->dobj_list); } - return 0; + return err; } @@ -821,7 +822,8 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, struct snd_soc_tplg_mixer_control *mc; struct soc_mixer_control *sm; struct snd_kcontrol_new kc; - int i, err; + int i; + int err = 0; if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_mixer_control), @@ -880,7 +882,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, if (err) { soc_control_err(tplg, &mc->hdr, mc->hdr.name); kfree(sm); - continue; + break; } /* create any TLV data */ @@ -889,7 +891,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); kfree(sm); - continue; + break; } /* pass control to driver for optional further init */ @@ -900,7 +902,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, mc->hdr.name); soc_tplg_free_tlv(tplg, &kc); kfree(sm); - continue; + break; } /* register control here */ @@ -911,13 +913,13 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, mc->hdr.name); soc_tplg_free_tlv(tplg, &kc); kfree(sm); - continue; + break; } list_add(&sm->dobj.list, &tplg->comp->dobj_list); } - return 0; + return err; } static int soc_tplg_denum_create_texts(struct soc_enum *se, @@ -997,7 +999,8 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, struct snd_soc_tplg_enum_control *ec; struct soc_enum *se; struct snd_kcontrol_new kc; - int i, ret, err; + int i; + int err = 0; if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_enum_control), @@ -1052,8 +1055,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, dev_err(tplg->dev, "ASoC: could not create values for %s\n", ec->hdr.name); - kfree(se); - continue; + goto err_denum; } /* fall through */ case SND_SOC_TPLG_CTL_ENUM: @@ -1064,24 +1066,22 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, dev_err(tplg->dev, "ASoC: could not create texts for %s\n", ec->hdr.name); - kfree(se); - continue; + goto err_denum; } break; default: + err = -EINVAL; dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n", ec->hdr.ops.info, ec->hdr.name); - kfree(se); - continue; + goto err_denum; } /* map io handlers */ err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg); if (err) { soc_control_err(tplg, &ec->hdr, ec->hdr.name); - kfree(se); - continue; + goto err_denum; } /* pass control to driver for optional further init */ @@ -1090,24 +1090,25 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", ec->hdr.name); - kfree(se); - continue; + goto err_denum; } /* register control here */ - ret = soc_tplg_add_kcontrol(tplg, - &kc, &se->dobj.control.kcontrol); - if (ret < 0) { + err = soc_tplg_add_kcontrol(tplg, + &kc, &se->dobj.control.kcontrol); + if (err < 0) { dev_err(tplg->dev, "ASoC: could not add kcontrol %s\n", ec->hdr.name); - kfree(se); - continue; + goto err_denum; } list_add(&se->dobj.list, &tplg->comp->dobj_list); } - return 0; + +err_denum: + kfree(se); + return err; } static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, @@ -1262,6 +1263,7 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, ret = soc_tplg_add_route(tplg, routes[i]); if (ret < 0) { + dev_err(tplg->dev, "ASoC: topology: add_route failed: %d\n", ret); /* * this route was added to the list, it will * be freed in remove_route() so increment the @@ -1361,8 +1363,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( if (err < 0) { dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); - kfree(sm); - continue; + goto err_sm; } /* pass control to driver for optional further init */ @@ -2743,15 +2744,21 @@ static int soc_tplg_process_headers(struct soc_tplg *tplg) /* make sure header is valid before loading */ ret = soc_valid_header(tplg, hdr); - if (ret < 0) + if (ret < 0) { + dev_err(tplg->dev, + "ASoC: topology: invalid header: %d\n", ret); return ret; - else if (ret == 0) + } else if (ret == 0) { break; + } /* load the header object */ ret = soc_tplg_load_header(tplg, hdr); - if (ret < 0) + if (ret < 0) { + dev_err(tplg->dev, + "ASoC: topology: could not load header: %d\n", ret); return ret; + } /* goto next header */ tplg->hdr_pos += le32_to_cpu(hdr->payload_size) + diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 922eac930df912978392a8ae78a5492754d2e540..f27f94ca064bca45c28e3077d630e3e9f6558d63 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -66,7 +66,7 @@ static const struct snd_pcm_hardware dummy_dma_hardware = { static int dummy_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* BE's dont need dummy params */ if (!rtd->dai_link->no_pcm) @@ -86,12 +86,13 @@ static const struct snd_soc_component_driver dummy_codec = { .non_legacy_dai_naming = 1, }; -#define STUB_RATES SNDRV_PCM_RATE_8000_192000 +#define STUB_RATES SNDRV_PCM_RATE_8000_384000 #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ SNDRV_PCM_FMTBIT_U8 | \ SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_U16_LE | \ SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | \ SNDRV_PCM_FMTBIT_U24_LE | \ SNDRV_PCM_FMTBIT_S32_LE | \ SNDRV_PCM_FMTBIT_U32_LE | \ diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index a4fa8451d8cb39feaedf7e0d26b5a7f1d57e955c..bc0628c7b88c486d0d944904d06bf6d903270073 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -374,7 +374,7 @@ static int imx8_ipc_pcm_params(struct snd_sof_dev *sdev, static struct snd_soc_dai_driver imx8_dai[] = { { - .name = "esai-port", + .name = "esai0", .playback = { .channels_min = 1, .channels_max = 8, @@ -384,6 +384,17 @@ static struct snd_soc_dai_driver imx8_dai[] = { .channels_max = 8, }, }, +{ + .name = "sai1", + .playback = { + .channels_min = 1, + .channels_max = 32, + }, + .capture = { + .channels_min = 1, + .channels_max = 32, + }, +}, }; /* i.MX8 ops */ @@ -415,7 +426,14 @@ struct snd_sof_dsp_ops sof_imx8_ops = { /* DAI drivers */ .drv = imx8_dai, - .num_drv = 1, /* we have only 1 ESAI interface on i.MX8 */ + .num_drv = ARRAY_SIZE(imx8_dai), + + /* ALSA HW info flags */ + .hw_info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, }; EXPORT_SYMBOL(sof_imx8_ops); @@ -448,7 +466,7 @@ struct snd_sof_dsp_ops sof_imx8x_ops = { /* DAI drivers */ .drv = imx8_dai, - .num_drv = 1, /* we have only 1 ESAI interface on i.MX8 */ + .num_drv = ARRAY_SIZE(imx8_dai), /* ALSA HW info flags */ .hw_info = SNDRV_PCM_INFO_MMAP | diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index 287114a37688c676f503495a2c95c8032683ce92..86320941fcee2cf6636a7b3bd98a101e2b4149fb 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -188,8 +188,7 @@ static int imx8m_probe(struct snd_sof_dev *sdev) } sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, res.start, - res.end - res.start + - 1); + resource_size(&res)); if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) { dev_err(sdev->dev, "failed to ioremap mem 0x%x size 0x%x\n", base, size); @@ -239,7 +238,7 @@ static int imx8m_ipc_pcm_params(struct snd_sof_dev *sdev, static struct snd_soc_dai_driver imx8m_dai[] = { { - .name = "sai-port", + .name = "sai3", .playback = { .channels_min = 1, .channels_max = 32, @@ -280,7 +279,7 @@ struct snd_sof_dsp_ops sof_imx8m_ops = { /* DAI drivers */ .drv = imx8m_dai, - .num_drv = 1, /* we have only 1 SAI interface on i.MX8M */ + .num_drv = ARRAY_SIZE(imx8m_dai), .hw_info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 3934cd6bf87a3f8a5d55564a46eb6d6922fb3a5c..df1c6997cb4e28aea17266527d1ec85c0259a739 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -56,7 +56,7 @@ static struct hdac_ext_stream * hda_link_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sof_intel_hda_stream *hda_stream; struct hdac_ext_stream *res = NULL; struct hdac_stream *stream = NULL; @@ -203,7 +203,7 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream, struct hdac_stream *hstream = substream->runtime->private_data; struct hdac_bus *bus = hstream->bus; struct hdac_ext_stream *link_dev; - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct sof_intel_hda_stream *hda_stream; struct hda_pipe_params p_params = {0}; @@ -264,7 +264,7 @@ static int hda_link_pcm_prepare(struct snd_pcm_substream *substream, snd_soc_dai_get_dma_data(dai, substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int stream = substream->stream; if (link_dev->link_prepared) @@ -291,7 +291,7 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, hstream = substream->runtime->private_data; bus = hstream->bus; - rtd = snd_pcm_substream_chip(substream); + rtd = asoc_substream_to_rtd(substream); link = snd_hdac_ext_bus_get_link(bus, asoc_rtd_to_codec(rtd, 0)->component->name); if (!link) @@ -357,7 +357,7 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream, hstream = substream->runtime->private_data; bus = hstream->bus; - rtd = snd_pcm_substream_chip(substream); + rtd = asoc_substream_to_rtd(substream); link_dev = snd_soc_dai_get_dma_data(dai, substream); if (!link_dev) { diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 9e5ff8c18f9943065b99a747e9cee6d986ec70e4..ed4d65a29d3ae297fc0f95a9ccb4c3c348e4e43e 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -408,11 +408,13 @@ static int hda_dsp_set_D0_state(struct snd_sof_dev *sdev, value = SOF_HDA_VS_D0I3C_I3; /* - * Trace DMA is disabled by default when the DSP enters D0I3. - * But it can be kept enabled when the DSP enters D0I3 while the - * system is in S0 for debug. + * Trace DMA need to be disabled when the DSP enters + * D0I3 for S0Ix suspend, but it can be kept enabled + * when the DSP enters D0I3 while the system is in S0 + * for debug purpose. */ - if (hda_enable_trace_D0I3_S0 && + if (!sdev->dtrace_is_supported || + !hda_enable_trace_D0I3_S0 || sdev->system_suspend_target != SOF_SUSPEND_NONE) flags = HDA_PM_NO_DMA_TRACE; } else { @@ -696,12 +698,35 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) .state = SOF_DSP_PM_D0, .substate = SOF_HDA_DSP_PM_D0I0, }; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_ext_link *hlink = NULL; +#endif int ret; /* resume from D0I3 */ if (sdev->dsp_power_state.state == SOF_DSP_PM_D0) { hda_codec_i915_display_power(sdev, true); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* power up links that were active before suspend */ + list_for_each_entry(hlink, &bus->hlink_list, list) { + if (hlink->ref_count) { + ret = snd_hdac_ext_bus_link_power_up(hlink); + if (ret < 0) { + dev_dbg(sdev->dev, + "error %x in %s: failed to power up links", + ret, __func__); + return ret; + } + } + } + + /* set up CORB/RIRB buffers if was on before suspend */ + if (bus->cmd_dma_state) + snd_hdac_bus_init_cmd_io(bus); +#endif + /* Set DSP power state */ ret = snd_sof_dsp_set_power_state(sdev, &target_state); if (ret < 0) { @@ -808,6 +833,21 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + /* stop the CORB/RIRB DMA if it is On */ + if (bus->cmd_dma_state) + snd_hdac_bus_stop_cmd_io(bus); + + /* no link can be powered in s0ix state */ + ret = snd_hdac_ext_bus_link_power_down_all(bus); + if (ret < 0) { + dev_dbg(sdev->dev, + "error %d in %s: failed to power down links", + ret, __func__); + return ret; + } +#endif + /* enable the system waking up via IPC IRQ */ enable_irq_wake(pci->irq); pci_save_state(pci); @@ -846,7 +886,7 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) * explicitly during suspend. */ if (stream->link_substream) { - rtd = snd_pcm_substream_chip(stream->link_substream); + rtd = asoc_substream_to_rtd(stream->link_substream); name = asoc_rtd_to_codec(rtd, 0)->component->name; link = snd_hdac_ext_bus_get_link(bus, name); if (!link) diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index 53a875ac52d6523e6a08ac82b16d594093c8dad4..b527d5958ae548417e15f92e2ee28d03c50cd13b 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -147,7 +147,7 @@ int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev, snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *scomp = sdev->component; struct hdac_stream *hstream = substream->runtime->private_data; struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index d03b5be31255b3afa6cc7cef0e43f2358a66f4b8..9e922df6a710186532615b141e923fef8e57ec5e 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -14,6 +14,7 @@ static struct snd_soc_card sof_nocodec_card = { .name = "nocodec", /* the sof- prefix is added by the core */ + .owner = THIS_MODULE }; static int sof_nocodec_bes_setup(struct device *dev, diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 22fe9d5e932bc69e9258df35a200486465ccd692..d730e437e4ba84d2d447b5dfb06f47a58af21005 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -25,7 +25,7 @@ static int create_page_table(struct snd_soc_component *component, struct snd_pcm_substream *substream, unsigned char *dma_area, size_t size) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_pcm *spcm; struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream); int stream = substream->stream; @@ -71,7 +71,7 @@ void snd_sof_pcm_period_elapsed_work(struct work_struct *work) */ void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_pcm *spcm; @@ -120,7 +120,7 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; @@ -237,7 +237,7 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, static int sof_pcm_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; int ret, err = 0; @@ -273,7 +273,7 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, static int sof_pcm_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_pcm *spcm; int ret; @@ -310,7 +310,7 @@ static int sof_pcm_prepare(struct snd_soc_component *component, static int sof_pcm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; struct sof_ipc_stream stream; @@ -423,7 +423,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component, static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; snd_pcm_uframes_t host, dai; @@ -456,7 +456,7 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component, static int sof_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); const struct snd_sof_dsp_ops *ops = sof_ops(sdev); @@ -528,7 +528,7 @@ static int sof_pcm_open(struct snd_soc_component *component, static int sof_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; int err; @@ -718,17 +718,25 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, /* do nothing for ALH dai_link */ break; case SOF_DAI_IMX_ESAI: + rate->min = dai->dai_config->esai.fsync_rate; + rate->max = dai->dai_config->esai.fsync_rate; channels->min = dai->dai_config->esai.tdm_slots; channels->max = dai->dai_config->esai.tdm_slots; + dev_dbg(component->dev, + "rate_min: %d rate_max: %d\n", rate->min, rate->max); dev_dbg(component->dev, "channels_min: %d channels_max: %d\n", channels->min, channels->max); break; case SOF_DAI_IMX_SAI: + rate->min = dai->dai_config->sai.fsync_rate; + rate->max = dai->dai_config->sai.fsync_rate; channels->min = dai->dai_config->sai.tdm_slots; channels->max = dai->dai_config->sai.tdm_slots; + dev_dbg(component->dev, + "rate_min: %d rate_max: %d\n", rate->min, rate->max); dev_dbg(component->dev, "channels_min: %d channels_max: %d\n", channels->min, channels->max); diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index c5eaaa9780549d5cfa2b16b899b44ca425696ced..8aecc46b364782b2bedb0e56dd0805671e762c27 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -35,7 +35,7 @@ MODULE_PARM_DESC(sof_acpi_debug, "SOF ACPI debug options (0x0 all off)"); #define SOF_ACPI_DISABLE_PM_RUNTIME BIT(0) -#if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) +#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) static const struct sof_dev_desc sof_acpi_broadwell_desc = { .machines = snd_soc_acpi_intel_broadwell_machines, .resindex_lpe_base = 0, @@ -51,7 +51,7 @@ static const struct sof_dev_desc sof_acpi_broadwell_desc = { }; #endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) /* BYTCR uses different IRQ index */ static const struct sof_dev_desc sof_acpi_baytrailcr_desc = { @@ -133,7 +133,7 @@ static int sof_acpi_probe(struct platform_device *pdev) if (!desc) return -ENODEV; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) if (desc == &sof_acpi_baytrail_desc && soc_intel_is_byt_cr(pdev)) desc = &sof_acpi_baytrailcr_desc; #endif @@ -191,6 +191,7 @@ static int sof_acpi_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_ACPI static const struct acpi_device_id sof_acpi_match[] = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) { "INT3438", (unsigned long)&sof_acpi_broadwell_desc }, @@ -202,6 +203,7 @@ static const struct acpi_device_id sof_acpi_match[] = { { } }; MODULE_DEVICE_TABLE(acpi, sof_acpi_match); +#endif /* acpi_driver definition */ static struct platform_driver snd_sof_acpi_driver = { diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 6a9703e5ff60d76f92f03666adb8b3f01d96e1a1..13e10a0c0b05d84de50e65e4f15e16c75e82c03a 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2831,6 +2831,8 @@ static int sof_link_sai_load(struct snd_soc_component *scomp, int index, } config->sai.mclk_rate = le32_to_cpu(hw_config->mclk_rate); + config->sai.bclk_rate = le32_to_cpu(hw_config->bclk_rate); + config->sai.fsync_rate = le32_to_cpu(hw_config->fsync_rate); config->sai.mclk_direction = hw_config->mclk_direction; config->sai.tdm_slots = le32_to_cpu(hw_config->tdm_slots); diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c index 58d5843811f9421a96fa66ec84b452678bf8ce59..38f9fff5be6bc2b70b00b2888486879a139c11f8 100644 --- a/sound/soc/spear/spdif_out.c +++ b/sound/soc/spear/spdif_out.c @@ -188,7 +188,7 @@ static int spdif_out_trigger(struct snd_pcm_substream *substream, int cmd, return ret; } -static int spdif_digital_mute(struct snd_soc_dai *dai, int mute) +static int spdif_mute(struct snd_soc_dai *dai, int mute, int direction) { struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai); u32 val; @@ -229,7 +229,8 @@ static int spdif_mute_put(struct snd_kcontrol *kcontrol, if (host->saved_params.mute == ucontrol->value.integer.value[0]) return 0; - spdif_digital_mute(cpu_dai, ucontrol->value.integer.value[0]); + spdif_mute(cpu_dai, ucontrol->value.integer.value[0], + SNDRV_PCM_STREAM_PLAYBACK); return 1; } @@ -250,11 +251,12 @@ static int spdif_soc_dai_probe(struct snd_soc_dai *dai) } static const struct snd_soc_dai_ops spdif_out_dai_ops = { - .digital_mute = spdif_digital_mute, + .mute_stream = spdif_mute, .startup = spdif_out_startup, .shutdown = spdif_out_shutdown, .trigger = spdif_out_trigger, .hw_params = spdif_out_hw_params, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver spdif_out_dai = { diff --git a/sound/soc/sprd/sprd-pcm-dma.c b/sound/soc/sprd/sprd-pcm-dma.c index 5074123f88559fce86c161a20f762fff6f573653..5e3a96d4793cd91f97508e0b206bfb6c5a8c05b5 100644 --- a/sound/soc/sprd/sprd-pcm-dma.c +++ b/sound/soc/sprd/sprd-pcm-dma.c @@ -190,7 +190,7 @@ static int sprd_pcm_hw_params(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = substream->runtime; struct sprd_pcm_dma_private *dma_private = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sprd_pcm_dma_params *dma_params; size_t totsize = params_buffer_bytes(params); size_t period = params_period_bytes(params); diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index 2dc2da5d458bd13d8f71f2fddd83fa3b407e2d47..a16adeb7c1e98fd8b33ce20b79588d2a5de10395 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1348,7 +1348,7 @@ struct sti_uniperiph_data { struct sti_uniperiph_dai dai_data; }; -static const struct snd_pcm_hardware uni_tdm_hw = { +static __maybe_unused const struct snd_pcm_hardware uni_tdm_hw = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID, diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index 16ff02953015cfaa448c6b1f2e64fd445e567c6d..ec27c13af04f66aeee863c79636bd62394262590 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -168,7 +168,7 @@ static void stm32_memcpy_32to16(void *dest, const void *src, size_t n) static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private) { struct stm32_adfsdm_priv *priv = private; - struct snd_soc_pcm_runtime *rtd = priv->substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(priv->substream); u8 *pcm_buff = priv->pcm_buff; u8 *src_buff = (u8 *)data; unsigned int old_pos = priv->pos; @@ -213,7 +213,7 @@ static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private) static int stm32_adfsdm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); @@ -234,7 +234,7 @@ static int stm32_adfsdm_trigger(struct snd_soc_component *component, static int stm32_adfsdm_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); int ret; @@ -248,7 +248,7 @@ static int stm32_adfsdm_pcm_open(struct snd_soc_component *component, static int stm32_adfsdm_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); @@ -261,7 +261,7 @@ static snd_pcm_uframes_t stm32_adfsdm_pcm_pointer( struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); @@ -272,7 +272,7 @@ static int stm32_adfsdm_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); @@ -344,12 +344,17 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL); if (!component) return -ENOMEM; + + ret = snd_soc_component_initialize(component, + &stm32_adfsdm_soc_platform, + &pdev->dev); + if (ret < 0) + return ret; #ifdef CONFIG_DEBUG_FS component->debugfs_prefix = "pcm"; #endif - ret = snd_soc_add_component(&pdev->dev, component, - &stm32_adfsdm_soc_platform, NULL, 0); + ret = snd_soc_add_component(component, NULL, 0); if (ret < 0) dev_err(&pdev->dev, "%s: Failed to register PCM platform\n", __func__); diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 41f01c3e639eeb9a57333e513b0119051ec0e554..3fb9513cedb2583d6fb753b9acbb33680c1db66b 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1237,7 +1237,7 @@ static int stm32_sai_pcm_process_spdif(struct snd_pcm_substream *substream, void *buf, unsigned long bytes) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); int *ptr = (int *)(runtime->dma_area + hwoff + diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 34f3e0be30581cea3b769975786d064d040e4a40..2af6404dbd62fdaa740304fb8e193850329e1ad6 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -286,7 +286,7 @@ static void sun4i_codec_stop_capture(struct sun4i_codec *scodec) static int sun4i_codec_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); switch (cmd) { @@ -318,7 +318,7 @@ static int sun4i_codec_trigger(struct snd_pcm_substream *substream, int cmd, static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); @@ -360,7 +360,7 @@ static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream, static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); u32 val; @@ -573,7 +573,7 @@ static int sun4i_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); unsigned long clk_freq; int ret, hwrate; @@ -614,7 +614,7 @@ static struct snd_pcm_hw_constraint_list sun4i_codec_constraints = { static int sun4i_codec_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); snd_pcm_hw_constraint_list(substream->runtime, 0, @@ -634,7 +634,7 @@ static int sun4i_codec_startup(struct snd_pcm_substream *substream, static void sun4i_codec_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); clk_disable_unprepare(scodec->clk_module); diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index d0a8d5810c0a5ddf50dc87450838bc55547588d1..f23ff29e7c1d32cb977d8107d776f21e39613c96 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -128,13 +128,21 @@ struct sun4i_i2s; /** * struct sun4i_i2s_quirks - Differences between SoC variants. - * * @has_reset: SoC needs reset deasserted. * @reg_offset_txdata: offset of the tx fifo. * @sun4i_i2s_regmap: regmap config to use. * @field_clkdiv_mclk_en: regmap field to enable mclk output. * @field_fmt_wss: regmap field to set word select size. * @field_fmt_sr: regmap field to set sample resolution. + * @bclk_dividers: bit clock dividers array + * @num_bclk_dividers: number of bit clock dividers + * @mclk_dividers: mclk dividers array + * @num_mclk_dividers: number of mclk dividers + * @get_bclk_parent_rate: callback to get bclk parent rate + * @get_sr: callback to get sample resolution + * @get_wss: callback to get word select size + * @set_chan_cfg: callback to set channel configuration + * @set_fmt: callback to set format */ struct sun4i_i2s_quirks { bool has_reset; diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index 86779a99df751db7c0a9d1ef36c5b42a070a01ac..228485fe073426229566eb3bf0d3a23fd7c34275 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -167,7 +167,7 @@ /** * struct sun4i_spdif_quirks - Differences between SoC variants. * - * @reg_dac_tx_data: TX FIFO offset for DMA config. + * @reg_dac_txdata: TX FIFO offset for DMA config. * @has_reset: SoC needs reset deasserted. * @val_fctl_ftx: TX FIFO flush bitmask. */ @@ -243,7 +243,7 @@ static void sun4i_snd_txctrl_off(struct snd_pcm_substream *substream, static int sun4i_spdif_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct sun4i_spdif_dev *host = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index addadc827b9197e6466e351b087b86c44cb320e9..3d91bd3e59cd9da5ecef8ac9b54e5dda8235efc0 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -62,6 +62,62 @@ config SND_SOC_TEGRA30_I2S Tegra30 I2S interface. You will also need to select the individual machine drivers to support below. +config SND_SOC_TEGRA210_AHUB + tristate "Tegra210 AHUB module" + depends on SND_SOC_TEGRA + help + Config to enable Audio Hub (AHUB) module, which comprises of a + switch called Audio Crossbar (AXBAR) used to configure or modify + the audio routing path between various HW accelerators present in + AHUB. + Say Y or M if you want to add support for Tegra210 AHUB module. + +config SND_SOC_TEGRA210_DMIC + tristate "Tegra210 DMIC module" + depends on SND_SOC_TEGRA + help + Config to enable the Digital MIC (DMIC) controller which is used + to interface with Pulse Density Modulation (PDM) input devices. + The DMIC controller implements a converter to convert PDM signals + to Pulse Code Modulation (PCM) signals. This can be viewed as a + PDM receiver. + Say Y or M if you want to add support for Tegra210 DMIC module. + +config SND_SOC_TEGRA210_I2S + tristate "Tegra210 I2S module" + depends on SND_SOC_TEGRA + help + Config to enable the Inter-IC Sound (I2S) Controller which + implements full-duplex and bidirectional and single direction + point-to-point serial interfaces. It can interface with I2S + compatible devices. + Say Y or M if you want to add support for Tegra210 I2S module. + +config SND_SOC_TEGRA186_DSPK + tristate "Tegra186 DSPK module" + depends on SND_SOC_TEGRA + help + Config to enable the Digital Speaker Controller (DSPK) which + converts the multi-bit Pulse Code Modulation (PCM) audio input to + oversampled 1-bit Pulse Density Modulation (PDM) output. From the + signal flow perspective DSPK can be viewed as a PDM transmitter + that up-samples the input to the desired sampling rate by + interpolation and then converts the oversampled PCM input to + the desired 1-bit output via Delta Sigma Modulation (DSM). + Say Y or M if you want to add support for Tegra186 DSPK module. + +config SND_SOC_TEGRA210_ADMAIF + tristate "Tegra210 ADMAIF module" + depends on SND_SOC_TEGRA + help + Config to enable ADMAIF which is the interface between ADMA and + Audio Hub (AHUB). Each ADMA channel that sends/receives data to/ + from AHUB must interface through an ADMAIF channel. ADMA channel + sending data to AHUB pairs with an ADMAIF Tx channel, where as + ADMA channel receiving data from AHUB pairs with an ADMAIF Rx + channel. Buffer size is configurable for each ADMAIIF channel. + Say Y or M if you want to add support for Tegra210 ADMAIF module. + config SND_SOC_TEGRA_RT5640 tristate "SoC Audio support for Tegra boards using an RT5640 codec" depends on SND_SOC_TEGRA && I2C && GPIOLIB diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index c84f183919f2f1abbc1bb1587c401da7e08631c1..60040a06b814fb90ca6940bb8f1b1a215cfbf778 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile @@ -8,6 +8,11 @@ snd-soc-tegra20-i2s-objs := tegra20_i2s.o snd-soc-tegra20-spdif-objs := tegra20_spdif.o snd-soc-tegra30-ahub-objs := tegra30_ahub.o snd-soc-tegra30-i2s-objs := tegra30_i2s.o +snd-soc-tegra210-ahub-objs := tegra210_ahub.o +snd-soc-tegra210-dmic-objs := tegra210_dmic.o +snd-soc-tegra210-i2s-objs := tegra210_i2s.o +snd-soc-tegra186-dspk-objs := tegra186_dspk.o +snd-soc-tegra210-admaif-objs := tegra210_admaif.o obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o @@ -17,6 +22,11 @@ obj-$(CONFIG_SND_SOC_TEGRA20_I2S) += snd-soc-tegra20-i2s.o obj-$(CONFIG_SND_SOC_TEGRA20_SPDIF) += snd-soc-tegra20-spdif.o obj-$(CONFIG_SND_SOC_TEGRA30_AHUB) += snd-soc-tegra30-ahub.o obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o +obj-$(CONFIG_SND_SOC_TEGRA210_DMIC) += snd-soc-tegra210-dmic.o +obj-$(CONFIG_SND_SOC_TEGRA210_AHUB) += snd-soc-tegra210-ahub.o +obj-$(CONFIG_SND_SOC_TEGRA210_I2S) += snd-soc-tegra210-i2s.o +obj-$(CONFIG_SND_SOC_TEGRA186_DSPK) += snd-soc-tegra186-dspk.o +obj-$(CONFIG_SND_SOC_TEGRA210_ADMAIF) += snd-soc-tegra210-admaif.o # Tegra machine Support snd-soc-tegra-rt5640-objs := tegra_rt5640.o diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c new file mode 100644 index 0000000000000000000000000000000000000000..fe7117171a0e7a0441454efeef639c2b28498c84 --- /dev/null +++ b/sound/soc/tegra/tegra186_dspk.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra186_dspk.c - Tegra186 DSPK driver +// +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tegra186_dspk.h" +#include "tegra_cif.h" + +static const struct reg_default tegra186_dspk_reg_defaults[] = { + { TEGRA186_DSPK_RX_INT_MASK, 0x00000007 }, + { TEGRA186_DSPK_RX_CIF_CTRL, 0x00007700 }, + { TEGRA186_DSPK_CG, 0x00000001 }, + { TEGRA186_DSPK_CORE_CTRL, 0x00000310 }, + { TEGRA186_DSPK_CODEC_CTRL, 0x03000000 }, +}; + +static int tegra186_dspk_get_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); + + if (strstr(kcontrol->id.name, "FIFO Threshold")) + ucontrol->value.integer.value[0] = dspk->rx_fifo_th; + else if (strstr(kcontrol->id.name, "OSR Value")) + ucontrol->value.integer.value[0] = dspk->osr_val; + else if (strstr(kcontrol->id.name, "LR Polarity Select")) + ucontrol->value.integer.value[0] = dspk->lrsel; + else if (strstr(kcontrol->id.name, "Channel Select")) + ucontrol->value.integer.value[0] = dspk->ch_sel; + else if (strstr(kcontrol->id.name, "Mono To Stereo")) + ucontrol->value.integer.value[0] = dspk->mono_to_stereo; + else if (strstr(kcontrol->id.name, "Stereo To Mono")) + ucontrol->value.integer.value[0] = dspk->stereo_to_mono; + + return 0; +} + +static int tegra186_dspk_put_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); + int val = ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "FIFO Threshold")) + dspk->rx_fifo_th = val; + else if (strstr(kcontrol->id.name, "OSR Value")) + dspk->osr_val = val; + else if (strstr(kcontrol->id.name, "LR Polarity Select")) + dspk->lrsel = val; + else if (strstr(kcontrol->id.name, "Channel Select")) + dspk->ch_sel = val; + else if (strstr(kcontrol->id.name, "Mono To Stereo")) + dspk->mono_to_stereo = val; + else if (strstr(kcontrol->id.name, "Stereo To Mono")) + dspk->stereo_to_mono = val; + + return 0; +} + +static int tegra186_dspk_runtime_suspend(struct device *dev) +{ + struct tegra186_dspk *dspk = dev_get_drvdata(dev); + + regcache_cache_only(dspk->regmap, true); + regcache_mark_dirty(dspk->regmap); + + clk_disable_unprepare(dspk->clk_dspk); + + return 0; +} + +static int tegra186_dspk_runtime_resume(struct device *dev) +{ + struct tegra186_dspk *dspk = dev_get_drvdata(dev); + int err; + + err = clk_prepare_enable(dspk->clk_dspk); + if (err) { + dev_err(dev, "failed to enable DSPK clock, err: %d\n", err); + return err; + } + + regcache_cache_only(dspk->regmap, false); + regcache_sync(dspk->regmap); + + return 0; +} + +static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct tegra186_dspk *dspk = snd_soc_dai_get_drvdata(dai); + unsigned int channels, srate, dspk_clk; + struct device *dev = dai->dev; + struct tegra_cif_conf cif_conf; + unsigned int max_th; + int err; + + memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); + + channels = params_channels(params); + cif_conf.audio_ch = channels; + + /* Client channel */ + switch (dspk->ch_sel) { + case DSPK_CH_SELECT_LEFT: + case DSPK_CH_SELECT_RIGHT: + cif_conf.client_ch = 1; + break; + case DSPK_CH_SELECT_STEREO: + cif_conf.client_ch = 2; + break; + default: + dev_err(dev, "Invalid DSPK client channels\n"); + return -EINVAL; + } + + cif_conf.client_bits = TEGRA_ACIF_BITS_24; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_16; + break; + case SNDRV_PCM_FORMAT_S32_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_32; + break; + default: + dev_err(dev, "unsupported format!\n"); + return -EOPNOTSUPP; + } + + srate = params_rate(params); + + /* RX FIFO threshold in terms of frames */ + max_th = (TEGRA186_DSPK_RX_FIFO_DEPTH / cif_conf.audio_ch) - 1; + + if (dspk->rx_fifo_th > max_th) + dspk->rx_fifo_th = max_th; + + cif_conf.threshold = dspk->rx_fifo_th; + cif_conf.mono_conv = dspk->mono_to_stereo; + cif_conf.stereo_conv = dspk->stereo_to_mono; + + tegra_set_cif(dspk->regmap, TEGRA186_DSPK_RX_CIF_CTRL, + &cif_conf); + + /* + * DSPK clock and PDM codec clock should be synchronous with 4:1 ratio, + * this is because it takes 4 clock cycles to send out one sample to + * codec by sigma delta modulator. Finally the clock rate is a multiple + * of 'Over Sampling Ratio', 'Sample Rate' and 'Interface Clock Ratio'. + */ + dspk_clk = (DSPK_OSR_FACTOR << dspk->osr_val) * srate * DSPK_CLK_RATIO; + + err = clk_set_rate(dspk->clk_dspk, dspk_clk); + if (err) { + dev_err(dev, "can't set DSPK clock rate %u, err: %d\n", + dspk_clk, err); + + return err; + } + + regmap_update_bits(dspk->regmap, + /* Reg */ + TEGRA186_DSPK_CORE_CTRL, + /* Mask */ + TEGRA186_DSPK_OSR_MASK | + TEGRA186_DSPK_CHANNEL_SELECT_MASK | + TEGRA186_DSPK_CTRL_LRSEL_POLARITY_MASK, + /* Value */ + (dspk->osr_val << DSPK_OSR_SHIFT) | + ((dspk->ch_sel + 1) << CH_SEL_SHIFT) | + (dspk->lrsel << LRSEL_POL_SHIFT)); + + return 0; +} + +static const struct snd_soc_dai_ops tegra186_dspk_dai_ops = { + .hw_params = tegra186_dspk_hw_params, +}; + +static struct snd_soc_dai_driver tegra186_dspk_dais[] = { + { + .name = "DSPK-CIF", + .playback = { + .stream_name = "CIF-Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + }, + { + .name = "DSPK-DAP", + .playback = { + .stream_name = "DAP-Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &tegra186_dspk_dai_ops, + .symmetric_rates = 1, + }, +}; + +static const struct snd_soc_dapm_widget tegra186_dspk_widgets[] = { + SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA186_DSPK_ENABLE, 0, 0), + SND_SOC_DAPM_SPK("SPK", NULL), +}; + +static const struct snd_soc_dapm_route tegra186_dspk_routes[] = { + { "XBAR-Playback", NULL, "XBAR-TX" }, + { "CIF-Playback", NULL, "XBAR-Playback" }, + { "RX", NULL, "CIF-Playback" }, + { "DAP-Playback", NULL, "RX" }, + { "SPK", NULL, "DAP-Playback" }, +}; + +static const char * const tegra186_dspk_ch_sel_text[] = { + "Left", "Right", "Stereo", +}; + +static const struct soc_enum tegra186_dspk_ch_sel_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_ch_sel_text), + tegra186_dspk_ch_sel_text); + +static const char * const tegra186_dspk_osr_text[] = { + "OSR_32", "OSR_64", "OSR_128", "OSR_256", +}; + +static const struct soc_enum tegra186_dspk_osr_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_osr_text), + tegra186_dspk_osr_text); + +static const char * const tegra186_dspk_lrsel_text[] = { + "Left", "Right", +}; + +static const char * const tegra186_dspk_mono_conv_text[] = { + "Zero", "Copy", +}; + +static const struct soc_enum tegra186_dspk_mono_conv_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, + ARRAY_SIZE(tegra186_dspk_mono_conv_text), + tegra186_dspk_mono_conv_text); + +static const char * const tegra186_dspk_stereo_conv_text[] = { + "CH0", "CH1", "AVG", +}; + +static const struct soc_enum tegra186_dspk_stereo_conv_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, + ARRAY_SIZE(tegra186_dspk_stereo_conv_text), + tegra186_dspk_stereo_conv_text); + +static const struct soc_enum tegra186_dspk_lrsel_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_lrsel_text), + tegra186_dspk_lrsel_text); + +static const struct snd_kcontrol_new tegrat186_dspk_controls[] = { + SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0, + TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0, + tegra186_dspk_get_control, tegra186_dspk_put_control), + SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum, + tegra186_dspk_get_control, tegra186_dspk_put_control), + SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum, + tegra186_dspk_get_control, tegra186_dspk_put_control), + SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum, + tegra186_dspk_get_control, tegra186_dspk_put_control), + SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum, + tegra186_dspk_get_control, tegra186_dspk_put_control), + SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum, + tegra186_dspk_get_control, tegra186_dspk_put_control), +}; + +static const struct snd_soc_component_driver tegra186_dspk_cmpnt = { + .dapm_widgets = tegra186_dspk_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra186_dspk_widgets), + .dapm_routes = tegra186_dspk_routes, + .num_dapm_routes = ARRAY_SIZE(tegra186_dspk_routes), + .controls = tegrat186_dspk_controls, + .num_controls = ARRAY_SIZE(tegrat186_dspk_controls), +}; + +static bool tegra186_dspk_wr_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA186_DSPK_RX_INT_MASK ... TEGRA186_DSPK_RX_CIF_CTRL: + case TEGRA186_DSPK_ENABLE ... TEGRA186_DSPK_CG: + case TEGRA186_DSPK_CORE_CTRL ... TEGRA186_DSPK_CODEC_CTRL: + return true; + default: + return false; + }; +} + +static bool tegra186_dspk_rd_reg(struct device *dev, unsigned int reg) +{ + if (tegra186_dspk_wr_reg(dev, reg)) + return true; + + switch (reg) { + case TEGRA186_DSPK_RX_STATUS: + case TEGRA186_DSPK_RX_INT_STATUS: + case TEGRA186_DSPK_STATUS: + case TEGRA186_DSPK_INT_STATUS: + return true; + default: + return false; + }; +} + +static bool tegra186_dspk_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA186_DSPK_RX_STATUS: + case TEGRA186_DSPK_RX_INT_STATUS: + case TEGRA186_DSPK_STATUS: + case TEGRA186_DSPK_INT_STATUS: + return true; + default: + return false; + }; +} + +static const struct regmap_config tegra186_dspk_regmap = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA186_DSPK_CODEC_CTRL, + .writeable_reg = tegra186_dspk_wr_reg, + .readable_reg = tegra186_dspk_rd_reg, + .volatile_reg = tegra186_dspk_volatile_reg, + .reg_defaults = tegra186_dspk_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tegra186_dspk_reg_defaults), + .cache_type = REGCACHE_FLAT, +}; + +static const struct of_device_id tegra186_dspk_of_match[] = { + { .compatible = "nvidia,tegra186-dspk" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra186_dspk_of_match); + +static int tegra186_dspk_platform_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra186_dspk *dspk; + void __iomem *regs; + int err; + + dspk = devm_kzalloc(dev, sizeof(*dspk), GFP_KERNEL); + if (!dspk) + return -ENOMEM; + + dspk->osr_val = DSPK_OSR_64; + dspk->lrsel = DSPK_LRSEL_LEFT; + dspk->ch_sel = DSPK_CH_SELECT_STEREO; + dspk->mono_to_stereo = 0; /* "Zero" */ + + dev_set_drvdata(dev, dspk); + + dspk->clk_dspk = devm_clk_get(dev, "dspk"); + if (IS_ERR(dspk->clk_dspk)) { + dev_err(dev, "can't retrieve DSPK clock\n"); + return PTR_ERR(dspk->clk_dspk); + } + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + dspk->regmap = devm_regmap_init_mmio(dev, regs, &tegra186_dspk_regmap); + if (IS_ERR(dspk->regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(dspk->regmap); + } + + regcache_cache_only(dspk->regmap, true); + + err = devm_snd_soc_register_component(dev, &tegra186_dspk_cmpnt, + tegra186_dspk_dais, + ARRAY_SIZE(tegra186_dspk_dais)); + if (err) { + dev_err(dev, "can't register DSPK component, err: %d\n", + err); + return err; + } + + pm_runtime_enable(dev); + + return 0; +} + +static int tegra186_dspk_platform_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops tegra186_dspk_pm_ops = { + SET_RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend, + tegra186_dspk_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver tegra186_dspk_driver = { + .driver = { + .name = "tegra186-dspk", + .of_match_table = tegra186_dspk_of_match, + .pm = &tegra186_dspk_pm_ops, + }, + .probe = tegra186_dspk_platform_probe, + .remove = tegra186_dspk_platform_remove, +}; +module_platform_driver(tegra186_dspk_driver); + +MODULE_AUTHOR("Mohan Kumar "); +MODULE_AUTHOR("Sameer Pujar "); +MODULE_DESCRIPTION("Tegra186 ASoC DSPK driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/tegra/tegra186_dspk.h b/sound/soc/tegra/tegra186_dspk.h new file mode 100644 index 0000000000000000000000000000000000000000..b2a879065d3c9d9c8a344dc4b697abe70c2e164d --- /dev/null +++ b/sound/soc/tegra/tegra186_dspk.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra186_dspk.h - Definitions for Tegra186 DSPK driver + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA186_DSPK_H__ +#define __TEGRA186_DSPK_H__ + +/* Register offsets from DSPK BASE */ +#define TEGRA186_DSPK_RX_STATUS 0x0c +#define TEGRA186_DSPK_RX_INT_STATUS 0x10 +#define TEGRA186_DSPK_RX_INT_MASK 0x14 +#define TEGRA186_DSPK_RX_INT_SET 0x18 +#define TEGRA186_DSPK_RX_INT_CLEAR 0x1c +#define TEGRA186_DSPK_RX_CIF_CTRL 0x20 +#define TEGRA186_DSPK_ENABLE 0x40 +#define TEGRA186_DSPK_SOFT_RESET 0x44 +#define TEGRA186_DSPK_CG 0x48 +#define TEGRA186_DSPK_STATUS 0x4c +#define TEGRA186_DSPK_INT_STATUS 0x50 +#define TEGRA186_DSPK_CORE_CTRL 0x60 +#define TEGRA186_DSPK_CODEC_CTRL 0x64 + +/* DSPK CORE CONTROL fields */ +#define CH_SEL_SHIFT 8 +#define TEGRA186_DSPK_CHANNEL_SELECT_MASK (0x3 << CH_SEL_SHIFT) +#define DSPK_OSR_SHIFT 4 +#define TEGRA186_DSPK_OSR_MASK (0x3 << DSPK_OSR_SHIFT) +#define LRSEL_POL_SHIFT 0 +#define TEGRA186_DSPK_CTRL_LRSEL_POLARITY_MASK (0x1 << LRSEL_POL_SHIFT) +#define TEGRA186_DSPK_RX_FIFO_DEPTH 64 + +#define DSPK_OSR_FACTOR 32 + +/* DSPK interface clock ratio */ +#define DSPK_CLK_RATIO 4 + +enum tegra_dspk_osr { + DSPK_OSR_32, + DSPK_OSR_64, + DSPK_OSR_128, + DSPK_OSR_256, +}; + +enum tegra_dspk_ch_sel { + DSPK_CH_SELECT_LEFT, + DSPK_CH_SELECT_RIGHT, + DSPK_CH_SELECT_STEREO, +}; + +enum tegra_dspk_lrsel { + DSPK_LRSEL_LEFT, + DSPK_LRSEL_RIGHT, +}; + +struct tegra186_dspk { + unsigned int rx_fifo_th; + unsigned int osr_val; + unsigned int lrsel; + unsigned int ch_sel; + unsigned int mono_to_stereo; + unsigned int stereo_to_mono; + struct clk *clk_dspk; + struct regmap *regmap; +}; + +#endif diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c index 1070b2710d5e6789efe4c263bdab8d7d4377de99..79dba878d8542abbd6762603a6e198bffe0b0d48 100644 --- a/sound/soc/tegra/tegra20_das.c +++ b/sound/soc/tegra/tegra20_das.c @@ -98,8 +98,7 @@ EXPORT_SYMBOL_GPL(tegra20_das_connect_dac_to_dap); static bool tegra20_das_wr_rd_reg(struct device *dev, unsigned int reg) { - if ((reg >= TEGRA20_DAS_DAP_CTRL_SEL) && - (reg <= LAST_REG(DAP_CTRL_SEL))) + if (reg <= LAST_REG(DAP_CTRL_SEL)) return true; if ((reg >= TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL) && (reg <= LAST_REG(DAC_INPUT_DATA_CLK_SEL))) diff --git a/sound/soc/tegra/tegra20_das.h b/sound/soc/tegra/tegra20_das.h index 16b95b770a1de6c31cf9fac38f03d8a68a1bc64e..d22abc4d08e65957b1c7257e959a8bf60ebfee93 100644 --- a/sound/soc/tegra/tegra20_das.h +++ b/sound/soc/tegra/tegra20_das.h @@ -91,14 +91,14 @@ struct tegra20_das { */ /* - * Connect a DAP to to a DAC + * Connect a DAP to a DAC * dap_id: DAP to connect: TEGRA20_DAS_DAP_ID_* * dac_sel: DAC to connect to: TEGRA20_DAS_DAP_SEL_DAC* */ extern int tegra20_das_connect_dap_to_dac(int dap_id, int dac_sel); /* - * Connect a DAP to to another DAP + * Connect a DAP to another DAP * dap_id: DAP to connect: TEGRA20_DAS_DAP_ID_* * other_dap_sel: DAP to connect to: TEGRA20_DAS_DAP_SEL_DAP* * master: Is this DAP the master (1) or slave (0) diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c new file mode 100644 index 0000000000000000000000000000000000000000..4894e8e6ee7fdae7a226c2b75c8fee269f383e9d --- /dev/null +++ b/sound/soc/tegra/tegra210_admaif.c @@ -0,0 +1,800 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra210_admaif.c - Tegra ADMAIF driver +// +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tegra210_admaif.h" +#include "tegra_cif.h" +#include "tegra_pcm.h" + +#define CH_REG(offset, reg, id) \ + ((offset) + (reg) + (TEGRA_ADMAIF_CHANNEL_REG_STRIDE * (id))) + +#define CH_TX_REG(reg, id) CH_REG(admaif->soc_data->tx_base, reg, id) + +#define CH_RX_REG(reg, id) CH_REG(admaif->soc_data->rx_base, reg, id) + +#define REG_DEFAULTS(id, rx_ctrl, tx_ctrl, tx_base, rx_base) \ + { CH_REG(rx_base, TEGRA_ADMAIF_RX_INT_MASK, id), 0x00000001 }, \ + { CH_REG(rx_base, TEGRA_ADMAIF_CH_ACIF_RX_CTRL, id), 0x00007700 }, \ + { CH_REG(rx_base, TEGRA_ADMAIF_RX_FIFO_CTRL, id), rx_ctrl }, \ + { CH_REG(tx_base, TEGRA_ADMAIF_TX_INT_MASK, id), 0x00000001 }, \ + { CH_REG(tx_base, TEGRA_ADMAIF_CH_ACIF_TX_CTRL, id), 0x00007700 }, \ + { CH_REG(tx_base, TEGRA_ADMAIF_TX_FIFO_CTRL, id), tx_ctrl } + +#define ADMAIF_REG_DEFAULTS(id, chip) \ + REG_DEFAULTS((id) - 1, \ + chip ## _ADMAIF_RX ## id ## _FIFO_CTRL_REG_DEFAULT, \ + chip ## _ADMAIF_TX ## id ## _FIFO_CTRL_REG_DEFAULT, \ + chip ## _ADMAIF_TX_BASE, \ + chip ## _ADMAIF_RX_BASE) + +static const struct reg_default tegra186_admaif_reg_defaults[] = { + {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA186_ADMAIF_GLOBAL_BASE), 0x00000003}, + ADMAIF_REG_DEFAULTS(1, TEGRA186), + ADMAIF_REG_DEFAULTS(2, TEGRA186), + ADMAIF_REG_DEFAULTS(3, TEGRA186), + ADMAIF_REG_DEFAULTS(4, TEGRA186), + ADMAIF_REG_DEFAULTS(5, TEGRA186), + ADMAIF_REG_DEFAULTS(6, TEGRA186), + ADMAIF_REG_DEFAULTS(7, TEGRA186), + ADMAIF_REG_DEFAULTS(8, TEGRA186), + ADMAIF_REG_DEFAULTS(9, TEGRA186), + ADMAIF_REG_DEFAULTS(10, TEGRA186), + ADMAIF_REG_DEFAULTS(11, TEGRA186), + ADMAIF_REG_DEFAULTS(12, TEGRA186), + ADMAIF_REG_DEFAULTS(13, TEGRA186), + ADMAIF_REG_DEFAULTS(14, TEGRA186), + ADMAIF_REG_DEFAULTS(15, TEGRA186), + ADMAIF_REG_DEFAULTS(16, TEGRA186), + ADMAIF_REG_DEFAULTS(17, TEGRA186), + ADMAIF_REG_DEFAULTS(18, TEGRA186), + ADMAIF_REG_DEFAULTS(19, TEGRA186), + ADMAIF_REG_DEFAULTS(20, TEGRA186) +}; + +static const struct reg_default tegra210_admaif_reg_defaults[] = { + {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA210_ADMAIF_GLOBAL_BASE), 0x00000003}, + ADMAIF_REG_DEFAULTS(1, TEGRA210), + ADMAIF_REG_DEFAULTS(2, TEGRA210), + ADMAIF_REG_DEFAULTS(3, TEGRA210), + ADMAIF_REG_DEFAULTS(4, TEGRA210), + ADMAIF_REG_DEFAULTS(5, TEGRA210), + ADMAIF_REG_DEFAULTS(6, TEGRA210), + ADMAIF_REG_DEFAULTS(7, TEGRA210), + ADMAIF_REG_DEFAULTS(8, TEGRA210), + ADMAIF_REG_DEFAULTS(9, TEGRA210), + ADMAIF_REG_DEFAULTS(10, TEGRA210) +}; + +static bool tegra_admaif_wr_reg(struct device *dev, unsigned int reg) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE; + unsigned int num_ch = admaif->soc_data->num_ch; + unsigned int rx_base = admaif->soc_data->rx_base; + unsigned int tx_base = admaif->soc_data->tx_base; + unsigned int global_base = admaif->soc_data->global_base; + unsigned int reg_max = admaif->soc_data->regmap_conf->max_register; + unsigned int rx_max = rx_base + (num_ch * ch_stride); + unsigned int tx_max = tx_base + (num_ch * ch_stride); + + if ((reg >= rx_base) && (reg < rx_max)) { + reg = (reg - rx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_RX_ENABLE) || + (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) || + (reg == TEGRA_ADMAIF_RX_SOFT_RESET) || + (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL)) + return true; + } else if ((reg >= tx_base) && (reg < tx_max)) { + reg = (reg - tx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_TX_ENABLE) || + (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) || + (reg == TEGRA_ADMAIF_TX_SOFT_RESET) || + (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL)) + return true; + } else if ((reg >= global_base) && (reg < reg_max)) { + if (reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE)) + return true; + } + + return false; +} + +static bool tegra_admaif_rd_reg(struct device *dev, unsigned int reg) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE; + unsigned int num_ch = admaif->soc_data->num_ch; + unsigned int rx_base = admaif->soc_data->rx_base; + unsigned int tx_base = admaif->soc_data->tx_base; + unsigned int global_base = admaif->soc_data->global_base; + unsigned int reg_max = admaif->soc_data->regmap_conf->max_register; + unsigned int rx_max = rx_base + (num_ch * ch_stride); + unsigned int tx_max = tx_base + (num_ch * ch_stride); + + if ((reg >= rx_base) && (reg < rx_max)) { + reg = (reg - rx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_RX_ENABLE) || + (reg == TEGRA_ADMAIF_RX_STATUS) || + (reg == TEGRA_ADMAIF_RX_INT_STATUS) || + (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) || + (reg == TEGRA_ADMAIF_RX_SOFT_RESET) || + (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL)) + return true; + } else if ((reg >= tx_base) && (reg < tx_max)) { + reg = (reg - tx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_TX_ENABLE) || + (reg == TEGRA_ADMAIF_TX_STATUS) || + (reg == TEGRA_ADMAIF_TX_INT_STATUS) || + (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) || + (reg == TEGRA_ADMAIF_TX_SOFT_RESET) || + (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL)) + return true; + } else if ((reg >= global_base) && (reg < reg_max)) { + if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE)) || + (reg == (global_base + TEGRA_ADMAIF_GLOBAL_CG_0)) || + (reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) || + (reg == (global_base + + TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) || + (reg == (global_base + + TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS))) + return true; + } + + return false; +} + +static bool tegra_admaif_volatile_reg(struct device *dev, unsigned int reg) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE; + unsigned int num_ch = admaif->soc_data->num_ch; + unsigned int rx_base = admaif->soc_data->rx_base; + unsigned int tx_base = admaif->soc_data->tx_base; + unsigned int global_base = admaif->soc_data->global_base; + unsigned int reg_max = admaif->soc_data->regmap_conf->max_register; + unsigned int rx_max = rx_base + (num_ch * ch_stride); + unsigned int tx_max = tx_base + (num_ch * ch_stride); + + if ((reg >= rx_base) && (reg < rx_max)) { + reg = (reg - rx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_RX_ENABLE) || + (reg == TEGRA_ADMAIF_RX_STATUS) || + (reg == TEGRA_ADMAIF_RX_INT_STATUS) || + (reg == TEGRA_ADMAIF_RX_SOFT_RESET)) + return true; + } else if ((reg >= tx_base) && (reg < tx_max)) { + reg = (reg - tx_base) % ch_stride; + if ((reg == TEGRA_ADMAIF_TX_ENABLE) || + (reg == TEGRA_ADMAIF_TX_STATUS) || + (reg == TEGRA_ADMAIF_TX_INT_STATUS) || + (reg == TEGRA_ADMAIF_TX_SOFT_RESET)) + return true; + } else if ((reg >= global_base) && (reg < reg_max)) { + if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) || + (reg == (global_base + + TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) || + (reg == (global_base + + TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS))) + return true; + } + + return false; +} + +static const struct regmap_config tegra210_admaif_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA210_ADMAIF_LAST_REG, + .writeable_reg = tegra_admaif_wr_reg, + .readable_reg = tegra_admaif_rd_reg, + .volatile_reg = tegra_admaif_volatile_reg, + .reg_defaults = tegra210_admaif_reg_defaults, + .num_reg_defaults = TEGRA210_ADMAIF_CHANNEL_COUNT * 6 + 1, + .cache_type = REGCACHE_FLAT, +}; + +static const struct regmap_config tegra186_admaif_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA186_ADMAIF_LAST_REG, + .writeable_reg = tegra_admaif_wr_reg, + .readable_reg = tegra_admaif_rd_reg, + .volatile_reg = tegra_admaif_volatile_reg, + .reg_defaults = tegra186_admaif_reg_defaults, + .num_reg_defaults = TEGRA186_ADMAIF_CHANNEL_COUNT * 6 + 1, + .cache_type = REGCACHE_FLAT, +}; + +static int tegra_admaif_runtime_suspend(struct device *dev) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + + regcache_cache_only(admaif->regmap, true); + regcache_mark_dirty(admaif->regmap); + + return 0; +} + +static int tegra_admaif_runtime_resume(struct device *dev) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + + regcache_cache_only(admaif->regmap, false); + regcache_sync(admaif->regmap); + + return 0; +} + +static int tegra_admaif_set_pack_mode(struct regmap *map, unsigned int reg, + int valid_bit) +{ + switch (valid_bit) { + case DATA_8BIT: + regmap_update_bits(map, reg, PACK8_EN_MASK, PACK8_EN); + regmap_update_bits(map, reg, PACK16_EN_MASK, 0); + break; + case DATA_16BIT: + regmap_update_bits(map, reg, PACK16_EN_MASK, PACK16_EN); + regmap_update_bits(map, reg, PACK8_EN_MASK, 0); + break; + case DATA_32BIT: + regmap_update_bits(map, reg, PACK16_EN_MASK, 0); + regmap_update_bits(map, reg, PACK8_EN_MASK, 0); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int tegra_admaif_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct device *dev = dai->dev; + struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); + struct tegra_cif_conf cif_conf; + unsigned int reg, path; + int valid_bit, channels; + + memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + cif_conf.audio_bits = TEGRA_ACIF_BITS_8; + cif_conf.client_bits = TEGRA_ACIF_BITS_8; + valid_bit = DATA_8BIT; + break; + case SNDRV_PCM_FORMAT_S16_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_16; + cif_conf.client_bits = TEGRA_ACIF_BITS_16; + valid_bit = DATA_16BIT; + break; + case SNDRV_PCM_FORMAT_S32_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_32; + cif_conf.client_bits = TEGRA_ACIF_BITS_32; + valid_bit = DATA_32BIT; + break; + default: + dev_err(dev, "unsupported format!\n"); + return -EOPNOTSUPP; + } + + channels = params_channels(params); + cif_conf.client_ch = channels; + cif_conf.audio_ch = channels; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + path = ADMAIF_TX_PATH; + reg = CH_TX_REG(TEGRA_ADMAIF_CH_ACIF_TX_CTRL, dai->id); + } else { + path = ADMAIF_RX_PATH; + reg = CH_RX_REG(TEGRA_ADMAIF_CH_ACIF_RX_CTRL, dai->id); + } + + cif_conf.mono_conv = admaif->mono_to_stereo[path][dai->id]; + cif_conf.stereo_conv = admaif->stereo_to_mono[path][dai->id]; + + tegra_admaif_set_pack_mode(admaif->regmap, reg, valid_bit); + + tegra_set_cif(admaif->regmap, reg, &cif_conf); + + return 0; +} + +static int tegra_admaif_start(struct snd_soc_dai *dai, int direction) +{ + struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); + unsigned int reg, mask, val; + + switch (direction) { + case SNDRV_PCM_STREAM_PLAYBACK: + mask = TX_ENABLE_MASK; + val = TX_ENABLE; + reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id); + break; + case SNDRV_PCM_STREAM_CAPTURE: + mask = RX_ENABLE_MASK; + val = RX_ENABLE; + reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id); + break; + default: + return -EINVAL; + } + + regmap_update_bits(admaif->regmap, reg, mask, val); + + return 0; +} + +static int tegra_admaif_stop(struct snd_soc_dai *dai, int direction) +{ + struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); + unsigned int enable_reg, status_reg, reset_reg, mask, val; + char *dir_name; + int err, enable; + + switch (direction) { + case SNDRV_PCM_STREAM_PLAYBACK: + mask = TX_ENABLE_MASK; + enable = TX_ENABLE; + dir_name = "TX"; + enable_reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id); + status_reg = CH_TX_REG(TEGRA_ADMAIF_TX_STATUS, dai->id); + reset_reg = CH_TX_REG(TEGRA_ADMAIF_TX_SOFT_RESET, dai->id); + break; + case SNDRV_PCM_STREAM_CAPTURE: + mask = RX_ENABLE_MASK; + enable = RX_ENABLE; + dir_name = "RX"; + enable_reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id); + status_reg = CH_RX_REG(TEGRA_ADMAIF_RX_STATUS, dai->id); + reset_reg = CH_RX_REG(TEGRA_ADMAIF_RX_SOFT_RESET, dai->id); + break; + default: + return -EINVAL; + } + + /* Disable TX/RX channel */ + regmap_update_bits(admaif->regmap, enable_reg, mask, ~enable); + + /* Wait until ADMAIF TX/RX status is disabled */ + err = regmap_read_poll_timeout_atomic(admaif->regmap, status_reg, val, + !(val & enable), 10, 10000); + if (err < 0) + dev_warn(dai->dev, "timeout: failed to disable ADMAIF%d_%s\n", + dai->id + 1, dir_name); + + /* SW reset */ + regmap_update_bits(admaif->regmap, reset_reg, SW_RESET_MASK, SW_RESET); + + /* Wait till SW reset is complete */ + err = regmap_read_poll_timeout_atomic(admaif->regmap, reset_reg, val, + !(val & SW_RESET_MASK & SW_RESET), + 10, 10000); + if (err) { + dev_err(dai->dev, "timeout: SW reset failed for ADMAIF%d_%s\n", + dai->id + 1, dir_name); + return err; + } + + return 0; +} + +static int tegra_admaif_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + int err; + + err = snd_dmaengine_pcm_trigger(substream, cmd); + if (err) + return err; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: + return tegra_admaif_start(dai, substream->stream); + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + return tegra_admaif_stop(dai, substream->stream); + default: + return -EINVAL; + } +} + +static const struct snd_soc_dai_ops tegra_admaif_dai_ops = { + .hw_params = tegra_admaif_hw_params, + .trigger = tegra_admaif_trigger, +}; + +static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); + long *uctl_val = &ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) + *uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]; + else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) + *uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]; + else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) + *uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]; + else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) + *uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]; + + return 0; +} + +static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); + int value = ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) + admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value; + else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) + admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value; + else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) + admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value; + else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) + admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value; + + return 0; +} + +static int tegra_admaif_dai_probe(struct snd_soc_dai *dai) +{ + struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); + + dai->capture_dma_data = &admaif->capture_dma_data[dai->id]; + dai->playback_dma_data = &admaif->playback_dma_data[dai->id]; + + return 0; +} + +#define DAI(dai_name) \ + { \ + .name = dai_name, \ + .probe = tegra_admaif_dai_probe, \ + .playback = { \ + .stream_name = dai_name " Playback", \ + .channels_min = 1, \ + .channels_max = 16, \ + .rates = SNDRV_PCM_RATE_8000_192000, \ + .formats = SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S32_LE, \ + }, \ + .capture = { \ + .stream_name = dai_name " Capture", \ + .channels_min = 1, \ + .channels_max = 16, \ + .rates = SNDRV_PCM_RATE_8000_192000, \ + .formats = SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S32_LE, \ + }, \ + .ops = &tegra_admaif_dai_ops, \ + } + +static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais[] = { + DAI("ADMAIF1"), + DAI("ADMAIF2"), + DAI("ADMAIF3"), + DAI("ADMAIF4"), + DAI("ADMAIF5"), + DAI("ADMAIF6"), + DAI("ADMAIF7"), + DAI("ADMAIF8"), + DAI("ADMAIF9"), + DAI("ADMAIF10"), +}; + +static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais[] = { + DAI("ADMAIF1"), + DAI("ADMAIF2"), + DAI("ADMAIF3"), + DAI("ADMAIF4"), + DAI("ADMAIF5"), + DAI("ADMAIF6"), + DAI("ADMAIF7"), + DAI("ADMAIF8"), + DAI("ADMAIF9"), + DAI("ADMAIF10"), + DAI("ADMAIF11"), + DAI("ADMAIF12"), + DAI("ADMAIF13"), + DAI("ADMAIF14"), + DAI("ADMAIF15"), + DAI("ADMAIF16"), + DAI("ADMAIF17"), + DAI("ADMAIF18"), + DAI("ADMAIF19"), + DAI("ADMAIF20"), +}; + +static const char * const tegra_admaif_stereo_conv_text[] = { + "CH0", "CH1", "AVG", +}; + +static const char * const tegra_admaif_mono_conv_text[] = { + "Zero", "Copy", +}; + +/* + * Below macro is added to avoid looping over all ADMAIFx controls related + * to mono/stereo conversions in get()/put() callbacks. + */ +#define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text) \ +{ \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .info = snd_soc_info_enum_double, \ + .name = xname, \ + .get = xhandler_get, \ + .put = xhandler_put, \ + .private_value = (unsigned long)&(struct soc_enum) \ + SOC_ENUM_SINGLE(xreg, 0, ARRAY_SIZE(xenum_text), xenum_text) \ +} + +#define TEGRA_ADMAIF_CIF_CTRL(reg) \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,\ + tegra_admaif_get_control, tegra_admaif_put_control, \ + tegra_admaif_mono_conv_text), \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,\ + tegra_admaif_get_control, tegra_admaif_put_control, \ + tegra_admaif_stereo_conv_text), \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ + tegra_admaif_get_control, tegra_admaif_put_control, \ + tegra_admaif_mono_conv_text), \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ + tegra_admaif_get_control, tegra_admaif_put_control, \ + tegra_admaif_stereo_conv_text) + +static struct snd_kcontrol_new tegra210_admaif_controls[] = { + TEGRA_ADMAIF_CIF_CTRL(1), + TEGRA_ADMAIF_CIF_CTRL(2), + TEGRA_ADMAIF_CIF_CTRL(3), + TEGRA_ADMAIF_CIF_CTRL(4), + TEGRA_ADMAIF_CIF_CTRL(5), + TEGRA_ADMAIF_CIF_CTRL(6), + TEGRA_ADMAIF_CIF_CTRL(7), + TEGRA_ADMAIF_CIF_CTRL(8), + TEGRA_ADMAIF_CIF_CTRL(9), + TEGRA_ADMAIF_CIF_CTRL(10), +}; + +static struct snd_kcontrol_new tegra186_admaif_controls[] = { + TEGRA_ADMAIF_CIF_CTRL(1), + TEGRA_ADMAIF_CIF_CTRL(2), + TEGRA_ADMAIF_CIF_CTRL(3), + TEGRA_ADMAIF_CIF_CTRL(4), + TEGRA_ADMAIF_CIF_CTRL(5), + TEGRA_ADMAIF_CIF_CTRL(6), + TEGRA_ADMAIF_CIF_CTRL(7), + TEGRA_ADMAIF_CIF_CTRL(8), + TEGRA_ADMAIF_CIF_CTRL(9), + TEGRA_ADMAIF_CIF_CTRL(10), + TEGRA_ADMAIF_CIF_CTRL(11), + TEGRA_ADMAIF_CIF_CTRL(12), + TEGRA_ADMAIF_CIF_CTRL(13), + TEGRA_ADMAIF_CIF_CTRL(14), + TEGRA_ADMAIF_CIF_CTRL(15), + TEGRA_ADMAIF_CIF_CTRL(16), + TEGRA_ADMAIF_CIF_CTRL(17), + TEGRA_ADMAIF_CIF_CTRL(18), + TEGRA_ADMAIF_CIF_CTRL(19), + TEGRA_ADMAIF_CIF_CTRL(20), +}; + +static const struct snd_soc_component_driver tegra210_admaif_cmpnt = { + .controls = tegra210_admaif_controls, + .num_controls = ARRAY_SIZE(tegra210_admaif_controls), + .pcm_construct = tegra_pcm_construct, + .pcm_destruct = tegra_pcm_destruct, + .open = tegra_pcm_open, + .close = tegra_pcm_close, + .hw_params = tegra_pcm_hw_params, + .hw_free = tegra_pcm_hw_free, + .mmap = tegra_pcm_mmap, + .pointer = tegra_pcm_pointer, +}; + +static const struct snd_soc_component_driver tegra186_admaif_cmpnt = { + .controls = tegra186_admaif_controls, + .num_controls = ARRAY_SIZE(tegra186_admaif_controls), + .pcm_construct = tegra_pcm_construct, + .pcm_destruct = tegra_pcm_destruct, + .open = tegra_pcm_open, + .close = tegra_pcm_close, + .hw_params = tegra_pcm_hw_params, + .hw_free = tegra_pcm_hw_free, + .mmap = tegra_pcm_mmap, + .pointer = tegra_pcm_pointer, +}; + +static const struct tegra_admaif_soc_data soc_data_tegra210 = { + .num_ch = TEGRA210_ADMAIF_CHANNEL_COUNT, + .cmpnt = &tegra210_admaif_cmpnt, + .dais = tegra210_admaif_cmpnt_dais, + .regmap_conf = &tegra210_admaif_regmap_config, + .global_base = TEGRA210_ADMAIF_GLOBAL_BASE, + .tx_base = TEGRA210_ADMAIF_TX_BASE, + .rx_base = TEGRA210_ADMAIF_RX_BASE, +}; + +static const struct tegra_admaif_soc_data soc_data_tegra186 = { + .num_ch = TEGRA186_ADMAIF_CHANNEL_COUNT, + .cmpnt = &tegra186_admaif_cmpnt, + .dais = tegra186_admaif_cmpnt_dais, + .regmap_conf = &tegra186_admaif_regmap_config, + .global_base = TEGRA186_ADMAIF_GLOBAL_BASE, + .tx_base = TEGRA186_ADMAIF_TX_BASE, + .rx_base = TEGRA186_ADMAIF_RX_BASE, +}; + +static const struct of_device_id tegra_admaif_of_match[] = { + { .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 }, + { .compatible = "nvidia,tegra186-admaif", .data = &soc_data_tegra186 }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra_admaif_of_match); + +static int tegra_admaif_probe(struct platform_device *pdev) +{ + struct tegra_admaif *admaif; + void __iomem *regs; + struct resource *res; + int err, i; + + admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL); + if (!admaif) + return -ENOMEM; + + admaif->soc_data = of_device_get_match_data(&pdev->dev); + + dev_set_drvdata(&pdev->dev, admaif); + + admaif->capture_dma_data = + devm_kcalloc(&pdev->dev, + admaif->soc_data->num_ch, + sizeof(struct snd_dmaengine_dai_dma_data), + GFP_KERNEL); + if (!admaif->capture_dma_data) + return -ENOMEM; + + admaif->playback_dma_data = + devm_kcalloc(&pdev->dev, + admaif->soc_data->num_ch, + sizeof(struct snd_dmaengine_dai_dma_data), + GFP_KERNEL); + if (!admaif->playback_dma_data) + return -ENOMEM; + + for (i = 0; i < ADMAIF_PATHS; i++) { + admaif->mono_to_stereo[i] = + devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch, + sizeof(unsigned int), GFP_KERNEL); + if (!admaif->mono_to_stereo[i]) + return -ENOMEM; + + admaif->stereo_to_mono[i] = + devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch, + sizeof(unsigned int), GFP_KERNEL); + if (!admaif->stereo_to_mono[i]) + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + admaif->regmap = devm_regmap_init_mmio(&pdev->dev, regs, + admaif->soc_data->regmap_conf); + if (IS_ERR(admaif->regmap)) { + dev_err(&pdev->dev, "regmap init failed\n"); + return PTR_ERR(admaif->regmap); + } + + regcache_cache_only(admaif->regmap, true); + + regmap_update_bits(admaif->regmap, admaif->soc_data->global_base + + TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1); + + for (i = 0; i < admaif->soc_data->num_ch; i++) { + admaif->playback_dma_data[i].addr = res->start + + CH_TX_REG(TEGRA_ADMAIF_TX_FIFO_WRITE, i); + + admaif->capture_dma_data[i].addr = res->start + + CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ, i); + + admaif->playback_dma_data[i].addr_width = 32; + + if (of_property_read_string_index(pdev->dev.of_node, + "dma-names", (i * 2) + 1, + &admaif->playback_dma_data[i].chan_name) < 0) { + dev_err(&pdev->dev, + "missing property nvidia,dma-names\n"); + + return -ENODEV; + } + + admaif->capture_dma_data[i].addr_width = 32; + + if (of_property_read_string_index(pdev->dev.of_node, + "dma-names", + (i * 2), + &admaif->capture_dma_data[i].chan_name) < 0) { + dev_err(&pdev->dev, + "missing property nvidia,dma-names\n"); + + return -ENODEV; + } + } + + err = devm_snd_soc_register_component(&pdev->dev, + admaif->soc_data->cmpnt, + admaif->soc_data->dais, + admaif->soc_data->num_ch); + if (err) { + dev_err(&pdev->dev, + "can't register ADMAIF component, err: %d\n", err); + return err; + } + + pm_runtime_enable(&pdev->dev); + + return 0; +} + +static int tegra_admaif_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops tegra_admaif_pm_ops = { + SET_RUNTIME_PM_OPS(tegra_admaif_runtime_suspend, + tegra_admaif_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver tegra_admaif_driver = { + .probe = tegra_admaif_probe, + .remove = tegra_admaif_remove, + .driver = { + .name = "tegra210-admaif", + .of_match_table = tegra_admaif_of_match, + .pm = &tegra_admaif_pm_ops, + }, +}; +module_platform_driver(tegra_admaif_driver); + +MODULE_AUTHOR("Songhee Baek "); +MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/tegra/tegra210_admaif.h b/sound/soc/tegra/tegra210_admaif.h new file mode 100644 index 0000000000000000000000000000000000000000..96686dc92081dada9d1536c8bf57f2e704cc7b12 --- /dev/null +++ b/sound/soc/tegra/tegra210_admaif.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra210_admaif.h - Tegra ADMAIF registers + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA_ADMAIF_H__ +#define __TEGRA_ADMAIF_H__ + +#define TEGRA_ADMAIF_CHANNEL_REG_STRIDE 0x40 +/* Tegra210 specific */ +#define TEGRA210_ADMAIF_LAST_REG 0x75f +#define TEGRA210_ADMAIF_CHANNEL_COUNT 10 +#define TEGRA210_ADMAIF_RX_BASE 0x0 +#define TEGRA210_ADMAIF_TX_BASE 0x300 +#define TEGRA210_ADMAIF_GLOBAL_BASE 0x700 +/* Tegra186 specific */ +#define TEGRA186_ADMAIF_LAST_REG 0xd5f +#define TEGRA186_ADMAIF_CHANNEL_COUNT 20 +#define TEGRA186_ADMAIF_RX_BASE 0x0 +#define TEGRA186_ADMAIF_TX_BASE 0x500 +#define TEGRA186_ADMAIF_GLOBAL_BASE 0xd00 +/* Global registers */ +#define TEGRA_ADMAIF_GLOBAL_ENABLE 0x0 +#define TEGRA_ADMAIF_GLOBAL_CG_0 0x8 +#define TEGRA_ADMAIF_GLOBAL_STATUS 0x10 +#define TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS 0x20 +#define TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS 0x24 +/* RX channel registers */ +#define TEGRA_ADMAIF_RX_ENABLE 0x0 +#define TEGRA_ADMAIF_RX_SOFT_RESET 0x4 +#define TEGRA_ADMAIF_RX_STATUS 0xc +#define TEGRA_ADMAIF_RX_INT_STATUS 0x10 +#define TEGRA_ADMAIF_RX_INT_MASK 0x14 +#define TEGRA_ADMAIF_RX_INT_SET 0x18 +#define TEGRA_ADMAIF_RX_INT_CLEAR 0x1c +#define TEGRA_ADMAIF_CH_ACIF_RX_CTRL 0x20 +#define TEGRA_ADMAIF_RX_FIFO_CTRL 0x28 +#define TEGRA_ADMAIF_RX_FIFO_READ 0x2c +/* TX channel registers */ +#define TEGRA_ADMAIF_TX_ENABLE 0x0 +#define TEGRA_ADMAIF_TX_SOFT_RESET 0x4 +#define TEGRA_ADMAIF_TX_STATUS 0xc +#define TEGRA_ADMAIF_TX_INT_STATUS 0x10 +#define TEGRA_ADMAIF_TX_INT_MASK 0x14 +#define TEGRA_ADMAIF_TX_INT_SET 0x18 +#define TEGRA_ADMAIF_TX_INT_CLEAR 0x1c +#define TEGRA_ADMAIF_CH_ACIF_TX_CTRL 0x20 +#define TEGRA_ADMAIF_TX_FIFO_CTRL 0x28 +#define TEGRA_ADMAIF_TX_FIFO_WRITE 0x2c +/* Bit fields */ +#define PACK8_EN_SHIFT 31 +#define PACK8_EN_MASK BIT(PACK8_EN_SHIFT) +#define PACK8_EN BIT(PACK8_EN_SHIFT) +#define PACK16_EN_SHIFT 30 +#define PACK16_EN_MASK BIT(PACK16_EN_SHIFT) +#define PACK16_EN BIT(PACK16_EN_SHIFT) +#define TX_ENABLE_SHIFT 0 +#define TX_ENABLE_MASK BIT(TX_ENABLE_SHIFT) +#define TX_ENABLE BIT(TX_ENABLE_SHIFT) +#define RX_ENABLE_SHIFT 0 +#define RX_ENABLE_MASK BIT(RX_ENABLE_SHIFT) +#define RX_ENABLE BIT(RX_ENABLE_SHIFT) +#define SW_RESET_MASK 1 +#define SW_RESET 1 +/* Default values - Tegra210 */ +#define TEGRA210_ADMAIF_RX1_FIFO_CTRL_REG_DEFAULT 0x00000300 +#define TEGRA210_ADMAIF_RX2_FIFO_CTRL_REG_DEFAULT 0x00000304 +#define TEGRA210_ADMAIF_RX3_FIFO_CTRL_REG_DEFAULT 0x00000208 +#define TEGRA210_ADMAIF_RX4_FIFO_CTRL_REG_DEFAULT 0x0000020b +#define TEGRA210_ADMAIF_RX5_FIFO_CTRL_REG_DEFAULT 0x0000020e +#define TEGRA210_ADMAIF_RX6_FIFO_CTRL_REG_DEFAULT 0x00000211 +#define TEGRA210_ADMAIF_RX7_FIFO_CTRL_REG_DEFAULT 0x00000214 +#define TEGRA210_ADMAIF_RX8_FIFO_CTRL_REG_DEFAULT 0x00000217 +#define TEGRA210_ADMAIF_RX9_FIFO_CTRL_REG_DEFAULT 0x0000021a +#define TEGRA210_ADMAIF_RX10_FIFO_CTRL_REG_DEFAULT 0x0000021d +#define TEGRA210_ADMAIF_TX1_FIFO_CTRL_REG_DEFAULT 0x02000300 +#define TEGRA210_ADMAIF_TX2_FIFO_CTRL_REG_DEFAULT 0x02000304 +#define TEGRA210_ADMAIF_TX3_FIFO_CTRL_REG_DEFAULT 0x01800208 +#define TEGRA210_ADMAIF_TX4_FIFO_CTRL_REG_DEFAULT 0x0180020b +#define TEGRA210_ADMAIF_TX5_FIFO_CTRL_REG_DEFAULT 0x0180020e +#define TEGRA210_ADMAIF_TX6_FIFO_CTRL_REG_DEFAULT 0x01800211 +#define TEGRA210_ADMAIF_TX7_FIFO_CTRL_REG_DEFAULT 0x01800214 +#define TEGRA210_ADMAIF_TX8_FIFO_CTRL_REG_DEFAULT 0x01800217 +#define TEGRA210_ADMAIF_TX9_FIFO_CTRL_REG_DEFAULT 0x0180021a +#define TEGRA210_ADMAIF_TX10_FIFO_CTRL_REG_DEFAULT 0x0180021d +/* Default values - Tegra186 */ +#define TEGRA186_ADMAIF_RX1_FIFO_CTRL_REG_DEFAULT 0x00000300 +#define TEGRA186_ADMAIF_RX2_FIFO_CTRL_REG_DEFAULT 0x00000304 +#define TEGRA186_ADMAIF_RX3_FIFO_CTRL_REG_DEFAULT 0x00000308 +#define TEGRA186_ADMAIF_RX4_FIFO_CTRL_REG_DEFAULT 0x0000030c +#define TEGRA186_ADMAIF_RX5_FIFO_CTRL_REG_DEFAULT 0x00000210 +#define TEGRA186_ADMAIF_RX6_FIFO_CTRL_REG_DEFAULT 0x00000213 +#define TEGRA186_ADMAIF_RX7_FIFO_CTRL_REG_DEFAULT 0x00000216 +#define TEGRA186_ADMAIF_RX8_FIFO_CTRL_REG_DEFAULT 0x00000219 +#define TEGRA186_ADMAIF_RX9_FIFO_CTRL_REG_DEFAULT 0x0000021c +#define TEGRA186_ADMAIF_RX10_FIFO_CTRL_REG_DEFAULT 0x0000021f +#define TEGRA186_ADMAIF_RX11_FIFO_CTRL_REG_DEFAULT 0x00000222 +#define TEGRA186_ADMAIF_RX12_FIFO_CTRL_REG_DEFAULT 0x00000225 +#define TEGRA186_ADMAIF_RX13_FIFO_CTRL_REG_DEFAULT 0x00000228 +#define TEGRA186_ADMAIF_RX14_FIFO_CTRL_REG_DEFAULT 0x0000022b +#define TEGRA186_ADMAIF_RX15_FIFO_CTRL_REG_DEFAULT 0x0000022e +#define TEGRA186_ADMAIF_RX16_FIFO_CTRL_REG_DEFAULT 0x00000231 +#define TEGRA186_ADMAIF_RX17_FIFO_CTRL_REG_DEFAULT 0x00000234 +#define TEGRA186_ADMAIF_RX18_FIFO_CTRL_REG_DEFAULT 0x00000237 +#define TEGRA186_ADMAIF_RX19_FIFO_CTRL_REG_DEFAULT 0x0000023a +#define TEGRA186_ADMAIF_RX20_FIFO_CTRL_REG_DEFAULT 0x0000023d +#define TEGRA186_ADMAIF_TX1_FIFO_CTRL_REG_DEFAULT 0x02000300 +#define TEGRA186_ADMAIF_TX2_FIFO_CTRL_REG_DEFAULT 0x02000304 +#define TEGRA186_ADMAIF_TX3_FIFO_CTRL_REG_DEFAULT 0x02000308 +#define TEGRA186_ADMAIF_TX4_FIFO_CTRL_REG_DEFAULT 0x0200030c +#define TEGRA186_ADMAIF_TX5_FIFO_CTRL_REG_DEFAULT 0x01800210 +#define TEGRA186_ADMAIF_TX6_FIFO_CTRL_REG_DEFAULT 0x01800213 +#define TEGRA186_ADMAIF_TX7_FIFO_CTRL_REG_DEFAULT 0x01800216 +#define TEGRA186_ADMAIF_TX8_FIFO_CTRL_REG_DEFAULT 0x01800219 +#define TEGRA186_ADMAIF_TX9_FIFO_CTRL_REG_DEFAULT 0x0180021c +#define TEGRA186_ADMAIF_TX10_FIFO_CTRL_REG_DEFAULT 0x0180021f +#define TEGRA186_ADMAIF_TX11_FIFO_CTRL_REG_DEFAULT 0x01800222 +#define TEGRA186_ADMAIF_TX12_FIFO_CTRL_REG_DEFAULT 0x01800225 +#define TEGRA186_ADMAIF_TX13_FIFO_CTRL_REG_DEFAULT 0x01800228 +#define TEGRA186_ADMAIF_TX14_FIFO_CTRL_REG_DEFAULT 0x0180022b +#define TEGRA186_ADMAIF_TX15_FIFO_CTRL_REG_DEFAULT 0x0180022e +#define TEGRA186_ADMAIF_TX16_FIFO_CTRL_REG_DEFAULT 0x01800231 +#define TEGRA186_ADMAIF_TX17_FIFO_CTRL_REG_DEFAULT 0x01800234 +#define TEGRA186_ADMAIF_TX18_FIFO_CTRL_REG_DEFAULT 0x01800237 +#define TEGRA186_ADMAIF_TX19_FIFO_CTRL_REG_DEFAULT 0x0180023a +#define TEGRA186_ADMAIF_TX20_FIFO_CTRL_REG_DEFAULT 0x0180023d + +enum { + DATA_8BIT, + DATA_16BIT, + DATA_32BIT +}; + +enum { + ADMAIF_RX_PATH, + ADMAIF_TX_PATH, + ADMAIF_PATHS, +}; + +struct tegra_admaif_soc_data { + const struct snd_soc_component_driver *cmpnt; + const struct regmap_config *regmap_conf; + struct snd_soc_dai_driver *dais; + unsigned int global_base; + unsigned int tx_base; + unsigned int rx_base; + unsigned int num_ch; +}; + +struct tegra_admaif { + struct snd_dmaengine_dai_dma_data *capture_dma_data; + struct snd_dmaengine_dai_dma_data *playback_dma_data; + const struct tegra_admaif_soc_data *soc_data; + unsigned int *mono_to_stereo[ADMAIF_PATHS]; + unsigned int *stereo_to_mono[ADMAIF_PATHS]; + struct regmap *regmap; +}; + +#endif diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c new file mode 100644 index 0000000000000000000000000000000000000000..5123a96fdde8f8f6a6d161cc9e198129ea595ecf --- /dev/null +++ b/sound/soc/tegra/tegra210_ahub.c @@ -0,0 +1,676 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra210_ahub.c - Tegra210 AHUB driver +// +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include "tegra210_ahub.h" + +static int tegra_ahub_get_value_enum(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *uctl) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_kcontrol_component(kctl); + struct tegra_ahub *ahub = snd_soc_component_get_drvdata(cmpnt); + struct soc_enum *e = (struct soc_enum *)kctl->private_value; + unsigned int reg, i, bit_pos = 0; + + /* + * Find the bit position of current MUX input. + * If nothing is set, position would be 0 and it corresponds to 'None'. + */ + for (i = 0; i < ahub->soc_data->reg_count; i++) { + unsigned int reg_val; + + reg = e->reg + (TEGRA210_XBAR_PART1_RX * i); + reg_val = snd_soc_component_read(cmpnt, reg); + reg_val &= ahub->soc_data->mask[i]; + + if (reg_val) { + bit_pos = ffs(reg_val) + + (8 * cmpnt->val_bytes * i); + break; + } + } + + /* Find index related to the item in array *_ahub_mux_texts[] */ + for (i = 0; i < e->items; i++) { + if (bit_pos == e->values[i]) { + uctl->value.enumerated.item[0] = i; + break; + } + } + + return 0; +} + +static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *uctl) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_kcontrol_component(kctl); + struct tegra_ahub *ahub = snd_soc_component_get_drvdata(cmpnt); + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctl); + struct soc_enum *e = (struct soc_enum *)kctl->private_value; + struct snd_soc_dapm_update update[TEGRA_XBAR_UPDATE_MAX_REG] = { }; + unsigned int *item = uctl->value.enumerated.item; + unsigned int value = e->values[item[0]]; + unsigned int i, bit_pos, reg_idx = 0, reg_val = 0; + + if (item[0] >= e->items) + return -EINVAL; + + if (value) { + /* Get the register index and value to set */ + reg_idx = (value - 1) / (8 * cmpnt->val_bytes); + bit_pos = (value - 1) % (8 * cmpnt->val_bytes); + reg_val = BIT(bit_pos); + } + + /* + * Run through all parts of a MUX register to find the state changes. + * There will be an additional update if new MUX input value is from + * different part of the MUX register. + */ + for (i = 0; i < ahub->soc_data->reg_count; i++) { + update[i].reg = e->reg + (TEGRA210_XBAR_PART1_RX * i); + update[i].val = (i == reg_idx) ? reg_val : 0; + update[i].mask = ahub->soc_data->mask[i]; + update[i].kcontrol = kctl; + + /* Update widget power if state has changed */ + if (snd_soc_component_test_bits(cmpnt, update[i].reg, + update[i].mask, update[i].val)) + snd_soc_dapm_mux_update_power(dapm, kctl, item[0], e, + &update[i]); + } + + return 0; +} + +static struct snd_soc_dai_driver tegra210_ahub_dais[] = { + DAI(ADMAIF1), + DAI(ADMAIF2), + DAI(ADMAIF3), + DAI(ADMAIF4), + DAI(ADMAIF5), + DAI(ADMAIF6), + DAI(ADMAIF7), + DAI(ADMAIF8), + DAI(ADMAIF9), + DAI(ADMAIF10), + DAI(I2S1), + DAI(I2S2), + DAI(I2S3), + DAI(I2S4), + DAI(I2S5), + DAI(DMIC1), + DAI(DMIC2), + DAI(DMIC3), +}; + +static struct snd_soc_dai_driver tegra186_ahub_dais[] = { + DAI(ADMAIF1), + DAI(ADMAIF2), + DAI(ADMAIF3), + DAI(ADMAIF4), + DAI(ADMAIF5), + DAI(ADMAIF6), + DAI(ADMAIF7), + DAI(ADMAIF8), + DAI(ADMAIF9), + DAI(ADMAIF10), + DAI(ADMAIF11), + DAI(ADMAIF12), + DAI(ADMAIF13), + DAI(ADMAIF14), + DAI(ADMAIF15), + DAI(ADMAIF16), + DAI(ADMAIF17), + DAI(ADMAIF18), + DAI(ADMAIF19), + DAI(ADMAIF20), + DAI(I2S1), + DAI(I2S2), + DAI(I2S3), + DAI(I2S4), + DAI(I2S5), + DAI(I2S6), + DAI(DMIC1), + DAI(DMIC2), + DAI(DMIC3), + DAI(DMIC4), + DAI(DSPK1), + DAI(DSPK2), +}; + +static const char * const tegra210_ahub_mux_texts[] = { + "None", + "ADMAIF1", + "ADMAIF2", + "ADMAIF3", + "ADMAIF4", + "ADMAIF5", + "ADMAIF6", + "ADMAIF7", + "ADMAIF8", + "ADMAIF9", + "ADMAIF10", + "I2S1", + "I2S2", + "I2S3", + "I2S4", + "I2S5", + "DMIC1", + "DMIC2", + "DMIC3", +}; + +static const char * const tegra186_ahub_mux_texts[] = { + "None", + "ADMAIF1", + "ADMAIF2", + "ADMAIF3", + "ADMAIF4", + "ADMAIF5", + "ADMAIF6", + "ADMAIF7", + "ADMAIF8", + "ADMAIF9", + "ADMAIF10", + "ADMAIF11", + "ADMAIF12", + "ADMAIF13", + "ADMAIF14", + "ADMAIF15", + "ADMAIF16", + "I2S1", + "I2S2", + "I2S3", + "I2S4", + "I2S5", + "I2S6", + "ADMAIF17", + "ADMAIF18", + "ADMAIF19", + "ADMAIF20", + "DMIC1", + "DMIC2", + "DMIC3", + "DMIC4", +}; + +static const unsigned int tegra210_ahub_mux_values[] = { + 0, + MUX_VALUE(0, 0), + MUX_VALUE(0, 1), + MUX_VALUE(0, 2), + MUX_VALUE(0, 3), + MUX_VALUE(0, 4), + MUX_VALUE(0, 5), + MUX_VALUE(0, 6), + MUX_VALUE(0, 7), + MUX_VALUE(0, 8), + MUX_VALUE(0, 9), + MUX_VALUE(0, 16), + MUX_VALUE(0, 17), + MUX_VALUE(0, 18), + MUX_VALUE(0, 19), + MUX_VALUE(0, 20), + MUX_VALUE(2, 18), + MUX_VALUE(2, 19), + MUX_VALUE(2, 20), +}; + +static const unsigned int tegra186_ahub_mux_values[] = { + 0, + MUX_VALUE(0, 0), + MUX_VALUE(0, 1), + MUX_VALUE(0, 2), + MUX_VALUE(0, 3), + MUX_VALUE(0, 4), + MUX_VALUE(0, 5), + MUX_VALUE(0, 6), + MUX_VALUE(0, 7), + MUX_VALUE(0, 8), + MUX_VALUE(0, 9), + MUX_VALUE(0, 10), + MUX_VALUE(0, 11), + MUX_VALUE(0, 12), + MUX_VALUE(0, 13), + MUX_VALUE(0, 14), + MUX_VALUE(0, 15), + MUX_VALUE(0, 16), + MUX_VALUE(0, 17), + MUX_VALUE(0, 18), + MUX_VALUE(0, 19), + MUX_VALUE(0, 20), + MUX_VALUE(0, 21), + MUX_VALUE(3, 16), + MUX_VALUE(3, 17), + MUX_VALUE(3, 18), + MUX_VALUE(3, 19), + MUX_VALUE(2, 18), + MUX_VALUE(2, 19), + MUX_VALUE(2, 20), + MUX_VALUE(2, 21), +}; + +/* Controls for t210 */ +MUX_ENUM_CTRL_DECL(t210_admaif1_tx, 0x00); +MUX_ENUM_CTRL_DECL(t210_admaif2_tx, 0x01); +MUX_ENUM_CTRL_DECL(t210_admaif3_tx, 0x02); +MUX_ENUM_CTRL_DECL(t210_admaif4_tx, 0x03); +MUX_ENUM_CTRL_DECL(t210_admaif5_tx, 0x04); +MUX_ENUM_CTRL_DECL(t210_admaif6_tx, 0x05); +MUX_ENUM_CTRL_DECL(t210_admaif7_tx, 0x06); +MUX_ENUM_CTRL_DECL(t210_admaif8_tx, 0x07); +MUX_ENUM_CTRL_DECL(t210_admaif9_tx, 0x08); +MUX_ENUM_CTRL_DECL(t210_admaif10_tx, 0x09); +MUX_ENUM_CTRL_DECL(t210_i2s1_tx, 0x10); +MUX_ENUM_CTRL_DECL(t210_i2s2_tx, 0x11); +MUX_ENUM_CTRL_DECL(t210_i2s3_tx, 0x12); +MUX_ENUM_CTRL_DECL(t210_i2s4_tx, 0x13); +MUX_ENUM_CTRL_DECL(t210_i2s5_tx, 0x14); + +/* Controls for t186 */ +MUX_ENUM_CTRL_DECL_186(t186_admaif1_tx, 0x00); +MUX_ENUM_CTRL_DECL_186(t186_admaif2_tx, 0x01); +MUX_ENUM_CTRL_DECL_186(t186_admaif3_tx, 0x02); +MUX_ENUM_CTRL_DECL_186(t186_admaif4_tx, 0x03); +MUX_ENUM_CTRL_DECL_186(t186_admaif5_tx, 0x04); +MUX_ENUM_CTRL_DECL_186(t186_admaif6_tx, 0x05); +MUX_ENUM_CTRL_DECL_186(t186_admaif7_tx, 0x06); +MUX_ENUM_CTRL_DECL_186(t186_admaif8_tx, 0x07); +MUX_ENUM_CTRL_DECL_186(t186_admaif9_tx, 0x08); +MUX_ENUM_CTRL_DECL_186(t186_admaif10_tx, 0x09); +MUX_ENUM_CTRL_DECL_186(t186_i2s1_tx, 0x10); +MUX_ENUM_CTRL_DECL_186(t186_i2s2_tx, 0x11); +MUX_ENUM_CTRL_DECL_186(t186_i2s3_tx, 0x12); +MUX_ENUM_CTRL_DECL_186(t186_i2s4_tx, 0x13); +MUX_ENUM_CTRL_DECL_186(t186_i2s5_tx, 0x14); +MUX_ENUM_CTRL_DECL_186(t186_admaif11_tx, 0x0a); +MUX_ENUM_CTRL_DECL_186(t186_admaif12_tx, 0x0b); +MUX_ENUM_CTRL_DECL_186(t186_admaif13_tx, 0x0c); +MUX_ENUM_CTRL_DECL_186(t186_admaif14_tx, 0x0d); +MUX_ENUM_CTRL_DECL_186(t186_admaif15_tx, 0x0e); +MUX_ENUM_CTRL_DECL_186(t186_admaif16_tx, 0x0f); +MUX_ENUM_CTRL_DECL_186(t186_i2s6_tx, 0x15); +MUX_ENUM_CTRL_DECL_186(t186_dspk1_tx, 0x30); +MUX_ENUM_CTRL_DECL_186(t186_dspk2_tx, 0x31); +MUX_ENUM_CTRL_DECL_186(t186_admaif17_tx, 0x68); +MUX_ENUM_CTRL_DECL_186(t186_admaif18_tx, 0x69); +MUX_ENUM_CTRL_DECL_186(t186_admaif19_tx, 0x6a); +MUX_ENUM_CTRL_DECL_186(t186_admaif20_tx, 0x6b); + +/* + * The number of entries in, and order of, this array is closely tied to the + * calculation of tegra210_ahub_codec.num_dapm_widgets near the end of + * tegra210_ahub_probe() + */ +static const struct snd_soc_dapm_widget tegra210_ahub_widgets[] = { + WIDGETS("ADMAIF1", t210_admaif1_tx), + WIDGETS("ADMAIF2", t210_admaif2_tx), + WIDGETS("ADMAIF3", t210_admaif3_tx), + WIDGETS("ADMAIF4", t210_admaif4_tx), + WIDGETS("ADMAIF5", t210_admaif5_tx), + WIDGETS("ADMAIF6", t210_admaif6_tx), + WIDGETS("ADMAIF7", t210_admaif7_tx), + WIDGETS("ADMAIF8", t210_admaif8_tx), + WIDGETS("ADMAIF9", t210_admaif9_tx), + WIDGETS("ADMAIF10", t210_admaif10_tx), + WIDGETS("I2S1", t210_i2s1_tx), + WIDGETS("I2S2", t210_i2s2_tx), + WIDGETS("I2S3", t210_i2s3_tx), + WIDGETS("I2S4", t210_i2s4_tx), + WIDGETS("I2S5", t210_i2s5_tx), + TX_WIDGETS("DMIC1"), + TX_WIDGETS("DMIC2"), + TX_WIDGETS("DMIC3"), +}; + +static const struct snd_soc_dapm_widget tegra186_ahub_widgets[] = { + WIDGETS("ADMAIF1", t186_admaif1_tx), + WIDGETS("ADMAIF2", t186_admaif2_tx), + WIDGETS("ADMAIF3", t186_admaif3_tx), + WIDGETS("ADMAIF4", t186_admaif4_tx), + WIDGETS("ADMAIF5", t186_admaif5_tx), + WIDGETS("ADMAIF6", t186_admaif6_tx), + WIDGETS("ADMAIF7", t186_admaif7_tx), + WIDGETS("ADMAIF8", t186_admaif8_tx), + WIDGETS("ADMAIF9", t186_admaif9_tx), + WIDGETS("ADMAIF10", t186_admaif10_tx), + WIDGETS("ADMAIF11", t186_admaif11_tx), + WIDGETS("ADMAIF12", t186_admaif12_tx), + WIDGETS("ADMAIF13", t186_admaif13_tx), + WIDGETS("ADMAIF14", t186_admaif14_tx), + WIDGETS("ADMAIF15", t186_admaif15_tx), + WIDGETS("ADMAIF16", t186_admaif16_tx), + WIDGETS("ADMAIF17", t186_admaif17_tx), + WIDGETS("ADMAIF18", t186_admaif18_tx), + WIDGETS("ADMAIF19", t186_admaif19_tx), + WIDGETS("ADMAIF20", t186_admaif20_tx), + WIDGETS("I2S1", t186_i2s1_tx), + WIDGETS("I2S2", t186_i2s2_tx), + WIDGETS("I2S3", t186_i2s3_tx), + WIDGETS("I2S4", t186_i2s4_tx), + WIDGETS("I2S5", t186_i2s5_tx), + WIDGETS("I2S6", t186_i2s6_tx), + TX_WIDGETS("DMIC1"), + TX_WIDGETS("DMIC2"), + TX_WIDGETS("DMIC3"), + TX_WIDGETS("DMIC4"), + WIDGETS("DSPK1", t186_dspk1_tx), + WIDGETS("DSPK2", t186_dspk2_tx), +}; + +#define TEGRA_COMMON_MUX_ROUTES(name) \ + { name " XBAR-TX", NULL, name " Mux" }, \ + { name " Mux", "ADMAIF1", "ADMAIF1 XBAR-RX" }, \ + { name " Mux", "ADMAIF2", "ADMAIF2 XBAR-RX" }, \ + { name " Mux", "ADMAIF3", "ADMAIF3 XBAR-RX" }, \ + { name " Mux", "ADMAIF4", "ADMAIF4 XBAR-RX" }, \ + { name " Mux", "ADMAIF5", "ADMAIF5 XBAR-RX" }, \ + { name " Mux", "ADMAIF6", "ADMAIF6 XBAR-RX" }, \ + { name " Mux", "ADMAIF7", "ADMAIF7 XBAR-RX" }, \ + { name " Mux", "ADMAIF8", "ADMAIF8 XBAR-RX" }, \ + { name " Mux", "ADMAIF9", "ADMAIF9 XBAR-RX" }, \ + { name " Mux", "ADMAIF10", "ADMAIF10 XBAR-RX" }, \ + { name " Mux", "I2S1", "I2S1 XBAR-RX" }, \ + { name " Mux", "I2S2", "I2S2 XBAR-RX" }, \ + { name " Mux", "I2S3", "I2S3 XBAR-RX" }, \ + { name " Mux", "I2S4", "I2S4 XBAR-RX" }, \ + { name " Mux", "I2S5", "I2S5 XBAR-RX" }, \ + { name " Mux", "DMIC1", "DMIC1 XBAR-RX" }, \ + { name " Mux", "DMIC2", "DMIC2 XBAR-RX" }, \ + { name " Mux", "DMIC3", "DMIC3 XBAR-RX" }, + +#define TEGRA186_ONLY_MUX_ROUTES(name) \ + { name " Mux", "ADMAIF11", "ADMAIF11 XBAR-RX" }, \ + { name " Mux", "ADMAIF12", "ADMAIF12 XBAR-RX" }, \ + { name " Mux", "ADMAIF13", "ADMAIF13 XBAR-RX" }, \ + { name " Mux", "ADMAIF14", "ADMAIF14 XBAR-RX" }, \ + { name " Mux", "ADMAIF15", "ADMAIF15 XBAR-RX" }, \ + { name " Mux", "ADMAIF16", "ADMAIF16 XBAR-RX" }, \ + { name " Mux", "ADMAIF17", "ADMAIF17 XBAR-RX" }, \ + { name " Mux", "ADMAIF18", "ADMAIF18 XBAR-RX" }, \ + { name " Mux", "ADMAIF19", "ADMAIF19 XBAR-RX" }, \ + { name " Mux", "ADMAIF20", "ADMAIF20 XBAR-RX" }, \ + { name " Mux", "I2S6", "I2S6 XBAR-RX" }, \ + { name " Mux", "DMIC4", "DMIC4 XBAR-RX" }, + +#define TEGRA210_MUX_ROUTES(name) \ + TEGRA_COMMON_MUX_ROUTES(name) + +#define TEGRA186_MUX_ROUTES(name) \ + TEGRA_COMMON_MUX_ROUTES(name) \ + TEGRA186_ONLY_MUX_ROUTES(name) + +/* Connect FEs with XBAR */ +#define TEGRA_FE_ROUTES(name) \ + { name " XBAR-Playback", NULL, name " Playback" }, \ + { name " XBAR-RX", NULL, name " XBAR-Playback"}, \ + { name " XBAR-Capture", NULL, name " XBAR-TX" }, \ + { name " Capture", NULL, name " XBAR-Capture" }, + +/* + * The number of entries in, and order of, this array is closely tied to the + * calculation of tegra210_ahub_codec.num_dapm_routes near the end of + * tegra210_ahub_probe() + */ +static const struct snd_soc_dapm_route tegra210_ahub_routes[] = { + TEGRA_FE_ROUTES("ADMAIF1") + TEGRA_FE_ROUTES("ADMAIF2") + TEGRA_FE_ROUTES("ADMAIF3") + TEGRA_FE_ROUTES("ADMAIF4") + TEGRA_FE_ROUTES("ADMAIF5") + TEGRA_FE_ROUTES("ADMAIF6") + TEGRA_FE_ROUTES("ADMAIF7") + TEGRA_FE_ROUTES("ADMAIF8") + TEGRA_FE_ROUTES("ADMAIF9") + TEGRA_FE_ROUTES("ADMAIF10") + TEGRA210_MUX_ROUTES("ADMAIF1") + TEGRA210_MUX_ROUTES("ADMAIF2") + TEGRA210_MUX_ROUTES("ADMAIF3") + TEGRA210_MUX_ROUTES("ADMAIF4") + TEGRA210_MUX_ROUTES("ADMAIF5") + TEGRA210_MUX_ROUTES("ADMAIF6") + TEGRA210_MUX_ROUTES("ADMAIF7") + TEGRA210_MUX_ROUTES("ADMAIF8") + TEGRA210_MUX_ROUTES("ADMAIF9") + TEGRA210_MUX_ROUTES("ADMAIF10") + TEGRA210_MUX_ROUTES("I2S1") + TEGRA210_MUX_ROUTES("I2S2") + TEGRA210_MUX_ROUTES("I2S3") + TEGRA210_MUX_ROUTES("I2S4") + TEGRA210_MUX_ROUTES("I2S5") +}; + +static const struct snd_soc_dapm_route tegra186_ahub_routes[] = { + TEGRA_FE_ROUTES("ADMAIF1") + TEGRA_FE_ROUTES("ADMAIF2") + TEGRA_FE_ROUTES("ADMAIF3") + TEGRA_FE_ROUTES("ADMAIF4") + TEGRA_FE_ROUTES("ADMAIF5") + TEGRA_FE_ROUTES("ADMAIF6") + TEGRA_FE_ROUTES("ADMAIF7") + TEGRA_FE_ROUTES("ADMAIF8") + TEGRA_FE_ROUTES("ADMAIF9") + TEGRA_FE_ROUTES("ADMAIF10") + TEGRA_FE_ROUTES("ADMAIF11") + TEGRA_FE_ROUTES("ADMAIF12") + TEGRA_FE_ROUTES("ADMAIF13") + TEGRA_FE_ROUTES("ADMAIF14") + TEGRA_FE_ROUTES("ADMAIF15") + TEGRA_FE_ROUTES("ADMAIF16") + TEGRA_FE_ROUTES("ADMAIF17") + TEGRA_FE_ROUTES("ADMAIF18") + TEGRA_FE_ROUTES("ADMAIF19") + TEGRA_FE_ROUTES("ADMAIF20") + TEGRA186_MUX_ROUTES("ADMAIF1") + TEGRA186_MUX_ROUTES("ADMAIF2") + TEGRA186_MUX_ROUTES("ADMAIF3") + TEGRA186_MUX_ROUTES("ADMAIF4") + TEGRA186_MUX_ROUTES("ADMAIF5") + TEGRA186_MUX_ROUTES("ADMAIF6") + TEGRA186_MUX_ROUTES("ADMAIF7") + TEGRA186_MUX_ROUTES("ADMAIF8") + TEGRA186_MUX_ROUTES("ADMAIF9") + TEGRA186_MUX_ROUTES("ADMAIF10") + TEGRA186_MUX_ROUTES("ADMAIF11") + TEGRA186_MUX_ROUTES("ADMAIF12") + TEGRA186_MUX_ROUTES("ADMAIF13") + TEGRA186_MUX_ROUTES("ADMAIF14") + TEGRA186_MUX_ROUTES("ADMAIF15") + TEGRA186_MUX_ROUTES("ADMAIF16") + TEGRA186_MUX_ROUTES("ADMAIF17") + TEGRA186_MUX_ROUTES("ADMAIF18") + TEGRA186_MUX_ROUTES("ADMAIF19") + TEGRA186_MUX_ROUTES("ADMAIF20") + TEGRA186_MUX_ROUTES("I2S1") + TEGRA186_MUX_ROUTES("I2S2") + TEGRA186_MUX_ROUTES("I2S3") + TEGRA186_MUX_ROUTES("I2S4") + TEGRA186_MUX_ROUTES("I2S5") + TEGRA186_MUX_ROUTES("I2S6") + TEGRA186_MUX_ROUTES("DSPK1") + TEGRA186_MUX_ROUTES("DSPK2") +}; + +static const struct snd_soc_component_driver tegra210_ahub_component = { + .dapm_widgets = tegra210_ahub_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra210_ahub_widgets), + .dapm_routes = tegra210_ahub_routes, + .num_dapm_routes = ARRAY_SIZE(tegra210_ahub_routes), +}; + +static const struct snd_soc_component_driver tegra186_ahub_component = { + .dapm_widgets = tegra186_ahub_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra186_ahub_widgets), + .dapm_routes = tegra186_ahub_routes, + .num_dapm_routes = ARRAY_SIZE(tegra186_ahub_routes), +}; + +static const struct regmap_config tegra210_ahub_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = TEGRA210_MAX_REGISTER_ADDR, + .cache_type = REGCACHE_FLAT, +}; + +static const struct regmap_config tegra186_ahub_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = TEGRA186_MAX_REGISTER_ADDR, + .cache_type = REGCACHE_FLAT, +}; + +static const struct tegra_ahub_soc_data soc_data_tegra210 = { + .cmpnt_drv = &tegra210_ahub_component, + .dai_drv = tegra210_ahub_dais, + .num_dais = ARRAY_SIZE(tegra210_ahub_dais), + .regmap_config = &tegra210_ahub_regmap_config, + .mask[0] = TEGRA210_XBAR_REG_MASK_0, + .mask[1] = TEGRA210_XBAR_REG_MASK_1, + .mask[2] = TEGRA210_XBAR_REG_MASK_2, + .mask[3] = TEGRA210_XBAR_REG_MASK_3, + .reg_count = TEGRA210_XBAR_UPDATE_MAX_REG, +}; + +static const struct tegra_ahub_soc_data soc_data_tegra186 = { + .cmpnt_drv = &tegra186_ahub_component, + .dai_drv = tegra186_ahub_dais, + .num_dais = ARRAY_SIZE(tegra186_ahub_dais), + .regmap_config = &tegra186_ahub_regmap_config, + .mask[0] = TEGRA186_XBAR_REG_MASK_0, + .mask[1] = TEGRA186_XBAR_REG_MASK_1, + .mask[2] = TEGRA186_XBAR_REG_MASK_2, + .mask[3] = TEGRA186_XBAR_REG_MASK_3, + .reg_count = TEGRA186_XBAR_UPDATE_MAX_REG, +}; + +static const struct of_device_id tegra_ahub_of_match[] = { + { .compatible = "nvidia,tegra210-ahub", .data = &soc_data_tegra210 }, + { .compatible = "nvidia,tegra186-ahub", .data = &soc_data_tegra186 }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra_ahub_of_match); + +static int tegra_ahub_runtime_suspend(struct device *dev) +{ + struct tegra_ahub *ahub = dev_get_drvdata(dev); + + regcache_cache_only(ahub->regmap, true); + regcache_mark_dirty(ahub->regmap); + + clk_disable_unprepare(ahub->clk); + + return 0; +} + +static int tegra_ahub_runtime_resume(struct device *dev) +{ + struct tegra_ahub *ahub = dev_get_drvdata(dev); + int err; + + err = clk_prepare_enable(ahub->clk); + if (err) { + dev_err(dev, "failed to enable AHUB clock, err: %d\n", err); + return err; + } + + regcache_cache_only(ahub->regmap, false); + regcache_sync(ahub->regmap); + + return 0; +} + +static int tegra_ahub_probe(struct platform_device *pdev) +{ + struct tegra_ahub *ahub; + void __iomem *regs; + int err; + + ahub = devm_kzalloc(&pdev->dev, sizeof(*ahub), GFP_KERNEL); + if (!ahub) + return -ENOMEM; + + ahub->soc_data = of_device_get_match_data(&pdev->dev); + + platform_set_drvdata(pdev, ahub); + + ahub->clk = devm_clk_get(&pdev->dev, "ahub"); + if (IS_ERR(ahub->clk)) { + dev_err(&pdev->dev, "can't retrieve AHUB clock\n"); + return PTR_ERR(ahub->clk); + } + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + ahub->regmap = devm_regmap_init_mmio(&pdev->dev, regs, + ahub->soc_data->regmap_config); + if (IS_ERR(ahub->regmap)) { + dev_err(&pdev->dev, "regmap init failed\n"); + return PTR_ERR(ahub->regmap); + } + + regcache_cache_only(ahub->regmap, true); + + err = devm_snd_soc_register_component(&pdev->dev, + ahub->soc_data->cmpnt_drv, + ahub->soc_data->dai_drv, + ahub->soc_data->num_dais); + if (err) { + dev_err(&pdev->dev, "can't register AHUB component, err: %d\n", + err); + return err; + } + + err = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); + if (err) + return err; + + pm_runtime_enable(&pdev->dev); + + return 0; +} + +static int tegra_ahub_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops tegra_ahub_pm_ops = { + SET_RUNTIME_PM_OPS(tegra_ahub_runtime_suspend, + tegra_ahub_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver tegra_ahub_driver = { + .probe = tegra_ahub_probe, + .remove = tegra_ahub_remove, + .driver = { + .name = "tegra210-ahub", + .of_match_table = tegra_ahub_of_match, + .pm = &tegra_ahub_pm_ops, + }, +}; +module_platform_driver(tegra_ahub_driver); + +MODULE_AUTHOR("Stephen Warren "); +MODULE_AUTHOR("Mohan Kumar "); +MODULE_DESCRIPTION("Tegra210 ASoC AHUB driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/tegra/tegra210_ahub.h b/sound/soc/tegra/tegra210_ahub.h new file mode 100644 index 0000000000000000000000000000000000000000..47802bbe17a96a12cd879b85fe6e1765df1e1e6e --- /dev/null +++ b/sound/soc/tegra/tegra210_ahub.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra210_ahub.h - TEGRA210 AHUB + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA210_AHUB__H__ +#define __TEGRA210_AHUB__H__ + +/* Tegra210 specific */ +#define TEGRA210_XBAR_PART1_RX 0x200 +#define TEGRA210_XBAR_PART2_RX 0x400 +#define TEGRA210_XBAR_RX_STRIDE 0x4 +#define TEGRA210_XBAR_AUDIO_RX_COUNT 90 +#define TEGRA210_XBAR_REG_MASK_0 0xf1f03ff +#define TEGRA210_XBAR_REG_MASK_1 0x3f30031f +#define TEGRA210_XBAR_REG_MASK_2 0xff1cf313 +#define TEGRA210_XBAR_REG_MASK_3 0x0 +#define TEGRA210_XBAR_UPDATE_MAX_REG 3 +/* Tegra186 specific */ +#define TEGRA186_XBAR_PART3_RX 0x600 +#define TEGRA186_XBAR_AUDIO_RX_COUNT 115 +#define TEGRA186_XBAR_REG_MASK_0 0xf3fffff +#define TEGRA186_XBAR_REG_MASK_1 0x3f310f1f +#define TEGRA186_XBAR_REG_MASK_2 0xff3cf311 +#define TEGRA186_XBAR_REG_MASK_3 0x3f0f00ff +#define TEGRA186_XBAR_UPDATE_MAX_REG 4 + +#define TEGRA_XBAR_UPDATE_MAX_REG (TEGRA186_XBAR_UPDATE_MAX_REG) + +#define TEGRA186_MAX_REGISTER_ADDR (TEGRA186_XBAR_PART3_RX + \ + (TEGRA210_XBAR_RX_STRIDE * (TEGRA186_XBAR_AUDIO_RX_COUNT - 1))) + +#define TEGRA210_MAX_REGISTER_ADDR (TEGRA210_XBAR_PART2_RX + \ + (TEGRA210_XBAR_RX_STRIDE * (TEGRA210_XBAR_AUDIO_RX_COUNT - 1))) + +#define MUX_REG(id) (TEGRA210_XBAR_RX_STRIDE * (id)) + +#define MUX_VALUE(npart, nbit) (1 + (nbit) + (npart) * 32) + +#define SOC_VALUE_ENUM_WIDE(xreg, shift, xmax, xtexts, xvalues) \ + { \ + .reg = xreg, \ + .shift_l = shift, \ + .shift_r = shift, \ + .items = xmax, \ + .texts = xtexts, \ + .values = xvalues, \ + .mask = xmax ? roundup_pow_of_two(xmax) - 1 : 0 \ + } + +#define SOC_VALUE_ENUM_WIDE_DECL(name, xreg, shift, xtexts, xvalues) \ + static struct soc_enum name = \ + SOC_VALUE_ENUM_WIDE(xreg, shift, ARRAY_SIZE(xtexts), \ + xtexts, xvalues) + +#define MUX_ENUM_CTRL_DECL(ename, id) \ + SOC_VALUE_ENUM_WIDE_DECL(ename##_enum, MUX_REG(id), 0, \ + tegra210_ahub_mux_texts, \ + tegra210_ahub_mux_values); \ + static const struct snd_kcontrol_new ename##_control = \ + SOC_DAPM_ENUM_EXT("Route", ename##_enum, \ + tegra_ahub_get_value_enum, \ + tegra_ahub_put_value_enum) + +#define MUX_ENUM_CTRL_DECL_186(ename, id) \ + SOC_VALUE_ENUM_WIDE_DECL(ename##_enum, MUX_REG(id), 0, \ + tegra186_ahub_mux_texts, \ + tegra186_ahub_mux_values); \ + static const struct snd_kcontrol_new ename##_control = \ + SOC_DAPM_ENUM_EXT("Route", ename##_enum, \ + tegra_ahub_get_value_enum, \ + tegra_ahub_put_value_enum) + +#define WIDGETS(sname, ename) \ + SND_SOC_DAPM_AIF_IN(sname " XBAR-RX", NULL, 0, SND_SOC_NOPM, 0, 0), \ + SND_SOC_DAPM_AIF_OUT(sname " XBAR-TX", NULL, 0, SND_SOC_NOPM, 0, 0), \ + SND_SOC_DAPM_MUX(sname " Mux", SND_SOC_NOPM, 0, 0, \ + &ename##_control) + +#define TX_WIDGETS(sname) \ + SND_SOC_DAPM_AIF_IN(sname " XBAR-RX", NULL, 0, SND_SOC_NOPM, 0, 0), \ + SND_SOC_DAPM_AIF_OUT(sname " XBAR-TX", NULL, 0, SND_SOC_NOPM, 0, 0) + +#define DAI(sname) \ + { \ + .name = "XBAR-" #sname, \ + .playback = { \ + .stream_name = #sname " XBAR-Playback", \ + .channels_min = 1, \ + .channels_max = 16, \ + .rates = SNDRV_PCM_RATE_8000_192000, \ + .formats = SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE, \ + }, \ + .capture = { \ + .stream_name = #sname " XBAR-Capture", \ + .channels_min = 1, \ + .channels_max = 16, \ + .rates = SNDRV_PCM_RATE_8000_192000, \ + .formats = SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE, \ + }, \ + } + +struct tegra_ahub_soc_data { + const struct regmap_config *regmap_config; + const struct snd_soc_component_driver *cmpnt_drv; + struct snd_soc_dai_driver *dai_drv; + unsigned int mask[4]; + unsigned int reg_count; + unsigned int num_dais; +}; + +struct tegra_ahub { + const struct tegra_ahub_soc_data *soc_data; + struct regmap *regmap; + struct clk *clk; +}; + +#endif diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c new file mode 100644 index 0000000000000000000000000000000000000000..d682414ad90dc0b49594374834637fff3553a9ee --- /dev/null +++ b/sound/soc/tegra/tegra210_dmic.c @@ -0,0 +1,456 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra210_dmic.c - Tegra210 DMIC driver +// +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tegra210_dmic.h" +#include "tegra_cif.h" + +static const struct reg_default tegra210_dmic_reg_defaults[] = { + { TEGRA210_DMIC_TX_INT_MASK, 0x00000001 }, + { TEGRA210_DMIC_TX_CIF_CTRL, 0x00007700 }, + { TEGRA210_DMIC_CG, 0x1 }, + { TEGRA210_DMIC_CTRL, 0x00000301 }, + /* Below enables all filters - DCR, LP and SC */ + { TEGRA210_DMIC_DBG_CTRL, 0xe }, + /* Below as per latest POR value */ + { TEGRA210_DMIC_DCR_BIQUAD_0_COEF_4, 0x0 }, + /* LP filter is configured for pass through and used to apply gain */ + { TEGRA210_DMIC_LP_BIQUAD_0_COEF_0, 0x00800000 }, + { TEGRA210_DMIC_LP_BIQUAD_0_COEF_1, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_0_COEF_2, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_0_COEF_3, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_0_COEF_4, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_1_COEF_0, 0x00800000 }, + { TEGRA210_DMIC_LP_BIQUAD_1_COEF_1, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_1_COEF_2, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_1_COEF_3, 0x0 }, + { TEGRA210_DMIC_LP_BIQUAD_1_COEF_4, 0x0 }, +}; + +static int tegra210_dmic_runtime_suspend(struct device *dev) +{ + struct tegra210_dmic *dmic = dev_get_drvdata(dev); + + regcache_cache_only(dmic->regmap, true); + regcache_mark_dirty(dmic->regmap); + + clk_disable_unprepare(dmic->clk_dmic); + + return 0; +} + +static int tegra210_dmic_runtime_resume(struct device *dev) +{ + struct tegra210_dmic *dmic = dev_get_drvdata(dev); + int err; + + err = clk_prepare_enable(dmic->clk_dmic); + if (err) { + dev_err(dev, "failed to enable DMIC clock, err: %d\n", err); + return err; + } + + regcache_cache_only(dmic->regmap, false); + regcache_sync(dmic->regmap); + + return 0; +} + +static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct tegra210_dmic *dmic = snd_soc_dai_get_drvdata(dai); + unsigned int srate, clk_rate, channels; + struct tegra_cif_conf cif_conf; + unsigned long long gain_q23 = DEFAULT_GAIN_Q23; + int err; + + memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); + + channels = params_channels(params); + + cif_conf.audio_ch = channels; + + switch (dmic->ch_select) { + case DMIC_CH_SELECT_LEFT: + case DMIC_CH_SELECT_RIGHT: + cif_conf.client_ch = 1; + break; + case DMIC_CH_SELECT_STEREO: + cif_conf.client_ch = 2; + break; + default: + dev_err(dai->dev, "invalid DMIC client channels\n"); + return -EINVAL; + } + + srate = params_rate(params); + + /* + * DMIC clock rate is a multiple of 'Over Sampling Ratio' and + * 'Sample Rate'. The supported OSR values are 64, 128 and 256. + */ + clk_rate = (DMIC_OSR_FACTOR << dmic->osr_val) * srate; + + err = clk_set_rate(dmic->clk_dmic, clk_rate); + if (err) { + dev_err(dai->dev, "can't set DMIC clock rate %u, err: %d\n", + clk_rate, err); + return err; + } + + regmap_update_bits(dmic->regmap, + /* Reg */ + TEGRA210_DMIC_CTRL, + /* Mask */ + TEGRA210_DMIC_CTRL_LRSEL_POLARITY_MASK | + TEGRA210_DMIC_CTRL_OSR_MASK | + TEGRA210_DMIC_CTRL_CHANNEL_SELECT_MASK, + /* Value */ + (dmic->lrsel << LRSEL_POL_SHIFT) | + (dmic->osr_val << OSR_SHIFT) | + ((dmic->ch_select + 1) << CH_SEL_SHIFT)); + + /* + * Use LP filter gain register to apply boost. + * Boost Gain Volume control has 100x factor. + */ + if (dmic->boost_gain) + gain_q23 = div_u64(gain_q23 * dmic->boost_gain, 100); + + regmap_write(dmic->regmap, TEGRA210_DMIC_LP_FILTER_GAIN, + (unsigned int)gain_q23); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_16; + break; + case SNDRV_PCM_FORMAT_S32_LE: + cif_conf.audio_bits = TEGRA_ACIF_BITS_32; + break; + default: + dev_err(dai->dev, "unsupported format!\n"); + return -EOPNOTSUPP; + } + + cif_conf.client_bits = TEGRA_ACIF_BITS_24; + cif_conf.mono_conv = dmic->mono_to_stereo; + cif_conf.stereo_conv = dmic->stereo_to_mono; + + tegra_set_cif(dmic->regmap, TEGRA210_DMIC_TX_CIF_CTRL, &cif_conf); + + return 0; +} + +static int tegra210_dmic_get_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); + + if (strstr(kcontrol->id.name, "Boost Gain Volume")) + ucontrol->value.integer.value[0] = dmic->boost_gain; + else if (strstr(kcontrol->id.name, "Channel Select")) + ucontrol->value.integer.value[0] = dmic->ch_select; + else if (strstr(kcontrol->id.name, "Mono To Stereo")) + ucontrol->value.integer.value[0] = dmic->mono_to_stereo; + else if (strstr(kcontrol->id.name, "Stereo To Mono")) + ucontrol->value.integer.value[0] = dmic->stereo_to_mono; + else if (strstr(kcontrol->id.name, "OSR Value")) + ucontrol->value.integer.value[0] = dmic->osr_val; + else if (strstr(kcontrol->id.name, "LR Polarity Select")) + ucontrol->value.integer.value[0] = dmic->lrsel; + + return 0; +} + +static int tegra210_dmic_put_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); + int value = ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "Boost Gain Volume")) + dmic->boost_gain = value; + else if (strstr(kcontrol->id.name, "Channel Select")) + dmic->ch_select = ucontrol->value.integer.value[0]; + else if (strstr(kcontrol->id.name, "Mono To Stereo")) + dmic->mono_to_stereo = value; + else if (strstr(kcontrol->id.name, "Stereo To Mono")) + dmic->stereo_to_mono = value; + else if (strstr(kcontrol->id.name, "OSR Value")) + dmic->osr_val = value; + else if (strstr(kcontrol->id.name, "LR Polarity Select")) + dmic->lrsel = value; + + return 0; +} + +static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = { + .hw_params = tegra210_dmic_hw_params, +}; + +static struct snd_soc_dai_driver tegra210_dmic_dais[] = { + { + .name = "DMIC-CIF", + .capture = { + .stream_name = "CIF-Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + }, + { + .name = "DMIC-DAP", + .capture = { + .stream_name = "DAP-Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &tegra210_dmic_dai_ops, + .symmetric_rates = 1, + }, +}; + +static const struct snd_soc_dapm_widget tegra210_dmic_widgets[] = { + SND_SOC_DAPM_AIF_OUT("TX", NULL, 0, TEGRA210_DMIC_ENABLE, 0, 0), + SND_SOC_DAPM_MIC("MIC", NULL), +}; + +static const struct snd_soc_dapm_route tegra210_dmic_routes[] = { + { "XBAR-RX", NULL, "XBAR-Capture" }, + { "XBAR-Capture", NULL, "CIF-Capture" }, + { "CIF-Capture", NULL, "TX" }, + { "TX", NULL, "DAP-Capture" }, + { "DAP-Capture", NULL, "MIC" }, +}; + +static const char * const tegra210_dmic_ch_select[] = { + "Left", "Right", "Stereo", +}; + +static const struct soc_enum tegra210_dmic_ch_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_ch_select), + tegra210_dmic_ch_select); + +static const char * const tegra210_dmic_mono_conv_text[] = { + "Zero", "Copy", +}; + +static const char * const tegra210_dmic_stereo_conv_text[] = { + "CH0", "CH1", "AVG", +}; + +static const struct soc_enum tegra210_dmic_mono_conv_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_mono_conv_text), + tegra210_dmic_mono_conv_text); + +static const struct soc_enum tegra210_dmic_stereo_conv_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_stereo_conv_text), + tegra210_dmic_stereo_conv_text); + +static const char * const tegra210_dmic_osr_text[] = { + "OSR_64", "OSR_128", "OSR_256", +}; + +static const struct soc_enum tegra210_dmic_osr_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_osr_text), + tegra210_dmic_osr_text); + +static const char * const tegra210_dmic_lrsel_text[] = { + "Left", "Right", +}; + +static const struct soc_enum tegra210_dmic_lrsel_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_lrsel_text), + tegra210_dmic_lrsel_text); + +static const struct snd_kcontrol_new tegra210_dmic_controls[] = { + SOC_SINGLE_EXT("Boost Gain Volume", 0, 0, MAX_BOOST_GAIN, 0, + tegra210_dmic_get_control, tegra210_dmic_put_control), + SOC_ENUM_EXT("Channel Select", tegra210_dmic_ch_enum, + tegra210_dmic_get_control, tegra210_dmic_put_control), + SOC_ENUM_EXT("Mono To Stereo", + tegra210_dmic_mono_conv_enum, tegra210_dmic_get_control, + tegra210_dmic_put_control), + SOC_ENUM_EXT("Stereo To Mono", + tegra210_dmic_stereo_conv_enum, tegra210_dmic_get_control, + tegra210_dmic_put_control), + SOC_ENUM_EXT("OSR Value", tegra210_dmic_osr_enum, + tegra210_dmic_get_control, tegra210_dmic_put_control), + SOC_ENUM_EXT("LR Polarity Select", tegra210_dmic_lrsel_enum, + tegra210_dmic_get_control, tegra210_dmic_put_control), +}; + +static const struct snd_soc_component_driver tegra210_dmic_compnt = { + .dapm_widgets = tegra210_dmic_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra210_dmic_widgets), + .dapm_routes = tegra210_dmic_routes, + .num_dapm_routes = ARRAY_SIZE(tegra210_dmic_routes), + .controls = tegra210_dmic_controls, + .num_controls = ARRAY_SIZE(tegra210_dmic_controls), +}; + +static bool tegra210_dmic_wr_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_DMIC_TX_INT_MASK ... TEGRA210_DMIC_TX_CIF_CTRL: + case TEGRA210_DMIC_ENABLE ... TEGRA210_DMIC_CG: + case TEGRA210_DMIC_CTRL: + case TEGRA210_DMIC_DBG_CTRL: + case TEGRA210_DMIC_DCR_BIQUAD_0_COEF_4 ... TEGRA210_DMIC_LP_BIQUAD_1_COEF_4: + return true; + default: + return false; + }; +} + +static bool tegra210_dmic_rd_reg(struct device *dev, unsigned int reg) +{ + if (tegra210_dmic_wr_reg(dev, reg)) + return true; + + switch (reg) { + case TEGRA210_DMIC_TX_STATUS: + case TEGRA210_DMIC_TX_INT_STATUS: + case TEGRA210_DMIC_STATUS: + case TEGRA210_DMIC_INT_STATUS: + return true; + default: + return false; + }; +} + +static bool tegra210_dmic_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_DMIC_TX_STATUS: + case TEGRA210_DMIC_TX_INT_STATUS: + case TEGRA210_DMIC_TX_INT_SET: + case TEGRA210_DMIC_SOFT_RESET: + case TEGRA210_DMIC_STATUS: + case TEGRA210_DMIC_INT_STATUS: + return true; + default: + return false; + }; +} + +static const struct regmap_config tegra210_dmic_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA210_DMIC_LP_BIQUAD_1_COEF_4, + .writeable_reg = tegra210_dmic_wr_reg, + .readable_reg = tegra210_dmic_rd_reg, + .volatile_reg = tegra210_dmic_volatile_reg, + .reg_defaults = tegra210_dmic_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tegra210_dmic_reg_defaults), + .cache_type = REGCACHE_FLAT, +}; + +static int tegra210_dmic_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra210_dmic *dmic; + void __iomem *regs; + int err; + + dmic = devm_kzalloc(dev, sizeof(*dmic), GFP_KERNEL); + if (!dmic) + return -ENOMEM; + + dmic->osr_val = DMIC_OSR_64; + dmic->ch_select = DMIC_CH_SELECT_STEREO; + dmic->lrsel = DMIC_LRSEL_LEFT; + dmic->boost_gain = 0; + dmic->stereo_to_mono = 0; /* "CH0" */ + + dev_set_drvdata(dev, dmic); + + dmic->clk_dmic = devm_clk_get(dev, "dmic"); + if (IS_ERR(dmic->clk_dmic)) { + dev_err(dev, "can't retrieve DMIC clock\n"); + return PTR_ERR(dmic->clk_dmic); + } + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + dmic->regmap = devm_regmap_init_mmio(dev, regs, + &tegra210_dmic_regmap_config); + if (IS_ERR(dmic->regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(dmic->regmap); + } + + regcache_cache_only(dmic->regmap, true); + + err = devm_snd_soc_register_component(dev, &tegra210_dmic_compnt, + tegra210_dmic_dais, + ARRAY_SIZE(tegra210_dmic_dais)); + if (err) { + dev_err(dev, "can't register DMIC component, err: %d\n", err); + return err; + } + + pm_runtime_enable(dev); + + return 0; +} + +static int tegra210_dmic_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops tegra210_dmic_pm_ops = { + SET_RUNTIME_PM_OPS(tegra210_dmic_runtime_suspend, + tegra210_dmic_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static const struct of_device_id tegra210_dmic_of_match[] = { + { .compatible = "nvidia,tegra210-dmic" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra210_dmic_of_match); + +static struct platform_driver tegra210_dmic_driver = { + .driver = { + .name = "tegra210-dmic", + .of_match_table = tegra210_dmic_of_match, + .pm = &tegra210_dmic_pm_ops, + }, + .probe = tegra210_dmic_probe, + .remove = tegra210_dmic_remove, +}; +module_platform_driver(tegra210_dmic_driver) + +MODULE_AUTHOR("Rahul Mittal "); +MODULE_DESCRIPTION("Tegra210 ASoC DMIC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/tegra/tegra210_dmic.h b/sound/soc/tegra/tegra210_dmic.h new file mode 100644 index 0000000000000000000000000000000000000000..6418c223b1c89e361c30587c2e84f2afd08ceae7 --- /dev/null +++ b/sound/soc/tegra/tegra210_dmic.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra210_dmic.h - Definitions for Tegra210 DMIC driver + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA210_DMIC_H__ +#define __TEGRA210_DMIC_H__ + +/* Register offsets from DMIC BASE */ +#define TEGRA210_DMIC_TX_STATUS 0x0c +#define TEGRA210_DMIC_TX_INT_STATUS 0x10 +#define TEGRA210_DMIC_TX_INT_MASK 0x14 +#define TEGRA210_DMIC_TX_INT_SET 0x18 +#define TEGRA210_DMIC_TX_INT_CLEAR 0x1c +#define TEGRA210_DMIC_TX_CIF_CTRL 0x20 +#define TEGRA210_DMIC_ENABLE 0x40 +#define TEGRA210_DMIC_SOFT_RESET 0x44 +#define TEGRA210_DMIC_CG 0x48 +#define TEGRA210_DMIC_STATUS 0x4c +#define TEGRA210_DMIC_INT_STATUS 0x50 +#define TEGRA210_DMIC_CTRL 0x64 +#define TEGRA210_DMIC_DBG_CTRL 0x70 +#define TEGRA210_DMIC_DCR_BIQUAD_0_COEF_4 0x88 +#define TEGRA210_DMIC_LP_FILTER_GAIN 0x8c +#define TEGRA210_DMIC_LP_BIQUAD_0_COEF_0 0x90 +#define TEGRA210_DMIC_LP_BIQUAD_0_COEF_1 0x94 +#define TEGRA210_DMIC_LP_BIQUAD_0_COEF_2 0x98 +#define TEGRA210_DMIC_LP_BIQUAD_0_COEF_3 0x9c +#define TEGRA210_DMIC_LP_BIQUAD_0_COEF_4 0xa0 +#define TEGRA210_DMIC_LP_BIQUAD_1_COEF_0 0xa4 +#define TEGRA210_DMIC_LP_BIQUAD_1_COEF_1 0xa8 +#define TEGRA210_DMIC_LP_BIQUAD_1_COEF_2 0xac +#define TEGRA210_DMIC_LP_BIQUAD_1_COEF_3 0xb0 +#define TEGRA210_DMIC_LP_BIQUAD_1_COEF_4 0xb4 + +/* Fields in TEGRA210_DMIC_CTRL */ +#define CH_SEL_SHIFT 8 +#define TEGRA210_DMIC_CTRL_CHANNEL_SELECT_MASK (0x3 << CH_SEL_SHIFT) +#define LRSEL_POL_SHIFT 4 +#define TEGRA210_DMIC_CTRL_LRSEL_POLARITY_MASK (0x1 << LRSEL_POL_SHIFT) +#define OSR_SHIFT 0 +#define TEGRA210_DMIC_CTRL_OSR_MASK (0x3 << OSR_SHIFT) + +#define DMIC_OSR_FACTOR 64 + +#define DEFAULT_GAIN_Q23 0x800000 + +/* Max boost gain factor used for mixer control */ +#define MAX_BOOST_GAIN 25599 + +enum tegra_dmic_ch_select { + DMIC_CH_SELECT_LEFT, + DMIC_CH_SELECT_RIGHT, + DMIC_CH_SELECT_STEREO, +}; + +enum tegra_dmic_osr { + DMIC_OSR_64, + DMIC_OSR_128, + DMIC_OSR_256, +}; + +enum tegra_dmic_lrsel { + DMIC_LRSEL_LEFT, + DMIC_LRSEL_RIGHT, +}; + +struct tegra210_dmic { + struct clk *clk_dmic; + struct regmap *regmap; + unsigned int mono_to_stereo; + unsigned int stereo_to_mono; + unsigned int boost_gain; + unsigned int ch_select; + unsigned int osr_val; + unsigned int lrsel; +}; + +#endif diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c new file mode 100644 index 0000000000000000000000000000000000000000..722092181583e2f87f17ca67bbdf4fbc27b37348 --- /dev/null +++ b/sound/soc/tegra/tegra210_i2s.c @@ -0,0 +1,812 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra210_i2s.c - Tegra210 I2S driver +// +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tegra210_i2s.h" +#include "tegra_cif.h" + +static const struct reg_default tegra210_i2s_reg_defaults[] = { + { TEGRA210_I2S_RX_INT_MASK, 0x00000003 }, + { TEGRA210_I2S_RX_CIF_CTRL, 0x00007700 }, + { TEGRA210_I2S_TX_INT_MASK, 0x00000003 }, + { TEGRA210_I2S_TX_CIF_CTRL, 0x00007700 }, + { TEGRA210_I2S_CG, 0x1 }, + { TEGRA210_I2S_TIMING, 0x0000001f }, + { TEGRA210_I2S_ENABLE, 0x1 }, + /* + * Below update does not have any effect on Tegra186 and Tegra194. + * On Tegra210, I2S4 has "i2s4a" and "i2s4b" pins and below update + * is required to select i2s4b for it to be functional for I2S + * operation. + */ + { TEGRA210_I2S_CYA, 0x1 }, +}; + +static void tegra210_i2s_set_slot_ctrl(struct regmap *regmap, + unsigned int total_slots, + unsigned int tx_slot_mask, + unsigned int rx_slot_mask) +{ + regmap_write(regmap, TEGRA210_I2S_SLOT_CTRL, total_slots - 1); + regmap_write(regmap, TEGRA210_I2S_TX_SLOT_CTRL, tx_slot_mask); + regmap_write(regmap, TEGRA210_I2S_RX_SLOT_CTRL, rx_slot_mask); +} + +static int tegra210_i2s_set_clock_rate(struct device *dev, + unsigned int clock_rate) +{ + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + unsigned int val; + int err; + + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val); + + /* No need to set rates if I2S is being operated in slave */ + if (!(val & I2S_CTRL_MASTER_EN)) + return 0; + + err = clk_set_rate(i2s->clk_i2s, clock_rate); + if (err) { + dev_err(dev, "can't set I2S bit clock rate %u, err: %d\n", + clock_rate, err); + return err; + } + + if (!IS_ERR(i2s->clk_sync_input)) { + /* + * Other I/O modules in AHUB can use i2s bclk as reference + * clock. Below sets sync input clock rate as per bclk, + * which can be used as input to other I/O modules. + */ + err = clk_set_rate(i2s->clk_sync_input, clock_rate); + if (err) { + dev_err(dev, + "can't set I2S sync input rate %u, err = %d\n", + clock_rate, err); + return err; + } + } + + return 0; +} + +static int tegra210_i2s_sw_reset(struct snd_soc_component *compnt, + bool is_playback) +{ + struct device *dev = compnt->dev; + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + unsigned int reset_mask = I2S_SOFT_RESET_MASK; + unsigned int reset_en = I2S_SOFT_RESET_EN; + unsigned int reset_reg, cif_reg, stream_reg; + unsigned int cif_ctrl, stream_ctrl, i2s_ctrl, val; + int err; + + if (is_playback) { + reset_reg = TEGRA210_I2S_RX_SOFT_RESET; + cif_reg = TEGRA210_I2S_RX_CIF_CTRL; + stream_reg = TEGRA210_I2S_RX_CTRL; + } else { + reset_reg = TEGRA210_I2S_TX_SOFT_RESET; + cif_reg = TEGRA210_I2S_TX_CIF_CTRL; + stream_reg = TEGRA210_I2S_TX_CTRL; + } + + /* Store CIF and I2S control values */ + regmap_read(i2s->regmap, cif_reg, &cif_ctrl); + regmap_read(i2s->regmap, stream_reg, &stream_ctrl); + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &i2s_ctrl); + + /* Reset to make sure the previous transactions are clean */ + regmap_update_bits(i2s->regmap, reset_reg, reset_mask, reset_en); + + err = regmap_read_poll_timeout(i2s->regmap, reset_reg, val, + !(val & reset_mask & reset_en), + 10, 10000); + if (err) { + dev_err(dev, "timeout: failed to reset I2S for %s\n", + is_playback ? "playback" : "capture"); + return err; + } + + /* Restore CIF and I2S control values */ + regmap_write(i2s->regmap, cif_reg, cif_ctrl); + regmap_write(i2s->regmap, stream_reg, stream_ctrl); + regmap_write(i2s->regmap, TEGRA210_I2S_CTRL, i2s_ctrl); + + return 0; +} + +static int tegra210_i2s_init(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *compnt = snd_soc_dapm_to_component(w->dapm); + struct device *dev = compnt->dev; + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + unsigned int val, status_reg; + bool is_playback; + int err; + + switch (w->reg) { + case TEGRA210_I2S_RX_ENABLE: + is_playback = true; + status_reg = TEGRA210_I2S_RX_STATUS; + break; + case TEGRA210_I2S_TX_ENABLE: + is_playback = false; + status_reg = TEGRA210_I2S_TX_STATUS; + break; + default: + return -EINVAL; + } + + /* Ensure I2S is in disabled state before new session */ + err = regmap_read_poll_timeout(i2s->regmap, status_reg, val, + !(val & I2S_EN_MASK & I2S_EN), + 10, 10000); + if (err) { + dev_err(dev, "timeout: previous I2S %s is still active\n", + is_playback ? "playback" : "capture"); + return err; + } + + return tegra210_i2s_sw_reset(compnt, is_playback); +} + +static int tegra210_i2s_runtime_suspend(struct device *dev) +{ + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + + regcache_cache_only(i2s->regmap, true); + regcache_mark_dirty(i2s->regmap); + + clk_disable_unprepare(i2s->clk_i2s); + + return 0; +} + +static int tegra210_i2s_runtime_resume(struct device *dev) +{ + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + int err; + + err = clk_prepare_enable(i2s->clk_i2s); + if (err) { + dev_err(dev, "failed to enable I2S bit clock, err: %d\n", err); + return err; + } + + regcache_cache_only(i2s->regmap, false); + regcache_sync(i2s->regmap); + + return 0; +} + +static void tegra210_i2s_set_data_offset(struct tegra210_i2s *i2s, + unsigned int data_offset) +{ + /* Capture path */ + regmap_update_bits(i2s->regmap, TEGRA210_I2S_TX_CTRL, + I2S_CTRL_DATA_OFFSET_MASK, + data_offset << I2S_DATA_SHIFT); + + /* Playback path */ + regmap_update_bits(i2s->regmap, TEGRA210_I2S_RX_CTRL, + I2S_CTRL_DATA_OFFSET_MASK, + data_offset << I2S_DATA_SHIFT); +} + +static int tegra210_i2s_set_fmt(struct snd_soc_dai *dai, + unsigned int fmt) +{ + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); + unsigned int mask, val; + + mask = I2S_CTRL_MASTER_EN_MASK; + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + val = 0; + break; + case SND_SOC_DAIFMT_CBM_CFM: + val = I2S_CTRL_MASTER_EN; + break; + default: + return -EINVAL; + } + + mask |= I2S_CTRL_FRAME_FMT_MASK | I2S_CTRL_LRCK_POL_MASK; + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + val |= I2S_CTRL_FRAME_FMT_FSYNC_MODE; + val |= I2S_CTRL_LRCK_POL_HIGH; + tegra210_i2s_set_data_offset(i2s, 1); + break; + case SND_SOC_DAIFMT_DSP_B: + val |= I2S_CTRL_FRAME_FMT_FSYNC_MODE; + val |= I2S_CTRL_LRCK_POL_HIGH; + tegra210_i2s_set_data_offset(i2s, 0); + break; + /* I2S mode has data offset of 1 */ + case SND_SOC_DAIFMT_I2S: + val |= I2S_CTRL_FRAME_FMT_LRCK_MODE; + val |= I2S_CTRL_LRCK_POL_LOW; + tegra210_i2s_set_data_offset(i2s, 1); + break; + /* + * For RJ mode data offset is dependent on the sample size + * and the bclk ratio, and so is set when hw_params is called. + */ + case SND_SOC_DAIFMT_RIGHT_J: + val |= I2S_CTRL_FRAME_FMT_LRCK_MODE; + val |= I2S_CTRL_LRCK_POL_HIGH; + break; + case SND_SOC_DAIFMT_LEFT_J: + val |= I2S_CTRL_FRAME_FMT_LRCK_MODE; + val |= I2S_CTRL_LRCK_POL_HIGH; + tegra210_i2s_set_data_offset(i2s, 0); + break; + default: + return -EINVAL; + } + + mask |= I2S_CTRL_EDGE_CTRL_MASK; + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + val |= I2S_CTRL_EDGE_CTRL_POS_EDGE; + break; + case SND_SOC_DAIFMT_NB_IF: + val |= I2S_CTRL_EDGE_CTRL_POS_EDGE; + val ^= I2S_CTRL_LRCK_POL_MASK; + break; + case SND_SOC_DAIFMT_IB_NF: + val |= I2S_CTRL_EDGE_CTRL_NEG_EDGE; + break; + case SND_SOC_DAIFMT_IB_IF: + val |= I2S_CTRL_EDGE_CTRL_NEG_EDGE; + val ^= I2S_CTRL_LRCK_POL_MASK; + break; + default: + return -EINVAL; + } + + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, mask, val); + + i2s->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + + return 0; +} + +static int tegra210_i2s_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); + + /* Copy the required tx and rx mask */ + i2s->tx_mask = (tx_mask > DEFAULT_I2S_SLOT_MASK) ? + DEFAULT_I2S_SLOT_MASK : tx_mask; + i2s->rx_mask = (rx_mask > DEFAULT_I2S_SLOT_MASK) ? + DEFAULT_I2S_SLOT_MASK : rx_mask; + + return 0; +} + +static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, + unsigned int ratio) +{ + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); + + i2s->bclk_ratio = ratio; + + return 0; +} + +static int tegra210_i2s_get_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); + long *uctl_val = &ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "Loopback")) + *uctl_val = i2s->loopback; + else if (strstr(kcontrol->id.name, "FSYNC Width")) + *uctl_val = i2s->fsync_width; + else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) + *uctl_val = i2s->stereo_to_mono[I2S_TX_PATH]; + else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) + *uctl_val = i2s->mono_to_stereo[I2S_TX_PATH]; + else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) + *uctl_val = i2s->stereo_to_mono[I2S_RX_PATH]; + else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) + *uctl_val = i2s->mono_to_stereo[I2S_RX_PATH]; + else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) + *uctl_val = i2s->rx_fifo_th; + else if (strstr(kcontrol->id.name, "BCLK Ratio")) + *uctl_val = i2s->bclk_ratio; + + return 0; +} + +static int tegra210_i2s_put_control(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); + int value = ucontrol->value.integer.value[0]; + + if (strstr(kcontrol->id.name, "Loopback")) { + i2s->loopback = value; + + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, + I2S_CTRL_LPBK_MASK, + i2s->loopback << I2S_CTRL_LPBK_SHIFT); + + } else if (strstr(kcontrol->id.name, "FSYNC Width")) { + /* + * Frame sync width is used only for FSYNC modes and not + * applicable for LRCK modes. Reset value for this field is "0", + * which means the width is one bit clock wide. + * The width requirement may depend on the codec and in such + * cases mixer control is used to update custom values. A value + * of "N" here means, width is "N + 1" bit clock wide. + */ + i2s->fsync_width = value; + + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, + I2S_CTRL_FSYNC_WIDTH_MASK, + i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT); + + } else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) { + i2s->stereo_to_mono[I2S_TX_PATH] = value; + } else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) { + i2s->mono_to_stereo[I2S_TX_PATH] = value; + } else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) { + i2s->stereo_to_mono[I2S_RX_PATH] = value; + } else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) { + i2s->mono_to_stereo[I2S_RX_PATH] = value; + } else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) { + i2s->rx_fifo_th = value; + } else if (strstr(kcontrol->id.name, "BCLK Ratio")) { + i2s->bclk_ratio = value; + } + + return 0; +} + +static int tegra210_i2s_set_timing_params(struct device *dev, + unsigned int sample_size, + unsigned int srate, + unsigned int channels) +{ + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + unsigned int val, bit_count, bclk_rate, num_bclk = sample_size; + int err; + + if (i2s->bclk_ratio) + num_bclk *= i2s->bclk_ratio; + + if (i2s->dai_fmt == SND_SOC_DAIFMT_RIGHT_J) + tegra210_i2s_set_data_offset(i2s, num_bclk - sample_size); + + /* I2S bit clock rate */ + bclk_rate = srate * channels * num_bclk; + + err = tegra210_i2s_set_clock_rate(dev, bclk_rate); + if (err) { + dev_err(dev, "can't set I2S bit clock rate %u, err: %d\n", + bclk_rate, err); + return err; + } + + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val); + + /* + * For LRCK mode, channel bit count depends on number of bit clocks + * on the left channel, where as for FSYNC mode bit count depends on + * the number of bit clocks in both left and right channels for DSP + * mode or the number of bit clocks in one TDM frame. + * + */ + switch (val & I2S_CTRL_FRAME_FMT_MASK) { + case I2S_CTRL_FRAME_FMT_LRCK_MODE: + bit_count = (bclk_rate / (srate * 2)) - 1; + break; + case I2S_CTRL_FRAME_FMT_FSYNC_MODE: + bit_count = (bclk_rate / srate) - 1; + + tegra210_i2s_set_slot_ctrl(i2s->regmap, channels, + i2s->tx_mask, i2s->rx_mask); + break; + default: + dev_err(dev, "invalid I2S frame format\n"); + return -EINVAL; + } + + if (bit_count > I2S_TIMING_CH_BIT_CNT_MASK) { + dev_err(dev, "invalid I2S channel bit count %u\n", bit_count); + return -EINVAL; + } + + regmap_write(i2s->regmap, TEGRA210_I2S_TIMING, + bit_count << I2S_TIMING_CH_BIT_CNT_SHIFT); + + return 0; +} + +static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct device *dev = dai->dev; + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); + unsigned int sample_size, channels, srate, val, reg, path; + struct tegra_cif_conf cif_conf; + + memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); + + channels = params_channels(params); + if (channels < 1) { + dev_err(dev, "invalid I2S %d channel configuration\n", + channels); + return -EINVAL; + } + + cif_conf.audio_ch = channels; + cif_conf.client_ch = channels; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + val = I2S_BITS_8; + sample_size = 8; + cif_conf.audio_bits = TEGRA_ACIF_BITS_8; + cif_conf.client_bits = TEGRA_ACIF_BITS_8; + break; + case SNDRV_PCM_FORMAT_S16_LE: + val = I2S_BITS_16; + sample_size = 16; + cif_conf.audio_bits = TEGRA_ACIF_BITS_16; + cif_conf.client_bits = TEGRA_ACIF_BITS_16; + break; + case SNDRV_PCM_FORMAT_S32_LE: + val = I2S_BITS_32; + sample_size = 32; + cif_conf.audio_bits = TEGRA_ACIF_BITS_32; + cif_conf.client_bits = TEGRA_ACIF_BITS_32; + break; + default: + dev_err(dev, "unsupported format!\n"); + return -EOPNOTSUPP; + } + + /* Program sample size */ + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, + I2S_CTRL_BIT_SIZE_MASK, val); + + srate = params_rate(params); + + /* For playback I2S RX-CIF and for capture TX-CIF is used */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + path = I2S_RX_PATH; + else + path = I2S_TX_PATH; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + unsigned int max_th; + + /* FIFO threshold in terms of frames */ + max_th = (I2S_RX_FIFO_DEPTH / cif_conf.audio_ch) - 1; + + if (i2s->rx_fifo_th > max_th) + i2s->rx_fifo_th = max_th; + + cif_conf.threshold = i2s->rx_fifo_th; + + reg = TEGRA210_I2S_RX_CIF_CTRL; + } else { + reg = TEGRA210_I2S_TX_CIF_CTRL; + } + + cif_conf.mono_conv = i2s->mono_to_stereo[path]; + cif_conf.stereo_conv = i2s->stereo_to_mono[path]; + + tegra_set_cif(i2s->regmap, reg, &cif_conf); + + return tegra210_i2s_set_timing_params(dev, sample_size, srate, + cif_conf.client_ch); +} + +static const struct snd_soc_dai_ops tegra210_i2s_dai_ops = { + .set_fmt = tegra210_i2s_set_fmt, + .hw_params = tegra210_i2s_hw_params, + .set_bclk_ratio = tegra210_i2s_set_dai_bclk_ratio, + .set_tdm_slot = tegra210_i2s_set_tdm_slot, +}; + +static struct snd_soc_dai_driver tegra210_i2s_dais[] = { + { + .name = "I2S-CIF", + .playback = { + .stream_name = "CIF-Playback", + .channels_min = 1, + .channels_max = 16, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .stream_name = "CIF-Capture", + .channels_min = 1, + .channels_max = 16, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + }, + { + .name = "I2S-DAP", + .playback = { + .stream_name = "DAP-Playback", + .channels_min = 1, + .channels_max = 16, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .stream_name = "DAP-Capture", + .channels_min = 1, + .channels_max = 16, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &tegra210_i2s_dai_ops, + .symmetric_rates = 1, + }, +}; + +static const char * const tegra210_i2s_stereo_conv_text[] = { + "CH0", "CH1", "AVG", +}; + +static const char * const tegra210_i2s_mono_conv_text[] = { + "Zero", "Copy", +}; + +static const struct soc_enum tegra210_i2s_mono_conv_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_i2s_mono_conv_text), + tegra210_i2s_mono_conv_text); + +static const struct soc_enum tegra210_i2s_stereo_conv_enum = + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_i2s_stereo_conv_text), + tegra210_i2s_stereo_conv_text); + +static const struct snd_kcontrol_new tegra210_i2s_controls[] = { + SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_control, + tegra210_i2s_put_control), + SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0, tegra210_i2s_get_control, + tegra210_i2s_put_control), + SOC_ENUM_EXT("Capture Stereo To Mono", tegra210_i2s_stereo_conv_enum, + tegra210_i2s_get_control, tegra210_i2s_put_control), + SOC_ENUM_EXT("Capture Mono To Stereo", tegra210_i2s_mono_conv_enum, + tegra210_i2s_get_control, tegra210_i2s_put_control), + SOC_ENUM_EXT("Playback Stereo To Mono", tegra210_i2s_stereo_conv_enum, + tegra210_i2s_get_control, tegra210_i2s_put_control), + SOC_ENUM_EXT("Playback Mono To Stereo", tegra210_i2s_mono_conv_enum, + tegra210_i2s_get_control, tegra210_i2s_put_control), + SOC_SINGLE_EXT("Playback FIFO Threshold", 0, 0, I2S_RX_FIFO_DEPTH - 1, + 0, tegra210_i2s_get_control, tegra210_i2s_put_control), + SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0, tegra210_i2s_get_control, + tegra210_i2s_put_control), +}; + +static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] = { + SND_SOC_DAPM_AIF_IN_E("RX", NULL, 0, TEGRA210_I2S_RX_ENABLE, + 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_AIF_OUT_E("TX", NULL, 0, TEGRA210_I2S_TX_ENABLE, + 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_MIC("MIC", NULL), + SND_SOC_DAPM_SPK("SPK", NULL), +}; + +static const struct snd_soc_dapm_route tegra210_i2s_routes[] = { + /* Playback route from XBAR */ + { "XBAR-Playback", NULL, "XBAR-TX" }, + { "CIF-Playback", NULL, "XBAR-Playback" }, + { "RX", NULL, "CIF-Playback" }, + { "DAP-Playback", NULL, "RX" }, + { "SPK", NULL, "DAP-Playback" }, + /* Capture route to XBAR */ + { "XBAR-RX", NULL, "XBAR-Capture" }, + { "XBAR-Capture", NULL, "CIF-Capture" }, + { "CIF-Capture", NULL, "TX" }, + { "TX", NULL, "DAP-Capture" }, + { "DAP-Capture", NULL, "MIC" }, +}; + +static const struct snd_soc_component_driver tegra210_i2s_cmpnt = { + .dapm_widgets = tegra210_i2s_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra210_i2s_widgets), + .dapm_routes = tegra210_i2s_routes, + .num_dapm_routes = ARRAY_SIZE(tegra210_i2s_routes), + .controls = tegra210_i2s_controls, + .num_controls = ARRAY_SIZE(tegra210_i2s_controls), + .non_legacy_dai_naming = 1, +}; + +static bool tegra210_i2s_wr_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_I2S_RX_ENABLE ... TEGRA210_I2S_RX_SOFT_RESET: + case TEGRA210_I2S_RX_INT_MASK ... TEGRA210_I2S_RX_CLK_TRIM: + case TEGRA210_I2S_TX_ENABLE ... TEGRA210_I2S_TX_SOFT_RESET: + case TEGRA210_I2S_TX_INT_MASK ... TEGRA210_I2S_TX_CLK_TRIM: + case TEGRA210_I2S_ENABLE ... TEGRA210_I2S_CG: + case TEGRA210_I2S_CTRL ... TEGRA210_I2S_CYA: + return true; + default: + return false; + }; +} + +static bool tegra210_i2s_rd_reg(struct device *dev, unsigned int reg) +{ + if (tegra210_i2s_wr_reg(dev, reg)) + return true; + + switch (reg) { + case TEGRA210_I2S_RX_STATUS: + case TEGRA210_I2S_RX_INT_STATUS: + case TEGRA210_I2S_RX_CIF_FIFO_STATUS: + case TEGRA210_I2S_TX_STATUS: + case TEGRA210_I2S_TX_INT_STATUS: + case TEGRA210_I2S_TX_CIF_FIFO_STATUS: + case TEGRA210_I2S_STATUS: + case TEGRA210_I2S_INT_STATUS: + return true; + default: + return false; + }; +} + +static bool tegra210_i2s_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_I2S_RX_STATUS: + case TEGRA210_I2S_RX_INT_STATUS: + case TEGRA210_I2S_RX_CIF_FIFO_STATUS: + case TEGRA210_I2S_TX_STATUS: + case TEGRA210_I2S_TX_INT_STATUS: + case TEGRA210_I2S_TX_CIF_FIFO_STATUS: + case TEGRA210_I2S_STATUS: + case TEGRA210_I2S_INT_STATUS: + case TEGRA210_I2S_RX_SOFT_RESET: + case TEGRA210_I2S_TX_SOFT_RESET: + return true; + default: + return false; + }; +} + +static const struct regmap_config tegra210_i2s_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA210_I2S_CYA, + .writeable_reg = tegra210_i2s_wr_reg, + .readable_reg = tegra210_i2s_rd_reg, + .volatile_reg = tegra210_i2s_volatile_reg, + .reg_defaults = tegra210_i2s_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tegra210_i2s_reg_defaults), + .cache_type = REGCACHE_FLAT, +}; + +static int tegra210_i2s_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra210_i2s *i2s; + void __iomem *regs; + int err; + + i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL); + if (!i2s) + return -ENOMEM; + + i2s->rx_fifo_th = DEFAULT_I2S_RX_FIFO_THRESHOLD; + i2s->tx_mask = DEFAULT_I2S_SLOT_MASK; + i2s->rx_mask = DEFAULT_I2S_SLOT_MASK; + i2s->loopback = false; + + dev_set_drvdata(dev, i2s); + + i2s->clk_i2s = devm_clk_get(dev, "i2s"); + if (IS_ERR(i2s->clk_i2s)) { + dev_err(dev, "can't retrieve I2S bit clock\n"); + return PTR_ERR(i2s->clk_i2s); + } + + /* + * Not an error, as this clock is needed only when some other I/O + * requires input clock from current I2S instance, which is + * configurable from DT. + */ + i2s->clk_sync_input = devm_clk_get(dev, "sync_input"); + if (IS_ERR(i2s->clk_sync_input)) + dev_dbg(dev, "can't retrieve I2S sync input clock\n"); + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + i2s->regmap = devm_regmap_init_mmio(dev, regs, + &tegra210_i2s_regmap_config); + if (IS_ERR(i2s->regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(i2s->regmap); + } + + regcache_cache_only(i2s->regmap, true); + + err = devm_snd_soc_register_component(dev, &tegra210_i2s_cmpnt, + tegra210_i2s_dais, + ARRAY_SIZE(tegra210_i2s_dais)); + if (err) { + dev_err(dev, "can't register I2S component, err: %d\n", err); + return err; + } + + pm_runtime_enable(dev); + + return 0; +} + +static int tegra210_i2s_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops tegra210_i2s_pm_ops = { + SET_RUNTIME_PM_OPS(tegra210_i2s_runtime_suspend, + tegra210_i2s_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static const struct of_device_id tegra210_i2s_of_match[] = { + { .compatible = "nvidia,tegra210-i2s" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra210_i2s_of_match); + +static struct platform_driver tegra210_i2s_driver = { + .driver = { + .name = "tegra210-i2s", + .of_match_table = tegra210_i2s_of_match, + .pm = &tegra210_i2s_pm_ops, + }, + .probe = tegra210_i2s_probe, + .remove = tegra210_i2s_remove, +}; +module_platform_driver(tegra210_i2s_driver) + +MODULE_AUTHOR("Songhee Baek "); +MODULE_DESCRIPTION("Tegra210 ASoC I2S driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/tegra/tegra210_i2s.h b/sound/soc/tegra/tegra210_i2s.h new file mode 100644 index 0000000000000000000000000000000000000000..030d70c45e18ba35757a13e32690183bd57cd387 --- /dev/null +++ b/sound/soc/tegra/tegra210_i2s.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra210_i2s.h - Definitions for Tegra210 I2S driver + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA210_I2S_H__ +#define __TEGRA210_I2S_H__ + +/* Register offsets from I2S*_BASE */ +#define TEGRA210_I2S_RX_ENABLE 0x0 +#define TEGRA210_I2S_RX_SOFT_RESET 0x4 +#define TEGRA210_I2S_RX_STATUS 0x0c +#define TEGRA210_I2S_RX_INT_STATUS 0x10 +#define TEGRA210_I2S_RX_INT_MASK 0x14 +#define TEGRA210_I2S_RX_INT_SET 0x18 +#define TEGRA210_I2S_RX_INT_CLEAR 0x1c +#define TEGRA210_I2S_RX_CIF_CTRL 0x20 +#define TEGRA210_I2S_RX_CTRL 0x24 +#define TEGRA210_I2S_RX_SLOT_CTRL 0x28 +#define TEGRA210_I2S_RX_CLK_TRIM 0x2c +#define TEGRA210_I2S_RX_CYA 0x30 +#define TEGRA210_I2S_RX_CIF_FIFO_STATUS 0x34 +#define TEGRA210_I2S_TX_ENABLE 0x40 +#define TEGRA210_I2S_TX_SOFT_RESET 0x44 +#define TEGRA210_I2S_TX_STATUS 0x4c +#define TEGRA210_I2S_TX_INT_STATUS 0x50 +#define TEGRA210_I2S_TX_INT_MASK 0x54 +#define TEGRA210_I2S_TX_INT_SET 0x58 +#define TEGRA210_I2S_TX_INT_CLEAR 0x5c +#define TEGRA210_I2S_TX_CIF_CTRL 0x60 +#define TEGRA210_I2S_TX_CTRL 0x64 +#define TEGRA210_I2S_TX_SLOT_CTRL 0x68 +#define TEGRA210_I2S_TX_CLK_TRIM 0x6c +#define TEGRA210_I2S_TX_CYA 0x70 +#define TEGRA210_I2S_TX_CIF_FIFO_STATUS 0x74 +#define TEGRA210_I2S_ENABLE 0x80 +#define TEGRA210_I2S_SOFT_RESET 0x84 +#define TEGRA210_I2S_CG 0x88 +#define TEGRA210_I2S_STATUS 0x8c +#define TEGRA210_I2S_INT_STATUS 0x90 +#define TEGRA210_I2S_CTRL 0xa0 +#define TEGRA210_I2S_TIMING 0xa4 +#define TEGRA210_I2S_SLOT_CTRL 0xa8 +#define TEGRA210_I2S_CLK_TRIM 0xac +#define TEGRA210_I2S_CYA 0xb0 + +/* Bit fields, shifts and masks */ +#define I2S_DATA_SHIFT 8 +#define I2S_CTRL_DATA_OFFSET_MASK (0x7ff << I2S_DATA_SHIFT) + +#define I2S_EN_SHIFT 0 +#define I2S_EN_MASK BIT(I2S_EN_SHIFT) +#define I2S_EN BIT(I2S_EN_SHIFT) + +#define I2S_FSYNC_WIDTH_SHIFT 24 +#define I2S_CTRL_FSYNC_WIDTH_MASK (0xff << I2S_FSYNC_WIDTH_SHIFT) + +#define I2S_POS_EDGE 0 +#define I2S_NEG_EDGE 1 +#define I2S_EDGE_SHIFT 20 +#define I2S_CTRL_EDGE_CTRL_MASK BIT(I2S_EDGE_SHIFT) +#define I2S_CTRL_EDGE_CTRL_POS_EDGE (I2S_POS_EDGE << I2S_EDGE_SHIFT) +#define I2S_CTRL_EDGE_CTRL_NEG_EDGE (I2S_NEG_EDGE << I2S_EDGE_SHIFT) + +#define I2S_FMT_LRCK 0 +#define I2S_FMT_FSYNC 1 +#define I2S_FMT_SHIFT 12 +#define I2S_CTRL_FRAME_FMT_MASK (7 << I2S_FMT_SHIFT) +#define I2S_CTRL_FRAME_FMT_LRCK_MODE (I2S_FMT_LRCK << I2S_FMT_SHIFT) +#define I2S_CTRL_FRAME_FMT_FSYNC_MODE (I2S_FMT_FSYNC << I2S_FMT_SHIFT) + +#define I2S_CTRL_MASTER_EN_SHIFT 10 +#define I2S_CTRL_MASTER_EN_MASK BIT(I2S_CTRL_MASTER_EN_SHIFT) +#define I2S_CTRL_MASTER_EN BIT(I2S_CTRL_MASTER_EN_SHIFT) + +#define I2S_CTRL_LRCK_POL_SHIFT 9 +#define I2S_CTRL_LRCK_POL_MASK BIT(I2S_CTRL_LRCK_POL_SHIFT) +#define I2S_CTRL_LRCK_POL_LOW (0 << I2S_CTRL_LRCK_POL_SHIFT) +#define I2S_CTRL_LRCK_POL_HIGH BIT(I2S_CTRL_LRCK_POL_SHIFT) + +#define I2S_CTRL_LPBK_SHIFT 8 +#define I2S_CTRL_LPBK_MASK BIT(I2S_CTRL_LPBK_SHIFT) +#define I2S_CTRL_LPBK_EN BIT(I2S_CTRL_LPBK_SHIFT) + +#define I2S_BITS_8 1 +#define I2S_BITS_16 3 +#define I2S_BITS_32 7 +#define I2S_CTRL_BIT_SIZE_MASK 0x7 + +#define I2S_TIMING_CH_BIT_CNT_MASK 0x7ff +#define I2S_TIMING_CH_BIT_CNT_SHIFT 0 + +#define I2S_SOFT_RESET_SHIFT 0 +#define I2S_SOFT_RESET_MASK BIT(I2S_SOFT_RESET_SHIFT) +#define I2S_SOFT_RESET_EN BIT(I2S_SOFT_RESET_SHIFT) + +#define I2S_RX_FIFO_DEPTH 64 +#define DEFAULT_I2S_RX_FIFO_THRESHOLD 3 + +#define DEFAULT_I2S_SLOT_MASK 0xffff + +enum tegra210_i2s_path { + I2S_RX_PATH, + I2S_TX_PATH, + I2S_PATHS, +}; + +struct tegra210_i2s { + struct clk *clk_i2s; + struct clk *clk_sync_input; + struct regmap *regmap; + unsigned int stereo_to_mono[I2S_PATHS]; + unsigned int mono_to_stereo[I2S_PATHS]; + unsigned int dai_fmt; + unsigned int fsync_width; + unsigned int bclk_ratio; + unsigned int tx_mask; + unsigned int rx_mask; + unsigned int rx_fifo_th; + bool loopback; +}; + +#endif diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 635eacbd28d473f2711e227d3706a2b462619537..156e3b9d613c6eabaa8745ed0cfa510e3aaaaf3e 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -643,8 +643,10 @@ static int tegra30_ahub_resume(struct device *dev) int ret; ret = pm_runtime_get_sync(dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put(dev); return ret; + } ret = regcache_sync(ahub->regmap_ahub); ret |= regcache_sync(ahub->regmap_apbif); pm_runtime_put(dev); diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index d59882ec48f164664ae9eb88b8e9859f27112dfc..db5a8587bfa4c38b10334ac61c108c44bc5b79dc 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -567,8 +567,10 @@ static int tegra30_i2s_resume(struct device *dev) int ret; ret = pm_runtime_get_sync(dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put(dev); return ret; + } ret = regcache_sync(i2s->regmap); pm_runtime_put(dev); diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 2839c6cb8c3867194eef33c1edcaeac24c5d1c56..8661877bf4c6f7cd2e4a3c9bd96bf30d913cf65a 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -36,7 +36,7 @@ struct tegra_alc5632 { static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_cif.h b/sound/soc/tegra/tegra_cif.h new file mode 100644 index 0000000000000000000000000000000000000000..7cca8068f4b58130b842cfe051f0cadff2620bd9 --- /dev/null +++ b/sound/soc/tegra/tegra_cif.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra_cif.h - TEGRA Audio CIF Programming + * + * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA_CIF_H__ +#define __TEGRA_CIF_H__ + +#include + +#define TEGRA_ACIF_CTRL_FIFO_TH_SHIFT 24 +#define TEGRA_ACIF_CTRL_AUDIO_CH_SHIFT 20 +#define TEGRA_ACIF_CTRL_CLIENT_CH_SHIFT 16 +#define TEGRA_ACIF_CTRL_AUDIO_BITS_SHIFT 12 +#define TEGRA_ACIF_CTRL_CLIENT_BITS_SHIFT 8 +#define TEGRA_ACIF_CTRL_EXPAND_SHIFT 6 +#define TEGRA_ACIF_CTRL_STEREO_CONV_SHIFT 4 +#define TEGRA_ACIF_CTRL_REPLICATE_SHIFT 3 +#define TEGRA_ACIF_CTRL_TRUNCATE_SHIFT 1 +#define TEGRA_ACIF_CTRL_MONO_CONV_SHIFT 0 + +/* AUDIO/CLIENT_BITS values */ +#define TEGRA_ACIF_BITS_8 1 +#define TEGRA_ACIF_BITS_16 3 +#define TEGRA_ACIF_BITS_24 5 +#define TEGRA_ACIF_BITS_32 7 + +#define TEGRA_ACIF_UPDATE_MASK 0x3ffffffb + +struct tegra_cif_conf { + unsigned int threshold; + unsigned int audio_ch; + unsigned int client_ch; + unsigned int audio_bits; + unsigned int client_bits; + unsigned int expand; + unsigned int stereo_conv; + unsigned int replicate; + unsigned int truncate; + unsigned int mono_conv; +}; + +static inline void tegra_set_cif(struct regmap *regmap, unsigned int reg, + struct tegra_cif_conf *conf) +{ + unsigned int value; + + value = (conf->threshold << TEGRA_ACIF_CTRL_FIFO_TH_SHIFT) | + ((conf->audio_ch - 1) << TEGRA_ACIF_CTRL_AUDIO_CH_SHIFT) | + ((conf->client_ch - 1) << TEGRA_ACIF_CTRL_CLIENT_CH_SHIFT) | + (conf->audio_bits << TEGRA_ACIF_CTRL_AUDIO_BITS_SHIFT) | + (conf->client_bits << TEGRA_ACIF_CTRL_CLIENT_BITS_SHIFT) | + (conf->expand << TEGRA_ACIF_CTRL_EXPAND_SHIFT) | + (conf->stereo_conv << TEGRA_ACIF_CTRL_STEREO_CONV_SHIFT) | + (conf->replicate << TEGRA_ACIF_CTRL_REPLICATE_SHIFT) | + (conf->truncate << TEGRA_ACIF_CTRL_TRUNCATE_SHIFT) | + (conf->mono_conv << TEGRA_ACIF_CTRL_MONO_CONV_SHIFT); + + regmap_update_bits(regmap, reg, TEGRA_ACIF_UPDATE_MASK, value); +} + +#endif diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c index ec9050516cd7e4488ca65854efb5def69821efe1..af3e9e6daa40583882ee3949d8d4b9977d1f840e 100644 --- a/sound/soc/tegra/tegra_max98090.c +++ b/sound/soc/tegra/tegra_max98090.c @@ -37,7 +37,7 @@ struct tegra_max98090 { static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index f246df8ecf7b7957aba8307944469e4a59fc9a42..b3f36515cbc188aa6ec0c1a938b5cdfdea865bf8 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -16,12 +16,12 @@ */ #include +#include #include #include #include #include #include - #include "tegra_pcm.h" static const struct snd_pcm_hardware tegra_pcm_hardware = { @@ -67,6 +67,239 @@ void tegra_pcm_platform_unregister(struct device *dev) } EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister); +int tegra_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_dmaengine_dai_dma_data *dmap; + struct dma_chan *chan; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + int ret; + + if (rtd->dai_link->no_pcm) + return 0; + + dmap = snd_soc_dai_get_dma_data(cpu_dai, substream); + + /* Set HW params now that initialization is complete */ + snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); + + /* Ensure period size is multiple of 8 */ + ret = snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x8); + if (ret) { + dev_err(rtd->dev, "failed to set constraint %d\n", ret); + return ret; + } + + chan = dma_request_slave_channel(cpu_dai->dev, dmap->chan_name); + if (!chan) { + dev_err(cpu_dai->dev, + "dmaengine request slave channel failed! (%s)\n", + dmap->chan_name); + return -ENODEV; + } + + ret = snd_dmaengine_pcm_open(substream, chan); + if (ret) { + dev_err(rtd->dev, + "dmaengine pcm open failed with err %d (%s)\n", ret, + dmap->chan_name); + + dma_release_channel(chan); + + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_pcm_open); + +int tegra_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + if (rtd->dai_link->no_pcm) + return 0; + + snd_dmaengine_pcm_close_release_chan(substream); + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_pcm_close); + +int tegra_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_dmaengine_dai_dma_data *dmap; + struct dma_slave_config slave_config; + struct dma_chan *chan; + int ret; + + if (rtd->dai_link->no_pcm) + return 0; + + dmap = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); + if (!dmap) + return 0; + + chan = snd_dmaengine_pcm_get_chan(substream); + + ret = snd_hwparams_to_dma_slave_config(substream, params, + &slave_config); + if (ret) { + dev_err(rtd->dev, "hw params config failed with err %d\n", ret); + return ret; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.dst_addr = dmap->addr; + slave_config.dst_maxburst = 8; + } else { + slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.src_addr = dmap->addr; + slave_config.src_maxburst = 8; + } + + ret = dmaengine_slave_config(chan, &slave_config); + if (ret < 0) { + dev_err(rtd->dev, "dma slave config failed with err %d\n", ret); + return ret; + } + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_pcm_hw_params); + +int tegra_pcm_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + if (rtd->dai_link->no_pcm) + return 0; + + snd_pcm_set_runtime_buffer(substream, NULL); + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_pcm_hw_free); + +int tegra_pcm_mmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + + if (rtd->dai_link->no_pcm) + return 0; + + return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area, + runtime->dma_addr, runtime->dma_bytes); +} +EXPORT_SYMBOL_GPL(tegra_pcm_mmap); + +snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + return snd_dmaengine_pcm_pointer(substream); +} +EXPORT_SYMBOL_GPL(tegra_pcm_pointer); + +static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream, + size_t size) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + + buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + + buf->private_data = NULL; + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->bytes = size; + + return 0; +} + +static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + + substream = pcm->streams[stream].substream; + if (!substream) + return; + + buf = &substream->dma_buffer; + if (!buf->area) + return; + + dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr); + buf->area = NULL; +} + +static int tegra_pcm_dma_allocate(struct snd_soc_pcm_runtime *rtd, + size_t size) +{ + struct snd_card *card = rtd->card->snd_card; + struct snd_pcm *pcm = rtd->pcm; + int ret; + + ret = dma_set_mask(card->dev, DMA_BIT_MASK(32)); + if (ret < 0) + return ret; + + ret = dma_set_coherent_mask(card->dev, DMA_BIT_MASK(32)); + if (ret < 0) + return ret; + + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { + ret = tegra_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_PLAYBACK, size); + if (ret) + goto err; + } + + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + ret = tegra_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_CAPTURE, size); + if (ret) + goto err_free_play; + } + + return 0; + +err_free_play: + tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); +err: + return ret; +} + +int tegra_pcm_construct(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + return tegra_pcm_dma_allocate(rtd, tegra_pcm_hardware.buffer_bytes_max); +} +EXPORT_SYMBOL_GPL(tegra_pcm_construct); + +void tegra_pcm_destruct(struct snd_soc_component *component, + struct snd_pcm *pcm) +{ + tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); + tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); +} +EXPORT_SYMBOL_GPL(tegra_pcm_destruct); + MODULE_AUTHOR("Stephen Warren "); MODULE_DESCRIPTION("Tegra PCM ASoC driver"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h index 0433372e68d4cd04d21b56eded01dc3df63f7555..4838cdcee20e49d60f1b6b3c7fa748c1c5592952 100644 --- a/sound/soc/tegra/tegra_pcm.h +++ b/sound/soc/tegra/tegra_pcm.h @@ -17,8 +17,27 @@ #ifndef __TEGRA_PCM_H__ #define __TEGRA_PCM_H__ -struct snd_dmaengine_pcm_config; +#include +#include +int tegra_pcm_construct(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd); +void tegra_pcm_destruct(struct snd_soc_component *component, + struct snd_pcm *pcm); +int tegra_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream); +int tegra_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream); +int tegra_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +int tegra_pcm_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream); +int tegra_pcm_mmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct vm_area_struct *vma); +snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream); int tegra_pcm_platform_register(struct device *dev); int tegra_pcm_platform_register_with_chan_names(struct device *dev, struct snd_dmaengine_pcm_config *config, diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index 201d132731f9b4a6c6c4a7f1fd182dfccc590360..d66d8659396b4a6fd7fe84ea5ab8c6b66a2cc4ca 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c @@ -39,7 +39,7 @@ struct tegra_rt5640 { static int tegra_rt5640_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_rt5677.c b/sound/soc/tegra/tegra_rt5677.c index 8f71e21f6ee9715412dad4594fb254347f07e82c..7504507dd8b855772e54beceb8e78fdb5aeb7129 100644 --- a/sound/soc/tegra/tegra_rt5677.c +++ b/sound/soc/tegra/tegra_rt5677.c @@ -41,7 +41,7 @@ struct tegra_rt5677 { static int tegra_rt5677_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_sgtl5000.c b/sound/soc/tegra/tegra_sgtl5000.c index 692fcc3d7d6e60b2903dc52456cc49def0c78309..e1dc8e7d337a2335ec2ffc72c2ee9dc7bf92ee8a 100644 --- a/sound/soc/tegra/tegra_sgtl5000.c +++ b/sound/soc/tegra/tegra_sgtl5000.c @@ -35,7 +35,7 @@ struct tegra_sgtl5000 { static int tegra_sgtl5000_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_sgtl5000 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 2ee2ed190872d3fcb7508bd9e06692241e5ca005..ec3ee0580867eef34f54e4f9fc2193fbce3c4593 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c @@ -39,7 +39,7 @@ struct tegra_wm8753 { static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index d3ead0213cef028ba5944d3ae7c0f2e3db289389..ef6652aaac9b6ef9d57e75297f4cba4b3c5cde33 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -44,7 +44,7 @@ struct tegra_wm8903 { static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 6dca6836aa048bb771ad95d7a36e504eb98c1131..cdb386d6e5c3c73f375b79b69a719f490af4bcef 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -34,7 +34,7 @@ struct tegra_trimslice { static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig index c5408c129f342d63dbd85d90a2b87cdfa2d053a3..1e6ab87e446092dce9add20961eb4455b56e3a34 100644 --- a/sound/soc/ti/Kconfig +++ b/sound/soc/ti/Kconfig @@ -219,5 +219,14 @@ config SND_SOC_DM365_VOICE_CODEC_MODULE The is an internal symbol needed to ensure that the codec and MFD driver can be built as loadable modules if necessary. +config SND_SOC_J721E_EVM + tristate "SoC Audio support for j721e EVM" + depends on ARCH_K3_J721E_SOC || COMPILE_TEST + depends on I2C + select SND_SOC_PCM3168A_I2C + select SND_SOC_DAVINCI_MCASP + help + Say Y if you want to add support for SoC audio on j721e Common + Processor Board and Infotainment expansion board. endmenu diff --git a/sound/soc/ti/Makefile b/sound/soc/ti/Makefile index ea48c6679cc72f8b1d92299c53bc2d982e763eac..a21e5b0061de3ca53a59d1c562dc51be84188e7a 100644 --- a/sound/soc/ti/Makefile +++ b/sound/soc/ti/Makefile @@ -34,6 +34,7 @@ snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o snd-soc-ams-delta-objs := ams-delta.o snd-soc-omap-hdmi-objs := omap-hdmi.o snd-soc-osk5912-objs := osk5912.o +snd-soc-j721e-evm-objs := j721e-evm.o obj-$(CONFIG_SND_SOC_DAVINCI_EVM) += snd-soc-davinci-evm.o obj-$(CONFIG_SND_SOC_NOKIA_N810) += snd-soc-n810.o @@ -44,3 +45,4 @@ obj-$(CONFIG_SND_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o obj-$(CONFIG_SND_SOC_OMAP_AMS_DELTA) += snd-soc-ams-delta.o obj-$(CONFIG_SND_SOC_OMAP_HDMI) += snd-soc-omap-hdmi.o obj-$(CONFIG_SND_SOC_OMAP_OSK5912) += snd-soc-osk5912.o +obj-$(CONFIG_SND_SOC_J721E_EVM) += snd-soc-j721e-evm.o diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c index e17cd5e939f0806fa55d25105b3b4a82b9438fb0..5c47de96c529860c086c4af3f309b6e5861038f6 100644 --- a/sound/soc/ti/ams-delta.c +++ b/sound/soc/ti/ams-delta.c @@ -420,7 +420,7 @@ static struct snd_soc_ops ams_delta_ops; * Shares hardware with codec config pulse generation */ static bool ams_delta_muted = 1; -static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute) +static int ams_delta_mute(struct snd_soc_dai *dai, int mute, int direction) { int apply; @@ -439,18 +439,19 @@ static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute) /* Our codec DAI probably doesn't have its own .ops structure */ static const struct snd_soc_dai_ops ams_delta_dai_ops = { - .digital_mute = ams_delta_digital_mute, + .mute_stream = ams_delta_mute, + .no_capture_mute = 1, }; /* Will be used if the codec ever has its own digital_mute function */ static int ams_delta_startup(struct snd_pcm_substream *substream) { - return ams_delta_digital_mute(NULL, 0); + return ams_delta_digital_mute(NULL, 0, substream->stream); } static void ams_delta_shutdown(struct snd_pcm_substream *substream) { - ams_delta_digital_mute(NULL, 1); + ams_delta_digital_mute(NULL, 1, substream->stream); } diff --git a/sound/soc/ti/davinci-evm.c b/sound/soc/ti/davinci-evm.c index 2cfbeebdfb41b6a6a1d1a77fe1aa7a577515022a..105e56ab9cdc25b06226f504f9dd4d517599945c 100644 --- a/sound/soc/ti/davinci-evm.c +++ b/sound/soc/ti/davinci-evm.c @@ -28,7 +28,7 @@ struct snd_soc_card_drvdata_davinci { static int evm_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *soc_card = rtd->card; struct snd_soc_card_drvdata_davinci *drvdata = snd_soc_card_get_drvdata(soc_card); @@ -41,7 +41,7 @@ static int evm_startup(struct snd_pcm_substream *substream) static void evm_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *soc_card = rtd->card; struct snd_soc_card_drvdata_davinci *drvdata = snd_soc_card_get_drvdata(soc_card); @@ -53,7 +53,7 @@ static void evm_shutdown(struct snd_pcm_substream *substream) static int evm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_card *soc_card = rtd->card; diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index b93c1ee302c0c438ee10228033ac85ff4dec5730..617440767c45fd66c0f6e1b113823804a29e44d2 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -1623,12 +1623,14 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { .name = "davinci-mcasp.0", .probe = davinci_mcasp_dai_probe, .playback = { + .stream_name = "IIS Playback", .channels_min = 1, .channels_max = 32 * 16, .rates = DAVINCI_MCASP_RATES, .formats = DAVINCI_MCASP_PCM_FMTS, }, .capture = { + .stream_name = "IIS Capture", .channels_min = 1, .channels_max = 32 * 16, .rates = DAVINCI_MCASP_RATES, @@ -1642,6 +1644,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { .name = "davinci-mcasp.1", .probe = davinci_mcasp_dai_probe, .playback = { + .stream_name = "DIT Playback", .channels_min = 1, .channels_max = 384, .rates = DAVINCI_MCASP_RATES, diff --git a/sound/soc/ti/davinci-vcif.c b/sound/soc/ti/davinci-vcif.c index ee4d3ef821a1335a00fd85428385b8c1fcdf07f7..f810123cc40703d09afa439911976ff32727f30d 100644 --- a/sound/soc/ti/davinci-vcif.c +++ b/sound/soc/ti/davinci-vcif.c @@ -41,7 +41,7 @@ struct davinci_vcif_dev { static void davinci_vcif_start(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; @@ -60,7 +60,7 @@ static void davinci_vcif_start(struct snd_pcm_substream *substream) static void davinci_vcif_stop(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; diff --git a/sound/soc/ti/j721e-evm.c b/sound/soc/ti/j721e-evm.c new file mode 100644 index 0000000000000000000000000000000000000000..cb074af47a7d0abdebc8a8fdacb61ec2e31fa61e --- /dev/null +++ b/sound/soc/ti/j721e-evm.c @@ -0,0 +1,896 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com + * Author: Peter Ujfalusi + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "davinci-mcasp.h" + +/* + * Maximum number of configuration entries for prefixes: + * CPB: 2 (mcasp10 + codec) + * IVI: 3 (mcasp0 + 2x codec) + */ +#define J721E_CODEC_CONF_COUNT 5 + +#define J721E_AUDIO_DOMAIN_CPB 0 +#define J721E_AUDIO_DOMAIN_IVI 1 + +#define J721E_CLK_PARENT_48000 0 +#define J721E_CLK_PARENT_44100 1 + +#define J721E_MAX_CLK_HSDIV 128 +#define PCM1368A_MAX_SYSCLK 36864000 + +#define J721E_DAI_FMT (SND_SOC_DAIFMT_RIGHT_J | \ + SND_SOC_DAIFMT_NB_NF | \ + SND_SOC_DAIFMT_CBS_CFS) + +enum j721e_board_type { + J721E_BOARD_CPB = 1, + J721E_BOARD_CPB_IVI, +}; + +struct j721e_audio_match_data { + enum j721e_board_type board_type; + int num_links; + unsigned int pll_rates[2]; +}; + +static unsigned int ratios_for_pcm3168a[] = { + 256, + 512, + 768, +}; + +struct j721e_audio_clocks { + struct clk *target; + struct clk *parent[2]; +}; + +struct j721e_audio_domain { + struct j721e_audio_clocks codec; + struct j721e_audio_clocks mcasp; + int parent_clk_id; + + int active; + unsigned int active_link; + unsigned int rate; +}; + +struct j721e_priv { + struct device *dev; + struct snd_soc_card card; + struct snd_soc_dai_link *dai_links; + struct snd_soc_codec_conf codec_conf[J721E_CODEC_CONF_COUNT]; + struct snd_interval rate_range; + const struct j721e_audio_match_data *match_data; + u32 pll_rates[2]; + unsigned int hsdiv_rates[2]; + + struct j721e_audio_domain audio_domains[2]; + + struct mutex mutex; +}; + +static const struct snd_soc_dapm_widget j721e_cpb_dapm_widgets[] = { + SND_SOC_DAPM_HP("CPB Stereo HP 1", NULL), + SND_SOC_DAPM_HP("CPB Stereo HP 2", NULL), + SND_SOC_DAPM_HP("CPB Stereo HP 3", NULL), + SND_SOC_DAPM_LINE("CPB Line Out", NULL), + SND_SOC_DAPM_MIC("CPB Stereo Mic 1", NULL), + SND_SOC_DAPM_MIC("CPB Stereo Mic 2", NULL), + SND_SOC_DAPM_LINE("CPB Line In", NULL), +}; + +static const struct snd_soc_dapm_route j721e_cpb_dapm_routes[] = { + {"CPB Stereo HP 1", NULL, "codec-1 AOUT1L"}, + {"CPB Stereo HP 1", NULL, "codec-1 AOUT1R"}, + {"CPB Stereo HP 2", NULL, "codec-1 AOUT2L"}, + {"CPB Stereo HP 2", NULL, "codec-1 AOUT2R"}, + {"CPB Stereo HP 3", NULL, "codec-1 AOUT3L"}, + {"CPB Stereo HP 3", NULL, "codec-1 AOUT3R"}, + {"CPB Line Out", NULL, "codec-1 AOUT4L"}, + {"CPB Line Out", NULL, "codec-1 AOUT4R"}, + + {"codec-1 AIN1L", NULL, "CPB Stereo Mic 1"}, + {"codec-1 AIN1R", NULL, "CPB Stereo Mic 1"}, + {"codec-1 AIN2L", NULL, "CPB Stereo Mic 2"}, + {"codec-1 AIN2R", NULL, "CPB Stereo Mic 2"}, + {"codec-1 AIN3L", NULL, "CPB Line In"}, + {"codec-1 AIN3R", NULL, "CPB Line In"}, +}; + +static const struct snd_soc_dapm_widget j721e_ivi_codec_a_dapm_widgets[] = { + SND_SOC_DAPM_LINE("IVI A Line Out 1", NULL), + SND_SOC_DAPM_LINE("IVI A Line Out 2", NULL), + SND_SOC_DAPM_LINE("IVI A Line Out 3", NULL), + SND_SOC_DAPM_LINE("IVI A Line Out 4", NULL), + SND_SOC_DAPM_MIC("IVI A Stereo Mic 1", NULL), + SND_SOC_DAPM_MIC("IVI A Stereo Mic 2", NULL), + SND_SOC_DAPM_LINE("IVI A Line In", NULL), +}; + +static const struct snd_soc_dapm_route j721e_codec_a_dapm_routes[] = { + {"IVI A Line Out 1", NULL, "codec-a AOUT1L"}, + {"IVI A Line Out 1", NULL, "codec-a AOUT1R"}, + {"IVI A Line Out 2", NULL, "codec-a AOUT2L"}, + {"IVI A Line Out 2", NULL, "codec-a AOUT2R"}, + {"IVI A Line Out 3", NULL, "codec-a AOUT3L"}, + {"IVI A Line Out 3", NULL, "codec-a AOUT3R"}, + {"IVI A Line Out 4", NULL, "codec-a AOUT4L"}, + {"IVI A Line Out 4", NULL, "codec-a AOUT4R"}, + + {"codec-a AIN1L", NULL, "IVI A Stereo Mic 1"}, + {"codec-a AIN1R", NULL, "IVI A Stereo Mic 1"}, + {"codec-a AIN2L", NULL, "IVI A Stereo Mic 2"}, + {"codec-a AIN2R", NULL, "IVI A Stereo Mic 2"}, + {"codec-a AIN3L", NULL, "IVI A Line In"}, + {"codec-a AIN3R", NULL, "IVI A Line In"}, +}; + +static const struct snd_soc_dapm_widget j721e_ivi_codec_b_dapm_widgets[] = { + SND_SOC_DAPM_LINE("IVI B Line Out 1", NULL), + SND_SOC_DAPM_LINE("IVI B Line Out 2", NULL), + SND_SOC_DAPM_LINE("IVI B Line Out 3", NULL), + SND_SOC_DAPM_LINE("IVI B Line Out 4", NULL), + SND_SOC_DAPM_MIC("IVI B Stereo Mic 1", NULL), + SND_SOC_DAPM_MIC("IVI B Stereo Mic 2", NULL), + SND_SOC_DAPM_LINE("IVI B Line In", NULL), +}; + +static const struct snd_soc_dapm_route j721e_codec_b_dapm_routes[] = { + {"IVI B Line Out 1", NULL, "codec-b AOUT1L"}, + {"IVI B Line Out 1", NULL, "codec-b AOUT1R"}, + {"IVI B Line Out 2", NULL, "codec-b AOUT2L"}, + {"IVI B Line Out 2", NULL, "codec-b AOUT2R"}, + {"IVI B Line Out 3", NULL, "codec-b AOUT3L"}, + {"IVI B Line Out 3", NULL, "codec-b AOUT3R"}, + {"IVI B Line Out 4", NULL, "codec-b AOUT4L"}, + {"IVI B Line Out 4", NULL, "codec-b AOUT4R"}, + + {"codec-b AIN1L", NULL, "IVI B Stereo Mic 1"}, + {"codec-b AIN1R", NULL, "IVI B Stereo Mic 1"}, + {"codec-b AIN2L", NULL, "IVI B Stereo Mic 2"}, + {"codec-b AIN2R", NULL, "IVI B Stereo Mic 2"}, + {"codec-b AIN3L", NULL, "IVI B Line In"}, + {"codec-b AIN3R", NULL, "IVI B Line In"}, +}; + +static int j721e_configure_refclk(struct j721e_priv *priv, + unsigned int audio_domain, unsigned int rate) +{ + struct j721e_audio_domain *domain = &priv->audio_domains[audio_domain]; + unsigned int scki; + int ret = -EINVAL; + int i, clk_id; + + if (!(rate % 8000) && priv->pll_rates[J721E_CLK_PARENT_48000]) + clk_id = J721E_CLK_PARENT_48000; + else if (!(rate % 11025) && priv->pll_rates[J721E_CLK_PARENT_44100]) + clk_id = J721E_CLK_PARENT_44100; + else + return ret; + + for (i = 0; i < ARRAY_SIZE(ratios_for_pcm3168a); i++) { + scki = ratios_for_pcm3168a[i] * rate; + + if (priv->pll_rates[clk_id] / scki <= J721E_MAX_CLK_HSDIV) { + ret = 0; + break; + } + } + + if (ret) { + dev_err(priv->dev, "No valid clock configuration for %u Hz\n", + rate); + return ret; + } + + if (priv->hsdiv_rates[domain->parent_clk_id] != scki) { + dev_dbg(priv->dev, + "%s configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n", + audio_domain == J721E_AUDIO_DOMAIN_CPB ? "CPB" : "IVI", + rate, + clk_id == J721E_CLK_PARENT_48000 ? "PLL4" : "PLL15", + ratios_for_pcm3168a[i], scki); + + if (domain->parent_clk_id != clk_id) { + ret = clk_set_parent(domain->codec.target, + domain->codec.parent[clk_id]); + if (ret) + return ret; + + ret = clk_set_parent(domain->mcasp.target, + domain->mcasp.parent[clk_id]); + if (ret) + return ret; + + domain->parent_clk_id = clk_id; + } + + ret = clk_set_rate(domain->codec.target, scki); + if (ret) { + dev_err(priv->dev, "codec set rate failed for %u Hz\n", + scki); + return ret; + } + + ret = clk_set_rate(domain->mcasp.target, scki); + if (!ret) { + priv->hsdiv_rates[domain->parent_clk_id] = scki; + } else { + dev_err(priv->dev, "mcasp set rate failed for %u Hz\n", + scki); + return ret; + } + } + + return ret; +} + +static int j721e_rule_rate(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_interval *t = rule->private; + + return snd_interval_refine(hw_param_interval(params, rule->var), t); +} + +static int j721e_audio_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); + unsigned int domain_id = rtd->dai_link->id; + struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai; + unsigned int active_rate; + int ret = 0; + int i; + + mutex_lock(&priv->mutex); + + domain->active++; + + if (priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate) + active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate; + else + active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].rate; + + if (active_rate) + ret = snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, + active_rate); + else + ret = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + j721e_rule_rate, &priv->rate_range, + SNDRV_PCM_HW_PARAM_RATE, -1); + + mutex_unlock(&priv->mutex); + + if (ret) + return ret; + + /* Reset TDM slots to 32 */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); + if (ret && ret != -ENOTSUPP) + return ret; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 32); + if (ret && ret != -ENOTSUPP) + return ret; + } + + return 0; +} + +static int j721e_audio_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct j721e_priv *priv = snd_soc_card_get_drvdata(card); + unsigned int domain_id = rtd->dai_link->id; + struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai; + unsigned int sysclk_rate; + int slot_width = 32; + int ret; + int i; + + mutex_lock(&priv->mutex); + + if (domain->rate && domain->rate != params_rate(params)) { + ret = -EINVAL; + goto out; + } + + if (params_width(params) == 16) + slot_width = 16; + + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, slot_width); + if (ret && ret != -ENOTSUPP) + goto out; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, + slot_width); + if (ret && ret != -ENOTSUPP) + goto out; + } + + ret = j721e_configure_refclk(priv, domain_id, params_rate(params)); + if (ret) + goto out; + + sysclk_rate = priv->hsdiv_rates[domain->parent_clk_id]; + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk_rate, + SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) { + dev_err(priv->dev, + "codec set_sysclk failed for %u Hz\n", + sysclk_rate); + goto out; + } + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, MCASP_CLK_HCLK_AUXCLK, + sysclk_rate, SND_SOC_CLOCK_IN); + + if (ret && ret != -ENOTSUPP) { + dev_err(priv->dev, "mcasp set_sysclk failed for %u Hz\n", + sysclk_rate); + } else { + domain->rate = params_rate(params); + ret = 0; + } + +out: + mutex_unlock(&priv->mutex); + return ret; +} + +static void j721e_audio_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); + unsigned int domain_id = rtd->dai_link->id; + struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; + + mutex_lock(&priv->mutex); + + domain->active--; + if (!domain->active) { + domain->rate = 0; + domain->active_link = 0; + } + + mutex_unlock(&priv->mutex); +} + +static const struct snd_soc_ops j721e_audio_ops = { + .startup = j721e_audio_startup, + .hw_params = j721e_audio_hw_params, + .shutdown = j721e_audio_shutdown, +}; + +static int j721e_audio_init(struct snd_soc_pcm_runtime *rtd) +{ + struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); + unsigned int domain_id = rtd->dai_link->id; + struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai; + unsigned int sysclk_rate; + int i, ret; + + /* Set up initial clock configuration */ + ret = j721e_configure_refclk(priv, domain_id, 48000); + if (ret) + return ret; + + sysclk_rate = priv->hsdiv_rates[domain->parent_clk_id]; + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk_rate, + SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) + return ret; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, MCASP_CLK_HCLK_AUXCLK, + sysclk_rate, SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) + return ret; + + /* Set initial tdm slots */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); + if (ret && ret != -ENOTSUPP) + return ret; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 32); + if (ret && ret != -ENOTSUPP) + return ret; + } + + return 0; +} + +static int j721e_audio_init_ivi(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dapm_context *dapm = &rtd->card->dapm; + + snd_soc_dapm_new_controls(dapm, j721e_ivi_codec_a_dapm_widgets, + ARRAY_SIZE(j721e_ivi_codec_a_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, j721e_codec_a_dapm_routes, + ARRAY_SIZE(j721e_codec_a_dapm_routes)); + snd_soc_dapm_new_controls(dapm, j721e_ivi_codec_b_dapm_widgets, + ARRAY_SIZE(j721e_ivi_codec_b_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, j721e_codec_b_dapm_routes, + ARRAY_SIZE(j721e_codec_b_dapm_routes)); + + return j721e_audio_init(rtd); +} + +static int j721e_get_clocks(struct device *dev, + struct j721e_audio_clocks *clocks, char *prefix) +{ + struct clk *parent; + char *clk_name; + int ret; + + clocks->target = devm_clk_get(dev, prefix); + if (IS_ERR(clocks->target)) { + ret = PTR_ERR(clocks->target); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to acquire %s: %d\n", + prefix, ret); + return ret; + } + + clk_name = kasprintf(GFP_KERNEL, "%s-48000", prefix); + if (clk_name) { + parent = devm_clk_get(dev, clk_name); + kfree(clk_name); + if (IS_ERR(parent)) { + ret = PTR_ERR(parent); + if (ret == -EPROBE_DEFER) + return ret; + + dev_dbg(dev, "no 48KHz parent for %s: %d\n", prefix, ret); + parent = NULL; + } + clocks->parent[J721E_CLK_PARENT_48000] = parent; + } else { + return -ENOMEM; + } + + clk_name = kasprintf(GFP_KERNEL, "%s-44100", prefix); + if (clk_name) { + parent = devm_clk_get(dev, clk_name); + kfree(clk_name); + if (IS_ERR(parent)) { + ret = PTR_ERR(parent); + if (ret == -EPROBE_DEFER) + return ret; + + dev_dbg(dev, "no 44.1KHz parent for %s: %d\n", prefix, ret); + parent = NULL; + } + clocks->parent[J721E_CLK_PARENT_44100] = parent; + } else { + return -ENOMEM; + } + + if (!clocks->parent[J721E_CLK_PARENT_44100] && + !clocks->parent[J721E_CLK_PARENT_48000]) { + dev_err(dev, "At least one parent clock is needed for %s\n", + prefix); + return -EINVAL; + } + + return 0; +} + +static const struct j721e_audio_match_data j721e_cpb_data = { + .board_type = J721E_BOARD_CPB, + .num_links = 2, /* CPB pcm3168a */ + .pll_rates = { + [J721E_CLK_PARENT_44100] = 1083801600, /* PLL15 */ + [J721E_CLK_PARENT_48000] = 1179648000, /* PLL4 */ + }, +}; + +static const struct j721e_audio_match_data j721e_cpb_ivi_data = { + .board_type = J721E_BOARD_CPB_IVI, + .num_links = 4, /* CPB pcm3168a + 2x pcm3168a on IVI */ + .pll_rates = { + [J721E_CLK_PARENT_44100] = 1083801600, /* PLL15 */ + [J721E_CLK_PARENT_48000] = 1179648000, /* PLL4 */ + }, +}; + +static const struct of_device_id j721e_audio_of_match[] = { + { + .compatible = "ti,j721e-cpb-audio", + .data = &j721e_cpb_data, + }, { + .compatible = "ti,j721e-cpb-ivi-audio", + .data = &j721e_cpb_ivi_data, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, j721e_audio_of_match); + +static int j721e_calculate_rate_range(struct j721e_priv *priv) +{ + const struct j721e_audio_match_data *match_data = priv->match_data; + struct j721e_audio_clocks *domain_clocks; + unsigned int min_rate, max_rate, pll_rate; + struct clk *pll; + + domain_clocks = &priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].mcasp; + + pll = clk_get_parent(domain_clocks->parent[J721E_CLK_PARENT_44100]); + if (IS_ERR_OR_NULL(pll)) { + priv->pll_rates[J721E_CLK_PARENT_44100] = + match_data->pll_rates[J721E_CLK_PARENT_44100]; + } else { + priv->pll_rates[J721E_CLK_PARENT_44100] = clk_get_rate(pll); + clk_put(pll); + } + + pll = clk_get_parent(domain_clocks->parent[J721E_CLK_PARENT_48000]); + if (IS_ERR_OR_NULL(pll)) { + priv->pll_rates[J721E_CLK_PARENT_48000] = + match_data->pll_rates[J721E_CLK_PARENT_48000]; + } else { + priv->pll_rates[J721E_CLK_PARENT_48000] = clk_get_rate(pll); + clk_put(pll); + } + + if (!priv->pll_rates[J721E_CLK_PARENT_44100] && + !priv->pll_rates[J721E_CLK_PARENT_48000]) { + dev_err(priv->dev, "At least one PLL is needed\n"); + return -EINVAL; + } + + if (priv->pll_rates[J721E_CLK_PARENT_44100]) + pll_rate = priv->pll_rates[J721E_CLK_PARENT_44100]; + else + pll_rate = priv->pll_rates[J721E_CLK_PARENT_48000]; + + min_rate = pll_rate / J721E_MAX_CLK_HSDIV; + min_rate /= ratios_for_pcm3168a[ARRAY_SIZE(ratios_for_pcm3168a) - 1]; + + if (priv->pll_rates[J721E_CLK_PARENT_48000]) + pll_rate = priv->pll_rates[J721E_CLK_PARENT_48000]; + else + pll_rate = priv->pll_rates[J721E_CLK_PARENT_44100]; + + if (pll_rate > PCM1368A_MAX_SYSCLK) + pll_rate = PCM1368A_MAX_SYSCLK; + + max_rate = pll_rate / ratios_for_pcm3168a[0]; + + snd_interval_any(&priv->rate_range); + priv->rate_range.min = min_rate; + priv->rate_range.max = max_rate; + + return 0; +} + +static int j721e_soc_probe_cpb(struct j721e_priv *priv, int *link_idx, + int *conf_idx) +{ + struct device_node *node = priv->dev->of_node; + struct snd_soc_dai_link_component *compnent; + struct device_node *dai_node, *codec_node; + struct j721e_audio_domain *domain; + int comp_count, comp_idx; + int ret; + + dai_node = of_parse_phandle(node, "ti,cpb-mcasp", 0); + if (!dai_node) { + dev_err(priv->dev, "CPB McASP node is not provided\n"); + return -EINVAL; + } + + codec_node = of_parse_phandle(node, "ti,cpb-codec", 0); + if (!codec_node) { + dev_err(priv->dev, "CPB codec node is not provided\n"); + return -EINVAL; + } + + domain = &priv->audio_domains[J721E_AUDIO_DOMAIN_CPB]; + ret = j721e_get_clocks(priv->dev, &domain->codec, "cpb-codec-scki"); + if (ret) + return ret; + + ret = j721e_get_clocks(priv->dev, &domain->mcasp, "cpb-mcasp-auxclk"); + if (ret) + return ret; + + /* + * Common Processor Board, two links + * Link 1: McASP10 -> pcm3168a_1 DAC + * Link 2: McASP10 <- pcm3168a_1 ADC + */ + comp_count = 6; + compnent = devm_kzalloc(priv->dev, comp_count * sizeof(*compnent), + GFP_KERNEL); + if (!compnent) + return -ENOMEM; + + comp_idx = 0; + priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_cpus = 1; + priv->dai_links[*link_idx].codecs = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_codecs = 1; + priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_platforms = 1; + + priv->dai_links[*link_idx].name = "CPB PCM3168A Playback"; + priv->dai_links[*link_idx].stream_name = "CPB PCM3168A Analog"; + priv->dai_links[*link_idx].cpus->of_node = dai_node; + priv->dai_links[*link_idx].platforms->of_node = dai_node; + priv->dai_links[*link_idx].codecs->of_node = codec_node; + priv->dai_links[*link_idx].codecs->dai_name = "pcm3168a-dac"; + priv->dai_links[*link_idx].playback_only = 1; + priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_CPB; + priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; + priv->dai_links[*link_idx].init = j721e_audio_init; + priv->dai_links[*link_idx].ops = &j721e_audio_ops; + (*link_idx)++; + + priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_cpus = 1; + priv->dai_links[*link_idx].codecs = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_codecs = 1; + priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_platforms = 1; + + priv->dai_links[*link_idx].name = "CPB PCM3168A Capture"; + priv->dai_links[*link_idx].stream_name = "CPB PCM3168A Analog"; + priv->dai_links[*link_idx].cpus->of_node = dai_node; + priv->dai_links[*link_idx].platforms->of_node = dai_node; + priv->dai_links[*link_idx].codecs->of_node = codec_node; + priv->dai_links[*link_idx].codecs->dai_name = "pcm3168a-adc"; + priv->dai_links[*link_idx].capture_only = 1; + priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_CPB; + priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; + priv->dai_links[*link_idx].init = j721e_audio_init; + priv->dai_links[*link_idx].ops = &j721e_audio_ops; + (*link_idx)++; + + priv->codec_conf[*conf_idx].dlc.of_node = codec_node; + priv->codec_conf[*conf_idx].name_prefix = "codec-1"; + (*conf_idx)++; + priv->codec_conf[*conf_idx].dlc.of_node = dai_node; + priv->codec_conf[*conf_idx].name_prefix = "McASP10"; + (*conf_idx)++; + + return 0; +} + +static int j721e_soc_probe_ivi(struct j721e_priv *priv, int *link_idx, + int *conf_idx) +{ + struct device_node *node = priv->dev->of_node; + struct snd_soc_dai_link_component *compnent; + struct device_node *dai_node, *codeca_node, *codecb_node; + struct j721e_audio_domain *domain; + int comp_count, comp_idx; + int ret; + + if (priv->match_data->board_type != J721E_BOARD_CPB_IVI) + return 0; + + dai_node = of_parse_phandle(node, "ti,ivi-mcasp", 0); + if (!dai_node) { + dev_err(priv->dev, "IVI McASP node is not provided\n"); + return -EINVAL; + } + + codeca_node = of_parse_phandle(node, "ti,ivi-codec-a", 0); + if (!codeca_node) { + dev_err(priv->dev, "IVI codec-a node is not provided\n"); + return -EINVAL; + } + + codecb_node = of_parse_phandle(node, "ti,ivi-codec-b", 0); + if (!codecb_node) { + dev_warn(priv->dev, "IVI codec-b node is not provided\n"); + return 0; + } + + domain = &priv->audio_domains[J721E_AUDIO_DOMAIN_IVI]; + ret = j721e_get_clocks(priv->dev, &domain->codec, "ivi-codec-scki"); + if (ret) + return ret; + + ret = j721e_get_clocks(priv->dev, &domain->mcasp, "ivi-mcasp-auxclk"); + if (ret) + return ret; + + /* + * IVI extension, two links + * Link 1: McASP0 -> pcm3168a_a DAC + * \> pcm3168a_b DAC + * Link 2: McASP0 <- pcm3168a_a ADC + * \ pcm3168a_b ADC + */ + comp_count = 8; + compnent = devm_kzalloc(priv->dev, comp_count * sizeof(*compnent), + GFP_KERNEL); + if (!compnent) + return -ENOMEM; + + comp_idx = 0; + priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_cpus = 1; + priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_platforms = 1; + priv->dai_links[*link_idx].codecs = &compnent[comp_idx]; + priv->dai_links[*link_idx].num_codecs = 2; + comp_idx += 2; + + priv->dai_links[*link_idx].name = "IVI 2xPCM3168A Playback"; + priv->dai_links[*link_idx].stream_name = "IVI 2xPCM3168A Analog"; + priv->dai_links[*link_idx].cpus->of_node = dai_node; + priv->dai_links[*link_idx].platforms->of_node = dai_node; + priv->dai_links[*link_idx].codecs[0].of_node = codeca_node; + priv->dai_links[*link_idx].codecs[0].dai_name = "pcm3168a-dac"; + priv->dai_links[*link_idx].codecs[1].of_node = codecb_node; + priv->dai_links[*link_idx].codecs[1].dai_name = "pcm3168a-dac"; + priv->dai_links[*link_idx].playback_only = 1; + priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_IVI; + priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; + priv->dai_links[*link_idx].init = j721e_audio_init_ivi; + priv->dai_links[*link_idx].ops = &j721e_audio_ops; + (*link_idx)++; + + priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_cpus = 1; + priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; + priv->dai_links[*link_idx].num_platforms = 1; + priv->dai_links[*link_idx].codecs = &compnent[comp_idx]; + priv->dai_links[*link_idx].num_codecs = 2; + + priv->dai_links[*link_idx].name = "IVI 2xPCM3168A Capture"; + priv->dai_links[*link_idx].stream_name = "IVI 2xPCM3168A Analog"; + priv->dai_links[*link_idx].cpus->of_node = dai_node; + priv->dai_links[*link_idx].platforms->of_node = dai_node; + priv->dai_links[*link_idx].codecs[0].of_node = codeca_node; + priv->dai_links[*link_idx].codecs[0].dai_name = "pcm3168a-adc"; + priv->dai_links[*link_idx].codecs[1].of_node = codecb_node; + priv->dai_links[*link_idx].codecs[1].dai_name = "pcm3168a-adc"; + priv->dai_links[*link_idx].capture_only = 1; + priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_IVI; + priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; + priv->dai_links[*link_idx].init = j721e_audio_init; + priv->dai_links[*link_idx].ops = &j721e_audio_ops; + (*link_idx)++; + + priv->codec_conf[*conf_idx].dlc.of_node = codeca_node; + priv->codec_conf[*conf_idx].name_prefix = "codec-a"; + (*conf_idx)++; + + priv->codec_conf[*conf_idx].dlc.of_node = codecb_node; + priv->codec_conf[*conf_idx].name_prefix = "codec-b"; + (*conf_idx)++; + + priv->codec_conf[*conf_idx].dlc.of_node = dai_node; + priv->codec_conf[*conf_idx].name_prefix = "McASP0"; + (*conf_idx)++; + + return 0; +} + +static int j721e_soc_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct snd_soc_card *card; + const struct of_device_id *match; + struct j721e_priv *priv; + int link_cnt, conf_cnt, ret; + + if (!node) { + dev_err(&pdev->dev, "of node is missing.\n"); + return -ENODEV; + } + + match = of_match_node(j721e_audio_of_match, node); + if (!match) { + dev_err(&pdev->dev, "No compatible match found\n"); + return -ENODEV; + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->match_data = match->data; + + priv->dai_links = devm_kcalloc(&pdev->dev, priv->match_data->num_links, + sizeof(*priv->dai_links), GFP_KERNEL); + if (!priv->dai_links) + return -ENOMEM; + + priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].parent_clk_id = -1; + priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].parent_clk_id = -1; + priv->dev = &pdev->dev; + card = &priv->card; + card->dev = &pdev->dev; + card->owner = THIS_MODULE; + card->dapm_widgets = j721e_cpb_dapm_widgets; + card->num_dapm_widgets = ARRAY_SIZE(j721e_cpb_dapm_widgets); + card->dapm_routes = j721e_cpb_dapm_routes; + card->num_dapm_routes = ARRAY_SIZE(j721e_cpb_dapm_routes); + card->fully_routed = 1; + + if (snd_soc_of_parse_card_name(card, "model")) { + dev_err(&pdev->dev, "Card name is not provided\n"); + return -ENODEV; + } + + link_cnt = 0; + conf_cnt = 0; + ret = j721e_soc_probe_cpb(priv, &link_cnt, &conf_cnt); + if (ret) + return ret; + + ret = j721e_soc_probe_ivi(priv, &link_cnt, &conf_cnt); + if (ret) + return ret; + + card->dai_link = priv->dai_links; + card->num_links = link_cnt; + + card->codec_conf = priv->codec_conf; + card->num_configs = conf_cnt; + + ret = j721e_calculate_rate_range(priv); + if (ret) + return ret; + + snd_soc_card_set_drvdata(card, priv); + + mutex_init(&priv->mutex); + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) + dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n", + ret); + + return ret; +} + +static struct platform_driver j721e_soc_driver = { + .driver = { + .name = "j721e-audio", + .pm = &snd_soc_pm_ops, + .of_match_table = of_match_ptr(j721e_audio_of_match), + }, + .probe = j721e_soc_probe, +}; + +module_platform_driver(j721e_soc_driver); + +MODULE_AUTHOR("Peter Ujfalusi "); +MODULE_DESCRIPTION("ASoC machine driver for j721e Common Processor Board"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/ti/n810.c b/sound/soc/ti/n810.c index a1672b479cb78e768ca1a537bbff5841f35609c2..2802a33b9c5f1997a575a6001eb19dc366beb536 100644 --- a/sound/soc/ti/n810.c +++ b/sound/soc/ti/n810.c @@ -84,7 +84,7 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm) static int n810_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2); @@ -100,7 +100,7 @@ static void n810_shutdown(struct snd_pcm_substream *substream) static int n810_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int err; diff --git a/sound/soc/ti/omap-abe-twl6040.c b/sound/soc/ti/omap-abe-twl6040.c index 61e45fea5dd8f6ac5ecea36e94a4475f4e96c80d..16ea039ff8653bf3d3ecf284dca8bd0224557089 100644 --- a/sound/soc/ti/omap-abe-twl6040.c +++ b/sound/soc/ti/omap-abe-twl6040.c @@ -45,7 +45,7 @@ static struct platform_device *dmic_codec_dev; static int omap_abe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); @@ -77,7 +77,7 @@ static const struct snd_soc_ops omap_abe_ops = { static int omap_abe_dmic_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret = 0; diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c index def2a0ce88863e35b9ae2df8b55941509fc33cf2..3328c02f93c7443094baabd97e156b2dbdf00f04 100644 --- a/sound/soc/ti/omap-hdmi.c +++ b/sound/soc/ti/omap-hdmi.c @@ -2,7 +2,7 @@ /* * omap-hdmi-audio.c -- OMAP4+ DSS HDMI audio support library * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com * * Author: Jyri Sarha */ diff --git a/sound/soc/ti/omap-mcbsp-st.c b/sound/soc/ti/omap-mcbsp-st.c index 5a32b54bbf3bb541e47ff2e19ec84c8d321e65c6..0bc7d26c660aa42c0e45d4781d80c83cb837c9fa 100644 --- a/sound/soc/ti/omap-mcbsp-st.c +++ b/sound/soc/ti/omap-mcbsp-st.c @@ -142,11 +142,8 @@ static void omap_mcbsp_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir) static void omap_mcbsp_st_chgain(struct omap_mcbsp *mcbsp) { - u16 w; struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - w = MCBSP_ST_READ(mcbsp, SSELCR); - MCBSP_ST_WRITE(mcbsp, SGAINCR, ST_CH0GAIN(st_data->ch0gain) | ST_CH1GAIN(st_data->ch1gain)); } diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 32e3ccdbb7a27908039ae45eb12e9ec023aad8e5..6025b30bbe77ec4c5c787fabfc51dc8e6452850d 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -731,7 +731,7 @@ err_st: static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream, unsigned int packet_size) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); int words; @@ -896,7 +896,7 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay( struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); u16 fifo_use; diff --git a/sound/soc/ti/omap-twl4030.c b/sound/soc/ti/omap-twl4030.c index 92dbe2c67290dbf312e69af0eb72d51fa086b379..1da05a6cdc9f4ae6d91af25e109f344f45f02223 100644 --- a/sound/soc/ti/omap-twl4030.c +++ b/sound/soc/ti/omap-twl4030.c @@ -2,7 +2,7 @@ /* * omap-twl4030.c -- SoC audio for TI SoC based boards with twl4030 codec * - * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com * All rights reserved. * * Author: Peter Ujfalusi @@ -38,7 +38,7 @@ struct omap_twl4030 { static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int fmt; switch (params_channels(params)) { diff --git a/sound/soc/ti/omap3pandora.c b/sound/soc/ti/omap3pandora.c index b04146311b31acaf0a28bb865dd5304de5ddb031..a287e9747c2a12db70f12d191107c42d0c217b23 100644 --- a/sound/soc/ti/omap3pandora.c +++ b/sound/soc/ti/omap3pandora.c @@ -31,7 +31,7 @@ static struct regulator *omap3pandora_dac_reg; static int omap3pandora_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; diff --git a/sound/soc/ti/osk5912.c b/sound/soc/ti/osk5912.c index e01485cc51a151c6b0b8aa82cf4131d53f532760..40e29dda7e7a74f336701b76357430552781268f 100644 --- a/sound/soc/ti/osk5912.c +++ b/sound/soc/ti/osk5912.c @@ -38,7 +38,7 @@ static void osk_shutdown(struct snd_pcm_substream *substream) static int osk_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int err; diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index 2a714a0041636f9c95be71c3070accdd7549ce2d..2176a95201bf8b1341ca06102b49d2010d764f68 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c @@ -90,7 +90,7 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm) static int rx51_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2); @@ -102,7 +102,7 @@ static int rx51_startup(struct snd_pcm_substream *substream) static int rx51_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); /* Set the codec system clock for DAC and ADC */ diff --git a/sound/soc/ti/sdma-pcm.c b/sound/soc/ti/sdma-pcm.c index 2b0bc234e1b69f793b919e464eaa25175c18bd9a..9e7691103f0530a3f477025628aa566533a1d14f 100644 --- a/sound/soc/ti/sdma-pcm.c +++ b/sound/soc/ti/sdma-pcm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com * Author: Peter Ujfalusi */ diff --git a/sound/soc/ti/sdma-pcm.h b/sound/soc/ti/sdma-pcm.h index cb0627c8dd342ca71dbe99db8b7bb4cabc7aa8be..c19efb4c043d00a117275964e4ff692f49f264ab 100644 --- a/sound/soc/ti/sdma-pcm.h +++ b/sound/soc/ti/sdma-pcm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com * Author: Peter Ujfalusi */ diff --git a/sound/soc/ti/udma-pcm.c b/sound/soc/ti/udma-pcm.c index 39830caaaf7cbd7c51eb6b0e0604e93797678ea0..2ff0f518aba544457aeb1cc5ea5c48fbb84b7ccd 100644 --- a/sound/soc/ti/udma-pcm.c +++ b/sound/soc/ti/udma-pcm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com * Author: Peter Ujfalusi */ diff --git a/sound/soc/ti/udma-pcm.h b/sound/soc/ti/udma-pcm.h index 54111e7312c106b83ec61e16dc85b544e5584362..9ed588fd79b9f89ffd5d61f33230a4250713e628 100644 --- a/sound/soc/ti/udma-pcm.h +++ b/sound/soc/ti/udma-pcm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com */ #ifndef __UDMA_PCM_H__ diff --git a/sound/soc/uniphier/aio-core.c b/sound/soc/uniphier/aio-core.c index 9bcba06ba52ea36dc06527561aef739641d99fb2..b8195778953e1eab2fb7fb77ec4b61ff1d6aaaa2 100644 --- a/sound/soc/uniphier/aio-core.c +++ b/sound/soc/uniphier/aio-core.c @@ -93,9 +93,9 @@ void aio_iecout_set_enable(struct uniphier_aio_chip *chip, bool enable) /** * aio_chip_set_pll - set frequency to audio PLL - * @chip : the AIO chip pointer - * @source: PLL - * @freq : frequency in Hz, 0 is ignored + * @chip: the AIO chip pointer + * @pll_id: PLL + * @freq: frequency in Hz, 0 is ignored * * Sets frequency of audio PLL. This function can be called anytime, * but it takes time till PLL is locked. @@ -267,7 +267,6 @@ void aio_port_reset(struct uniphier_aio_sub *sub) /** * aio_port_set_ch - set channels of LPCM * @sub: the AIO substream pointer, PCM substream only - * @ch : count of channels * * Set suitable slot selecting to input/output port block of AIO. * diff --git a/sound/soc/uniphier/aio-dma.c b/sound/soc/uniphier/aio-dma.c index d6bcd476df12dec519976a737242594c598a33aa..3c1628a3a1acd86c1231889e00ebba4af17da870 100644 --- a/sound/soc/uniphier/aio-dma.c +++ b/sound/soc/uniphier/aio-dma.c @@ -108,7 +108,7 @@ static int uniphier_aiodma_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); struct uniphier_aio_sub *sub = &aio->sub[substream->stream]; int bytes = runtime->period_size * @@ -135,7 +135,7 @@ static int uniphier_aiodma_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); struct uniphier_aio_sub *sub = &aio->sub[substream->stream]; struct device *dev = &aio->chip->pdev->dev; @@ -171,7 +171,7 @@ static snd_pcm_uframes_t uniphier_aiodma_pointer( struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); struct uniphier_aio_sub *sub = &aio->sub[substream->stream]; int bytes = runtime->period_size * diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c index 6aaa19829a73a30acd4aa689d131089e95510939..2c39c7a2fd7dc408b9c84cbd77919788e2ef8879 100644 --- a/sound/soc/ux500/mop500_ab8500.c +++ b/sound/soc/ux500/mop500_ab8500.c @@ -190,7 +190,7 @@ static struct snd_kcontrol_new mop500_ab8500_ctrls[] = { static int mop500_ab8500_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); /* Set audio-clock source */ return mop500_ab8500_set_mclk(rtd->card->dev, @@ -199,7 +199,7 @@ static int mop500_ab8500_startup(struct snd_pcm_substream *substream) static void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct device *dev = rtd->card->dev; dev_dbg(dev, "%s: Enter\n", __func__); @@ -214,7 +214,7 @@ static void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct device *dev = rtd->card->dev; @@ -338,7 +338,7 @@ static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, static int mop500_ab8500_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); mutex_lock(&mop500_ab8500_params_lock); diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 394d8b2a4a1619cc8b8c43ff5aa67a11949ce92a..fd0b88bb7921266097dc450bcfe6e44ac6bee549 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -395,7 +395,7 @@ static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) static void flush_fifo_rx(struct ux500_msp *msp) { - u32 reg_val_DR, reg_val_GCR, reg_val_FLR; + u32 reg_val_GCR, reg_val_FLR; u32 limit = 32; reg_val_GCR = readl(msp->registers + MSP_GCR); @@ -403,7 +403,7 @@ static void flush_fifo_rx(struct ux500_msp *msp) reg_val_FLR = readl(msp->registers + MSP_FLR); while (!(reg_val_FLR & RX_FIFO_EMPTY) && limit--) { - reg_val_DR = readl(msp->registers + MSP_DR); + readl(msp->registers + MSP_DR); reg_val_FLR = readl(msp->registers + MSP_FLR); } @@ -412,7 +412,7 @@ static void flush_fifo_rx(struct ux500_msp *msp) static void flush_fifo_tx(struct ux500_msp *msp) { - u32 reg_val_TSTDR, reg_val_GCR, reg_val_FLR; + u32 reg_val_GCR, reg_val_FLR; u32 limit = 32; reg_val_GCR = readl(msp->registers + MSP_GCR); @@ -421,7 +421,7 @@ static void flush_fifo_tx(struct ux500_msp *msp) reg_val_FLR = readl(msp->registers + MSP_FLR); while (!(reg_val_FLR & TX_FIFO_EMPTY) && limit--) { - reg_val_TSTDR = readl(msp->registers + MSP_TSTDR); + readl(msp->registers + MSP_TSTDR); reg_val_FLR = readl(msp->registers + MSP_FLR); } writel(0x0, msp->registers + MSP_ITCR); diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index 39b96c132bc800a0c8d279b92ef6977b05269833..18191084b8b8474cb4339f17968123bfec88654f 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c @@ -85,7 +85,7 @@ static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct msp_i2s_platform_data *pdata = asoc_rtd_to_cpu(rtd, 0)->dev->platform_data; struct snd_dmaengine_dai_dma_data *snd_dma_params; struct ux500_msp_dma_params *ste_dma_params; diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c index 68af2176b19c95dfde171d4ff00c707672ee6090..aeb4b2c4d1d35df4057b08058d4d6cd13ece5295 100644 --- a/sound/soc/xtensa/xtfpga-i2s.c +++ b/sound/soc/xtensa/xtfpga-i2s.c @@ -369,7 +369,7 @@ static int xtfpga_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); void *p; snd_soc_set_runtime_hwparams(substream, &xtfpga_pcm_hardware); diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index cf70499992619bd59cb0eb5a3c5afc7b6b39a1b9..913adc8568d5acddf7c65f526c6b0b3c1fa190ea 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -22,7 +22,7 @@ * - Data sheet of the T7903, a newer but very similar ISA bus equivalent * available from the Lucent (formerly AT&T microelectronics) home * page. - * - http://www.freesoft.org/Linux/DBRI/ + * - https://www.freesoft.org/Linux/DBRI/ * - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec * Interfaces: CHI, Audio In & Out, 2 bits parallel * Documentation: from the Crystal Semiconductor home page. @@ -580,16 +580,16 @@ static __u32 reverse_bytes(__u32 b, int len) switch (len) { case 32: b = ((b & 0xffff0000) >> 16) | ((b & 0x0000ffff) << 16); - /* fall through */ + fallthrough; case 16: b = ((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8); - /* fall through */ + fallthrough; case 8: b = ((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4); - /* fall through */ + fallthrough; case 4: b = ((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2); - /* fall through */ + fallthrough; case 2: b = ((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1); case 1: diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index 20f34d2ace5f5de5199fe2fa1c80eef1e9ed5d00..9bd8dcbb68e419352b8e54480de8482b601cf8f5 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c @@ -539,7 +539,7 @@ static int usb6fire_control_add_virtual( ret = snd_ctl_add(card, control); if (ret < 0) return ret; - ret = snd_ctl_add_slave(vmaster, control); + ret = snd_ctl_add_follower(vmaster, control); if (ret < 0) return ret; i++; diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index e9243d53a107db72477ba5f2bf8f4723e9251438..3b6bb2cbe886b36e3dc3fcb6190823efd0351e5d 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -820,7 +820,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev) case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): cdev->samplerates |= SNDRV_PCM_RATE_192000; - /* fall thru */ + fallthrough; case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index b669e119f654659a8b256aee1b88f8b4978ede5f..2af3b7eb0a88c5618f962fe60dfcce2e6bcd6000 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -187,7 +187,7 @@ static void usb_ep1_command_reply_dispatch (struct urb* urb) break; } #ifdef CONFIG_SND_USB_CAIAQ_INPUT - /* fall through */ + fallthrough; case EP1_CMD_READ_ERP: case EP1_CMD_READ_ANALOG: snd_usb_caiaq_input_dispatch(cdev, buf, urb->actual_length); diff --git a/sound/usb/card.c b/sound/usb/card.c index c4bcb3434b127fd21517fabbd15185491980005c..a8367854a9788b7b9182077ee9d4b14a2578762c 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -409,7 +409,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) dev_warn(&dev->dev, "unknown interface protocol %#02x, assuming v1\n", protocol); - /* fall through */ + fallthrough; case UAC_VERSION_1: { struct uac1_ac_header_descriptor *h1; diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 9a97d7876f39fc59c3a67f407a394e94bd3d34b7..3d5603738d65a89aaf3b0d99cc6d4170cd10e0aa 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -675,7 +675,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, else return 0; } - /* fall through */ + fallthrough; case UAC_VERSION_2: return set_sample_rate_v2v3(chip, iface, alts, fmt, rate); } diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 01468d6ee35659f3699847cd50f941b154464ce9..5fbc8dd2f409ef33a8c540f6ab1a57df45e200d5 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -615,9 +615,8 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force) for (i = 0; i < ep->nurbs; i++) release_urb_ctx(&ep->urb[i]); - if (ep->syncbuf) - usb_free_coherent(ep->chip->dev, SYNC_URBS * 4, - ep->syncbuf, ep->sync_dma); + usb_free_coherent(ep->chip->dev, SYNC_URBS * 4, + ep->syncbuf, ep->sync_dma); ep->syncbuf = NULL; ep->nurbs = 0; diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 2746d969818070b999dc75e97b8fe6e12f9f4948..60674ce4879b17c41e4f1ba0e6d7db0b3b6d597c 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -97,7 +97,7 @@ static void line6_stop_listen(struct usb_line6 *line6) /* Send raw message in pieces of wMaxPacketSize bytes. */ -static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, +int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, int size) { int i, done = 0; @@ -132,6 +132,7 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, return done; } +EXPORT_SYMBOL_GPL(line6_send_raw_message); /* Notification of completion of asynchronous request transmission. diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index 1a4e3700c80c959074df9362052aee3d9c316a6f..71d3da1db8c815ac6c11a094657b744602e2a152 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -66,8 +66,8 @@ extern const unsigned char line6_midi_id[3]; -static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3; -static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4; +#define SYSEX_DATA_OFS (sizeof(line6_midi_id) + 3) +#define SYSEX_EXTRA_SIZE (sizeof(line6_midi_id) + 4) /* Common properties of Line 6 devices. @@ -108,6 +108,8 @@ enum { LINE6_CAP_CONTROL_MIDI = 1 << 4, /* device provides low-level information */ LINE6_CAP_CONTROL_INFO = 1 << 5, + /* device provides hardware monitoring volume control */ + LINE6_CAP_HWMON_CTL = 1 << 6, }; /* @@ -185,6 +187,8 @@ extern int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, unsigned datalen); extern int line6_read_serial_number(struct usb_line6 *line6, u32 *serial_number); +extern int line6_send_raw_message(struct usb_line6 *line6, + const char *buffer, int size); extern int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer, int size); extern int line6_send_sysex_message(struct usb_line6 *line6, diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index e39dc85c355a0c8828100854634a0ee85683f127..eef45f7fef0db04a107de2744f49f12b99ca8aa5 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "driver.h" @@ -37,6 +38,9 @@ struct usb_line6_podhd { /* Firmware version */ int firmware_version; + + /* Monitor level */ + int monitor_level; }; #define line6_to_podhd(x) container_of(x, struct usb_line6_podhd, line6) @@ -250,6 +254,116 @@ static void podhd_disconnect(struct usb_line6 *line6) } } +static const unsigned int float_zero_to_one_lookup[] = { +0x00000000, 0x3c23d70a, 0x3ca3d70a, 0x3cf5c28f, 0x3d23d70a, 0x3d4ccccd, +0x3d75c28f, 0x3d8f5c29, 0x3da3d70a, 0x3db851ec, 0x3dcccccd, 0x3de147ae, +0x3df5c28f, 0x3e051eb8, 0x3e0f5c29, 0x3e19999a, 0x3e23d70a, 0x3e2e147b, +0x3e3851ec, 0x3e428f5c, 0x3e4ccccd, 0x3e570a3d, 0x3e6147ae, 0x3e6b851f, +0x3e75c28f, 0x3e800000, 0x3e851eb8, 0x3e8a3d71, 0x3e8f5c29, 0x3e947ae1, +0x3e99999a, 0x3e9eb852, 0x3ea3d70a, 0x3ea8f5c3, 0x3eae147b, 0x3eb33333, +0x3eb851ec, 0x3ebd70a4, 0x3ec28f5c, 0x3ec7ae14, 0x3ecccccd, 0x3ed1eb85, +0x3ed70a3d, 0x3edc28f6, 0x3ee147ae, 0x3ee66666, 0x3eeb851f, 0x3ef0a3d7, +0x3ef5c28f, 0x3efae148, 0x3f000000, 0x3f028f5c, 0x3f051eb8, 0x3f07ae14, +0x3f0a3d71, 0x3f0ccccd, 0x3f0f5c29, 0x3f11eb85, 0x3f147ae1, 0x3f170a3d, +0x3f19999a, 0x3f1c28f6, 0x3f1eb852, 0x3f2147ae, 0x3f23d70a, 0x3f266666, +0x3f28f5c3, 0x3f2b851f, 0x3f2e147b, 0x3f30a3d7, 0x3f333333, 0x3f35c28f, +0x3f3851ec, 0x3f3ae148, 0x3f3d70a4, 0x3f400000, 0x3f428f5c, 0x3f451eb8, +0x3f47ae14, 0x3f4a3d71, 0x3f4ccccd, 0x3f4f5c29, 0x3f51eb85, 0x3f547ae1, +0x3f570a3d, 0x3f59999a, 0x3f5c28f6, 0x3f5eb852, 0x3f6147ae, 0x3f63d70a, +0x3f666666, 0x3f68f5c3, 0x3f6b851f, 0x3f6e147b, 0x3f70a3d7, 0x3f733333, +0x3f75c28f, 0x3f7851ec, 0x3f7ae148, 0x3f7d70a4, 0x3f800000 +}; + +static void podhd_set_monitor_level(struct usb_line6_podhd *podhd, int value) +{ + unsigned int fl; + static const unsigned char msg[16] = { + /* Chunk is 0xc bytes (without first word) */ + 0x0c, 0x00, + /* First chunk in the message */ + 0x01, 0x00, + /* Message size is 2 4-byte words */ + 0x02, 0x00, + /* Unknown */ + 0x04, 0x41, + /* Unknown */ + 0x04, 0x00, 0x13, 0x00, + /* Volume, LE float32, 0.0 - 1.0 */ + 0x00, 0x00, 0x00, 0x00 + }; + unsigned char *buf; + + buf = kmemdup(msg, sizeof(msg), GFP_KERNEL); + if (!buf) + return; + + if (value < 0) + value = 0; + + if (value >= ARRAY_SIZE(float_zero_to_one_lookup)) + value = ARRAY_SIZE(float_zero_to_one_lookup) - 1; + + fl = float_zero_to_one_lookup[value]; + + buf[12] = (fl >> 0) & 0xff; + buf[13] = (fl >> 8) & 0xff; + buf[14] = (fl >> 16) & 0xff; + buf[15] = (fl >> 24) & 0xff; + + line6_send_raw_message(&podhd->line6, buf, sizeof(msg)); + kfree(buf); + + podhd->monitor_level = value; +} + +/* control info callback */ +static int snd_podhd_control_monitor_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 100; + uinfo->value.integer.step = 1; + return 0; +} + +/* control get callback */ +static int snd_podhd_control_monitor_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); + struct usb_line6_podhd *podhd = line6_to_podhd(line6pcm->line6); + + ucontrol->value.integer.value[0] = podhd->monitor_level; + return 0; +} + +/* control put callback */ +static int snd_podhd_control_monitor_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); + struct usb_line6_podhd *podhd = line6_to_podhd(line6pcm->line6); + + if (ucontrol->value.integer.value[0] == podhd->monitor_level) + return 0; + + podhd_set_monitor_level(podhd, ucontrol->value.integer.value[0]); + return 1; +} + +/* control definition */ +static const struct snd_kcontrol_new podhd_control_monitor = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Monitor Playback Volume", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = snd_podhd_control_monitor_info, + .get = snd_podhd_control_monitor_get, + .put = snd_podhd_control_monitor_put +}; + /* Try to init POD HD device. */ @@ -298,6 +412,15 @@ static int podhd_init(struct usb_line6 *line6, return err; } + if (pod->line6.properties->capabilities & LINE6_CAP_HWMON_CTL) { + podhd_set_monitor_level(pod, 100); + err = snd_ctl_add(line6->card, + snd_ctl_new1(&podhd_control_monitor, + line6->line6pcm)); + if (err < 0) + return err; + } + if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) { /* register USB audio system directly */ return snd_card_register(line6->card); @@ -354,7 +477,7 @@ static const struct line6_properties podhd_properties_table[] = { .id = "PODHD500", .name = "POD HD500", .capabilities = LINE6_CAP_PCM | LINE6_CAP_CONTROL - | LINE6_CAP_HWMON, + | LINE6_CAP_HWMON | LINE6_CAP_HWMON_CTL, .altsetting = 1, .ctrl_if = 1, .ep_ctrl_r = 0x81, diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 354f576929384ceaca61b369d0f9e618f04f6d20..df639fe031181561290ca8f2295dac1c98e78d9e 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -2408,7 +2408,7 @@ int __snd_usbmidi_create(struct snd_card *card, break; case QUIRK_MIDI_US122L: umidi->usb_protocol_ops = &snd_usbmidi_122l_ops; - /* fall through */ + fallthrough; case QUIRK_MIDI_FIXED_ENDPOINT: memcpy(&endpoints[0], quirk->data, sizeof(struct snd_usb_midi_endpoint_info)); diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index eab0fd4fd7c334cff2671d0a2ff25cd95073d21c..6b0f3a8469efee2ffb1cf472bb5c0c806587cd2e 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1463,6 +1463,10 @@ static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol, snd_usb_unlock_shutdown(chip); if (ret < 0) { + if (strstr(kcontrol->id.name, "Speaker")) { + ucontrol->value.integer.value[0] = 1; + return 0; + } error: usb_audio_err(chip, "cannot get connectors status: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index 9af7aa93f6fabc2d826ae510e97e1f680e8c1719..c369c81e74c41f20fb67821283dbfd41dda4b228 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c @@ -233,7 +233,7 @@ static const struct usbmix_name_map maya44_map[] = { }; /* Section "justlink_map" below added by James Courtier-Dutton - * sourced from Maplin Electronics (http://www.maplin.co.uk), part number A56AK + * sourced from Maplin Electronics (https://www.maplin.co.uk), part number A56AK * Part has 2 connectors that act as a single output. (TOSLINK Optical for digital out, and 3.5mm Jack for Analogue out.) * The USB Mixer publishes a Microphone and extra Volume controls for it, but none exist on the device, * so this map removes all unwanted sliders from alsamixer @@ -370,6 +370,11 @@ static const struct usbmix_name_map asus_rog_map[] = { {} }; +static const struct usbmix_name_map lenovo_p620_rear_map[] = { + { 19, NULL, 12 }, /* FU, Input Gain Pad */ + {} +}; + /* TRX40 mobos with Realtek ALC1220-VB */ static const struct usbmix_name_map trx40_mobo_map[] = { { 18, NULL }, /* OT, IEC958 - broken response, disabled */ @@ -573,6 +578,10 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { .map = trx40_mobo_map, .connector_map = trx40_mobo_connector_map, }, + { /* Lenovo ThinkStation P620 Rear */ + .id = USB_ID(0x17aa, 0x1046), + .map = lenovo_p620_rear_map, + }, { 0 } /* terminator */ }; diff --git a/sound/usb/mixer_s1810c.c b/sound/usb/mixer_s1810c.c index 6483e47bafd01315f0abcda6abde66cb8345d65f..c53a9773f310bb84798ba1ca2d7dc3a95747b1b2 100644 --- a/sound/usb/mixer_s1810c.c +++ b/sound/usb/mixer_s1810c.c @@ -554,11 +554,11 @@ int snd_sc1810_init_mixer(struct usb_mixer_interface *mixer) dev_info(&dev->dev, "Presonus Studio 1810c, device_setup: %u\n", chip->setup); if (chip->setup == 1) - dev_info(&dev->dev, "(8out/18in @ 48KHz)\n"); + dev_info(&dev->dev, "(8out/18in @ 48kHz)\n"); else if (chip->setup == 2) - dev_info(&dev->dev, "(6out/8in @ 192KHz)\n"); + dev_info(&dev->dev, "(6out/8in @ 192kHz)\n"); else - dev_info(&dev->dev, "(8out/14in @ 96KHz)\n"); + dev_info(&dev->dev, "(8out/14in @ 96kHz)\n"); ret = snd_s1810c_init_mixer_maps(chip); if (ret < 0) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 74c00c905d24594236d95888835b4ec893c82fe3..0ffff7640892af689ab6827cf4af3312454aa327 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -332,7 +332,7 @@ static const struct scarlett2_device_info s18i8_gen2_info = { }, [SCARLETT2_PORT_TYPE_SPDIF] = { .id = 0x180, - /* S/PDIF outputs aren't available at 192KHz + /* S/PDIF outputs aren't available at 192kHz * but are included in the USB mux I/O * assignment message anyway */ @@ -401,7 +401,7 @@ static const struct scarlett2_device_info s18i20_gen2_info = { .dst_descr = "Analogue Output %02d Playback" }, [SCARLETT2_PORT_TYPE_SPDIF] = { - /* S/PDIF outputs aren't available at 192KHz + /* S/PDIF outputs aren't available at 192kHz * but are included in the USB mux I/O * assignment message anyway */ diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index e8ade766928a9854d202945c67fd63128ca1898e..67c57fe8209e48a1bd7250217a29043b5f6fa4b4 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1871,8 +1871,8 @@ static void retire_playback_urb(struct snd_usb_substream *subs, int processed = urb->transfer_buffer_length / ep->stride; int est_delay; - /* ignore the delay accounting when procssed=0 is given, i.e. - * silent payloads are procssed before handling the actual data + /* ignore the delay accounting when processed=0 is given, i.e. + * silent payloads are processed before handling the actual data */ if (!processed) return; @@ -1919,7 +1919,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea switch (cmd) { case SNDRV_PCM_TRIGGER_START: subs->trigger_tstamp_pending_update = true; - /* fall through */ + fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: subs->data_endpoint->prepare_data_urb = prepare_playback_urb; subs->data_endpoint->retire_data_urb = retire_playback_urb; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 9092cc0aa8072b4fc7a9a7ddf24a2917a022def2..adb3b62afed43eb08ae587746fb5be52be85c3c0 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -127,7 +127,7 @@ /* * HP Wireless Audio * When not ignored, causes instability issues for some users, forcing them to - * blacklist the entire module. + * skip the entire module. */ { USB_DEVICE(0x0424, 0xb832), @@ -2794,6 +2794,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), QUIRK_RENAME_DEVICE("Rane", "SL-1") }, +/* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */ +{ + USB_DEVICE(0x17aa, 0x1046), + QUIRK_DEVICE_PROFILE("Lenovo", "ThinkStation P620 Rear", + "Lenovo-ThinkStation-P620-Rear"), +}, +/* Lenovo ThinkStation P620 Internal Speaker + Front Headset */ +{ + USB_DEVICE(0x17aa, 0x104d), + QUIRK_DEVICE_PROFILE("Lenovo", "ThinkStation P620 Main", + "Lenovo-ThinkStation-P620-Main"), +}, + /* Native Instruments MK2 series */ { /* Komplete Audio 6 */ @@ -3252,11 +3265,15 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), } }, +/* + * The original product_name is "USB Sound Device", however this name + * is also used by the CM106 based cards, so make it unique. + */ +{ + USB_DEVICE(0x0d8c, 0x0102), + QUIRK_RENAME_DEVICE(NULL, "ICUSBAUDIO7D") +}, { - /* - * The original product_name is "USB Sound Device", however this name - * is also used by the CM106 based cards, so make it unique. - */ USB_DEVICE(0x0d8c, 0x0103), QUIRK_RENAME_DEVICE(NULL, "Audio Advantage MicroII") }, diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index fca72730a802ec617f267e858390babe37c56053..c551141f337ea366d7d3de5d8fa793274f37e309 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1144,14 +1144,14 @@ static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev) #define MAUDIO_SET 0x01 /* parse device_setup */ #define MAUDIO_SET_COMPATIBLE 0x80 /* use only "win-compatible" interfaces */ #define MAUDIO_SET_DTS 0x02 /* enable DTS Digital Output */ -#define MAUDIO_SET_96K 0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */ +#define MAUDIO_SET_96K 0x04 /* 48-96kHz rate if set, 8-48kHz otherwise */ #define MAUDIO_SET_24B 0x08 /* 24bits sample if set, 16bits otherwise */ #define MAUDIO_SET_DI 0x10 /* enable Digital Input */ #define MAUDIO_SET_MASK 0x1f /* bit mask for setup value */ -#define MAUDIO_SET_24B_48K_DI 0x19 /* 24bits+48KHz+Digital Input */ -#define MAUDIO_SET_24B_48K_NOTDI 0x09 /* 24bits+48KHz+No Digital Input */ -#define MAUDIO_SET_16B_48K_DI 0x11 /* 16bits+48KHz+Digital Input */ -#define MAUDIO_SET_16B_48K_NOTDI 0x01 /* 16bits+48KHz+No Digital Input */ +#define MAUDIO_SET_24B_48K_DI 0x19 /* 24bits+48kHz+Digital Input */ +#define MAUDIO_SET_24B_48K_NOTDI 0x09 /* 24bits+48kHz+No Digital Input */ +#define MAUDIO_SET_16B_48K_DI 0x11 /* 16bits+48kHz+Digital Input */ +#define MAUDIO_SET_16B_48K_NOTDI 0x01 /* 16bits+48kHz+No Digital Input */ static int quattro_skip_setting_quirk(struct snd_usb_audio *chip, int iface, int altno) @@ -1597,7 +1597,7 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) /* * M-Audio Fast Track C400/C600 - when packets are not skipped, real - * world latency varies by approx. +/- 50 frames (at 96KHz) each time + * world latency varies by approx. +/- 50 frames (at 96kHz) each time * the stream is (re)started. When skipping packets 16 at endpoint * start up, the real world latency is stable within +/- 1 frame (also * across power cycles). @@ -1839,7 +1839,7 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, /* * MaxPacketsOnly attribute is erroneously set in endpoint * descriptors. As a result this card produces noise with - * all sample rates other than 96 KHz. + * all sample rates other than 96 kHz. */ fp->attributes &= ~UAC_EP_CS_ATTR_FILL_MAX; break; diff --git a/sound/usb/stream.c b/sound/usb/stream.c index d6f0fd967c30484925805b8a749da54ce37583af..7d01530f002a63ab622fe3589ccf88b4038f402b 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1150,9 +1150,8 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, dev_dbg(&dev->dev, "%u:%d: unknown interface protocol %#02x, assuming v1\n", iface_no, altno, protocol); protocol = UAC_VERSION_1; - /* fall through */ + fallthrough; case UAC_VERSION_1: - /* fall through */ case UAC_VERSION_2: { int bm_quirk = 0; diff --git a/sound/xen/xen_snd_front.c b/sound/xen/xen_snd_front.c index a9e5c2cd76980982ee80d00fa3f3478e75c9f0d9..228d82031297319f7ca4224fc531d72459852810 100644 --- a/sound/xen/xen_snd_front.c +++ b/sound/xen/xen_snd_front.c @@ -114,7 +114,7 @@ int xen_snd_front_stream_prepare(struct xen_snd_front_evtchnl *evtchnl, int xen_snd_front_stream_close(struct xen_snd_front_evtchnl *evtchnl) { - struct xensnd_req *req; + __always_unused struct xensnd_req *req; int ret; mutex_lock(&evtchnl->u.req.req_io_lock); @@ -246,11 +246,8 @@ static void sndback_changed(struct xenbus_device *xb_dev, switch (backend_state) { case XenbusStateReconfiguring: - /* fall through */ case XenbusStateReconfigured: - /* fall through */ case XenbusStateInitialised: - /* fall through */ break; case XenbusStateInitialising: @@ -289,7 +286,6 @@ static void sndback_changed(struct xenbus_device *xb_dev, break; case XenbusStateUnknown: - /* fall through */ case XenbusStateClosed: if (xb_dev->state == XenbusStateClosed) break; diff --git a/sound/xen/xen_snd_front_evtchnl.c b/sound/xen/xen_snd_front_evtchnl.c index 102d6e096cc845cf7ab5a2cd4ef5488eb07a120f..29e0f0ea67ebdd262fae7eac290b03ed1ffe01df 100644 --- a/sound/xen/xen_snd_front_evtchnl.c +++ b/sound/xen/xen_snd_front_evtchnl.c @@ -46,13 +46,9 @@ again: continue; switch (resp->operation) { case XENSND_OP_OPEN: - /* fall through */ case XENSND_OP_CLOSE: - /* fall through */ case XENSND_OP_READ: - /* fall through */ case XENSND_OP_WRITE: - /* fall through */ case XENSND_OP_TRIGGER: channel->u.req.resp_status = resp->status; complete(&channel->u.req.completion); diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c index 45799606bb3e62e52a4dbe21c4e2746d70b93c5a..390f758d5a2717a5a31cccaeb361ec49b5e80b5e 100644 --- a/virt/kvm/async_pf.c +++ b/virt/kvm/async_pf.c @@ -156,17 +156,21 @@ void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu) } } -int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, - unsigned long hva, struct kvm_arch_async_pf *arch) +/* + * Try to schedule a job to handle page fault asynchronously. Returns 'true' on + * success, 'false' on failure (page fault has to be handled synchronously). + */ +bool kvm_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, + unsigned long hva, struct kvm_arch_async_pf *arch) { struct kvm_async_pf *work; if (vcpu->async_pf.queued >= ASYNC_PF_PER_VCPU) - return 0; + return false; /* Arch specific code should not do async PF in this case */ if (unlikely(kvm_is_error_hva(hva))) - return 0; + return false; /* * do alloc nowait since if we are going to sleep anyway we @@ -174,7 +178,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, */ work = kmem_cache_zalloc(async_pf_cache, GFP_NOWAIT | __GFP_NOWARN); if (!work) - return 0; + return false; work->wakeup_all = false; work->vcpu = vcpu; @@ -193,7 +197,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, schedule_work(&work->work); - return 1; + return true; } int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 0a68c9d3d3ab18ac56fb6883554f7a078b4134d4..2c2c0254c2d8d2e09c4041c1259ff177b6c8d225 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -340,6 +340,61 @@ void kvm_reload_remote_mmus(struct kvm *kvm) kvm_make_all_cpus_request(kvm, KVM_REQ_MMU_RELOAD); } +#ifdef KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE +static inline void *mmu_memory_cache_alloc_obj(struct kvm_mmu_memory_cache *mc, + gfp_t gfp_flags) +{ + gfp_flags |= mc->gfp_zero; + + if (mc->kmem_cache) + return kmem_cache_alloc(mc->kmem_cache, gfp_flags); + else + return (void *)__get_free_page(gfp_flags); +} + +int kvm_mmu_topup_memory_cache(struct kvm_mmu_memory_cache *mc, int min) +{ + void *obj; + + if (mc->nobjs >= min) + return 0; + while (mc->nobjs < ARRAY_SIZE(mc->objects)) { + obj = mmu_memory_cache_alloc_obj(mc, GFP_KERNEL_ACCOUNT); + if (!obj) + return mc->nobjs >= min ? 0 : -ENOMEM; + mc->objects[mc->nobjs++] = obj; + } + return 0; +} + +int kvm_mmu_memory_cache_nr_free_objects(struct kvm_mmu_memory_cache *mc) +{ + return mc->nobjs; +} + +void kvm_mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc) +{ + while (mc->nobjs) { + if (mc->kmem_cache) + kmem_cache_free(mc->kmem_cache, mc->objects[--mc->nobjs]); + else + free_page((unsigned long)mc->objects[--mc->nobjs]); + } +} + +void *kvm_mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) +{ + void *p; + + if (WARN_ON(!mc->nobjs)) + p = mmu_memory_cache_alloc_obj(mc, GFP_ATOMIC | __GFP_ACCOUNT); + else + p = mc->objects[--mc->nobjs]; + BUG_ON(!p); + return p; +} +#endif + static void kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id) { mutex_init(&vcpu->mutex); @@ -1626,6 +1681,14 @@ bool kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn) } EXPORT_SYMBOL_GPL(kvm_is_visible_gfn); +bool kvm_vcpu_is_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn) +{ + struct kvm_memory_slot *memslot = kvm_vcpu_gfn_to_memslot(vcpu, gfn); + + return kvm_is_visible_memslot(memslot); +} +EXPORT_SYMBOL_GPL(kvm_vcpu_is_visible_gfn); + unsigned long kvm_host_page_size(struct kvm_vcpu *vcpu, gfn_t gfn) { struct vm_area_struct *vma;