diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-18 21:05:34 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-18 21:05:34 +0300 |
commit | e6874fc29410fabfdbc8c12b467f41a16cbcfd2b (patch) | |
tree | bb869a9b481a6c05bf334a0a4db0b1397ce4ca90 | |
parent | e444d51b14c4795074f485c79debd234931f0e49 (diff) | |
parent | 3fb73eddba106ad2a265a5c5c29d14b0ed6aaee1 (diff) | |
download | linux-e6874fc29410fabfdbc8c12b467f41a16cbcfd2b.tar.xz |
Merge tag 'staging-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging and IIO driver updates from Greg KH:
"Here is the big staging/iio driver update for 5.4-rc1.
Lots of churn here, with a few driver/filesystems moving out of
staging finally:
- erofs moved out of staging
- greybus core code moved out of staging
Along with that, a new filesytem has been added:
- extfat
to provide support for those devices requiring that filesystem (i.e.
transfer devices to/from windows systems or printers)
Other than that, there a number of new IIO drivers, and lots and lots
and lots of staging driver cleanups and minor fixes as people continue
to dig into those for easy changes.
All of these have been in linux-next for a while with no reported
issues"
* tag 'staging-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (453 commits)
Staging: gasket: Use temporaries to reduce line length.
Staging: octeon: Avoid several usecases of strcpy
staging: vhciq_core: replace snprintf with scnprintf
staging: wilc1000: avoid twice IRQ handler execution for each single interrupt
staging: wilc1000: remove unused interrupt status handling code
staging: fbtft: make several arrays static const, makes object smaller
staging: rtl8188eu: make two arrays static const, makes object smaller
staging: rtl8723bs: core: Remove Macro "IS_MAC_ADDRESS_BROADCAST"
dt-bindings: anybus-controller: move to staging/ tree
staging: emxx_udc: remove local TRUE/FALSE definition
staging: wilc1000: look for rtc_clk clock
staging: dt-bindings: wilc1000: add optional rtc_clk property
staging: nvec: make use of devm_platform_ioremap_resource
staging: exfat: drop unused function parameter
Staging: exfat: Avoid use of strcpy
staging: exfat: use integer constants
staging: exfat: cleanup spacing for casts
staging: exfat: cleanup spacing for operators
staging: rtl8723bs: hal: remove redundant variable n
staging: pi433: Fix typo in documentation
...
448 files changed, 20318 insertions, 12333 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 index da9822309f07..0e66ae9b0071 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 +++ b/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 @@ -13,4 +13,4 @@ Description: error on writing If DFSDM input is SPI Slave: Reading returns value previously set. - Writing value before starting conversions.
\ No newline at end of file + Writing value before starting conversions. diff --git a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 index 161c147d3c40..b7259234ad70 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 +++ b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 @@ -91,29 +91,6 @@ Description: When counting down the counter start from preset value and fire event when reach 0. -What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available -KernelVersion: 4.12 -Contact: benjamin.gaignard@st.com -Description: - Reading returns the list possible quadrature modes. - -What: /sys/bus/iio/devices/iio:deviceX/in_count0_quadrature_mode -KernelVersion: 4.12 -Contact: benjamin.gaignard@st.com -Description: - Configure the device counter quadrature modes: - channel_A: - Encoder A input servers as the count input and B as - the UP/DOWN direction control input. - - channel_B: - Encoder B input serves as the count input and A as - the UP/DOWN direction control input. - - quadrature: - Encoder A and B inputs are mixed to get direction - and count with a scale of 0.25. - What: /sys/bus/iio/devices/iio:deviceX/in_count_enable_mode_available KernelVersion: 4.12 Contact: benjamin.gaignard@st.com diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml new file mode 100644 index 000000000000..676ec42e1438 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml @@ -0,0 +1,121 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2019 Analog Devices Inc. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bindings/iio/adc/adi,ad7192.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD7192 ADC device driver + +maintainers: + - Michael Hennerich <michael.hennerich@analog.com> + +description: | + Bindings for the Analog Devices AD7192 ADC device. Datasheet can be + found here: + https://www.analog.com/media/en/technical-documentation/data-sheets/AD7192.pdf + +properties: + compatible: + enum: + - adi,ad7190 + - adi,ad7192 + - adi,ad7193 + - adi,ad7195 + + reg: + maxItems: 1 + + spi-cpol: true + + spi-cpha: true + + clocks: + maxItems: 1 + description: phandle to the master clock (mclk) + + clock-names: + items: + - const: mclk + + interrupts: + maxItems: 1 + + dvdd-supply: + description: DVdd voltage supply + items: + - const: dvdd + + avdd-supply: + description: AVdd voltage supply + items: + - const: avdd + + adi,rejection-60-Hz-enable: + description: | + This bit enables a notch at 60 Hz when the first notch of the sinc + filter is at 50 Hz. When REJ60 is set, a filter notch is placed at + 60 Hz when the sinc filter first notch is at 50 Hz. This allows + simultaneous 50 Hz/ 60 Hz rejection. + type: boolean + + adi,refin2-pins-enable: + description: | + External reference applied between the P1/REFIN2(+) and P0/REFIN2(−) pins. + type: boolean + + adi,buffer-enable: + description: | + Enables the buffer on the analog inputs. If cleared, the analog inputs + are unbuffered, lowering the power consumption of the device. If this + bit is set, the analog inputs are buffered, allowing the user to place + source impedances on the front end without contributing gain errors to + the system. + type: boolean + + adi,burnout-currents-enable: + description: | + When this bit is set to 1, the 500 nA current sources in the signal + path are enabled. When BURN = 0, the burnout currents are disabled. + The burnout currents can be enabled only when the buffer is active + and when chop is disabled. + type: boolean + + bipolar: + description: see Documentation/devicetree/bindings/iio/adc/adc.txt + type: boolean + +required: + - compatible + - reg + - clocks + - clock-names + - interrupts + - dvdd-supply + - avdd-supply + - spi-cpol + - spi-cpha + +examples: + - | + spi0 { + adc@0 { + compatible = "adi,ad7192"; + reg = <0>; + spi-max-frequency = <1000000>; + spi-cpol; + spi-cpha; + clocks = <&ad7192_mclk>; + clock-names = "mclk"; + #interrupt-cells = <2>; + interrupts = <25 0x2>; + interrupt-parent = <&gpio>; + dvdd-supply = <&dvdd>; + avdd-supply = <&avdd>; + + adi,refin2-pins-enable; + adi,rejection-60-Hz-enable; + adi,buffer-enable; + adi,burnout-currents-enable; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt deleted file mode 100644 index d8652460198e..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt +++ /dev/null @@ -1,66 +0,0 @@ -Analog Devices AD7606 Simultaneous Sampling ADC - -Required properties for the AD7606: - -- compatible: Must be one of - * "adi,ad7605-4" - * "adi,ad7606-8" - * "adi,ad7606-6" - * "adi,ad7606-4" - * "adi,ad7616" -- reg: SPI chip select number for the device -- spi-max-frequency: Max SPI frequency to use - see: Documentation/devicetree/bindings/spi/spi-bus.txt -- spi-cpha: See Documentation/devicetree/bindings/spi/spi-bus.txt -- avcc-supply: phandle to the Avcc power supply -- interrupts: IRQ line for the ADC - see: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt -- adi,conversion-start-gpios: must be the device tree identifier of the CONVST pin. - This logic input is used to initiate conversions on the analog - input channels. As the line is active high, it should be marked - GPIO_ACTIVE_HIGH. - -Optional properties: - -- reset-gpios: must be the device tree identifier of the RESET pin. If specified, - it will be asserted during driver probe. As the line is active high, - it should be marked GPIO_ACTIVE_HIGH. -- standby-gpios: must be the device tree identifier of the STBY pin. This pin is used - to place the AD7606 into one of two power-down modes, Standby mode or - Shutdown mode. As the line is active low, it should be marked - GPIO_ACTIVE_LOW. -- adi,first-data-gpios: must be the device tree identifier of the FRSTDATA pin. - The FRSTDATA output indicates when the first channel, V1, is - being read back on either the parallel, byte or serial interface. - As the line is active high, it should be marked GPIO_ACTIVE_HIGH. -- adi,range-gpios: must be the device tree identifier of the RANGE pin. The polarity on - this pin determines the input range of the analog input channels. If - this pin is tied to a logic high, the analog input range is ±10V for - all channels. If this pin is tied to a logic low, the analog input range - is ±5V for all channels. As the line is active high, it should be marked - GPIO_ACTIVE_HIGH. -- adi,oversampling-ratio-gpios: must be the device tree identifier of the over-sampling - mode pins. As the line is active high, it should be marked - GPIO_ACTIVE_HIGH. - -Example: - - adc@0 { - compatible = "adi,ad7606-8"; - reg = <0>; - spi-max-frequency = <1000000>; - spi-cpol; - - avcc-supply = <&adc_vref>; - - interrupts = <25 IRQ_TYPE_EDGE_FALLING>; - interrupt-parent = <&gpio>; - - adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; - adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; - adi,oversampling-ratio-gpios = <&gpio 18 GPIO_ACTIVE_HIGH - &gpio 23 GPIO_ACTIVE_HIGH - &gpio 26 GPIO_ACTIVE_HIGH>; - standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>; - }; diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml new file mode 100644 index 000000000000..cc544fdc38be --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml @@ -0,0 +1,138 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ad7606.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD7606 Simultaneous Sampling ADC + +maintainers: + - Beniamin Bia <beniamin.bia@analog.com> + - Stefan Popa <stefan.popa@analog.com> + +description: | + Analog Devices AD7606 Simultaneous Sampling ADC + https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD7606B.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD7616.pdf + +properties: + compatible: + enum: + - adi,ad7605-4 + - adi,ad7606-8 + - adi,ad7606-6 + - adi,ad7606-4 + - adi,ad7606b + - adi,ad7616 + + reg: + maxItems: 1 + + spi-cpha: true + + avcc-supply: + description: + Phandle to the Avcc power supply + maxItems: 1 + + interrupts: + maxItems: 1 + + adi,conversion-start-gpios: + description: + Must be the device tree identifier of the CONVST pin. + This logic input is used to initiate conversions on the analog + input channels. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. + maxItems: 1 + + reset-gpios: + description: + Must be the device tree identifier of the RESET pin. If specified, + it will be asserted during driver probe. As the line is active high, + it should be marked GPIO_ACTIVE_HIGH. + maxItems: 1 + + standby-gpios: + description: + Must be the device tree identifier of the STBY pin. This pin is used + to place the AD7606 into one of two power-down modes, Standby mode or + Shutdown mode. As the line is active low, it should be marked + GPIO_ACTIVE_LOW. + maxItems: 1 + + adi,first-data-gpios: + description: + Must be the device tree identifier of the FRSTDATA pin. + The FRSTDATA output indicates when the first channel, V1, is + being read back on either the parallel, byte or serial interface. + As the line is active high, it should be marked GPIO_ACTIVE_HIGH. + maxItems: 1 + + adi,range-gpios: + description: + Must be the device tree identifier of the RANGE pin. The polarity on + this pin determines the input range of the analog input channels. If + this pin is tied to a logic high, the analog input range is ±10V for + all channels. If this pin is tied to a logic low, the analog input range + is ±5V for all channels. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. + maxItems: 1 + + adi,oversampling-ratio-gpios: + description: + Must be the device tree identifier of the over-sampling + mode pins. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. + maxItems: 1 + + adi,sw-mode: + description: + Software mode of operation, so far available only for ad7616 and ad7606b. + It is enabled when all three oversampling mode pins are connected to + high level. The device is configured by the corresponding registers. If the + adi,oversampling-ratio-gpios property is defined, then the driver will set the + oversampling gpios to high. Otherwise, it is assumed that the pins are hardwired + to VDD. + type: boolean + +required: + - compatible + - reg + - spi-cpha + - avcc-supply + - interrupts + - adi,conversion-start-gpios + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad7606-8"; + reg = <0>; + spi-max-frequency = <1000000>; + spi-cpol; + spi-cpha; + + avcc-supply = <&adc_vref>; + + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpio>; + + adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; + adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; + adi,oversampling-ratio-gpios = <&gpio 18 GPIO_ACTIVE_HIGH + &gpio 23 GPIO_ACTIVE_HIGH + &gpio 26 GPIO_ACTIVE_HIGH>; + standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>; + adi,sw-mode; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt index 93a0bd2efc05..4c0da8c74bb2 100644 --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt @@ -47,6 +47,12 @@ Required properties: Optional properties: - A pinctrl state named "default" for each ADC channel may be defined to set inX ADC pins in mode of operation for analog input on external pin. +- booster-supply: Phandle to the embedded booster regulator that can be used + to supply ADC analog input switches on stm32h7 and stm32mp1. +- vdd-supply: Phandle to the vdd input voltage. It can be used to supply ADC + analog input switches on stm32mp1. +- st,syscfg: Phandle to system configuration controller. It can be used to + control the analog circuitry on stm32mp1. Contents of a stm32 adc child node: ----------------------------------- diff --git a/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.txt b/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.txt deleted file mode 100644 index c52ea2126eaa..000000000000 --- a/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.txt +++ /dev/null @@ -1,26 +0,0 @@ -* Plantower PMS7003 particulate matter sensor - -Required properties: -- compatible: must one of: - "plantower,pms1003" - "plantower,pms3003" - "plantower,pms5003" - "plantower,pms6003" - "plantower,pms7003" - "plantower,pmsa003" -- vcc-supply: phandle to the regulator that provides power to the sensor - -Optional properties: -- plantower,set-gpios: phandle to the GPIO connected to the SET line -- reset-gpios: phandle to the GPIO connected to the RESET line - -Refer to serial/slave-device.txt for generic serial attached device bindings. - -Example: - -&uart0 { - air-pollution-sensor { - compatible = "plantower,pms7003"; - vcc-supply = <®_vcc5v0>; - }; -}; diff --git a/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml b/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml new file mode 100644 index 000000000000..a551d3101f93 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/chemical/plantower,pms7003.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Plantower PMS7003 air pollution sensor + +maintainers: + - Tomasz Duszynski <tduszyns@gmail.com> + +description: | + Air pollution sensor capable of measuring mass concentration of dust + particles. + +properties: + compatible: + enum: + - plantower,pms1003 + - plantower,pms3003 + - plantower,pms5003 + - plantower,pms6003 + - plantower,pms7003 + - plantower,pmsa003 + + vcc-supply: + description: regulator that provides power to the sensor + maxItems: 1 + + plantower,set-gpios: + description: GPIO connected to the SET line + maxItems: 1 + + reset-gpios: + description: GPIO connected to the RESET line + maxItems: 1 + +required: + - compatible + - vcc-supply + +examples: + - | + serial { + air-pollution-sensor { + compatible = "plantower,pms7003"; + vcc-supply = <®_vcc5v0>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml b/Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml new file mode 100644 index 000000000000..0c53009ba7d6 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/imu/adi,adis16460.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices ADIS16460 and similar IMUs + +maintainers: + - Dragos Bogdan <dragos.bogdan@analog.com> + +description: | + Analog Devices ADIS16460 and similar IMUs + https://www.analog.com/media/en/technical-documentation/data-sheets/ADIS16460.pdf + +properties: + compatible: + enum: + - adi,adis16460 + + reg: + maxItems: 1 + + spi-cpha: true + + spi-cpol: true + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + imu@0 { + compatible = "adi,adis16460"; + reg = <0>; + spi-max-frequency = <5000000>; + spi-cpol; + spi-cpha; + interrupt-parent = <&gpio0>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt index efec9ece034a..6d0c050d89fe 100644 --- a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt +++ b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt @@ -11,6 +11,9 @@ Required properties: "st,asm330lhh" "st,lsm6dsox" "st,lsm6dsr" + "st,lsm6ds3tr-c" + "st,ism330dhcx" + "st,lsm9ds1-imu" - reg: i2c address of the sensor / spi cs line Optional properties: diff --git a/Documentation/devicetree/bindings/iio/light/noa1305.yaml b/Documentation/devicetree/bindings/iio/light/noa1305.yaml new file mode 100644 index 000000000000..17e7f140b69b --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/noa1305.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/light/noa1305.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ON Semiconductor NOA1305 Ambient Light Sensor + +maintainers: + - Martyn Welch <martyn.welch@collabora.com> + +description: | + Ambient sensing with an i2c interface. + + https://www.onsemi.com/pub/Collateral/NOA1305-D.PDF + +properties: + compatible: + enum: + - onnn,noa1305 + + reg: + maxItems: 1 + + vin-supply: + description: Regulator that provides power to the sensor + +required: + - compatible + - reg + +examples: + - | + i2c { + + #address-cells = <1>; + #size-cells = <0>; + + light@39 { + compatible = "onnn,noa1305"; + reg = <0x39>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/light/isl29501.txt b/Documentation/devicetree/bindings/iio/light/renesas,isl29501.txt index 46957997fee3..46957997fee3 100644 --- a/Documentation/devicetree/bindings/iio/light/isl29501.txt +++ b/Documentation/devicetree/bindings/iio/light/renesas,isl29501.txt diff --git a/Documentation/devicetree/bindings/iio/light/stk33xx.yaml b/Documentation/devicetree/bindings/iio/light/stk33xx.yaml new file mode 100644 index 000000000000..aae8a6d627c9 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/stk33xx.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/light/stk33xx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: | + Sensortek STK33xx I2C Ambient Light and Proximity sensor + +maintainers: + - Jonathan Cameron <jic23@kernel.org> + +description: | + Ambient light and proximity sensor over an i2c interface. + +properties: + compatible: + enum: + - sensortek,stk3310 + - sensortek,stk3311 + - sensortek,stk3335 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + + i2c { + + #address-cells = <1>; + #size-cells = <0>; + + stk3310@48 { + compatible = "sensortek,stk3310"; + reg = <0x48>; + interrupt-parent = <&gpio1>; + interrupts = <5 IRQ_TYPE_LEVEL_LOW>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/mount-matrix.txt b/Documentation/devicetree/bindings/iio/mount-matrix.txt new file mode 100644 index 000000000000..c3344ab509a3 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/mount-matrix.txt @@ -0,0 +1,203 @@ +For discussion. Unclear are: +* is the definition of +/- values practical or counterintuitive? +* are the definitions unambiguous and easy to follow? +* are the examples correct? +* should we have HOWTO engineer a correct matrix for a new device (without comparing to a different one)? + +==== + + +Mounting matrix + +The mounting matrix is a device tree property used to orient any device +that produce three-dimensional data in relation to the world where it is +deployed. + +The purpose of the mounting matrix is to translate the sensor frame of +reference into the device frame of reference using a translation matrix as +defined in linear algebra. + +The typical usecase is that where a component has an internal representation +of the (x,y,z) triplets, such as different registers to read these coordinates, +and thus implying that the component should be mounted in a certain orientation +relative to some specific device frame of reference. + +For example a device with some kind of screen, where the user is supposed to +interact with the environment using an accelerometer, gyroscope or magnetometer +mounted on the same chassis as this screen, will likely take the screen as +reference to (x,y,z) orientation, with (x,y) corresponding to these axes on the +screen and (z) being depth, the axis perpendicular to the screen. + +For a screen you probably want (x) coordinates to go from negative on the left +to positive on the right, (y) from negative on the bottom to positive on top +and (z) depth to be negative under the screen and positive in front of it, +toward the face of the user. + +A sensor can be mounted in any angle along the axes relative to the frame of +reference. This means that the sensor may be flipped upside-down, left-right, +or tilted at any angle relative to the frame of reference. + +Another frame of reference is how the device with its sensor relates to the +external world, the environment where the device is deployed. Usually the data +from the sensor is used to figure out how the device is oriented with respect +to this world. When using the mounting matrix, the sensor and device orientation +becomes identical and we can focus on the data as it relates to the surrounding +world. + +Device-to-world examples for some three-dimensional sensor types: + +- Accelerometers have their world frame of reference toward the center of + gravity, usually to the core of the planet. A reading of the (x,y,z) values + from the sensor will give a projection of the gravity vector through the + device relative to the center of the planet, i.e. relative to its surface at + this point. Up and down in the world relative to the device frame of + reference can thus be determined. and users would likely expect a value of + 9.81 m/s^2 upwards along the (z) axis, i.e. out of the screen when the device + is held with its screen flat on the planets surface and 0 on the other axes, + as the gravity vector is projected 1:1 onto the sensors (z)-axis. + + If you tilt the device, the g vector virtually coming out of the display + is projected onto the (x,y) plane of the display panel. + + Example: + + ^ z: +g ^ z: > 0 + ! /! + ! x=y=0 / ! x: > 0 + +--------+ +--------+ + ! ! ! ! + +--------+ +--------+ + ! / + ! / + v v + center of center of + gravity gravity + + + If the device is tilted to the left, you get a positive x value. If you point + its top towards surface, you get a negative y axis. + + (---------) + ! ! y: -g + ! ! ^ + ! ! ! + ! ! + ! ! x: +g <- z: +g -> x: -g + ! 1 2 3 ! + ! 4 5 6 ! ! + ! 7 8 9 ! v + ! * 0 # ! y: +g + (---------) + + +- Magnetometers (compasses) have their world frame of reference relative to the + geomagnetic field. The system orientation vis-a-vis the world is defined with + respect to the local earth geomagnetic reference frame where (y) is in the + ground plane and positive towards magnetic North, (x) is in the ground plane, + perpendicular to the North axis and positive towards the East and (z) is + perpendicular to the ground plane and positive upwards. + + + ^^^ North: y > 0 + + (---------) + ! ! + ! ! + ! ! + ! ! > + ! ! > North: x > 0 + ! 1 2 3 ! > + ! 4 5 6 ! + ! 7 8 9 ! + ! * 0 # ! + (---------) + + Since the geomagnetic field is not uniform this definition fails if we come + closer to the poles. + + Sensors and driver can not and should not take care of this because there + are complex calculations and empirical data to be taken care of. We leave + this up to user space. + + The definition we take: + + If the device is placed at the equator and the top is pointing north, the + display is readable by a person standing upright on the earth surface, this + defines a positive y value. + + +- Gyroscopes detects the movement relative the device itself. The angular + velocity is defined as orthogonal to the plane of rotation, so if you put the + device on a flat surface and spin it around the z axis (such as rotating a + device with a screen lying flat on a table), you should get a negative value + along the (z) axis if rotated clockwise, and a positive value if rotated + counter-clockwise according to the right-hand rule. + + + (---------) y > 0 + ! ! v---\ + ! ! + ! ! + ! ! <--\ + ! ! ! z > 0 + ! 1 2 3 ! --/ + ! 4 5 6 ! + ! 7 8 9 ! + ! * 0 # ! + (---------) + + +So unless the sensor is ideally mounted, we need a means to indicate the +relative orientation of any given sensor of this type with respect to the +frame of reference. + +To achieve this, use the device tree property "mount-matrix" for the sensor. + +This supplies a 3x3 rotation matrix in the strict linear algebraic sense, +to orient the senor axes relative to a desired point of reference. This means +the resulting values from the sensor, after scaling to proper units, should be +multiplied by this matrix to give the proper vectors values in three-dimensional +space, relative to the device or world point of reference. + +For more information, consult: +https://en.wikipedia.org/wiki/Rotation_matrix + +The mounting matrix has the layout: + + (mxx, myx, mzx) + (mxy, myy, mzy) + (mxz, myz, mzz) + +Values are intended to be multiplied as: + + x' = mxx * x + myx * y + mzx * z + y' = mxy * x + myy * y + mzy * z + z' = mxz * x + myz * y + mzz * z + +It is represented as an array of strings containing the real values for +producing the transformation matrix. + +Examples: + +Identity matrix (nothing happens to the coordinates, which means the device was +mechanically mounted in an ideal way and we need no transformation): + +mount-matrix = "1", "0", "0", + "0", "1", "0", + "0", "0", "1"; + +The sensor is mounted 30 degrees (Pi/6 radians) tilted along the X axis, so we +compensate by performing a -30 degrees rotation around the X axis: + +mount-matrix = "1", "0", "0", + "0", "0.866", "0.5", + "0", "-0.5", "0.866"; + +The sensor is flipped 180 degrees (Pi radians) around the Z axis, i.e. mounted +upside-down: + +mount-matrix = "0.998", "0.054", "0", + "-0.054", "0.998", "0", + "0", "0", "1"; + +???: this does not match "180 degrees" - factors indicate ca. 3 degrees compensation diff --git a/Documentation/devicetree/bindings/iio/potentiometer/max5432.yaml b/Documentation/devicetree/bindings/iio/potentiometer/max5432.yaml new file mode 100644 index 000000000000..5082f919df2a --- /dev/null +++ b/Documentation/devicetree/bindings/iio/potentiometer/max5432.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/potentiometer/max5432.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim Integrated MAX5432-MAX5435 Digital Potentiometers + +maintainers: + - Martin Kaiser <martin@kaiser.cx> + +description: | + Maxim Integrated MAX5432-MAX5435 Digital Potentiometers connected via I2C + + Datasheet: + https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf + +properties: + compatible: + enum: + - maxim,max5432 + - maxim,max5433 + - maxim,max5434 + - maxim,max5435 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + max5434@28 { + compatible = "maxim,max5434"; + reg = <0x28>; + }; + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index de4240e0aa82..329b668dac0a 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -827,6 +827,8 @@ patternProperties: description: Semtech Corporation "^sensirion,.*": description: Sensirion AG + "^sensortek,.*": + description: Sensortek Technology Corporation "^sff,.*": description: Small Form Factor Committee "^sgd,.*": diff --git a/drivers/staging/erofs/Documentation/filesystems/erofs.txt b/Documentation/filesystems/erofs.txt index 74cf84ac48a3..b0c085326e2e 100644 --- a/drivers/staging/erofs/Documentation/filesystems/erofs.txt +++ b/Documentation/filesystems/erofs.txt @@ -49,22 +49,23 @@ Bugs and patches are welcome, please kindly help us and send to the following linux-erofs mailing list: >> linux-erofs mailing list <linux-erofs@lists.ozlabs.org> -Note that EROFS is still working in progress as a Linux staging driver, -Cc the staging mailing list as well is highly recommended: ->> Linux Driver Project Developer List <devel@driverdev.osuosl.org> - Mount options ============= -fault_injection=%d Enable fault injection in all supported types with - specified injection rate. Supported injection type: - Type_Name Type_Value - FAULT_KMALLOC 0x000000001 - FAULT_READ_IO 0x000000002 (no)user_xattr Setup Extended User Attributes. Note: xattr is enabled by default if CONFIG_EROFS_FS_XATTR is selected. (no)acl Setup POSIX Access Control List. Note: acl is enabled by default if CONFIG_EROFS_FS_POSIX_ACL is selected. +cache_strategy=%s Select a strategy for cached decompression from now on: + disabled: In-place I/O decompression only; + readahead: Cache the last incomplete compressed physical + cluster for further reading. It still does + in-place I/O decompression for the rest + compressed physical clusters; + readaround: Cache the both ends of incomplete compressed + physical clusters for further reading. + It still does in-place I/O decompression + for the rest compressed physical clusters. On-disk details =============== diff --git a/MAINTAINERS b/MAINTAINERS index 0e01ab35df04..0262f99df61d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -902,11 +902,12 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml ANALOG DEVICES INC AD7606 DRIVER M: Stefan Popa <stefan.popa@analog.com> +M: Beniamin Bia <beniamin.bia@analog.com> L: linux-iio@vger.kernel.org W: http://ez.analog.com/community/linux-device-drivers S: Supported F: drivers/iio/adc/ad7606.c -F: Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt +F: Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml ANALOG DEVICES INC AD7768-1 DRIVER M: Stefan Popa <stefan.popa@analog.com> @@ -944,6 +945,14 @@ L: linux-iio@vger.kernel.org F: include/linux/iio/imu/adis.h F: drivers/iio/imu/adis.c +ANALOG DEVICES INC ADIS16460 DRIVER +M: Dragos Bogdan <dragos.bogdan@analog.com> +S: Supported +L: linux-iio@vger.kernel.org +W: http://ez.analog.com/community/linux-device-drivers +F: drivers/iio/imu/adis16460.c +F: Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml + ANALOG DEVICES INC ADP5061 DRIVER M: Stefan Popa <stefan.popa@analog.com> L: linux-pm@vger.kernel.org @@ -6050,6 +6059,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git F: drivers/video/fbdev/s1d13xxxfb.c F: include/video/s1d13xxxfb.h +EROFS FILE SYSTEM +M: Gao Xiang <gaoxiang25@huawei.com> +M: Chao Yu <yuchao0@huawei.com> +L: linux-erofs@lists.ozlabs.org +S: Maintained +F: fs/erofs/ + ERRSEQ ERROR TRACKING INFRASTRUCTURE M: Jeff Layton <jlayton@kernel.org> S: Maintained @@ -6094,6 +6110,11 @@ F: include/trace/events/mdio.h F: include/uapi/linux/mdio.h F: include/uapi/linux/mii.h +EXFAT FILE SYSTEM +M: Valdis Kletnieks <valdis.kletnieks@vt.edu> +S: Maintained +F: drivers/staging/exfat/ + EXT2 FILE SYSTEM M: Jan Kara <jack@suse.com> L: linux-ext4@vger.kernel.org @@ -7001,6 +7022,9 @@ M: Alex Elder <elder@kernel.org> M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> S: Maintained F: drivers/staging/greybus/ +F: drivers/greybus/ +F: include/linux/greybus.h +F: include/linux/greybus/ L: greybus-dev@lists.linaro.org (moderated for non-subscribers) GREYBUS UART PROTOCOLS DRIVERS @@ -12803,6 +12827,12 @@ F: drivers/i2c/busses/i2c-puv3.c F: drivers/video/fbdev/fb-puv3.c F: drivers/rtc/rtc-puv3.c +PLANTOWER PMS7003 AIR POLLUTION SENSOR DRIVER +M: Tomasz Duszynski <tduszyns@gmail.com> +S: Maintained +F: drivers/iio/chemical/pms7003.c +F: Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml + PMBUS HARDWARE MONITORING DRIVERS M: Guenter Roeck <linux@roeck-us.net> L: linux-hwmon@vger.kernel.org @@ -15240,13 +15270,6 @@ M: H Hartley Sweeten <hsweeten@visionengravers.com> S: Odd Fixes F: drivers/staging/comedi/ -STAGING - EROFS FILE SYSTEM -M: Gao Xiang <gaoxiang25@huawei.com> -M: Chao Yu <yuchao0@huawei.com> -L: linux-erofs@lists.ozlabs.org -S: Maintained -F: drivers/staging/erofs/ - STAGING - FIELDBUS SUBSYSTEM M: Sven Van Asbroeck <TheSven73@gmail.com> S: Maintained diff --git a/drivers/Kconfig b/drivers/Kconfig index 13f09bf64a0f..8befa53f43be 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -142,6 +142,8 @@ source "drivers/hv/Kconfig" source "drivers/xen/Kconfig" +source "drivers/greybus/Kconfig" + source "drivers/staging/Kconfig" source "drivers/platform/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index ad66dc2325d7..aaef17cc6512 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -146,6 +146,7 @@ obj-$(CONFIG_BCMA) += bcma/ obj-$(CONFIG_VHOST_RING) += vhost/ obj-$(CONFIG_VHOST) += vhost/ obj-$(CONFIG_VLYNQ) += vlynq/ +obj-$(CONFIG_GREYBUS) += greybus/ obj-$(CONFIG_STAGING) += staging/ obj-y += platform/ diff --git a/drivers/counter/ftm-quaddec.c b/drivers/counter/ftm-quaddec.c index 68a9b7393457..4046aa9f9234 100644 --- a/drivers/counter/ftm-quaddec.c +++ b/drivers/counter/ftm-quaddec.c @@ -100,16 +100,18 @@ static void ftm_quaddec_init(struct ftm_quaddec *ftm) ftm_set_write_protection(ftm); } -static void ftm_quaddec_disable(struct ftm_quaddec *ftm) +static void ftm_quaddec_disable(void *ftm) { - ftm_clear_write_protection(ftm); - ftm_write(ftm, FTM_MODE, 0); - ftm_write(ftm, FTM_QDCTRL, 0); + struct ftm_quaddec *ftm_qua = ftm; + + ftm_clear_write_protection(ftm_qua); + ftm_write(ftm_qua, FTM_MODE, 0); + ftm_write(ftm_qua, FTM_QDCTRL, 0); /* * This is enough to disable the counter. No clock has been * selected by writing to FTM_SC in init() */ - ftm_set_write_protection(ftm); + ftm_set_write_protection(ftm_qua); } static int ftm_quaddec_get_prescaler(struct counter_device *counter, @@ -317,20 +319,13 @@ static int ftm_quaddec_probe(struct platform_device *pdev) ftm_quaddec_init(ftm); - ret = counter_register(&ftm->counter); + ret = devm_add_action_or_reset(&pdev->dev, ftm_quaddec_disable, ftm); if (ret) - ftm_quaddec_disable(ftm); - - return ret; -} + return ret; -static int ftm_quaddec_remove(struct platform_device *pdev) -{ - struct ftm_quaddec *ftm = platform_get_drvdata(pdev); - - counter_unregister(&ftm->counter); - - ftm_quaddec_disable(ftm); + ret = devm_counter_register(&pdev->dev, &ftm->counter); + if (ret) + return ret; return 0; } @@ -346,7 +341,6 @@ static struct platform_driver ftm_quaddec_driver = { .of_match_table = ftm_quaddec_match, }, .probe = ftm_quaddec_probe, - .remove = ftm_quaddec_remove, }; module_platform_driver(ftm_quaddec_driver); diff --git a/drivers/greybus/Kconfig b/drivers/greybus/Kconfig new file mode 100644 index 000000000000..b84fcaf8b105 --- /dev/null +++ b/drivers/greybus/Kconfig @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +menuconfig GREYBUS + tristate "Greybus support" + depends on SYSFS + ---help--- + This option enables the Greybus driver core. Greybus is an + hardware protocol that was designed to provide Unipro with a + sane application layer. It was originally designed for the + ARA project, a module phone system, but has shown up in other + phones, and can be tunneled over other busses in order to + control hardware devices. + + Say Y here to enable support for these types of drivers. + + To compile this code as a module, chose M here: the module + will be called greybus.ko + +if GREYBUS + +config GREYBUS_ES2 + tristate "Greybus ES3 USB host controller" + depends on USB + ---help--- + Select this option if you have a Toshiba ES3 USB device that + acts as a Greybus "host controller". This device is a bridge + from a USB device to a Unipro network. + + To compile this code as a module, chose M here: the module + will be called gb-es2.ko + +endif # GREYBUS + diff --git a/drivers/greybus/Makefile b/drivers/greybus/Makefile new file mode 100644 index 000000000000..9bccdd229aa2 --- /dev/null +++ b/drivers/greybus/Makefile @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +# Greybus core +greybus-y := core.o \ + debugfs.o \ + hd.o \ + manifest.o \ + module.o \ + interface.o \ + bundle.o \ + connection.o \ + control.o \ + svc.o \ + svc_watchdog.o \ + operation.o + +obj-$(CONFIG_GREYBUS) += greybus.o + +# needed for trace events +ccflags-y += -I$(src) + +# Greybus Host controller drivers +gb-es2-y := es2.o + +obj-$(CONFIG_GREYBUS_ES2) += gb-es2.o + + diff --git a/drivers/greybus/arpc.h b/drivers/greybus/arpc.h new file mode 100644 index 000000000000..c8b83c5cfa79 --- /dev/null +++ b/drivers/greybus/arpc.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. + */ + +#ifndef __ARPC_H +#define __ARPC_H + +/* APBridgeA RPC (ARPC) */ + +enum arpc_result { + ARPC_SUCCESS = 0x00, + ARPC_NO_MEMORY = 0x01, + ARPC_INVALID = 0x02, + ARPC_TIMEOUT = 0x03, + ARPC_UNKNOWN_ERROR = 0xff, +}; + +struct arpc_request_message { + __le16 id; /* RPC unique id */ + __le16 size; /* Size in bytes of header + payload */ + __u8 type; /* RPC type */ + __u8 data[0]; /* ARPC data */ +} __packed; + +struct arpc_response_message { + __le16 id; /* RPC unique id */ + __u8 result; /* Result of RPC */ +} __packed; + +/* ARPC requests */ +#define ARPC_TYPE_CPORT_CONNECTED 0x01 +#define ARPC_TYPE_CPORT_QUIESCE 0x02 +#define ARPC_TYPE_CPORT_CLEAR 0x03 +#define ARPC_TYPE_CPORT_FLUSH 0x04 +#define ARPC_TYPE_CPORT_SHUTDOWN 0x05 + +struct arpc_cport_connected_req { + __le16 cport_id; +} __packed; + +struct arpc_cport_quiesce_req { + __le16 cport_id; + __le16 peer_space; + __le16 timeout; +} __packed; + +struct arpc_cport_clear_req { + __le16 cport_id; +} __packed; + +struct arpc_cport_flush_req { + __le16 cport_id; +} __packed; + +struct arpc_cport_shutdown_req { + __le16 cport_id; + __le16 timeout; + __u8 phase; +} __packed; + +#endif /* __ARPC_H */ diff --git a/drivers/staging/greybus/bundle.c b/drivers/greybus/bundle.c index 3f702db9e098..84660729538b 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/greybus/bundle.c @@ -6,7 +6,7 @@ * Copyright 2014-2015 Linaro Ltd. */ -#include "greybus.h" +#include <linux/greybus.h> #include "greybus_trace.h" static ssize_t bundle_class_show(struct device *dev, diff --git a/drivers/staging/greybus/connection.c b/drivers/greybus/connection.c index eda964208cce..fc8f57f97ce6 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/greybus/connection.c @@ -7,8 +7,8 @@ */ #include <linux/workqueue.h> +#include <linux/greybus.h> -#include "greybus.h" #include "greybus_trace.h" #define GB_CONNECTION_CPORT_QUIESCE_TIMEOUT 1000 diff --git a/drivers/staging/greybus/control.c b/drivers/greybus/control.c index a9e8b6036cac..359a25841973 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/greybus/control.c @@ -9,7 +9,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> -#include "greybus.h" +#include <linux/greybus.h> /* Highest control-protocol version supported */ #define GB_CONTROL_VERSION_MAJOR 0 diff --git a/drivers/staging/greybus/core.c b/drivers/greybus/core.c index d6b0d49130c0..e546c6431877 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/greybus/core.c @@ -9,7 +9,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define CREATE_TRACE_POINTS -#include "greybus.h" +#include <linux/greybus.h> #include "greybus_trace.h" #define GB_BUNDLE_AUTOSUSPEND_MS 3000 diff --git a/drivers/staging/greybus/debugfs.c b/drivers/greybus/debugfs.c index 56e20c30feb5..e102d7badb9d 100644 --- a/drivers/staging/greybus/debugfs.c +++ b/drivers/greybus/debugfs.c @@ -7,8 +7,7 @@ */ #include <linux/debugfs.h> - -#include "greybus.h" +#include <linux/greybus.h> static struct dentry *gb_debug_root; diff --git a/drivers/staging/greybus/es2.c b/drivers/greybus/es2.c index be6af18cec31..366716f11b1a 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/greybus/es2.c @@ -11,12 +11,11 @@ #include <linux/kfifo.h> #include <linux/debugfs.h> #include <linux/list.h> +#include <linux/greybus.h> #include <asm/unaligned.h> #include "arpc.h" -#include "greybus.h" #include "greybus_trace.h" -#include "connection.h" /* Default timeout for USB vendor requests. */ diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/greybus/greybus_trace.h index 7b5e2c6b1f6b..1bc9f1275c65 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/greybus/greybus_trace.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus driver and device API * diff --git a/drivers/staging/greybus/hd.c b/drivers/greybus/hd.c index 969f86697673..72b21bf2d7d3 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/greybus/hd.c @@ -8,8 +8,8 @@ #include <linux/kernel.h> #include <linux/slab.h> +#include <linux/greybus.h> -#include "greybus.h" #include "greybus_trace.h" EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_create); @@ -31,7 +31,7 @@ int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, EXPORT_SYMBOL_GPL(gb_hd_output); static ssize_t bus_id_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct gb_host_device *hd = to_gb_host_device(dev); @@ -70,7 +70,7 @@ EXPORT_SYMBOL_GPL(gb_hd_cport_release_reserved); /* Locking: Caller guarantees serialisation */ int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, - unsigned long flags) + unsigned long flags) { struct ida *id_map = &hd->cport_id_map; int ida_start, ida_end; @@ -122,9 +122,9 @@ struct device_type greybus_hd_type = { }; struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, - struct device *parent, - size_t buffer_size_max, - size_t num_cports) + struct device *parent, + size_t buffer_size_max, + size_t num_cports) { struct gb_host_device *hd; int ret; diff --git a/drivers/staging/greybus/interface.c b/drivers/greybus/interface.c index d7b5b89a2f40..67dbe6fda9a1 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/greybus/interface.c @@ -7,8 +7,8 @@ */ #include <linux/delay.h> +#include <linux/greybus.h> -#include "greybus.h" #include "greybus_trace.h" #define GB_INTERFACE_MODE_SWITCH_TIMEOUT 2000 diff --git a/drivers/staging/greybus/manifest.c b/drivers/greybus/manifest.c index 08db49264f2b..dd7040697bde 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/greybus/manifest.c @@ -6,7 +6,7 @@ * Copyright 2014-2015 Linaro Ltd. */ -#include "greybus.h" +#include <linux/greybus.h> static const char *get_descriptor_type_string(u8 type) { @@ -104,15 +104,15 @@ static int identify_descriptor(struct gb_interface *intf, size_t expected_size; if (size < sizeof(*desc_header)) { - dev_err(&intf->dev, "manifest too small (%zu < %zu)\n", - size, sizeof(*desc_header)); + dev_err(&intf->dev, "manifest too small (%zu < %zu)\n", size, + sizeof(*desc_header)); return -EINVAL; /* Must at least have header */ } desc_size = le16_to_cpu(desc_header->size); if (desc_size > size) { dev_err(&intf->dev, "descriptor too big (%zu > %zu)\n", - desc_size, size); + desc_size, size); return -EINVAL; } @@ -139,22 +139,22 @@ static int identify_descriptor(struct gb_interface *intf, case GREYBUS_TYPE_INVALID: default: dev_err(&intf->dev, "invalid descriptor type (%u)\n", - desc_header->type); + desc_header->type); return -EINVAL; } if (desc_size < expected_size) { dev_err(&intf->dev, "%s descriptor too small (%zu < %zu)\n", - get_descriptor_type_string(desc_header->type), - desc_size, expected_size); + get_descriptor_type_string(desc_header->type), + desc_size, expected_size); return -EINVAL; } /* Descriptor bigger than what we expect */ if (desc_size > expected_size) { dev_warn(&intf->dev, "%s descriptor size mismatch (want %zu got %zu)\n", - get_descriptor_type_string(desc_header->type), - expected_size, desc_size); + get_descriptor_type_string(desc_header->type), + expected_size, desc_size); } descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); @@ -208,7 +208,7 @@ static char *gb_string_get(struct gb_interface *intf, u8 string_id) /* Allocate an extra byte so we can guarantee it's NUL-terminated */ string = kmemdup(&desc_string->string, desc_string->length + 1, - GFP_KERNEL); + GFP_KERNEL); if (!string) return ERR_PTR(-ENOMEM); string[desc_string->length] = '\0'; @@ -264,8 +264,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) desc_cport = tmp->data; if (cport_id == le16_to_cpu(desc_cport->id)) { dev_err(&bundle->dev, - "duplicate CPort %u found\n", - cport_id); + "duplicate CPort %u found\n", cport_id); goto exit; } } @@ -277,7 +276,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) return 0; bundle->cport_desc = kcalloc(count, sizeof(*bundle->cport_desc), - GFP_KERNEL); + GFP_KERNEL); if (!bundle->cport_desc) goto exit; @@ -287,7 +286,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) list_for_each_entry_safe(desc, next, &list, links) { desc_cport = desc->data; memcpy(&bundle->cport_desc[i++], desc_cport, - sizeof(*desc_cport)); + sizeof(*desc_cport)); /* Release the cport descriptor */ release_manifest_descriptor(desc); @@ -333,9 +332,9 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) /* Ignore any legacy control bundles */ if (bundle_id == GB_CONTROL_BUNDLE_ID) { dev_dbg(&intf->dev, "%s - ignoring control bundle\n", - __func__); + __func__); release_cport_descriptors(&intf->manifest_descs, - bundle_id); + bundle_id); continue; } @@ -468,7 +467,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) /* we have to have at _least_ the manifest header */ if (size < sizeof(*header)) { dev_err(&intf->dev, "short manifest (%zu < %zu)\n", - size, sizeof(*header)); + size, sizeof(*header)); return false; } @@ -478,15 +477,15 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) manifest_size = le16_to_cpu(header->size); if (manifest_size != size) { dev_err(&intf->dev, "manifest size mismatch (%zu != %u)\n", - size, manifest_size); + size, manifest_size); return false; } /* Validate major/minor number */ if (header->version_major > GREYBUS_VERSION_MAJOR) { dev_err(&intf->dev, "manifest version too new (%u.%u > %u.%u)\n", - header->version_major, header->version_minor, - GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); + header->version_major, header->version_minor, + GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); return false; } @@ -513,7 +512,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) } if (found != 1) { dev_err(&intf->dev, "manifest must have 1 interface descriptor (%u found)\n", - found); + found); result = false; goto out; } diff --git a/drivers/staging/greybus/module.c b/drivers/greybus/module.c index b251a53d0e8e..36f77f9e1d74 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/greybus/module.c @@ -6,7 +6,7 @@ * Copyright 2016 Linaro Ltd. */ -#include "greybus.h" +#include <linux/greybus.h> #include "greybus_trace.h" static ssize_t eject_store(struct device *dev, diff --git a/drivers/staging/greybus/operation.c b/drivers/greybus/operation.c index fe268f7b63ed..8459e9bc0749 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/greybus/operation.c @@ -12,8 +12,8 @@ #include <linux/sched.h> #include <linux/wait.h> #include <linux/workqueue.h> +#include <linux/greybus.h> -#include "greybus.h" #include "greybus_trace.h" static struct kmem_cache *gb_operation_cache; diff --git a/drivers/staging/greybus/svc.c b/drivers/greybus/svc.c index 05bc45287b87..ce7740ef449b 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/greybus/svc.c @@ -8,8 +8,7 @@ #include <linux/debugfs.h> #include <linux/workqueue.h> - -#include "greybus.h" +#include <linux/greybus.h> #define SVC_INTF_EJECT_TIMEOUT 9000 #define SVC_INTF_ACTIVATE_TIMEOUT 6000 diff --git a/drivers/staging/greybus/svc_watchdog.c b/drivers/greybus/svc_watchdog.c index 7868ad8211c5..b6b1682c19c4 100644 --- a/drivers/staging/greybus/svc_watchdog.c +++ b/drivers/greybus/svc_watchdog.c @@ -8,7 +8,7 @@ #include <linux/delay.h> #include <linux/suspend.h> #include <linux/workqueue.h> -#include "greybus.h" +#include <linux/greybus.h> #define SVC_WATCHDOG_PERIOD (2 * HZ) diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 9b9656ce37e6..d4ef35aeb579 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -202,9 +202,7 @@ config HID_SENSOR_ACCEL_3D config IIO_CROS_EC_ACCEL_LEGACY tristate "ChromeOS EC Legacy Accelerometer Sensor" - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - select CROS_EC_LPC_REGISTER_DEVICE + depends on IIO_CROS_EC_SENSORS_CORE help Say yes here to get support for accelerometers on Chromebook using legacy EC firmware. diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c index ad19d9c716f4..39002cb5605d 100644 --- a/drivers/iio/accel/cros_ec_accel_legacy.c +++ b/drivers/iio/accel/cros_ec_accel_legacy.c @@ -5,13 +5,14 @@ * Copyright 2017 Google, Inc * * This driver uses the memory mapper cros-ec interface to communicate - * with the Chrome OS EC about accelerometer data. + * with the Chrome OS EC about accelerometer data or older commands. * Accelerometer access is presented through iio sysfs. */ #include <linux/delay.h> #include <linux/device.h> #include <linux/iio/buffer.h> +#include <linux/iio/common/cros_ec_sensors_core.h> #include <linux/iio/iio.h> #include <linux/iio/kfifo_buf.h> #include <linux/iio/trigger_consumer.h> @@ -25,160 +26,41 @@ #define DRV_NAME "cros-ec-accel-legacy" +#define CROS_EC_SENSOR_LEGACY_NUM 2 /* * Sensor scale hard coded at 10 bits per g, computed as: * g / (2^10 - 1) = 0.009586168; with g = 9.80665 m.s^-2 */ #define ACCEL_LEGACY_NSCALE 9586168 -/* Indices for EC sensor values. */ -enum { - X, - Y, - Z, - MAX_AXIS, -}; - -/* State data for cros_ec_accel_legacy iio driver. */ -struct cros_ec_accel_legacy_state { - struct cros_ec_device *ec; - - /* - * Array holding data from a single capture. 2 bytes per channel - * for the 3 channels plus the timestamp which is always last and - * 8-bytes aligned. - */ - s16 capture_data[8]; - s8 sign[MAX_AXIS]; - u8 sensor_num; -}; - -static int ec_cmd_read_u8(struct cros_ec_device *ec, unsigned int offset, - u8 *dest) -{ - return ec->cmd_readmem(ec, offset, 1, dest); -} - -static int ec_cmd_read_u16(struct cros_ec_device *ec, unsigned int offset, - u16 *dest) -{ - __le16 tmp; - int ret = ec->cmd_readmem(ec, offset, 2, &tmp); - - *dest = le16_to_cpu(tmp); - - return ret; -} - -/** - * read_ec_until_not_busy() - Read from EC status byte until it reads not busy. - * @st: Pointer to state information for device. - * - * This function reads EC status until its busy bit gets cleared. It does not - * wait indefinitely and returns -EIO if the EC status is still busy after a - * few hundreds milliseconds. - * - * Return: 8-bit status if ok, -EIO on error - */ -static int read_ec_until_not_busy(struct cros_ec_accel_legacy_state *st) -{ - struct cros_ec_device *ec = st->ec; - u8 status; - int attempts = 0; - - ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status); - while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) { - /* Give up after enough attempts, return error. */ - if (attempts++ >= 50) - return -EIO; - - /* Small delay every so often. */ - if (attempts % 5 == 0) - msleep(25); - - ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status); - } - - return status; -} - -/** - * read_ec_accel_data_unsafe() - Read acceleration data from EC shared memory. - * @st: Pointer to state information for device. - * @scan_mask: Bitmap of the sensor indices to scan. - * @data: Location to store data. - * - * This is the unsafe function for reading the EC data. It does not guarantee - * that the EC will not modify the data as it is being read in. - */ -static void read_ec_accel_data_unsafe(struct cros_ec_accel_legacy_state *st, - unsigned long scan_mask, s16 *data) -{ - int i = 0; - int num_enabled = bitmap_weight(&scan_mask, MAX_AXIS); - - /* Read all sensors enabled in scan_mask. Each value is 2 bytes. */ - while (num_enabled--) { - i = find_next_bit(&scan_mask, MAX_AXIS, i); - ec_cmd_read_u16(st->ec, - EC_MEMMAP_ACC_DATA + - sizeof(s16) * - (1 + i + st->sensor_num * MAX_AXIS), - data); - *data *= st->sign[i]; - i++; - data++; - } -} - -/** - * read_ec_accel_data() - Read acceleration data from EC shared memory. - * @st: Pointer to state information for device. - * @scan_mask: Bitmap of the sensor indices to scan. - * @data: Location to store data. - * - * This is the safe function for reading the EC data. It guarantees that - * the data sampled was not modified by the EC while being read. - * - * Return: 0 if ok, -ve on error - */ -static int read_ec_accel_data(struct cros_ec_accel_legacy_state *st, - unsigned long scan_mask, s16 *data) +static int cros_ec_accel_legacy_read_cmd(struct iio_dev *indio_dev, + unsigned long scan_mask, s16 *data) { - u8 samp_id = 0xff; - u8 status = 0; + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); int ret; - int attempts = 0; + unsigned int i; + u8 sensor_num; /* - * Continually read all data from EC until the status byte after - * all reads reflects that the EC is not busy and the sample id - * matches the sample id from before all reads. This guarantees - * that data read in was not modified by the EC while reading. + * Read all sensor data through a command. + * Save sensor_num, it is assumed to stay. */ - while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT | - EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) { - /* If we have tried to read too many times, return error. */ - if (attempts++ >= 5) - return -EIO; - - /* Read status byte until EC is not busy. */ - ret = read_ec_until_not_busy(st); - if (ret < 0) - return ret; - status = ret; - - /* - * Store the current sample id so that we can compare to the - * sample id after reading the data. - */ - samp_id = status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK; - - /* Read all EC data, format it, and store it into data. */ - read_ec_accel_data_unsafe(st, scan_mask, data); + sensor_num = st->param.info.sensor_num; + st->param.cmd = MOTIONSENSE_CMD_DUMP; + st->param.dump.max_sensor_count = CROS_EC_SENSOR_LEGACY_NUM; + ret = cros_ec_motion_send_host_cmd(st, + sizeof(st->resp->dump) + CROS_EC_SENSOR_LEGACY_NUM * + sizeof(struct ec_response_motion_sensor_data)); + st->param.info.sensor_num = sensor_num; + if (ret != 0) { + dev_warn(&indio_dev->dev, "Unable to read sensor data\n"); + return ret; + } - /* Read status byte. */ - ec_cmd_read_u8(st->ec, EC_MEMMAP_ACC_STATUS, &status); + for_each_set_bit(i, &scan_mask, indio_dev->masklength) { + *data = st->resp->dump.sensor[sensor_num].data[i] * + st->sign[i]; + data++; } return 0; @@ -188,28 +70,40 @@ static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); s16 data = 0; - int ret = IIO_VAL_INT; + int ret; + int idx = chan->scan_index; + + mutex_lock(&st->cmd_lock); switch (mask) { case IIO_CHAN_INFO_RAW: - ret = read_ec_accel_data(st, (1 << chan->scan_index), &data); - if (ret) - return ret; + ret = st->read_ec_sensors_data(indio_dev, 1 << idx, &data); + if (ret < 0) + break; + ret = IIO_VAL_INT; *val = data; - return IIO_VAL_INT; + break; case IIO_CHAN_INFO_SCALE: + WARN_ON(st->type != MOTIONSENSE_TYPE_ACCEL); *val = 0; *val2 = ACCEL_LEGACY_NSCALE; - return IIO_VAL_INT_PLUS_NANO; + ret = IIO_VAL_INT_PLUS_NANO; + break; case IIO_CHAN_INFO_CALIBBIAS: /* Calibration not supported. */ *val = 0; - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; default: - return -EINVAL; + ret = cros_ec_sensors_core_read(st, chan, val, val2, + mask); + break; } + mutex_unlock(&st->cmd_lock); + + return ret; } static int cros_ec_accel_legacy_write(struct iio_dev *indio_dev, @@ -231,86 +125,14 @@ static const struct iio_info cros_ec_accel_legacy_info = { .write_raw = &cros_ec_accel_legacy_write, }; -/** - * cros_ec_accel_legacy_capture() - The trigger handler function - * @irq: The interrupt number. - * @p: Private data - always a pointer to the poll func. - * - * On a trigger event occurring, if the pollfunc is attached then this - * handler is called as a threaded interrupt (and hence may sleep). It - * is responsible for grabbing data from the device and pushing it into - * the associated buffer. - * - * Return: IRQ_HANDLED +/* + * Present the channel using HTML5 standard: + * need to invert X and Y and invert some lid axis. */ -static irqreturn_t cros_ec_accel_legacy_capture(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); - - /* Clear capture data. */ - memset(st->capture_data, 0, sizeof(st->capture_data)); - - /* - * Read data based on which channels are enabled in scan mask. Note - * that on a capture we are always reading the calibrated data. - */ - read_ec_accel_data(st, *indio_dev->active_scan_mask, st->capture_data); - - iio_push_to_buffers_with_timestamp(indio_dev, (void *)st->capture_data, - iio_get_time_ns(indio_dev)); - - /* - * Tell the core we are done with this trigger and ready for the - * next one. - */ - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} - -static char *cros_ec_accel_legacy_loc_strings[] = { - [MOTIONSENSE_LOC_BASE] = "base", - [MOTIONSENSE_LOC_LID] = "lid", - [MOTIONSENSE_LOC_MAX] = "unknown", -}; - -static ssize_t cros_ec_accel_legacy_loc(struct iio_dev *indio_dev, - uintptr_t private, - const struct iio_chan_spec *chan, - char *buf) -{ - struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%s\n", - cros_ec_accel_legacy_loc_strings[st->sensor_num + - MOTIONSENSE_LOC_BASE]); -} - -static ssize_t cros_ec_accel_legacy_id(struct iio_dev *indio_dev, - uintptr_t private, - const struct iio_chan_spec *chan, - char *buf) -{ - struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", st->sensor_num); -} - -static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = { - { - .name = "id", - .shared = IIO_SHARED_BY_ALL, - .read = cros_ec_accel_legacy_id, - }, - { - .name = "location", - .shared = IIO_SHARED_BY_ALL, - .read = cros_ec_accel_legacy_loc, - }, - { } -}; +#define CROS_EC_ACCEL_ROTATE_AXIS(_axis) \ + ((_axis) == CROS_EC_SENSOR_Z ? CROS_EC_SENSOR_Z : \ + ((_axis) == CROS_EC_SENSOR_X ? CROS_EC_SENSOR_Y : \ + CROS_EC_SENSOR_X)) #define CROS_EC_ACCEL_LEGACY_CHAN(_axis) \ { \ @@ -321,28 +143,28 @@ static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = { BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_CALIBBIAS), \ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \ - .ext_info = cros_ec_accel_legacy_ext_info, \ + .ext_info = cros_ec_sensors_ext_info, \ .scan_type = { \ .sign = 's', \ - .realbits = 16, \ - .storagebits = 16, \ + .realbits = CROS_EC_SENSOR_BITS, \ + .storagebits = CROS_EC_SENSOR_BITS, \ }, \ + .scan_index = CROS_EC_ACCEL_ROTATE_AXIS(_axis), \ } \ -static struct iio_chan_spec ec_accel_channels[] = { - CROS_EC_ACCEL_LEGACY_CHAN(X), - CROS_EC_ACCEL_LEGACY_CHAN(Y), - CROS_EC_ACCEL_LEGACY_CHAN(Z), - IIO_CHAN_SOFT_TIMESTAMP(MAX_AXIS) +static const struct iio_chan_spec cros_ec_accel_legacy_channels[] = { + CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_X), + CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_Y), + CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_Z), + IIO_CHAN_SOFT_TIMESTAMP(CROS_EC_SENSOR_MAX_AXIS) }; static int cros_ec_accel_legacy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct cros_ec_dev *ec = dev_get_drvdata(dev->parent); - struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); struct iio_dev *indio_dev; - struct cros_ec_accel_legacy_state *state; + struct cros_ec_sensors_core_state *state; int ret; if (!ec || !ec->ec_dev) { @@ -350,46 +172,32 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev) return -EINVAL; } - if (!ec->ec_dev->cmd_readmem) { - dev_warn(&pdev->dev, "EC does not support direct reads.\n"); - return -EINVAL; - } - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state)); if (!indio_dev) return -ENOMEM; - platform_set_drvdata(pdev, indio_dev); - state = iio_priv(indio_dev); - state->ec = ec->ec_dev; - state->sensor_num = sensor_platform->sensor_num; - - indio_dev->dev.parent = dev; - indio_dev->name = pdev->name; - indio_dev->channels = ec_accel_channels; - /* - * Present the channel using HTML5 standard: - * need to invert X and Y and invert some lid axis. - */ - ec_accel_channels[X].scan_index = Y; - ec_accel_channels[Y].scan_index = X; - ec_accel_channels[Z].scan_index = Z; + ret = cros_ec_sensors_core_init(pdev, indio_dev, true); + if (ret) + return ret; - state->sign[Y] = 1; + indio_dev->info = &cros_ec_accel_legacy_info; + state = iio_priv(indio_dev); - if (state->sensor_num == MOTIONSENSE_LOC_LID) - state->sign[X] = state->sign[Z] = -1; + if (state->ec->cmd_readmem != NULL) + state->read_ec_sensors_data = cros_ec_sensors_read_lpc; else - state->sign[X] = state->sign[Z] = 1; - - indio_dev->num_channels = ARRAY_SIZE(ec_accel_channels); - indio_dev->dev.parent = &pdev->dev; - indio_dev->info = &cros_ec_accel_legacy_info; - indio_dev->modes = INDIO_DIRECT_MODE; + state->read_ec_sensors_data = cros_ec_accel_legacy_read_cmd; + + indio_dev->channels = cros_ec_accel_legacy_channels; + indio_dev->num_channels = ARRAY_SIZE(cros_ec_accel_legacy_channels); + /* The lid sensor needs to be presented inverted. */ + if (state->loc == MOTIONSENSE_LOC_LID) { + state->sign[CROS_EC_SENSOR_X] = -1; + state->sign[CROS_EC_SENSOR_Z] = -1; + } ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, - cros_ec_accel_legacy_capture, - NULL); + cros_ec_sensors_capture, NULL); if (ret) return ret; diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 6645771aa349..fee535d6e45b 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1486,8 +1486,8 @@ static const struct acpi_device_id kx_acpi_match[] = { {"KIOX0008", KXCJ91008}, {"KIOX0009", KXTJ21009}, {"KIOX000A", KXCJ91008}, - {"KIOX010A", KXCJ91008}, /* KXCJ91008 inside the display of a 2-in-1 */ - {"KIOX020A", KXCJ91008}, + {"KIOX010A", KXCJ91008}, /* KXCJ91008 in the display of a yoga 2-in-1 */ + {"KIOX020A", KXCJ91008}, /* KXCJ91008 in the base of a yoga 2-in-1 */ {"KXTJ1009", KXTJ21009}, {"KXJ2109", KXTJ21009}, {"SMO8500", KXCJ91008}, diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c index 637e6e676061..3d5bea651923 100644 --- a/drivers/iio/accel/mxc4005.c +++ b/drivers/iio/accel/mxc4005.c @@ -424,7 +424,7 @@ static int mxc4005_probe(struct i2c_client *client, indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &mxc4005_info; - ret = iio_triggered_buffer_setup(indio_dev, + ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, iio_pollfunc_store_time, mxc4005_trigger_handler, NULL); @@ -452,7 +452,7 @@ static int mxc4005_probe(struct i2c_client *client, if (ret) { dev_err(&client->dev, "failed to init threaded irq\n"); - goto err_buffer_cleanup; + return ret; } data->dready_trig->dev.parent = &client->dev; @@ -460,43 +460,16 @@ static int mxc4005_probe(struct i2c_client *client, iio_trigger_set_drvdata(data->dready_trig, indio_dev); indio_dev->trig = data->dready_trig; iio_trigger_get(indio_dev->trig); - ret = iio_trigger_register(data->dready_trig); + ret = devm_iio_trigger_register(&client->dev, + data->dready_trig); if (ret) { dev_err(&client->dev, "failed to register trigger\n"); - goto err_trigger_unregister; + return ret; } } - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&client->dev, - "unable to register iio device %d\n", ret); - goto err_buffer_cleanup; - } - - return 0; - -err_trigger_unregister: - iio_trigger_unregister(data->dready_trig); -err_buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); - - return ret; -} - -static int mxc4005_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct mxc4005_data *data = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - iio_triggered_buffer_cleanup(indio_dev); - if (data->dready_trig) - iio_trigger_unregister(data->dready_trig); - - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct acpi_device_id mxc4005_acpi_match[] = { @@ -517,7 +490,6 @@ static struct i2c_driver mxc4005_driver = { .acpi_match_table = ACPI_PTR(mxc4005_acpi_match), }, .probe = mxc4005_probe, - .remove = mxc4005_remove, .id_table = mxc4005_id, }; diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index a923f90f6e80..66d768d971e1 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -111,7 +111,7 @@ /* Currently unsupported */ #define SCA3000_MD_CTRL_AND_Y BIT(3) #define SCA3000_MD_CTRL_AND_X BIT(4) -#define SAC3000_MD_CTRL_AND_Z BIT(5) +#define SCA3000_MD_CTRL_AND_Z BIT(5) /* * Some control registers of complex access methods requiring this register to diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h index 979ab9679b99..af09943f38c9 100644 --- a/drivers/iio/accel/st_accel.h +++ b/drivers/iio/accel/st_accel.h @@ -68,6 +68,7 @@ static const struct st_sensors_platform_data default_accel_pdata = { .drdy_int_pin = 1, }; +const struct st_sensor_settings *st_accel_get_settings(const char *name); int st_accel_common_probe(struct iio_dev *indio_dev); void st_accel_common_remove(struct iio_dev *indio_dev); diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c index 0205c0167cdd..9f2b40474b8e 100644 --- a/drivers/iio/accel/st_accel_buffer.c +++ b/drivers/iio/accel/st_accel_buffer.c @@ -29,65 +29,51 @@ int st_accel_trig_set_state(struct iio_trigger *trig, bool state) return st_sensors_set_dataready_irq(indio_dev, state); } -static int st_accel_buffer_preenable(struct iio_dev *indio_dev) -{ - return st_sensors_set_enable(indio_dev, true); -} - static int st_accel_buffer_postenable(struct iio_dev *indio_dev) { int err; - struct st_sensor_data *adata = iio_priv(indio_dev); - - adata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); - if (adata->buffer_data == NULL) { - err = -ENOMEM; - goto allocate_memory_error; - } err = iio_triggered_buffer_postenable(indio_dev); if (err < 0) - goto st_accel_buffer_postenable_error; + return err; err = st_sensors_set_axis_enable(indio_dev, - (u8)indio_dev->active_scan_mask[0]); + (u8)indio_dev->active_scan_mask[0]); if (err < 0) - goto st_sensors_set_axis_enable_error; + goto st_accel_buffer_predisable; - return err; + err = st_sensors_set_enable(indio_dev, true); + if (err < 0) + goto st_accel_buffer_enable_all_axis; -st_sensors_set_axis_enable_error: + return 0; + +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); -st_accel_buffer_postenable_error: - kfree(adata->buffer_data); -allocate_memory_error: return err; } static int st_accel_buffer_predisable(struct iio_dev *indio_dev) { int err, err2; - struct st_sensor_data *adata = iio_priv(indio_dev); - - err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); - if (err < 0) - goto st_accel_buffer_predisable_error; err = st_sensors_set_enable(indio_dev, false); if (err < 0) - goto st_accel_buffer_predisable_error; + goto st_accel_buffer_predisable; + + err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); -st_accel_buffer_predisable_error: +st_accel_buffer_predisable: err2 = iio_triggered_buffer_predisable(indio_dev); if (!err) err = err2; - kfree(adata->buffer_data); return err; } static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = { - .preenable = &st_accel_buffer_preenable, .postenable = &st_accel_buffer_postenable, .predisable = &st_accel_buffer_predisable, }; diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index e02b79931979..2e37f8a6d8cf 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -13,7 +13,6 @@ #include <linux/acpi.h> #include <linux/errno.h> #include <linux/types.h> -#include <linux/mutex.h> #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/gpio.h> @@ -1147,32 +1146,45 @@ out: #endif } +/* + * st_accel_get_settings() - get sensor settings from device name + * @name: device name buffer reference. + * + * Return: valid reference on success, NULL otherwise. + */ +const struct st_sensor_settings *st_accel_get_settings(const char *name) +{ + int index = st_sensors_get_settings_index(name, + st_accel_sensors_settings, + ARRAY_SIZE(st_accel_sensors_settings)); + if (index < 0) + return NULL; + + return &st_accel_sensors_settings[index]; +} +EXPORT_SYMBOL(st_accel_get_settings); + int st_accel_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *adata = iio_priv(indio_dev); struct st_sensors_platform_data *pdata = (struct st_sensors_platform_data *)adata->dev->platform_data; - int irq = adata->get_irq_data_ready(indio_dev); struct iio_chan_spec *channels; size_t channels_size; int err; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &accel_info; - mutex_init(&adata->tb.buf_lock); err = st_sensors_power_enable(indio_dev); if (err) return err; - err = st_sensors_check_device_support(indio_dev, - ARRAY_SIZE(st_accel_sensors_settings), - st_accel_sensors_settings); + err = st_sensors_verify_id(indio_dev); if (err < 0) goto st_accel_power_off; adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; - adata->multiread_bit = adata->sensor_settings->multi_read_bit; indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; channels_size = indio_dev->num_channels * sizeof(struct iio_chan_spec); @@ -1204,7 +1216,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev) if (err < 0) goto st_accel_power_off; - if (irq > 0) { + if (adata->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, ST_ACCEL_TRIGGER_OPS); if (err < 0) @@ -1221,7 +1233,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev) return 0; st_accel_device_register_error: - if (irq > 0) + if (adata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_accel_probe_trigger_error: st_accel_deallocate_ring(indio_dev); @@ -1239,7 +1251,7 @@ void st_accel_common_remove(struct iio_dev *indio_dev) st_sensors_power_disable(indio_dev); iio_device_unregister(indio_dev); - if (adata->get_irq_data_ready(indio_dev) > 0) + if (adata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_accel_deallocate_ring(indio_dev); diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index c3c8f2e73c2a..50fa0fc32baa 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -150,22 +150,33 @@ MODULE_DEVICE_TABLE(i2c, st_accel_id_table); static int st_accel_i2c_probe(struct i2c_client *client) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *adata; + struct iio_dev *indio_dev; const char *match; int ret; + match = device_get_match_data(&client->dev); + if (match) + strlcpy(client->name, match, sizeof(client->name)); + + settings = st_accel_get_settings(client->name); + if (!settings) { + dev_err(&client->dev, "device name %s not recognized.\n", + client->name); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adata)); if (!indio_dev) return -ENOMEM; adata = iio_priv(indio_dev); + adata->sensor_settings = (struct st_sensor_settings *)settings; - match = device_get_match_data(&client->dev); - if (match) - strlcpy(client->name, match, sizeof(client->name)); - - st_sensors_i2c_configure(indio_dev, client, adata); + ret = st_sensors_i2c_configure(indio_dev, client); + if (ret < 0) + return ret; ret = st_accel_common_probe(indio_dev); if (ret < 0) diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 474742e35d92..8af7027d5598 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -102,19 +102,31 @@ MODULE_DEVICE_TABLE(of, st_accel_of_match); static int st_accel_spi_probe(struct spi_device *spi) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *adata; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&spi->dev, st_accel_of_match, + spi->modalias, sizeof(spi->modalias)); + + settings = st_accel_get_settings(spi->modalias); + if (!settings) { + dev_err(&spi->dev, "device name %s not recognized.\n", + spi->modalias); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adata)); if (!indio_dev) return -ENOMEM; adata = iio_priv(indio_dev); + adata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_of_name_probe(&spi->dev, st_accel_of_match, - spi->modalias, sizeof(spi->modalias)); - st_sensors_spi_configure(indio_dev, spi, adata); + err = st_sensors_spi_configure(indio_dev, spi); + if (err < 0) + return err; err = st_accel_common_probe(indio_dev); if (err < 0) diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index aba0fd123a51..f5ba94c03a8d 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -35,6 +35,11 @@ static const unsigned int ad7606_scale_avail[2] = { 152588, 305176 }; + +static const unsigned int ad7616_sw_scale_avail[3] = { + 76293, 152588, 305176 +}; + static const unsigned int ad7606_oversampling_avail[7] = { 1, 2, 4, 8, 16, 32, 64, }; @@ -55,6 +60,29 @@ static int ad7606_reset(struct ad7606_state *st) return -ENODEV; } +static int ad7606_reg_access(struct iio_dev *indio_dev, + unsigned int reg, + unsigned int writeval, + unsigned int *readval) +{ + struct ad7606_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&st->lock); + if (readval) { + ret = st->bops->reg_read(st, reg); + if (ret < 0) + goto err_unlock; + *readval = ret; + ret = 0; + } else { + ret = st->bops->reg_write(st, reg, writeval); + } +err_unlock: + mutex_unlock(&st->lock); + return ret; +} + static int ad7606_read_samples(struct ad7606_state *st) { unsigned int num = st->chip_info->num_channels; @@ -308,29 +336,6 @@ static const struct attribute_group ad7606_attribute_group_range = { .attrs = ad7606_attributes_range, }; -#define AD760X_CHANNEL(num, mask) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = num, \ - .address = num, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ - .info_mask_shared_by_all = mask, \ - .scan_index = num, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 16, \ - .storagebits = 16, \ - .endianness = IIO_CPU, \ - }, \ -} - -#define AD7605_CHANNEL(num) \ - AD760X_CHANNEL(num, 0) - -#define AD7606_CHANNEL(num) \ - AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) - static const struct iio_chan_spec ad7605_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(4), AD7605_CHANNEL(0), @@ -405,12 +410,19 @@ static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), }, + [ID_AD7606B] = { + .channels = ad7606_channels, + .num_channels = 9, + .oversampling_avail = ad7606_oversampling_avail, + .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), + }, [ID_AD7616] = { .channels = ad7616_channels, .num_channels = 17, .oversampling_avail = ad7616_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail), .os_req_reset = true, + .init_delay_ms = 15, }, }; @@ -519,6 +531,14 @@ static const struct iio_info ad7606_info_os_and_range = { .validate_trigger = &ad7606_validate_trigger, }; +static const struct iio_info ad7606_info_os_range_and_debug = { + .read_raw = &ad7606_read_raw, + .write_raw = &ad7606_write_raw, + .debugfs_reg_access = &ad7606_reg_access, + .attrs = &ad7606_attribute_group_os_and_range, + .validate_trigger = &ad7606_validate_trigger, +}; + static const struct iio_info ad7606_info_os = { .read_raw = &ad7606_read_raw, .write_raw = &ad7606_write_raw, @@ -617,35 +637,29 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, if (ret) dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); + /* AD7616 requires al least 15ms to reconfigure after a reset */ + if (st->chip_info->init_delay_ms) { + if (msleep_interruptible(st->chip_info->init_delay_ms)) + return -ERESTARTSYS; + } + st->write_scale = ad7606_write_scale_hw; st->write_os = ad7606_write_os_hw; - if (st->chip_info->sw_mode_config) + if (st->bops->sw_mode_config) st->sw_mode_en = device_property_present(st->dev, "adi,sw-mode"); if (st->sw_mode_en) { + /* Scale of 0.076293 is only available in sw mode */ + st->scale_avail = ad7616_sw_scale_avail; + st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail); + /* After reset, in software mode, ±10 V is set by default */ memset32(st->range, 2, ARRAY_SIZE(st->range)); - indio_dev->info = &ad7606_info_os_and_range; - - /* - * In software mode, the range gpio has no longer its function. - * Instead, the scale can be configured individually for each - * channel from the range registers. - */ - if (st->chip_info->write_scale_sw) - st->write_scale = st->chip_info->write_scale_sw; - - /* - * In software mode, the oversampling is no longer configured - * with GPIO pins. Instead, the oversampling can be configured - * in configuratiion register. - */ - if (st->chip_info->write_os_sw) - st->write_os = st->chip_info->write_os_sw; - - ret = st->chip_info->sw_mode_config(indio_dev); + indio_dev->info = &ad7606_info_os_range_and_debug; + + ret = st->bops->sw_mode_config(indio_dev); if (ret < 0) return ret; } diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h index d8a509c2c428..9350ef1f63b5 100644 --- a/drivers/iio/adc/ad7606.h +++ b/drivers/iio/adc/ad7606.h @@ -8,6 +8,36 @@ #ifndef IIO_ADC_AD7606_H_ #define IIO_ADC_AD7606_H_ +#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = num, \ + .address = num, \ + .info_mask_separate = mask_sep, \ + .info_mask_shared_by_type = mask_type, \ + .info_mask_shared_by_all = mask_all, \ + .scan_index = num, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ +} + +#define AD7605_CHANNEL(num) \ + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ + BIT(IIO_CHAN_INFO_SCALE), 0) + +#define AD7606_CHANNEL(num) \ + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ + BIT(IIO_CHAN_INFO_SCALE), \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) + +#define AD7616_CHANNEL(num) \ + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),\ + 0, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) + /** * struct ad7606_chip_info - chip specific information * @channels: channel specification @@ -16,12 +46,8 @@ * oversampling ratios. * @oversampling_num number of elements stored in oversampling_avail array * @os_req_reset some devices require a reset to update oversampling - * @write_scale_sw pointer to the function which writes the scale via spi - in software mode - * @write_os_sw pointer to the function which writes the os via spi - in software mode - * @sw_mode_config: pointer to a function which configured the device - * for software mode + * @init_delay_ms required delay in miliseconds for initialization + * after a restart */ struct ad7606_chip_info { const struct iio_chan_spec *channels; @@ -29,9 +55,7 @@ struct ad7606_chip_info { const unsigned int *oversampling_avail; unsigned int oversampling_num; bool os_req_reset; - int (*write_scale_sw)(struct iio_dev *indio_dev, int ch, int val); - int (*write_os_sw)(struct iio_dev *indio_dev, int val); - int (*sw_mode_config)(struct iio_dev *indio_dev); + unsigned long init_delay_ms; }; /** @@ -63,6 +87,7 @@ struct ad7606_chip_info { * @complete completion to indicate end of conversion * @trig The IIO trigger associated with the device. * @data buffer for reading data from the device + * @d16 be16 buffer for reading data from the device */ struct ad7606_state { struct device *dev; @@ -96,15 +121,32 @@ struct ad7606_state { * 16 * 16-bit samples + 64-bit timestamp */ unsigned short data[20] ____cacheline_aligned; + __be16 d16[2]; }; /** * struct ad7606_bus_ops - driver bus operations * @read_block function pointer for reading blocks of data + * @sw_mode_config: pointer to a function which configured the device + * for software mode + * @reg_read function pointer for reading spi register + * @reg_write function pointer for writing spi register + * @write_mask function pointer for write spi register with mask + * @rd_wr_cmd pointer to the function which calculates the spi address */ struct ad7606_bus_ops { /* more methods added in future? */ int (*read_block)(struct device *dev, int num, void *data); + int (*sw_mode_config)(struct iio_dev *indio_dev); + int (*reg_read)(struct ad7606_state *st, unsigned int addr); + int (*reg_write)(struct ad7606_state *st, + unsigned int addr, + unsigned int val); + int (*write_mask)(struct ad7606_state *st, + unsigned int addr, + unsigned long mask, + unsigned int val); + u16 (*rd_wr_cmd)(int addr, char isWriteOp); }; int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, @@ -116,6 +158,7 @@ enum ad7606_supported_device_ids { ID_AD7606_8, ID_AD7606_6, ID_AD7606_4, + ID_AD7606B, ID_AD7616, }; diff --git a/drivers/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c index 1b08028facde..f732b3ac7878 100644 --- a/drivers/iio/adc/ad7606_par.c +++ b/drivers/iio/adc/ad7606_par.c @@ -53,10 +53,8 @@ static int ad7606_par_probe(struct platform_device *pdev) int irq; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq: %d\n", irq); + if (irq < 0) return irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); addr = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c index b7faef69a58f..29945ad07dca 100644 --- a/drivers/iio/adc/ad7606_spi.c +++ b/drivers/iio/adc/ad7606_spi.c @@ -15,6 +15,91 @@ #define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */ +#define AD7616_CONFIGURATION_REGISTER 0x02 +#define AD7616_OS_MASK GENMASK(4, 2) +#define AD7616_BURST_MODE BIT(6) +#define AD7616_SEQEN_MODE BIT(5) +#define AD7616_RANGE_CH_A_ADDR_OFF 0x04 +#define AD7616_RANGE_CH_B_ADDR_OFF 0x06 +/* + * Range of channels from a group are stored in 2 registers. + * 0, 1, 2, 3 in a register followed by 4, 5, 6, 7 in second register. + * For channels from second group(8-15) the order is the same, only with + * an offset of 2 for register address. + */ +#define AD7616_RANGE_CH_ADDR(ch) ((ch) >> 2) +/* The range of the channel is stored in 2 bits */ +#define AD7616_RANGE_CH_MSK(ch) (0b11 << (((ch) & 0b11) * 2)) +#define AD7616_RANGE_CH_MODE(ch, mode) ((mode) << ((((ch) & 0b11)) * 2)) + +#define AD7606_CONFIGURATION_REGISTER 0x02 +#define AD7606_SINGLE_DOUT 0x00 + +/* + * Range for AD7606B channels are stored in registers starting with address 0x3. + * Each register stores range for 2 channels(4 bits per channel). + */ +#define AD7606_RANGE_CH_MSK(ch) (GENMASK(3, 0) << (4 * ((ch) & 0x1))) +#define AD7606_RANGE_CH_MODE(ch, mode) \ + ((GENMASK(3, 0) & mode) << (4 * ((ch) & 0x1))) +#define AD7606_RANGE_CH_ADDR(ch) (0x03 + ((ch) >> 1)) +#define AD7606_OS_MODE 0x08 + +static const struct iio_chan_spec ad7616_sw_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(16), + AD7616_CHANNEL(0), + AD7616_CHANNEL(1), + AD7616_CHANNEL(2), + AD7616_CHANNEL(3), + AD7616_CHANNEL(4), + AD7616_CHANNEL(5), + AD7616_CHANNEL(6), + AD7616_CHANNEL(7), + AD7616_CHANNEL(8), + AD7616_CHANNEL(9), + AD7616_CHANNEL(10), + AD7616_CHANNEL(11), + AD7616_CHANNEL(12), + AD7616_CHANNEL(13), + AD7616_CHANNEL(14), + AD7616_CHANNEL(15), +}; + +static const struct iio_chan_spec ad7606b_sw_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(8), + AD7616_CHANNEL(0), + AD7616_CHANNEL(1), + AD7616_CHANNEL(2), + AD7616_CHANNEL(3), + AD7616_CHANNEL(4), + AD7616_CHANNEL(5), + AD7616_CHANNEL(6), + AD7616_CHANNEL(7), +}; + +static const unsigned int ad7606B_oversampling_avail[9] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256 +}; + +static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp) +{ + /* + * The address of register consist of one w/r bit + * 6 bits of address followed by one reserved bit. + */ + return ((addr & 0x7F) << 1) | ((isWriteOp & 0x1) << 7); +} + +static u16 ad7606B_spi_rd_wr_cmd(int addr, char is_write_op) +{ + /* + * The address of register consists of one bit which + * specifies a read command placed in bit 6, followed by + * 6 bits of address. + */ + return (addr & 0x3F) | (((~is_write_op) & 0x1) << 6); +} + static int ad7606_spi_read_block(struct device *dev, int count, void *buf) { @@ -35,17 +120,210 @@ static int ad7606_spi_read_block(struct device *dev, return 0; } +static int ad7606_spi_reg_read(struct ad7606_state *st, unsigned int addr) +{ + struct spi_device *spi = to_spi_device(st->dev); + struct spi_transfer t[] = { + { + .tx_buf = &st->d16[0], + .len = 2, + .cs_change = 0, + }, { + .rx_buf = &st->d16[1], + .len = 2, + }, + }; + int ret; + + st->d16[0] = cpu_to_be16(st->bops->rd_wr_cmd(addr, 0) << 8); + + ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t)); + if (ret < 0) + return ret; + + return be16_to_cpu(st->d16[1]); +} + +static int ad7606_spi_reg_write(struct ad7606_state *st, + unsigned int addr, + unsigned int val) +{ + struct spi_device *spi = to_spi_device(st->dev); + + st->d16[0] = cpu_to_be16((st->bops->rd_wr_cmd(addr, 1) << 8) | + (val & 0x1FF)); + + return spi_write(spi, &st->d16[0], sizeof(st->d16[0])); +} + +static int ad7606_spi_write_mask(struct ad7606_state *st, + unsigned int addr, + unsigned long mask, + unsigned int val) +{ + int readval; + + readval = st->bops->reg_read(st, addr); + if (readval < 0) + return readval; + + readval &= ~mask; + readval |= val; + + return st->bops->reg_write(st, addr, readval); +} + +static int ad7616_write_scale_sw(struct iio_dev *indio_dev, int ch, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + unsigned int ch_addr, mode, ch_index; + + + /* + * Ad7616 has 16 channels divided in group A and group B. + * The range of channels from A are stored in registers with address 4 + * while channels from B are stored in register with address 6. + * The last bit from channels determines if it is from group A or B + * because the order of channels in iio is 0A, 0B, 1A, 1B... + */ + ch_index = ch >> 1; + + ch_addr = AD7616_RANGE_CH_ADDR(ch_index); + + if ((ch & 0x1) == 0) /* channel A */ + ch_addr += AD7616_RANGE_CH_A_ADDR_OFF; + else /* channel B */ + ch_addr += AD7616_RANGE_CH_B_ADDR_OFF; + + /* 0b01 for 2.5v, 0b10 for 5v and 0b11 for 10v */ + mode = AD7616_RANGE_CH_MODE(ch_index, ((val + 1) & 0b11)); + return st->bops->write_mask(st, ch_addr, AD7616_RANGE_CH_MSK(ch_index), + mode); +} + +static int ad7616_write_os_sw(struct iio_dev *indio_dev, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + return st->bops->write_mask(st, AD7616_CONFIGURATION_REGISTER, + AD7616_OS_MASK, val << 2); +} + +static int ad7606_write_scale_sw(struct iio_dev *indio_dev, int ch, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + return ad7606_spi_write_mask(st, + AD7606_RANGE_CH_ADDR(ch), + AD7606_RANGE_CH_MSK(ch), + AD7606_RANGE_CH_MODE(ch, val)); +} + +static int ad7606_write_os_sw(struct iio_dev *indio_dev, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + return ad7606_spi_reg_write(st, AD7606_OS_MODE, val); +} + +static int ad7616_sw_mode_config(struct iio_dev *indio_dev) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + /* + * Scale can be configured individually for each channel + * in software mode. + */ + indio_dev->channels = ad7616_sw_channels; + + st->write_scale = ad7616_write_scale_sw; + st->write_os = &ad7616_write_os_sw; + + /* Activate Burst mode and SEQEN MODE */ + return st->bops->write_mask(st, + AD7616_CONFIGURATION_REGISTER, + AD7616_BURST_MODE | AD7616_SEQEN_MODE, + AD7616_BURST_MODE | AD7616_SEQEN_MODE); +} + +static int ad7606B_sw_mode_config(struct iio_dev *indio_dev) +{ + struct ad7606_state *st = iio_priv(indio_dev); + unsigned long os[3] = {1}; + + /* + * Software mode is enabled when all three oversampling + * pins are set to high. If oversampling gpios are defined + * in the device tree, then they need to be set to high, + * otherwise, they must be hardwired to VDD + */ + if (st->gpio_os) { + gpiod_set_array_value(ARRAY_SIZE(os), + st->gpio_os->desc, st->gpio_os->info, os); + } + /* OS of 128 and 256 are available only in software mode */ + st->oversampling_avail = ad7606B_oversampling_avail; + st->num_os_ratios = ARRAY_SIZE(ad7606B_oversampling_avail); + + st->write_scale = ad7606_write_scale_sw; + st->write_os = &ad7606_write_os_sw; + + /* Configure device spi to output on a single channel */ + st->bops->reg_write(st, + AD7606_CONFIGURATION_REGISTER, + AD7606_SINGLE_DOUT); + + /* + * Scale can be configured individually for each channel + * in software mode. + */ + indio_dev->channels = ad7606b_sw_channels; + + return 0; +} + static const struct ad7606_bus_ops ad7606_spi_bops = { .read_block = ad7606_spi_read_block, }; +static const struct ad7606_bus_ops ad7616_spi_bops = { + .read_block = ad7606_spi_read_block, + .reg_read = ad7606_spi_reg_read, + .reg_write = ad7606_spi_reg_write, + .write_mask = ad7606_spi_write_mask, + .rd_wr_cmd = ad7616_spi_rd_wr_cmd, + .sw_mode_config = ad7616_sw_mode_config, +}; + +static const struct ad7606_bus_ops ad7606B_spi_bops = { + .read_block = ad7606_spi_read_block, + .reg_read = ad7606_spi_reg_read, + .reg_write = ad7606_spi_reg_write, + .write_mask = ad7606_spi_write_mask, + .rd_wr_cmd = ad7606B_spi_rd_wr_cmd, + .sw_mode_config = ad7606B_sw_mode_config, +}; + static int ad7606_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); + const struct ad7606_bus_ops *bops; + + switch (id->driver_data) { + case ID_AD7616: + bops = &ad7616_spi_bops; + break; + case ID_AD7606B: + bops = &ad7606B_spi_bops; + break; + default: + bops = &ad7606_spi_bops; + break; + } return ad7606_probe(&spi->dev, spi->irq, NULL, id->name, id->driver_data, - &ad7606_spi_bops); + bops); } static const struct spi_device_id ad7606_id_table[] = { @@ -53,6 +331,7 @@ static const struct spi_device_id ad7606_id_table[] = { { "ad7606-4", ID_AD7606_4 }, { "ad7606-6", ID_AD7606_6 }, { "ad7606-8", ID_AD7606_8 }, + { "ad7606b", ID_AD7606B }, { "ad7616", ID_AD7616 }, {} }; @@ -63,6 +342,7 @@ static const struct of_device_id ad7606_of_match[] = { { .compatible = "adi,ad7606-4" }, { .compatible = "adi,ad7606-6" }, { .compatible = "adi,ad7606-8" }, + { .compatible = "adi,ad7606b" }, { .compatible = "adi,ad7616" }, { }, }; diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 32f1c4a33b20..abe99856c823 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -1179,10 +1179,8 @@ static int at91_adc_probe(struct platform_device *pdev) idev->info = &at91_adc_info; st->irq = platform_get_irq(pdev, 0); - if (st->irq < 0) { - dev_err(&pdev->dev, "No IRQ ID is designated\n"); + if (st->irq < 0) return -ENODEV; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 31d51bcc5f2c..adc9cf7a075d 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -225,10 +225,8 @@ static int axp288_adc_probe(struct platform_device *pdev) info = iio_priv(indio_dev); info->irq = platform_get_irq(pdev, 0); - if (info->irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (info->irq < 0) return info->irq; - } platform_set_drvdata(pdev, indio_dev); info->regmap = axp20x->regmap; /* diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c index c46c0aa15376..646ebdc0a8b4 100644 --- a/drivers/iio/adc/bcm_iproc_adc.c +++ b/drivers/iio/adc/bcm_iproc_adc.c @@ -540,11 +540,8 @@ static int iproc_adc_probe(struct platform_device *pdev) } adc_priv->irqno = platform_get_irq(pdev, 0); - if (adc_priv->irqno <= 0) { - dev_err(&pdev->dev, "platform_get_irq failed\n"); - ret = -ENODEV; - return ret; - } + if (adc_priv->irqno <= 0) + return -ENODEV; ret = regmap_update_bits(adc_priv->regmap, IPROC_REGCTL2, IPROC_ADC_AUXIN_SCAN_ENA, 0); diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c index 354433996101..ae8bcc32f63d 100644 --- a/drivers/iio/adc/da9150-gpadc.c +++ b/drivers/iio/adc/da9150-gpadc.c @@ -337,10 +337,8 @@ static int da9150_gpadc_probe(struct platform_device *pdev) init_completion(&gpadc->complete); irq = platform_get_irq_byname(pdev, "GPADC"); - if (irq < 0) { - dev_err(dev, "Failed to get IRQ: %d\n", irq); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq, IRQF_ONESHOT, "GPADC", gpadc); diff --git a/drivers/iio/adc/envelope-detector.c b/drivers/iio/adc/envelope-detector.c index 2f2b563c1162..28f3d6758eb5 100644 --- a/drivers/iio/adc/envelope-detector.c +++ b/drivers/iio/adc/envelope-detector.c @@ -357,11 +357,8 @@ static int envelope_detector_probe(struct platform_device *pdev) } env->comp_irq = platform_get_irq_byname(pdev, "comp"); - if (env->comp_irq < 0) { - if (env->comp_irq != -EPROBE_DEFER) - dev_err(dev, "failed to get compare interrupt\n"); + if (env->comp_irq < 0) return env->comp_irq; - } ret = devm_request_irq(dev, env->comp_irq, envelope_detector_comp_isr, 0, "envelope-detector", env); diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index d4c3ece21679..42a3ced11fbd 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -805,10 +805,8 @@ static int exynos_adc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (irq < 0) return irq; - } info->irq = irq; irq = platform_get_irq(pdev, 1); diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index df19ecae52f7..fa71489195c6 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -340,7 +340,6 @@ static int mx25_gcq_probe(struct platform_device *pdev) priv->irq = platform_get_irq(pdev, 0); if (priv->irq <= 0) { - dev_err(dev, "Failed to get IRQ\n"); ret = priv->irq; if (!ret) ret = -ENXIO; diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index 35951c47004e..8da45bf36d36 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -456,6 +456,11 @@ err_read: return IRQ_HANDLED; } +static void hi8435_triggered_event_cleanup(void *data) +{ + iio_triggered_event_cleanup(data); +} + static int hi8435_probe(struct spi_device *spi) { struct iio_dev *idev; @@ -477,7 +482,7 @@ static int hi8435_probe(struct spi_device *spi) hi8435_writeb(priv, HI8435_CTRL_REG, 0); } else { udelay(5); - gpiod_set_value(reset_gpio, 1); + gpiod_set_value_cansleep(reset_gpio, 1); } spi_set_drvdata(spi, idev); @@ -513,27 +518,13 @@ static int hi8435_probe(struct spi_device *spi) if (ret) return ret; - ret = iio_device_register(idev); - if (ret < 0) { - dev_err(&spi->dev, "unable to register device\n"); - goto unregister_triggered_event; - } - - return 0; - -unregister_triggered_event: - iio_triggered_event_cleanup(idev); - return ret; -} - -static int hi8435_remove(struct spi_device *spi) -{ - struct iio_dev *idev = spi_get_drvdata(spi); - - iio_device_unregister(idev); - iio_triggered_event_cleanup(idev); + ret = devm_add_action_or_reset(&spi->dev, + hi8435_triggered_event_cleanup, + idev); + if (ret) + return ret; - return 0; + return devm_iio_device_register(&spi->dev, idev); } static const struct of_device_id hi8435_dt_ids[] = { @@ -554,7 +545,6 @@ static struct spi_driver hi8435_driver = { .of_match_table = of_match_ptr(hi8435_dt_ids), }, .probe = hi8435_probe, - .remove = hi8435_remove, .id_table = hi8435_id, }; module_spi_driver(hi8435_driver); diff --git a/drivers/iio/adc/imx7d_adc.c b/drivers/iio/adc/imx7d_adc.c index 26a7bbe4d534..2a2fbf788e95 100644 --- a/drivers/iio/adc/imx7d_adc.c +++ b/drivers/iio/adc/imx7d_adc.c @@ -492,10 +492,8 @@ static int imx7d_adc_probe(struct platform_device *pdev) return PTR_ERR(info->regs); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "No irq resource?\n"); + if (irq < 0) return irq; - } info->clk = devm_clk_get(dev, "adc"); if (IS_ERR(info->clk)) { diff --git a/drivers/iio/adc/lpc32xx_adc.c b/drivers/iio/adc/lpc32xx_adc.c index a6ee1c3a9064..b896f7ff4572 100644 --- a/drivers/iio/adc/lpc32xx_adc.c +++ b/drivers/iio/adc/lpc32xx_adc.c @@ -172,10 +172,8 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, "failed getting interrupt resource\n"); + if (irq <= 0) return -ENXIO; - } retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0, LPC32XXAD_NAME, st); diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index da84adfdb819..214883458582 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -427,8 +427,9 @@ static int max1027_probe(struct spi_device *spi) return -ENOMEM; } - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - &max1027_trigger_handler, NULL); + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, + &iio_pollfunc_store_time, + &max1027_trigger_handler, NULL); if (ret < 0) { dev_err(&indio_dev->dev, "Failed to setup buffer\n"); return ret; @@ -439,7 +440,7 @@ static int max1027_probe(struct spi_device *spi) if (st->trig == NULL) { ret = -ENOMEM; dev_err(&indio_dev->dev, "Failed to allocate iio trigger\n"); - goto fail_trigger_alloc; + return ret; } st->trig->ops = &max1027_trigger_ops; @@ -454,7 +455,7 @@ static int max1027_probe(struct spi_device *spi) spi->dev.driver->name, st->trig); if (ret < 0) { dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n"); - goto fail_dev_register; + return ret; } /* Disable averaging */ @@ -462,34 +463,10 @@ static int max1027_probe(struct spi_device *spi) ret = spi_write(st->spi, &st->reg, 1); if (ret < 0) { dev_err(&indio_dev->dev, "Failed to configure averaging register\n"); - goto fail_dev_register; - } - - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&indio_dev->dev, "Failed to register iio device\n"); - goto fail_dev_register; + return ret; } - return 0; - -fail_dev_register: -fail_trigger_alloc: - iio_triggered_buffer_cleanup(indio_dev); - - return ret; -} - -static int max1027_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - pr_debug("%s: remove(spi = 0x%p)\n", __func__, spi); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static struct spi_driver max1027_driver = { @@ -498,7 +475,6 @@ static struct spi_driver max1027_driver = { .of_match_table = of_match_ptr(max1027_adc_dt_ids), }, .probe = max1027_probe, - .remove = max1027_remove, .id_table = max1027_id, }; module_spi_driver(max1027_driver); diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c index 193b3b81de4d..910f3585fa54 100644 --- a/drivers/iio/adc/npcm_adc.c +++ b/drivers/iio/adc/npcm_adc.c @@ -225,7 +225,6 @@ static int npcm_adc_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { - dev_err(dev, "failed getting interrupt resource\n"); ret = -EINVAL; goto err_disable_clk; } diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index dd8299831e09..582ba047c4a6 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -244,10 +244,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev) init_completion(&info->completion); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, 0, dev_name(&pdev->dev), info); diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c index f7f7a18904b4..a6c046575ec3 100644 --- a/drivers/iio/adc/sc27xx_adc.c +++ b/drivers/iio/adc/sc27xx_adc.c @@ -3,7 +3,6 @@ #include <linux/hwspinlock.h> #include <linux/iio/iio.h> -#include <linux/interrupt.h> #include <linux/module.h> #include <linux/nvmem-consumer.h> #include <linux/of.h> @@ -46,14 +45,18 @@ /* Bits definitions for SC27XX_ADC_INT_CLR registers */ #define SC27XX_ADC_IRQ_CLR BIT(0) +/* Bits definitions for SC27XX_ADC_INT_RAW registers */ +#define SC27XX_ADC_IRQ_RAW BIT(0) + /* Mask definition for SC27XX_ADC_DATA register */ #define SC27XX_ADC_DATA_MASK GENMASK(11, 0) /* Timeout (ms) for the trylock of hardware spinlocks */ #define SC27XX_ADC_HWLOCK_TIMEOUT 5000 -/* Timeout (ms) for ADC data conversion according to ADC datasheet */ -#define SC27XX_ADC_RDY_TIMEOUT 100 +/* Timeout (us) for ADC data conversion according to ADC datasheet */ +#define SC27XX_ADC_RDY_TIMEOUT 1000000 +#define SC27XX_ADC_POLL_RAW_STATUS 500 /* Maximum ADC channel number */ #define SC27XX_ADC_CHANNEL_MAX 32 @@ -72,10 +75,8 @@ struct sc27xx_adc_data { * subsystems which will access the unique ADC controller. */ struct hwspinlock *hwlock; - struct completion completion; int channel_scale[SC27XX_ADC_CHANNEL_MAX]; u32 base; - int value; int irq; }; @@ -188,9 +189,7 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, int scale, int *val) { int ret; - u32 tmp; - - reinit_completion(&data->completion); + u32 tmp, value, status; ret = hwspin_lock_timeout_raw(data->hwlock, SC27XX_ADC_HWLOCK_TIMEOUT); if (ret) { @@ -203,6 +202,11 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, if (ret) goto unlock_adc; + ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR, + SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR); + if (ret) + goto disable_adc; + /* Configure the channel id and scale */ tmp = (scale << SC27XX_ADC_SCALE_SHIFT) & SC27XX_ADC_SCALE_MASK; tmp |= channel & SC27XX_ADC_CHN_ID_MASK; @@ -226,15 +230,22 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, if (ret) goto disable_adc; - ret = wait_for_completion_timeout(&data->completion, - msecs_to_jiffies(SC27XX_ADC_RDY_TIMEOUT)); - if (!ret) { - dev_err(data->dev, "read ADC data timeout\n"); - ret = -ETIMEDOUT; - } else { - ret = 0; + ret = regmap_read_poll_timeout(data->regmap, + data->base + SC27XX_ADC_INT_RAW, + status, (status & SC27XX_ADC_IRQ_RAW), + SC27XX_ADC_POLL_RAW_STATUS, + SC27XX_ADC_RDY_TIMEOUT); + if (ret) { + dev_err(data->dev, "read adc timeout, status = 0x%x\n", status); + goto disable_adc; } + ret = regmap_read(data->regmap, data->base + SC27XX_ADC_DATA, &value); + if (ret) + goto disable_adc; + + value &= SC27XX_ADC_DATA_MASK; + disable_adc: regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL, SC27XX_ADC_EN, 0); @@ -242,32 +253,11 @@ unlock_adc: hwspin_unlock_raw(data->hwlock); if (!ret) - *val = data->value; + *val = value; return ret; } -static irqreturn_t sc27xx_adc_isr(int irq, void *dev_id) -{ - struct sc27xx_adc_data *data = dev_id; - int ret; - - ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR, - SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR); - if (ret) - return IRQ_RETVAL(ret); - - ret = regmap_read(data->regmap, data->base + SC27XX_ADC_DATA, - &data->value); - if (ret) - return IRQ_RETVAL(ret); - - data->value &= SC27XX_ADC_DATA_MASK; - complete(&data->completion); - - return IRQ_HANDLED; -} - static void sc27xx_adc_volt_ratio(struct sc27xx_adc_data *data, int channel, int scale, u32 *div_numerator, u32 *div_denominator) @@ -454,11 +444,6 @@ static int sc27xx_adc_enable(struct sc27xx_adc_data *data) if (ret) goto disable_adc; - ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_EN, - SC27XX_ADC_IRQ_EN, SC27XX_ADC_IRQ_EN); - if (ret) - goto disable_clk; - /* ADC channel scales' calibration from nvmem device */ ret = sc27xx_adc_scale_calibration(data, true); if (ret) @@ -484,9 +469,6 @@ static void sc27xx_adc_disable(void *_data) { struct sc27xx_adc_data *data = _data; - regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_EN, - SC27XX_ADC_IRQ_EN, 0); - /* Disable ADC work clock and controller clock */ regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN, SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0); @@ -504,88 +486,76 @@ static void sc27xx_adc_free_hwlock(void *_data) static int sc27xx_adc_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct sc27xx_adc_data *sc27xx_data; struct iio_dev *indio_dev; int ret; - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*sc27xx_data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*sc27xx_data)); if (!indio_dev) return -ENOMEM; sc27xx_data = iio_priv(indio_dev); - sc27xx_data->regmap = dev_get_regmap(pdev->dev.parent, NULL); + sc27xx_data->regmap = dev_get_regmap(dev->parent, NULL); if (!sc27xx_data->regmap) { - dev_err(&pdev->dev, "failed to get ADC regmap\n"); + dev_err(dev, "failed to get ADC regmap\n"); return -ENODEV; } ret = of_property_read_u32(np, "reg", &sc27xx_data->base); if (ret) { - dev_err(&pdev->dev, "failed to get ADC base address\n"); + dev_err(dev, "failed to get ADC base address\n"); return ret; } sc27xx_data->irq = platform_get_irq(pdev, 0); - if (sc27xx_data->irq < 0) { - dev_err(&pdev->dev, "failed to get ADC irq number\n"); + if (sc27xx_data->irq < 0) return sc27xx_data->irq; - } ret = of_hwspin_lock_get_id(np, 0); if (ret < 0) { - dev_err(&pdev->dev, "failed to get hwspinlock id\n"); + dev_err(dev, "failed to get hwspinlock id\n"); return ret; } sc27xx_data->hwlock = hwspin_lock_request_specific(ret); if (!sc27xx_data->hwlock) { - dev_err(&pdev->dev, "failed to request hwspinlock\n"); + dev_err(dev, "failed to request hwspinlock\n"); return -ENXIO; } - ret = devm_add_action(&pdev->dev, sc27xx_adc_free_hwlock, + ret = devm_add_action_or_reset(dev, sc27xx_adc_free_hwlock, sc27xx_data->hwlock); if (ret) { - sc27xx_adc_free_hwlock(sc27xx_data->hwlock); - dev_err(&pdev->dev, "failed to add hwspinlock action\n"); + dev_err(dev, "failed to add hwspinlock action\n"); return ret; } - init_completion(&sc27xx_data->completion); - sc27xx_data->dev = &pdev->dev; + sc27xx_data->dev = dev; ret = sc27xx_adc_enable(sc27xx_data); if (ret) { - dev_err(&pdev->dev, "failed to enable ADC module\n"); - return ret; - } - - ret = devm_add_action(&pdev->dev, sc27xx_adc_disable, sc27xx_data); - if (ret) { - sc27xx_adc_disable(sc27xx_data); - dev_err(&pdev->dev, "failed to add ADC disable action\n"); + dev_err(dev, "failed to enable ADC module\n"); return ret; } - ret = devm_request_threaded_irq(&pdev->dev, sc27xx_data->irq, NULL, - sc27xx_adc_isr, IRQF_ONESHOT, - pdev->name, sc27xx_data); + ret = devm_add_action_or_reset(dev, sc27xx_adc_disable, sc27xx_data); if (ret) { - dev_err(&pdev->dev, "failed to request ADC irq\n"); + dev_err(dev, "failed to add ADC disable action\n"); return ret; } - indio_dev->dev.parent = &pdev->dev; - indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.parent = dev; + indio_dev->name = dev_name(dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &sc27xx_info; indio_dev->channels = sc27xx_channels; indio_dev->num_channels = ARRAY_SIZE(sc27xx_channels); - ret = devm_iio_device_register(&pdev->dev, indio_dev); + ret = devm_iio_device_register(dev, indio_dev); if (ret) - dev_err(&pdev->dev, "could not register iio (ADC)"); + dev_err(dev, "could not register iio (ADC)"); return ret; } diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c index a33d0a4cc088..592b97c464da 100644 --- a/drivers/iio/adc/spear_adc.c +++ b/drivers/iio/adc/spear_adc.c @@ -301,7 +301,6 @@ static int spear_adc_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { - dev_err(dev, "failed getting interrupt resource\n"); ret = -EINVAL; goto errout2; } diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 1f7ce5186dfc..9b85fefc0a96 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -14,9 +14,11 @@ #include <linux/irqchip/chained_irq.h> #include <linux/irqdesc.h> #include <linux/irqdomain.h> +#include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of_device.h> #include <linux/pm_runtime.h> +#include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> @@ -51,6 +53,17 @@ #define STM32_ADC_CORE_SLEEP_DELAY_MS 2000 +/* SYSCFG registers */ +#define STM32MP1_SYSCFG_PMCSETR 0x04 +#define STM32MP1_SYSCFG_PMCCLRR 0x44 + +/* SYSCFG bit fields */ +#define STM32MP1_SYSCFG_ANASWVDD_MASK BIT(9) + +/* SYSCFG capability flags */ +#define HAS_VBOOSTER BIT(0) +#define HAS_ANASWVDD BIT(1) + /** * stm32_adc_common_regs - stm32 common registers, compatible dependent data * @csr: common status register offset @@ -74,11 +87,13 @@ struct stm32_adc_priv; * @regs: common registers for all instances * @clk_sel: clock selection routine * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet) + * @has_syscfg: SYSCFG capability flags */ struct stm32_adc_priv_cfg { const struct stm32_adc_common_regs *regs; int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *); u32 max_clk_rate_hz; + unsigned int has_syscfg; }; /** @@ -87,22 +102,32 @@ struct stm32_adc_priv_cfg { * @domain: irq domain reference * @aclk: clock reference for the analog circuitry * @bclk: bus clock common for all ADCs, depends on part used + * @booster: booster supply reference + * @vdd: vdd supply reference * @vdda: vdda analog supply reference * @vref: regulator reference + * @vdd_uv: vdd supply voltage (microvolts) + * @vdda_uv: vdda supply voltage (microvolts) * @cfg: compatible configuration data * @common: common data for all ADC instances * @ccr_bak: backup CCR in low power mode + * @syscfg: reference to syscon, system control registers */ struct stm32_adc_priv { int irq[STM32_ADC_MAX_ADCS]; struct irq_domain *domain; struct clk *aclk; struct clk *bclk; + struct regulator *booster; + struct regulator *vdd; struct regulator *vdda; struct regulator *vref; + int vdd_uv; + int vdda_uv; const struct stm32_adc_priv_cfg *cfg; struct stm32_adc_common common; u32 ccr_bak; + struct regmap *syscfg; }; static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com) @@ -349,7 +374,6 @@ static int stm32_adc_irq_probe(struct platform_device *pdev, */ if (i && priv->irq[i] == -ENXIO) continue; - dev_err(&pdev->dev, "failed to get irq\n"); return priv->irq[i]; } @@ -390,6 +414,82 @@ static void stm32_adc_irq_remove(struct platform_device *pdev, } } +static int stm32_adc_core_switches_supply_en(struct stm32_adc_priv *priv, + struct device *dev) +{ + int ret; + + /* + * On STM32H7 and STM32MP1, the ADC inputs are multiplexed with analog + * switches (via PCSEL) which have reduced performances when their + * supply is below 2.7V (vdda by default): + * - Voltage booster can be used, to get full ADC performances + * (increases power consumption). + * - Vdd can be used to supply them, if above 2.7V (STM32MP1 only). + * + * Recommended settings for ANASWVDD and EN_BOOSTER: + * - vdda < 2.7V but vdd > 2.7V: ANASWVDD = 1, EN_BOOSTER = 0 (stm32mp1) + * - vdda < 2.7V and vdd < 2.7V: ANASWVDD = 0, EN_BOOSTER = 1 + * - vdda >= 2.7V: ANASWVDD = 0, EN_BOOSTER = 0 (default) + */ + if (priv->vdda_uv < 2700000) { + if (priv->syscfg && priv->vdd_uv > 2700000) { + ret = regulator_enable(priv->vdd); + if (ret < 0) { + dev_err(dev, "vdd enable failed %d\n", ret); + return ret; + } + + ret = regmap_write(priv->syscfg, + STM32MP1_SYSCFG_PMCSETR, + STM32MP1_SYSCFG_ANASWVDD_MASK); + if (ret < 0) { + regulator_disable(priv->vdd); + dev_err(dev, "vdd select failed, %d\n", ret); + return ret; + } + dev_dbg(dev, "analog switches supplied by vdd\n"); + + return 0; + } + + if (priv->booster) { + /* + * This is optional, as this is a trade-off between + * analog performance and power consumption. + */ + ret = regulator_enable(priv->booster); + if (ret < 0) { + dev_err(dev, "booster enable failed %d\n", ret); + return ret; + } + dev_dbg(dev, "analog switches supplied by booster\n"); + + return 0; + } + } + + /* Fallback using vdda (default), nothing to do */ + dev_dbg(dev, "analog switches supplied by vdda (%d uV)\n", + priv->vdda_uv); + + return 0; +} + +static void stm32_adc_core_switches_supply_dis(struct stm32_adc_priv *priv) +{ + if (priv->vdda_uv < 2700000) { + if (priv->syscfg && priv->vdd_uv > 2700000) { + regmap_write(priv->syscfg, STM32MP1_SYSCFG_PMCCLRR, + STM32MP1_SYSCFG_ANASWVDD_MASK); + regulator_disable(priv->vdd); + return; + } + if (priv->booster) + regulator_disable(priv->booster); + } +} + static int stm32_adc_core_hw_start(struct device *dev) { struct stm32_adc_common *common = dev_get_drvdata(dev); @@ -402,10 +502,21 @@ static int stm32_adc_core_hw_start(struct device *dev) return ret; } + ret = regulator_get_voltage(priv->vdda); + if (ret < 0) { + dev_err(dev, "vdda get voltage failed, %d\n", ret); + goto err_vdda_disable; + } + priv->vdda_uv = ret; + + ret = stm32_adc_core_switches_supply_en(priv, dev); + if (ret < 0) + goto err_vdda_disable; + ret = regulator_enable(priv->vref); if (ret < 0) { dev_err(dev, "vref enable failed\n"); - goto err_vdda_disable; + goto err_switches_dis; } if (priv->bclk) { @@ -433,6 +544,8 @@ err_bclk_disable: clk_disable_unprepare(priv->bclk); err_regulator_disable: regulator_disable(priv->vref); +err_switches_dis: + stm32_adc_core_switches_supply_dis(priv); err_vdda_disable: regulator_disable(priv->vdda); @@ -451,9 +564,80 @@ static void stm32_adc_core_hw_stop(struct device *dev) if (priv->bclk) clk_disable_unprepare(priv->bclk); regulator_disable(priv->vref); + stm32_adc_core_switches_supply_dis(priv); regulator_disable(priv->vdda); } +static int stm32_adc_core_switches_probe(struct device *dev, + struct stm32_adc_priv *priv) +{ + struct device_node *np = dev->of_node; + int ret; + + /* Analog switches supply can be controlled by syscfg (optional) */ + priv->syscfg = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (IS_ERR(priv->syscfg)) { + ret = PTR_ERR(priv->syscfg); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Can't probe syscfg: %d\n", ret); + return ret; + } + priv->syscfg = NULL; + } + + /* Booster can be used to supply analog switches (optional) */ + if (priv->cfg->has_syscfg & HAS_VBOOSTER && + of_property_read_bool(np, "booster-supply")) { + priv->booster = devm_regulator_get_optional(dev, "booster"); + if (IS_ERR(priv->booster)) { + ret = PTR_ERR(priv->booster); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "can't get booster %d\n", + ret); + return ret; + } + priv->booster = NULL; + } + } + + /* Vdd can be used to supply analog switches (optional) */ + if (priv->cfg->has_syscfg & HAS_ANASWVDD && + of_property_read_bool(np, "vdd-supply")) { + priv->vdd = devm_regulator_get_optional(dev, "vdd"); + if (IS_ERR(priv->vdd)) { + ret = PTR_ERR(priv->vdd); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "can't get vdd %d\n", ret); + return ret; + } + priv->vdd = NULL; + } + } + + if (priv->vdd) { + ret = regulator_enable(priv->vdd); + if (ret < 0) { + dev_err(dev, "vdd enable failed %d\n", ret); + return ret; + } + + ret = regulator_get_voltage(priv->vdd); + if (ret < 0) { + dev_err(dev, "vdd get voltage failed %d\n", ret); + regulator_disable(priv->vdd); + return ret; + } + priv->vdd_uv = ret; + + regulator_disable(priv->vdd); + } + + return 0; +} + static int stm32_adc_probe(struct platform_device *pdev) { struct stm32_adc_priv *priv; @@ -514,6 +698,10 @@ static int stm32_adc_probe(struct platform_device *pdev) priv->bclk = NULL; } + ret = stm32_adc_core_switches_probe(dev, priv); + if (ret) + return ret; + pm_runtime_get_noresume(dev); pm_runtime_set_active(dev); pm_runtime_set_autosuspend_delay(dev, STM32_ADC_CORE_SLEEP_DELAY_MS); @@ -611,12 +799,14 @@ static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = { .regs = &stm32h7_adc_common_regs, .clk_sel = stm32h7_adc_clk_sel, .max_clk_rate_hz = 36000000, + .has_syscfg = HAS_VBOOSTER, }; static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = { .regs = &stm32h7_adc_common_regs, .clk_sel = stm32h7_adc_clk_sel, .max_clk_rate_hz = 40000000, + .has_syscfg = HAS_VBOOSTER | HAS_ANASWVDD, }; static const struct of_device_id stm32_adc_of_match[] = { diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 205e1699f954..6a7dd08b1e0b 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -1919,10 +1919,8 @@ static int stm32_adc_probe(struct platform_device *pdev) } adc->irq = platform_get_irq(pdev, 0); - if (adc->irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (adc->irq < 0) return adc->irq; - } ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr, 0, pdev->name, adc); diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index ee1e0569d0e1..e493242c266e 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1601,11 +1601,8 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev) * So IRQ associated to filter instance 0 is dedicated to the Filter 0. */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - if (irq != -EPROBE_DEFER) - dev_err(dev, "Failed to get IRQ: %d\n", irq); + if (irq < 0) return irq; - } ret = devm_request_irq(dev, irq, stm32_dfsdm_irq, 0, pdev->name, adc); diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index f13c6248a662..176e1cb4abb1 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -460,10 +460,8 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name, atomic_set(atomic, 1); ret = platform_get_irq_byname(pdev, name); - if (ret < 0) { - dev_err(&pdev->dev, "no %s interrupt registered\n", name); + if (ret < 0) return ret; - } ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret); if (ret < 0) { diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index 2fa6ec83bb13..f24148bd15de 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c @@ -905,10 +905,8 @@ static int twl6030_gpadc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(dev, irq, NULL, twl6030_gpadc_irq_handler, diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index 41d3621c4787..98b30475bbc6 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -821,10 +821,8 @@ static int vf610_adc_probe(struct platform_device *pdev) return PTR_ERR(info->regs); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(info->dev, irq, vf610_adc_isr, 0, 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 17af4e0fd5f8..6a4919cd83c3 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -63,10 +63,35 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev, /* Save values */ for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) - st->core.calib[i] = + st->core.calib[i].offset = st->core.resp->sensor_offset.offset[i]; ret = IIO_VAL_INT; - *val = st->core.calib[idx]; + *val = st->core.calib[idx].offset; + break; + case IIO_CHAN_INFO_CALIBSCALE: + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE; + st->core.param.sensor_offset.flags = 0; + + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret == -EPROTO) { + /* Reading calibscale is not supported on older EC. */ + *val = 1; + *val2 = 0; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + } else if (ret) { + break; + } + + /* Save values */ + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + st->core.calib[i].scale = + st->core.resp->sensor_scale.scale[i]; + + *val = st->core.calib[idx].scale >> 15; + *val2 = ((st->core.calib[idx].scale & 0x7FFF) * 1000000LL) / + MOTION_SENSE_DEFAULT_SCALE; + ret = IIO_VAL_INT_PLUS_MICRO; break; case IIO_CHAN_INFO_SCALE: st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; @@ -134,7 +159,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: - st->core.calib[idx] = val; + st->core.calib[idx].offset = val; /* Send to EC for each axis, even if not complete */ st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; @@ -142,12 +167,27 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, MOTION_SENSE_SET_OFFSET; for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) st->core.param.sensor_offset.offset[i] = - st->core.calib[i]; + st->core.calib[i].offset; st->core.param.sensor_offset.temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; ret = cros_ec_motion_send_host_cmd(&st->core, 0); break; + case IIO_CHAN_INFO_CALIBSCALE: + st->core.calib[idx].scale = val; + /* Send to EC for each axis, even if not complete */ + + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE; + st->core.param.sensor_offset.flags = + MOTION_SENSE_SET_OFFSET; + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + st->core.param.sensor_scale.scale[i] = + st->core.calib[i].scale; + st->core.param.sensor_scale.temp = + EC_MOTION_SENSE_INVALID_CALIB_TEMP; + + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + break; case IIO_CHAN_INFO_SCALE: if (st->core.type == MOTIONSENSE_TYPE_MAG) { ret = -EINVAL; @@ -175,6 +215,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, static const struct iio_info ec_sensors_info = { .read_raw = &cros_ec_sensors_read, .write_raw = &cros_ec_sensors_write, + .read_avail = &cros_ec_sensors_core_read_avail, }; static int cros_ec_sensors_probe(struct platform_device *pdev) @@ -206,11 +247,14 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) /* Common part */ channel->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_CALIBBIAS); + BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_CALIBSCALE); channel->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_FREQUENCY) | BIT(IIO_CHAN_INFO_SAMP_FREQ); + channel->info_mask_shared_by_all_available = + BIT(IIO_CHAN_INFO_SAMP_FREQ); channel->scan_type.realbits = CROS_EC_SENSOR_BITS; channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; channel->scan_index = i; 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 130362ca421b..d44ae126f457 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 @@ -25,6 +25,62 @@ static char *cros_ec_loc[] = { [MOTIONSENSE_LOC_MAX] = "unknown", }; +static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev, + u16 cmd_offset, u16 cmd, u32 *mask) +{ + int ret; + struct { + struct cros_ec_command msg; + union { + struct ec_params_get_cmd_versions params; + struct ec_response_get_cmd_versions resp; + }; + } __packed buf = { + .msg = { + .command = EC_CMD_GET_CMD_VERSIONS + cmd_offset, + .insize = sizeof(struct ec_response_get_cmd_versions), + .outsize = sizeof(struct ec_params_get_cmd_versions) + }, + .params = {.cmd = cmd} + }; + + ret = cros_ec_cmd_xfer_status(ec_dev, &buf.msg); + if (ret >= 0) + *mask = buf.resp.version_mask; + return ret; +} + +static void get_default_min_max_freq(enum motionsensor_type type, + u32 *min_freq, + u32 *max_freq) +{ + switch (type) { + case MOTIONSENSE_TYPE_ACCEL: + case MOTIONSENSE_TYPE_GYRO: + *min_freq = 12500; + *max_freq = 100000; + break; + case MOTIONSENSE_TYPE_MAG: + *min_freq = 5000; + *max_freq = 25000; + break; + case MOTIONSENSE_TYPE_PROX: + case MOTIONSENSE_TYPE_LIGHT: + *min_freq = 100; + *max_freq = 50000; + break; + case MOTIONSENSE_TYPE_BARO: + *min_freq = 250; + *max_freq = 20000; + break; + case MOTIONSENSE_TYPE_ACTIVITY: + default: + *min_freq = 0; + *max_freq = 0; + break; + } +} + int cros_ec_sensors_core_init(struct platform_device *pdev, struct iio_dev *indio_dev, bool physical_device) @@ -33,6 +89,8 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent); struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); + u32 ver_mask; + int ret, i; platform_set_drvdata(pdev, indio_dev); @@ -47,8 +105,15 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, mutex_init(&state->cmd_lock); + ret = cros_ec_get_host_cmd_version_mask(state->ec, + ec->cmd_offset, + EC_CMD_MOTION_SENSE_CMD, + &ver_mask); + if (ret < 0) + return ret; + /* Set up the host command structure. */ - state->msg->version = 2; + state->msg->version = fls(ver_mask) - 1; state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; state->msg->outsize = sizeof(struct ec_params_motion_sense); @@ -60,12 +125,32 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, state->param.cmd = MOTIONSENSE_CMD_INFO; state->param.info.sensor_num = sensor_platform->sensor_num; - if (cros_ec_motion_send_host_cmd(state, 0)) { + ret = cros_ec_motion_send_host_cmd(state, 0); + if (ret) { dev_warn(dev, "Can not access sensor info\n"); - return -EIO; + return ret; } state->type = state->resp->info.type; state->loc = state->resp->info.location; + + /* Set sign vector, only used for backward compatibility. */ + memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS); + + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + state->calib[i].scale = MOTION_SENSE_DEFAULT_SCALE; + + /* 0 is a correct value used to stop the device */ + state->frequencies[0] = 0; + if (state->msg->version < 3) { + get_default_min_max_freq(state->resp->info.type, + &state->frequencies[1], + &state->frequencies[2]); + } else { + state->frequencies[1] = + state->resp->info_3.min_frequency; + state->frequencies[2] = + state->resp->info_3.max_frequency; + } } return 0; @@ -86,7 +171,7 @@ int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state, ret = cros_ec_cmd_xfer_status(state->ec, state->msg); if (ret < 0) - return -EIO; + return ret; if (ret && state->resp != (struct ec_response_motion_sense *)state->msg->data) @@ -118,7 +203,7 @@ static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev, } else { /* Save values */ for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) - st->calib[i] = st->resp->perform_calib.offset[i]; + st->calib[i].offset = st->resp->perform_calib.offset[i]; } mutex_unlock(&st->cmd_lock); @@ -268,6 +353,7 @@ static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev, if (ret < 0) return ret; + *data *= st->sign[i]; data++; } @@ -396,7 +482,7 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - int ret = IIO_VAL_INT; + int ret; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: @@ -404,22 +490,27 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, st->param.ec_rate.data = EC_MOTION_SENSE_NO_VALUE; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; - else - *val = st->resp->ec_rate.ret; + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret) + break; + + *val = st->resp->ec_rate.ret; + ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_FREQUENCY: st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; st->param.sensor_odr.data = EC_MOTION_SENSE_NO_VALUE; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; - else - *val = st->resp->sensor_odr.ret; + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret) + break; + + *val = st->resp->sensor_odr.ret; + ret = IIO_VAL_INT; break; default: + ret = -EINVAL; break; } @@ -427,11 +518,32 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, } EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read); +int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, + int *type, + int *length, + long mask) +{ + struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *length = ARRAY_SIZE(state->frequencies); + *vals = (const int *)&state->frequencies; + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read_avail); + 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) { - int ret = 0; + int ret; switch (mask) { case IIO_CHAN_INFO_FREQUENCY: @@ -441,17 +553,16 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, /* Always roundup, so caller gets at least what it asks for. */ st->param.sensor_odr.roundup = 1; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(st, 0); break; case IIO_CHAN_INFO_SAMP_FREQ: st->param.cmd = MOTIONSENSE_CMD_EC_RATE; st->param.ec_rate.data = val; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; - else - st->curr_sampl_freq = val; + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret) + break; + st->curr_sampl_freq = val; break; default: ret = -EINVAL; diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index a8a3fe428d8d..442ff787f7af 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c @@ -8,11 +8,16 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/kernel.h> #include <linux/slab.h> +#include <linux/time.h> + #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> +#define HZ_PER_MHZ 1000000L + static struct { u32 usage_id; int unit; /* 0 for default others from HID sensor spec */ @@ -68,16 +73,6 @@ static struct { {HID_USAGE_SENSOR_HUMIDITY, 0, 1000, 0}, }; -static int pow_10(unsigned power) -{ - int i; - int ret = 1; - for (i = 0; i < power; ++i) - ret = ret * 10; - - return ret; -} - static void simple_div(int dividend, int divisor, int *whole, int *micro_frac) { @@ -96,14 +91,16 @@ static void simple_div(int dividend, int divisor, int *whole, rem *= 10; exp++; } - *micro_frac = (rem / divisor) * pow_10(6-exp); + *micro_frac = (rem / divisor) * int_pow(10, 6 - exp); } } static void split_micro_fraction(unsigned int no, int exp, int *val1, int *val2) { - *val1 = no/pow_10(exp); - *val2 = no%pow_10(exp) * pow_10(6-exp); + int divisor = int_pow(10, exp); + + *val1 = no / divisor; + *val2 = no % divisor * int_pow(10, 6 - exp); } /* @@ -125,7 +122,7 @@ static void convert_from_vtf_format(u32 value, int size, int exp, } exp = hid_sensor_convert_exponent(exp); if (exp >= 0) { - *val1 = sign * value * pow_10(exp); + *val1 = sign * value * int_pow(10, exp); *val2 = 0; } else { split_micro_fraction(value, -exp, val1, val2); @@ -138,6 +135,7 @@ static void convert_from_vtf_format(u32 value, int size, int exp, static u32 convert_to_vtf_format(int size, int exp, int val1, int val2) { + int divisor; u32 value; int sign = 1; @@ -145,10 +143,13 @@ static u32 convert_to_vtf_format(int size, int exp, int val1, int val2) sign = -1; exp = hid_sensor_convert_exponent(exp); if (exp < 0) { - value = abs(val1) * pow_10(-exp); - value += abs(val2) / pow_10(6+exp); - } else - value = abs(val1) / pow_10(exp); + divisor = int_pow(10, 6 + exp); + value = abs(val1) * int_pow(10, -exp); + value += abs(val2) / divisor; + } else { + divisor = int_pow(10, exp); + value = abs(val1) / divisor; + } if (sign < 0) value = ((1LL << (size * 8)) - value); @@ -211,12 +212,12 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, if (val1 < 0 || val2 < 0) return -EINVAL; - value = val1 * pow_10(6) + val2; + value = val1 * HZ_PER_MHZ + val2; if (value) { if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND) - value = pow_10(9)/value; + value = NSEC_PER_SEC / value; else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) - value = pow_10(6)/value; + value = USEC_PER_SEC / value; else value = 0; } @@ -305,40 +306,44 @@ EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); static void adjust_exponent_nano(int *val0, int *val1, int scale0, int scale1, int exp) { + int divisor; int i; int x; int res; int rem; if (exp > 0) { - *val0 = scale0 * pow_10(exp); + *val0 = scale0 * int_pow(10, exp); res = 0; if (exp > 9) { *val1 = 0; return; } for (i = 0; i < exp; ++i) { - x = scale1 / pow_10(8 - i); - res += (pow_10(exp - 1 - i) * x); - scale1 = scale1 % pow_10(8 - i); + divisor = int_pow(10, 8 - i); + x = scale1 / divisor; + res += int_pow(10, exp - 1 - i) * x; + scale1 = scale1 % divisor; } *val0 += res; - *val1 = scale1 * pow_10(exp); + *val1 = scale1 * int_pow(10, exp); } else if (exp < 0) { exp = abs(exp); if (exp > 9) { *val0 = *val1 = 0; return; } - *val0 = scale0 / pow_10(exp); - rem = scale0 % pow_10(exp); + divisor = int_pow(10, exp); + *val0 = scale0 / divisor; + rem = scale0 % divisor; res = 0; for (i = 0; i < (9 - exp); ++i) { - x = scale1 / pow_10(8 - i); - res += (pow_10(8 - exp - i) * x); - scale1 = scale1 % pow_10(8 - i); + divisor = int_pow(10, 8 - i); + x = scale1 / divisor; + res += int_pow(10, 8 - exp - i) * x; + scale1 = scale1 % divisor; } - *val1 = rem * pow_10(9 - exp) + res; + *val1 = rem * int_pow(10, 9 - exp) + res; } else { *val0 = scale0; *val1 = scale1; diff --git a/drivers/iio/common/st_sensors/Kconfig b/drivers/iio/common/st_sensors/Kconfig index 91b98e152d75..9364ec7a811f 100644 --- a/drivers/iio/common/st_sensors/Kconfig +++ b/drivers/iio/common/st_sensors/Kconfig @@ -5,9 +5,11 @@ config IIO_ST_SENSORS_I2C tristate + select REGMAP_I2C config IIO_ST_SENSORS_SPI tristate + select REGMAP_SPI config IIO_ST_SENSORS_CORE tristate diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c index 4a68669dc555..eee30130ae23 100644 --- a/drivers/iio/common/st_sensors/st_sensors_buffer.c +++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c @@ -17,15 +17,16 @@ #include <linux/iio/trigger_consumer.h> #include <linux/iio/triggered_buffer.h> #include <linux/irqreturn.h> +#include <linux/regmap.h> #include <linux/iio/common/st_sensors.h> static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) { - int i; struct st_sensor_data *sdata = iio_priv(indio_dev); unsigned int num_data_channels = sdata->num_data_channels; + int i; for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) { const struct iio_chan_spec *channel = &indio_dev->channels[i]; @@ -36,11 +37,8 @@ static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) channel->scan_type.storagebits >> 3; buf = PTR_ALIGN(buf, storage_bytes); - if (sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, - channel->address, - bytes_to_read, buf, - sdata->multiread_bit) < - bytes_to_read) + if (regmap_bulk_read(sdata->regmap, channel->address, + buf, bytes_to_read) < 0) return -EIO; /* Advance the buffer pointer */ diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 8b22dc241482..4a3064fb6cd9 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -15,6 +15,7 @@ #include <linux/regulator/consumer.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/regmap.h> #include <asm/unaligned.h> #include <linux/iio/common/st_sensors.h> @@ -28,19 +29,10 @@ static inline u32 st_sensors_get_unaligned_le24(const u8 *p) int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, u8 reg_addr, u8 mask, u8 data) { - int err; - u8 new_data; struct st_sensor_data *sdata = iio_priv(indio_dev); - err = sdata->tf->read_byte(&sdata->tb, sdata->dev, reg_addr, &new_data); - if (err < 0) - goto st_sensors_write_data_with_mask_error; - - new_data = ((new_data & (~mask)) | ((data << __ffs(mask)) & mask)); - err = sdata->tf->write_byte(&sdata->tb, sdata->dev, reg_addr, new_data); - -st_sensors_write_data_with_mask_error: - return err; + return regmap_update_bits(sdata->regmap, + reg_addr, mask, data << __ffs(mask)); } int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, @@ -48,19 +40,15 @@ int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, unsigned *readval) { struct st_sensor_data *sdata = iio_priv(indio_dev); - u8 readdata; int err; if (!readval) - return sdata->tf->write_byte(&sdata->tb, sdata->dev, - (u8)reg, (u8)writeval); + return regmap_write(sdata->regmap, reg, writeval); - err = sdata->tf->read_byte(&sdata->tb, sdata->dev, (u8)reg, &readdata); + err = regmap_read(sdata->regmap, reg, readval); if (err < 0) return err; - *readval = (unsigned)readdata; - return 0; } EXPORT_SYMBOL(st_sensors_debugfs_reg_access); @@ -545,7 +533,7 @@ st_sensors_match_scale_error: EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain); static int st_sensors_read_axis_data(struct iio_dev *indio_dev, - struct iio_chan_spec const *ch, int *data) + struct iio_chan_spec const *ch, int *data) { int err; u8 *outdata; @@ -554,13 +542,12 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev, byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits + ch->scan_type.shift, 8); - outdata = kmalloc(byte_for_channel, GFP_KERNEL); + outdata = kmalloc(byte_for_channel, GFP_DMA | GFP_KERNEL); if (!outdata) return -ENOMEM; - err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, - ch->address, byte_for_channel, - outdata, sdata->multiread_bit); + err = regmap_bulk_read(sdata->regmap, ch->address, + outdata, byte_for_channel); if (err < 0) goto st_sensors_free_memory; @@ -608,69 +595,55 @@ out: } EXPORT_SYMBOL(st_sensors_read_info_raw); -static int st_sensors_init_interface_mode(struct iio_dev *indio_dev, - const struct st_sensor_settings *sensor_settings) +/* + * st_sensors_get_settings_index() - get index of the sensor settings for a + * specific device from list of settings + * @name: device name buffer reference. + * @list: sensor settings list. + * @list_length: length of sensor settings list. + * + * Return: non negative number on success (valid index), + * negative error code otherwise. + */ +int st_sensors_get_settings_index(const char *name, + const struct st_sensor_settings *list, + const int list_length) { - struct st_sensor_data *sdata = iio_priv(indio_dev); - struct device_node *np = sdata->dev->of_node; - struct st_sensors_platform_data *pdata; + int i, n; - pdata = (struct st_sensors_platform_data *)sdata->dev->platform_data; - if (((np && of_property_read_bool(np, "spi-3wire")) || - (pdata && pdata->spi_3wire)) && sensor_settings->sim.addr) { - int err; - - err = sdata->tf->write_byte(&sdata->tb, sdata->dev, - sensor_settings->sim.addr, - sensor_settings->sim.value); - if (err < 0) { - dev_err(&indio_dev->dev, - "failed to init interface mode\n"); - return err; + for (i = 0; i < list_length; i++) { + for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) { + if (strcmp(name, list[i].sensors_supported[n]) == 0) + return i; } } - return 0; + return -ENODEV; } +EXPORT_SYMBOL(st_sensors_get_settings_index); -int st_sensors_check_device_support(struct iio_dev *indio_dev, - int num_sensors_list, - const struct st_sensor_settings *sensor_settings) +/* + * st_sensors_verify_id() - verify sensor ID (WhoAmI) is matching with the + * expected value + * @indio_dev: IIO device reference. + * + * Return: 0 on success (valid sensor ID), else a negative error code. + */ +int st_sensors_verify_id(struct iio_dev *indio_dev) { - int i, n, err = 0; - u8 wai; struct st_sensor_data *sdata = iio_priv(indio_dev); + int wai, err; - for (i = 0; i < num_sensors_list; i++) { - for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) { - if (strcmp(indio_dev->name, - sensor_settings[i].sensors_supported[n]) == 0) { - break; - } - } - if (n < ST_SENSORS_MAX_4WAI) - break; - } - if (i == num_sensors_list) { - dev_err(&indio_dev->dev, "device name %s not recognized.\n", - indio_dev->name); - return -ENODEV; - } - - err = st_sensors_init_interface_mode(indio_dev, &sensor_settings[i]); - if (err < 0) - return err; - - if (sensor_settings[i].wai_addr) { - err = sdata->tf->read_byte(&sdata->tb, sdata->dev, - sensor_settings[i].wai_addr, &wai); + if (sdata->sensor_settings->wai_addr) { + err = regmap_read(sdata->regmap, + sdata->sensor_settings->wai_addr, &wai); if (err < 0) { dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n"); return err; } - if (sensor_settings[i].wai != wai) { + if (sdata->sensor_settings->wai != wai) { dev_err(&indio_dev->dev, "%s: WhoAmI mismatch (0x%x).\n", indio_dev->name, wai); @@ -678,12 +651,9 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev, } } - sdata->sensor_settings = - (struct st_sensor_settings *)&sensor_settings[i]; - - return i; + return 0; } -EXPORT_SYMBOL(st_sensors_check_device_support); +EXPORT_SYMBOL(st_sensors_verify_id); ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c index b1c9812407e7..aa89d54a7c59 100644 --- a/drivers/iio/common/st_sensors/st_sensors_i2c.c +++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c @@ -13,68 +13,58 @@ #include <linux/iio/iio.h> #include <linux/of_device.h> #include <linux/acpi.h> +#include <linux/regmap.h> #include <linux/iio/common/st_sensors_i2c.h> #define ST_SENSORS_I2C_MULTIREAD 0x80 -static unsigned int st_sensors_i2c_get_irq(struct iio_dev *indio_dev) -{ - struct st_sensor_data *sdata = iio_priv(indio_dev); - - return to_i2c_client(sdata->dev)->irq; -} - -static int st_sensors_i2c_read_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 *res_byte) -{ - int err; - - err = i2c_smbus_read_byte_data(to_i2c_client(dev), reg_addr); - if (err < 0) - goto st_accel_i2c_read_byte_error; - - *res_byte = err & 0xff; - -st_accel_i2c_read_byte_error: - return err < 0 ? err : 0; -} - -static int st_sensors_i2c_read_multiple_byte( - struct st_sensor_transfer_buffer *tb, struct device *dev, - u8 reg_addr, int len, u8 *data, bool multiread_bit) -{ - if (multiread_bit) - reg_addr |= ST_SENSORS_I2C_MULTIREAD; - - return i2c_smbus_read_i2c_block_data_or_emulated(to_i2c_client(dev), - reg_addr, len, data); -} - -static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 data) -{ - return i2c_smbus_write_byte_data(to_i2c_client(dev), reg_addr, data); -} +static const struct regmap_config st_sensors_i2c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; -static const struct st_sensor_transfer_function st_sensors_tf_i2c = { - .read_byte = st_sensors_i2c_read_byte, - .write_byte = st_sensors_i2c_write_byte, - .read_multiple_byte = st_sensors_i2c_read_multiple_byte, +static const struct regmap_config st_sensors_i2c_regmap_multiread_bit_config = { + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = ST_SENSORS_I2C_MULTIREAD, }; -void st_sensors_i2c_configure(struct iio_dev *indio_dev, - struct i2c_client *client, struct st_sensor_data *sdata) +/* + * st_sensors_i2c_configure() - configure I2C interface + * @indio_dev: IIO device reference. + * @client: i2c client reference. + * + * Return: 0 on success, else a negative error code. + */ +int st_sensors_i2c_configure(struct iio_dev *indio_dev, + struct i2c_client *client) { + struct st_sensor_data *sdata = iio_priv(indio_dev); + const struct regmap_config *config; + + if (sdata->sensor_settings->multi_read_bit) + config = &st_sensors_i2c_regmap_multiread_bit_config; + else + config = &st_sensors_i2c_regmap_config; + + sdata->regmap = devm_regmap_init_i2c(client, config); + if (IS_ERR(sdata->regmap)) { + dev_err(&client->dev, "Failed to register i2c regmap (%d)\n", + (int)PTR_ERR(sdata->regmap)); + return PTR_ERR(sdata->regmap); + } + i2c_set_clientdata(client, indio_dev); indio_dev->dev.parent = &client->dev; indio_dev->name = client->name; sdata->dev = &client->dev; - sdata->tf = &st_sensors_tf_i2c; - sdata->get_irq_data_ready = st_sensors_i2c_get_irq; + sdata->irq = client->irq; + + return 0; } EXPORT_SYMBOL(st_sensors_i2c_configure); diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c index 2213843f02cb..2262f81b07c2 100644 --- a/drivers/iio/common/st_sensors/st_sensors_spi.c +++ b/drivers/iio/common/st_sensors/st_sensors_spi.c @@ -11,108 +11,108 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/iio/iio.h> +#include <linux/regmap.h> #include <linux/iio/common/st_sensors_spi.h> - +#include "st_sensors_core.h" #define ST_SENSORS_SPI_MULTIREAD 0xc0 -#define ST_SENSORS_SPI_READ 0x80 -static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev) -{ - struct st_sensor_data *sdata = iio_priv(indio_dev); +static const struct regmap_config st_sensors_spi_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; - return to_spi_device(sdata->dev)->irq; -} +static const struct regmap_config st_sensors_spi_regmap_multiread_bit_config = { + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = ST_SENSORS_SPI_MULTIREAD, +}; -static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit) +/* + * st_sensors_is_spi_3_wire() - check if SPI 3-wire mode has been selected + * @spi: spi device reference. + * + * Return: true if SPI 3-wire mode is selected, false otherwise. + */ +static bool st_sensors_is_spi_3_wire(struct spi_device *spi) { - int err; - - struct spi_transfer xfers[] = { - { - .tx_buf = tb->tx_buf, - .bits_per_word = 8, - .len = 1, - }, - { - .rx_buf = tb->rx_buf, - .bits_per_word = 8, - .len = len, - } - }; - - mutex_lock(&tb->buf_lock); - if ((multiread_bit) && (len > 1)) - tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_MULTIREAD; - else - tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ; + struct device_node *np = spi->dev.of_node; + struct st_sensors_platform_data *pdata; - err = spi_sync_transfer(to_spi_device(dev), xfers, ARRAY_SIZE(xfers)); - if (err) - goto acc_spi_read_error; + pdata = (struct st_sensors_platform_data *)spi->dev.platform_data; + if ((np && of_property_read_bool(np, "spi-3wire")) || + (pdata && pdata->spi_3wire)) { + return true; + } - memcpy(data, tb->rx_buf, len); - mutex_unlock(&tb->buf_lock); - return len; - -acc_spi_read_error: - mutex_unlock(&tb->buf_lock); - return err; + return false; } -static int st_sensors_spi_read_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 *res_byte) +/* + * st_sensors_configure_spi_3_wire() - configure SPI 3-wire if needed + * @spi: spi device reference. + * @settings: sensor specific settings reference. + * + * Return: 0 on success, else a negative error code. + */ +static int st_sensors_configure_spi_3_wire(struct spi_device *spi, + struct st_sensor_settings *settings) { - return st_sensors_spi_read(tb, dev, reg_addr, 1, res_byte, false); -} + if (settings->sim.addr) { + u8 buffer[] = { + settings->sim.addr, + settings->sim.value + }; -static int st_sensors_spi_read_multiple_byte( - struct st_sensor_transfer_buffer *tb, struct device *dev, - u8 reg_addr, int len, u8 *data, bool multiread_bit) -{ - return st_sensors_spi_read(tb, dev, reg_addr, len, data, multiread_bit); + return spi_write(spi, buffer, 2); + } + + return 0; } -static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 data) +/* + * st_sensors_spi_configure() - configure SPI interface + * @indio_dev: IIO device reference. + * @spi: spi device reference. + * + * Return: 0 on success, else a negative error code. + */ +int st_sensors_spi_configure(struct iio_dev *indio_dev, + struct spi_device *spi) { + struct st_sensor_data *sdata = iio_priv(indio_dev); + const struct regmap_config *config; int err; - struct spi_transfer xfers = { - .tx_buf = tb->tx_buf, - .bits_per_word = 8, - .len = 2, - }; + if (st_sensors_is_spi_3_wire(spi)) { + err = st_sensors_configure_spi_3_wire(spi, + sdata->sensor_settings); + if (err < 0) + return err; + } - mutex_lock(&tb->buf_lock); - tb->tx_buf[0] = reg_addr; - tb->tx_buf[1] = data; - - err = spi_sync_transfer(to_spi_device(dev), &xfers, 1); - mutex_unlock(&tb->buf_lock); + if (sdata->sensor_settings->multi_read_bit) + config = &st_sensors_spi_regmap_multiread_bit_config; + else + config = &st_sensors_spi_regmap_config; - return err; -} + sdata->regmap = devm_regmap_init_spi(spi, config); + if (IS_ERR(sdata->regmap)) { + dev_err(&spi->dev, "Failed to register spi regmap (%d)\n", + (int)PTR_ERR(sdata->regmap)); + return PTR_ERR(sdata->regmap); + } -static const struct st_sensor_transfer_function st_sensors_tf_spi = { - .read_byte = st_sensors_spi_read_byte, - .write_byte = st_sensors_spi_write_byte, - .read_multiple_byte = st_sensors_spi_read_multiple_byte, -}; - -void st_sensors_spi_configure(struct iio_dev *indio_dev, - struct spi_device *spi, struct st_sensor_data *sdata) -{ spi_set_drvdata(spi, indio_dev); indio_dev->dev.parent = &spi->dev; indio_dev->name = spi->modalias; sdata->dev = &spi->dev; - sdata->tf = &st_sensors_tf_spi; - sdata->get_irq_data_ready = st_sensors_spi_get_irq; + sdata->irq = spi->irq; + + return 0; } EXPORT_SYMBOL(st_sensors_spi_configure); diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index 630c8cb35e8b..4a2efa00f7f2 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -13,6 +13,7 @@ #include <linux/iio/iio.h> #include <linux/iio/trigger.h> #include <linux/interrupt.h> +#include <linux/regmap.h> #include <linux/iio/common/st_sensors.h> #include "st_sensors_core.h" @@ -26,8 +27,7 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev, struct st_sensor_data *sdata) { - u8 status; - int ret; + int ret, status; /* How would I know if I can't check it? */ if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) @@ -37,9 +37,9 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev, if (!indio_dev->active_scan_mask) return 0; - ret = sdata->tf->read_byte(&sdata->tb, sdata->dev, - sdata->sensor_settings->drdy_irq.stat_drdy.addr, - &status); + ret = regmap_read(sdata->regmap, + sdata->sensor_settings->drdy_irq.stat_drdy.addr, + &status); if (ret < 0) { dev_err(sdata->dev, "error checking samples available\n"); @@ -121,9 +121,9 @@ static irqreturn_t st_sensors_irq_thread(int irq, void *p) int st_sensors_allocate_trigger(struct iio_dev *indio_dev, const struct iio_trigger_ops *trigger_ops) { - int err, irq; struct st_sensor_data *sdata = iio_priv(indio_dev); unsigned long irq_trig; + int err; sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name); if (sdata->trig == NULL) { @@ -135,8 +135,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->trig->ops = trigger_ops; sdata->trig->dev.parent = sdata->dev; - irq = sdata->get_irq_data_ready(indio_dev); - irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); + irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq)); /* * If the IRQ is triggered on falling edge, we need to mark the * interrupt as active low, if the hardware supports this. @@ -206,12 +205,12 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->sensor_settings->drdy_irq.stat_drdy.addr) irq_trig |= IRQF_SHARED; - err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev), - st_sensors_irq_handler, - st_sensors_irq_thread, - irq_trig, - sdata->trig->name, - sdata->trig); + err = request_threaded_irq(sdata->irq, + st_sensors_irq_handler, + st_sensors_irq_thread, + irq_trig, + sdata->trig->name, + sdata->trig); if (err) { dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); goto iio_trigger_free; @@ -227,7 +226,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, return 0; iio_trigger_register_error: - free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); + free_irq(sdata->irq, sdata->trig); iio_trigger_free: iio_trigger_free(sdata->trig); return err; @@ -239,7 +238,7 @@ void st_sensors_deallocate_trigger(struct iio_dev *indio_dev) struct st_sensor_data *sdata = iio_priv(indio_dev); iio_trigger_unregister(sdata->trig); - free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); + free_irq(sdata->irq, sdata->trig); iio_trigger_free(sdata->trig); } EXPORT_SYMBOL(st_sensors_deallocate_trigger); diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 4335214800d2..2ebe08326048 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -220,7 +220,7 @@ static int ad5380_read_raw(struct iio_dev *indio_dev, if (ret) return ret; *val >>= chan->scan_type.shift; - val -= (1 << chan->scan_type.realbits) / 2; + *val -= (1 << chan->scan_type.realbits) / 2; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = 2 * st->vref; diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h index 460d190be4a4..592f6b34e987 100644 --- a/drivers/iio/gyro/st_gyro.h +++ b/drivers/iio/gyro/st_gyro.h @@ -32,6 +32,7 @@ static const struct st_sensors_platform_data gyro_pdata = { .drdy_int_pin = 2, }; +const struct st_sensor_settings *st_gyro_get_settings(const char *name); int st_gyro_common_probe(struct iio_dev *indio_dev); void st_gyro_common_remove(struct iio_dev *indio_dev); diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c index 6e362f735e92..7465ad62391c 100644 --- a/drivers/iio/gyro/st_gyro_buffer.c +++ b/drivers/iio/gyro/st_gyro_buffer.c @@ -29,61 +29,51 @@ int st_gyro_trig_set_state(struct iio_trigger *trig, bool state) return st_sensors_set_dataready_irq(indio_dev, state); } -static int st_gyro_buffer_preenable(struct iio_dev *indio_dev) -{ - return st_sensors_set_enable(indio_dev, true); -} - static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) { int err; - struct st_sensor_data *gdata = iio_priv(indio_dev); - gdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); - if (gdata->buffer_data == NULL) { - err = -ENOMEM; - goto allocate_memory_error; - } + err = iio_triggered_buffer_postenable(indio_dev); + if (err < 0) + return err; err = st_sensors_set_axis_enable(indio_dev, - (u8)indio_dev->active_scan_mask[0]); + (u8)indio_dev->active_scan_mask[0]); if (err < 0) - goto st_gyro_buffer_postenable_error; + goto st_gyro_buffer_predisable; - err = iio_triggered_buffer_postenable(indio_dev); + err = st_sensors_set_enable(indio_dev, true); if (err < 0) - goto st_gyro_buffer_postenable_error; + goto st_gyro_buffer_enable_all_axis; - return err; + return 0; -st_gyro_buffer_postenable_error: - kfree(gdata->buffer_data); -allocate_memory_error: +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; - struct st_sensor_data *gdata = iio_priv(indio_dev); + int err, err2; - err = iio_triggered_buffer_predisable(indio_dev); + err = st_sensors_set_enable(indio_dev, false); if (err < 0) - goto st_gyro_buffer_predisable_error; + goto st_gyro_buffer_predisable; err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); - if (err < 0) - goto st_gyro_buffer_predisable_error; - err = st_sensors_set_enable(indio_dev, false); +st_gyro_buffer_predisable: + err2 = iio_triggered_buffer_predisable(indio_dev); + if (!err) + err = err2; -st_gyro_buffer_predisable_error: - kfree(gdata->buffer_data); return err; } static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = { - .preenable = &st_gyro_buffer_preenable, .postenable = &st_gyro_buffer_postenable, .predisable = &st_gyro_buffer_predisable, }; diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index e995dc77e30e..c0acbb5d2ffb 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -12,7 +12,6 @@ #include <linux/slab.h> #include <linux/errno.h> #include <linux/types.h> -#include <linux/mutex.h> #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/gpio.h> @@ -368,28 +367,41 @@ static const struct iio_trigger_ops st_gyro_trigger_ops = { #define ST_GYRO_TRIGGER_OPS NULL #endif +/* + * st_gyro_get_settings() - get sensor settings from device name + * @name: device name buffer reference. + * + * Return: valid reference on success, NULL otherwise. + */ +const struct st_sensor_settings *st_gyro_get_settings(const char *name) +{ + int index = st_sensors_get_settings_index(name, + st_gyro_sensors_settings, + ARRAY_SIZE(st_gyro_sensors_settings)); + if (index < 0) + return NULL; + + return &st_gyro_sensors_settings[index]; +} +EXPORT_SYMBOL(st_gyro_get_settings); + int st_gyro_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *gdata = iio_priv(indio_dev); - int irq = gdata->get_irq_data_ready(indio_dev); int err; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &gyro_info; - mutex_init(&gdata->tb.buf_lock); err = st_sensors_power_enable(indio_dev); if (err) return err; - err = st_sensors_check_device_support(indio_dev, - ARRAY_SIZE(st_gyro_sensors_settings), - st_gyro_sensors_settings); + err = st_sensors_verify_id(indio_dev); if (err < 0) goto st_gyro_power_off; gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS; - gdata->multiread_bit = gdata->sensor_settings->multi_read_bit; indio_dev->channels = gdata->sensor_settings->ch; indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; @@ -406,7 +418,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) if (err < 0) goto st_gyro_power_off; - if (irq > 0) { + if (gdata->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, ST_GYRO_TRIGGER_OPS); if (err < 0) @@ -423,7 +435,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) return 0; st_gyro_device_register_error: - if (irq > 0) + if (gdata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_gyro_probe_trigger_error: st_gyro_deallocate_ring(indio_dev); @@ -441,7 +453,7 @@ void st_gyro_common_remove(struct iio_dev *indio_dev) st_sensors_power_disable(indio_dev); iio_device_unregister(indio_dev); - if (gdata->get_irq_data_ready(indio_dev) > 0) + if (gdata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_gyro_deallocate_ring(indio_dev); diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index f2a8683db7d9..05a1a0874bd5 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -63,21 +63,33 @@ MODULE_DEVICE_TABLE(of, st_gyro_of_match); #endif static int st_gyro_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *gdata; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&client->dev, st_gyro_of_match, + client->name, sizeof(client->name)); + + settings = st_gyro_get_settings(client->name); + if (!settings) { + dev_err(&client->dev, "device name %s not recognized.\n", + client->name); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*gdata)); if (!indio_dev) return -ENOMEM; gdata = iio_priv(indio_dev); - st_sensors_of_name_probe(&client->dev, st_gyro_of_match, - client->name, sizeof(client->name)); + gdata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_i2c_configure(indio_dev, client, gdata); + err = st_sensors_i2c_configure(indio_dev, client); + if (err < 0) + return err; err = st_gyro_common_probe(indio_dev); if (err < 0) diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index 93c48248bea6..b5c624251231 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -69,19 +69,31 @@ MODULE_DEVICE_TABLE(of, st_gyro_of_match); static int st_gyro_spi_probe(struct spi_device *spi) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *gdata; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&spi->dev, st_gyro_of_match, + spi->modalias, sizeof(spi->modalias)); + + settings = st_gyro_get_settings(spi->modalias); + if (!settings) { + dev_err(&spi->dev, "device name %s not recognized.\n", + spi->modalias); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*gdata)); if (!indio_dev) return -ENOMEM; gdata = iio_priv(indio_dev); + gdata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_of_name_probe(&spi->dev, st_gyro_of_match, - spi->modalias, sizeof(spi->modalias)); - st_sensors_spi_configure(indio_dev, spi, gdata); + err = st_sensors_spi_configure(indio_dev, spi); + if (err < 0) + return err; err = st_gyro_common_probe(indio_dev); if (err < 0) diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index f18da7859229..3bac98e731d9 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c @@ -240,32 +240,15 @@ static int am2315_probe(struct i2c_client *client, indio_dev->channels = am2315_channels; indio_dev->num_channels = ARRAY_SIZE(am2315_channels); - ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time, + ret = devm_iio_triggered_buffer_setup(&client->dev, + indio_dev, iio_pollfunc_store_time, am2315_trigger_handler, NULL); if (ret < 0) { dev_err(&client->dev, "iio triggered buffer setup failed\n"); return ret; } - ret = iio_device_register(indio_dev); - if (ret < 0) - goto err_buffer_cleanup; - - return 0; - -err_buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); - return ret; -} - -static int am2315_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id am2315_i2c_id[] = { @@ -287,7 +270,6 @@ static struct i2c_driver am2315_driver = { .acpi_match_table = ACPI_PTR(am2315_acpi_id), }, .probe = am2315_probe, - .remove = am2315_remove, .id_table = am2315_i2c_id, }; diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index 066e05f92081..bfe1cdb16846 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -385,28 +385,16 @@ static int hdc100x_probe(struct i2c_client *client, hdc100x_set_it_time(data, 1, hdc100x_int_time[1][0]); hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0); - ret = iio_triggered_buffer_setup(indio_dev, NULL, + ret = devm_iio_triggered_buffer_setup(&client->dev, + indio_dev, NULL, hdc100x_trigger_handler, &hdc_buffer_setup_ops); if (ret < 0) { dev_err(&client->dev, "iio triggered buffer setup failed\n"); return ret; } - ret = iio_device_register(indio_dev); - if (ret < 0) - iio_triggered_buffer_cleanup(indio_dev); - return ret; -} - -static int hdc100x_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id hdc100x_id[] = { @@ -436,7 +424,6 @@ static struct i2c_driver hdc100x_driver = { .of_match_table = of_match_ptr(hdc100x_dt_ids), }, .probe = hdc100x_probe, - .remove = hdc100x_remove, .id_table = hdc100x_id, }; module_i2c_driver(hdc100x_driver); diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index 4957e6df447e..f3c7282321a8 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -17,6 +17,18 @@ config ADIS16400 adis16365, adis16400 and adis16405 triaxial inertial sensors (adis16400 series also have magnetometers). +config ADIS16460 + tristate "Analog Devices ADIS16460 and similar IMU driver" + depends on SPI + select IIO_ADIS_LIB + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER + help + Say yes here to build support for Analog Devices ADIS16460 inertial + sensor. + + To compile this driver as a module, choose M here: the module will be + called adis16460. + config ADIS16480 tristate "Analog Devices ADIS16480 and similar IMU driver" depends on SPI diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 9e452fce1aaf..4a6958865504 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -5,6 +5,7 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_ADIS16400) += adis16400.o +obj-$(CONFIG_ADIS16460) += adis16460.o obj-$(CONFIG_ADIS16480) += adis16480.o adis_lib-y += adis.o diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 30281e91dbf9..1631c255deab 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -39,18 +39,24 @@ int adis_write_reg(struct adis *adis, unsigned int reg, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 2, .bits_per_word = 8, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 4, .bits_per_word = 8, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 6, .bits_per_word = 8, @@ -133,12 +139,16 @@ int adis_read_reg(struct adis *adis, unsigned int reg, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 2, .bits_per_word = 8, .len = 2, .cs_change = 1, .delay_usecs = adis->data->read_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 4, .rx_buf = adis->rx, @@ -146,6 +156,8 @@ int adis_read_reg(struct adis *adis, unsigned int reg, .len = 2, .cs_change = 1, .delay_usecs = adis->data->read_delay, + .cs_change_delay = adis->data->cs_change_delay, + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, }, { .rx_buf = adis->rx + 2, .bits_per_word = 8, diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c new file mode 100644 index 000000000000..6aed9e84abbf --- /dev/null +++ b/drivers/iio/imu/adis16460.c @@ -0,0 +1,489 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * ADIS16460 IMU driver + * + * Copyright 2019 Analog Devices Inc. + */ + +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/spi/spi.h> + +#include <linux/iio/iio.h> +#include <linux/iio/imu/adis.h> + +#include <linux/debugfs.h> + +#define ADIS16460_REG_FLASH_CNT 0x00 +#define ADIS16460_REG_DIAG_STAT 0x02 +#define ADIS16460_REG_X_GYRO_LOW 0x04 +#define ADIS16460_REG_X_GYRO_OUT 0x06 +#define ADIS16460_REG_Y_GYRO_LOW 0x08 +#define ADIS16460_REG_Y_GYRO_OUT 0x0A +#define ADIS16460_REG_Z_GYRO_LOW 0x0C +#define ADIS16460_REG_Z_GYRO_OUT 0x0E +#define ADIS16460_REG_X_ACCL_LOW 0x10 +#define ADIS16460_REG_X_ACCL_OUT 0x12 +#define ADIS16460_REG_Y_ACCL_LOW 0x14 +#define ADIS16460_REG_Y_ACCL_OUT 0x16 +#define ADIS16460_REG_Z_ACCL_LOW 0x18 +#define ADIS16460_REG_Z_ACCL_OUT 0x1A +#define ADIS16460_REG_SMPL_CNTR 0x1C +#define ADIS16460_REG_TEMP_OUT 0x1E +#define ADIS16460_REG_X_DELT_ANG 0x24 +#define ADIS16460_REG_Y_DELT_ANG 0x26 +#define ADIS16460_REG_Z_DELT_ANG 0x28 +#define ADIS16460_REG_X_DELT_VEL 0x2A +#define ADIS16460_REG_Y_DELT_VEL 0x2C +#define ADIS16460_REG_Z_DELT_VEL 0x2E +#define ADIS16460_REG_MSC_CTRL 0x32 +#define ADIS16460_REG_SYNC_SCAL 0x34 +#define ADIS16460_REG_DEC_RATE 0x36 +#define ADIS16460_REG_FLTR_CTRL 0x38 +#define ADIS16460_REG_GLOB_CMD 0x3E +#define ADIS16460_REG_X_GYRO_OFF 0x40 +#define ADIS16460_REG_Y_GYRO_OFF 0x42 +#define ADIS16460_REG_Z_GYRO_OFF 0x44 +#define ADIS16460_REG_X_ACCL_OFF 0x46 +#define ADIS16460_REG_Y_ACCL_OFF 0x48 +#define ADIS16460_REG_Z_ACCL_OFF 0x4A +#define ADIS16460_REG_LOT_ID1 0x52 +#define ADIS16460_REG_LOT_ID2 0x54 +#define ADIS16460_REG_PROD_ID 0x56 +#define ADIS16460_REG_SERIAL_NUM 0x58 +#define ADIS16460_REG_CAL_SGNTR 0x60 +#define ADIS16460_REG_CAL_CRC 0x62 +#define ADIS16460_REG_CODE_SGNTR 0x64 +#define ADIS16460_REG_CODE_CRC 0x66 + +struct adis16460_chip_info { + unsigned int num_channels; + const struct iio_chan_spec *channels; + unsigned int gyro_max_val; + unsigned int gyro_max_scale; + unsigned int accel_max_val; + unsigned int accel_max_scale; +}; + +struct adis16460 { + const struct adis16460_chip_info *chip_info; + struct adis adis; +}; + +#ifdef CONFIG_DEBUG_FS + +static int adis16460_show_serial_number(void *arg, u64 *val) +{ + struct adis16460 *adis16460 = arg; + u16 serial; + int ret; + + ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_SERIAL_NUM, + &serial); + if (ret < 0) + return ret; + + *val = serial; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(adis16460_serial_number_fops, + adis16460_show_serial_number, NULL, "0x%.4llx\n"); + +static int adis16460_show_product_id(void *arg, u64 *val) +{ + struct adis16460 *adis16460 = arg; + u16 prod_id; + int ret; + + ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_PROD_ID, + &prod_id); + if (ret < 0) + return ret; + + *val = prod_id; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(adis16460_product_id_fops, + adis16460_show_product_id, NULL, "%llu\n"); + +static int adis16460_show_flash_count(void *arg, u64 *val) +{ + struct adis16460 *adis16460 = arg; + u32 flash_count; + int ret; + + ret = adis_read_reg_32(&adis16460->adis, ADIS16460_REG_FLASH_CNT, + &flash_count); + if (ret < 0) + return ret; + + *val = flash_count; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(adis16460_flash_count_fops, + adis16460_show_flash_count, NULL, "%lld\n"); + +static int adis16460_debugfs_init(struct iio_dev *indio_dev) +{ + struct adis16460 *adis16460 = iio_priv(indio_dev); + + debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry, + adis16460, &adis16460_serial_number_fops); + debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry, + adis16460, &adis16460_product_id_fops); + debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry, + adis16460, &adis16460_flash_count_fops); + + return 0; +} + +#else + +static int adis16460_debugfs_init(struct iio_dev *indio_dev) +{ + return 0; +} + +#endif + +static int adis16460_set_freq(struct iio_dev *indio_dev, int val, int val2) +{ + struct adis16460 *st = iio_priv(indio_dev); + int t; + + t = val * 1000 + val2 / 1000; + if (t <= 0) + return -EINVAL; + + t = 2048000 / t; + if (t > 2048) + t = 2048; + + if (t != 0) + t--; + + return adis_write_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, t); +} + +static int adis16460_get_freq(struct iio_dev *indio_dev, int *val, int *val2) +{ + struct adis16460 *st = iio_priv(indio_dev); + uint16_t t; + int ret; + unsigned int freq; + + ret = adis_read_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, &t); + if (ret < 0) + return ret; + + freq = 2048000 / (t + 1); + *val = freq / 1000; + *val2 = (freq % 1000) * 1000; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int adis16460_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, int *val2, long info) +{ + struct adis16460 *st = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, 0, val); + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + *val = st->chip_info->gyro_max_scale; + *val2 = st->chip_info->gyro_max_val; + return IIO_VAL_FRACTIONAL; + case IIO_ACCEL: + *val = st->chip_info->accel_max_scale; + *val2 = st->chip_info->accel_max_val; + return IIO_VAL_FRACTIONAL; + case IIO_TEMP: + *val = 50; /* 50 milli degrees Celsius/LSB */ + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OFFSET: + *val = 500; /* 25 degrees Celsius = 0x0000 */ + return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: + return adis16460_get_freq(indio_dev, val, val2); + default: + return -EINVAL; + } +} + +static int adis16460_write_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int val, int val2, long info) +{ + switch (info) { + case IIO_CHAN_INFO_SAMP_FREQ: + return adis16460_set_freq(indio_dev, val, val2); + default: + return -EINVAL; + } +} + +enum { + ADIS16460_SCAN_GYRO_X, + ADIS16460_SCAN_GYRO_Y, + ADIS16460_SCAN_GYRO_Z, + ADIS16460_SCAN_ACCEL_X, + ADIS16460_SCAN_ACCEL_Y, + ADIS16460_SCAN_ACCEL_Z, + ADIS16460_SCAN_TEMP, +}; + +#define ADIS16460_MOD_CHANNEL(_type, _mod, _address, _si, _bits) \ + { \ + .type = (_type), \ + .modified = 1, \ + .channel2 = (_mod), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = (_address), \ + .scan_index = (_si), \ + .scan_type = { \ + .sign = 's', \ + .realbits = (_bits), \ + .storagebits = (_bits), \ + .endianness = IIO_BE, \ + }, \ + } + +#define ADIS16460_GYRO_CHANNEL(_mod) \ + ADIS16460_MOD_CHANNEL(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \ + ADIS16460_REG_ ## _mod ## _GYRO_LOW, ADIS16460_SCAN_GYRO_ ## _mod, \ + 32) + +#define ADIS16460_ACCEL_CHANNEL(_mod) \ + ADIS16460_MOD_CHANNEL(IIO_ACCEL, IIO_MOD_ ## _mod, \ + ADIS16460_REG_ ## _mod ## _ACCL_LOW, ADIS16460_SCAN_ACCEL_ ## _mod, \ + 32) + +#define ADIS16460_TEMP_CHANNEL() { \ + .type = IIO_TEMP, \ + .indexed = 1, \ + .channel = 0, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = ADIS16460_REG_TEMP_OUT, \ + .scan_index = ADIS16460_SCAN_TEMP, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + } + +static const struct iio_chan_spec adis16460_channels[] = { + ADIS16460_GYRO_CHANNEL(X), + ADIS16460_GYRO_CHANNEL(Y), + ADIS16460_GYRO_CHANNEL(Z), + ADIS16460_ACCEL_CHANNEL(X), + ADIS16460_ACCEL_CHANNEL(Y), + ADIS16460_ACCEL_CHANNEL(Z), + ADIS16460_TEMP_CHANNEL(), + IIO_CHAN_SOFT_TIMESTAMP(7) +}; + +static const struct adis16460_chip_info adis16460_chip_info = { + .channels = adis16460_channels, + .num_channels = ARRAY_SIZE(adis16460_channels), + /* + * storing the value in rad/degree and the scale in degree + * gives us the result in rad and better precession than + * storing the scale directly in rad. + */ + .gyro_max_val = IIO_RAD_TO_DEGREE(200 << 16), + .gyro_max_scale = 1, + .accel_max_val = IIO_M_S_2_TO_G(20000 << 16), + .accel_max_scale = 5, +}; + +static const struct iio_info adis16460_info = { + .read_raw = &adis16460_read_raw, + .write_raw = &adis16460_write_raw, + .update_scan_mode = adis_update_scan_mode, + .debugfs_reg_access = adis_debugfs_reg_access, +}; + +static int adis16460_enable_irq(struct adis *adis, bool enable) +{ + /* + * There is no way to gate the data-ready signal internally inside the + * ADIS16460 :( + */ + if (enable) + enable_irq(adis->spi->irq); + else + disable_irq(adis->spi->irq); + + return 0; +} + +static int adis16460_initial_setup(struct iio_dev *indio_dev) +{ + struct adis16460 *st = iio_priv(indio_dev); + uint16_t prod_id; + unsigned int device_id; + int ret; + + adis_reset(&st->adis); + msleep(222); + + ret = adis_write_reg_16(&st->adis, ADIS16460_REG_GLOB_CMD, BIT(1)); + if (ret) + return ret; + msleep(75); + + ret = adis_check_status(&st->adis); + if (ret) + return ret; + + ret = adis_read_reg_16(&st->adis, ADIS16460_REG_PROD_ID, &prod_id); + if (ret) + return ret; + + ret = sscanf(indio_dev->name, "adis%u\n", &device_id); + if (ret != 1) + return -EINVAL; + + if (prod_id != device_id) + dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", + device_id, prod_id); + + return 0; +} + +#define ADIS16460_DIAG_STAT_IN_CLK_OOS 7 +#define ADIS16460_DIAG_STAT_FLASH_MEM 6 +#define ADIS16460_DIAG_STAT_SELF_TEST 5 +#define ADIS16460_DIAG_STAT_OVERRANGE 4 +#define ADIS16460_DIAG_STAT_SPI_COMM 3 +#define ADIS16460_DIAG_STAT_FLASH_UPT 2 + +static const char * const adis16460_status_error_msgs[] = { + [ADIS16460_DIAG_STAT_IN_CLK_OOS] = "Input clock out of sync", + [ADIS16460_DIAG_STAT_FLASH_MEM] = "Flash memory failure", + [ADIS16460_DIAG_STAT_SELF_TEST] = "Self test diagnostic failure", + [ADIS16460_DIAG_STAT_OVERRANGE] = "Sensor overrange", + [ADIS16460_DIAG_STAT_SPI_COMM] = "SPI communication failure", + [ADIS16460_DIAG_STAT_FLASH_UPT] = "Flash update failure", +}; + +static const struct adis_data adis16460_data = { + .diag_stat_reg = ADIS16460_REG_DIAG_STAT, + .glob_cmd_reg = ADIS16460_REG_GLOB_CMD, + .has_paging = false, + .read_delay = 5, + .write_delay = 5, + .cs_change_delay = 16, + .status_error_msgs = adis16460_status_error_msgs, + .status_error_mask = BIT(ADIS16460_DIAG_STAT_IN_CLK_OOS) | + BIT(ADIS16460_DIAG_STAT_FLASH_MEM) | + BIT(ADIS16460_DIAG_STAT_SELF_TEST) | + BIT(ADIS16460_DIAG_STAT_OVERRANGE) | + BIT(ADIS16460_DIAG_STAT_SPI_COMM) | + BIT(ADIS16460_DIAG_STAT_FLASH_UPT), + .enable_irq = adis16460_enable_irq, +}; + +static int adis16460_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct adis16460 *st; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + spi_set_drvdata(spi, indio_dev); + + 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; + indio_dev->info = &adis16460_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = adis_init(&st->adis, indio_dev, spi, &adis16460_data); + if (ret) + return ret; + + ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); + if (ret) + return ret; + + adis16460_enable_irq(&st->adis, 0); + + ret = adis16460_initial_setup(indio_dev); + if (ret) + goto error_cleanup_buffer; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_cleanup_buffer; + + adis16460_debugfs_init(indio_dev); + + return 0; + +error_cleanup_buffer: + adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); + return ret; +} + +static int adis16460_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adis16460 *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); + + return 0; +} + +static const struct spi_device_id adis16460_ids[] = { + { "adis16460", 0 }, + {} +}; +MODULE_DEVICE_TABLE(spi, adis16460_ids); + +static const struct of_device_id adis16460_of_match[] = { + { .compatible = "adi,adis16460" }, + {} +}; +MODULE_DEVICE_TABLE(of, adis16460_of_match); + +static struct spi_driver adis16460_driver = { + .driver = { + .name = "adis16460", + .of_match_table = adis16460_of_match, + }, + .id_table = adis16460_ids, + .probe = adis16460_probe, + .remove = adis16460_remove, +}; +module_spi_driver(adis16460_driver); + +MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>"); +MODULE_DESCRIPTION("Analog Devices ADIS16460 IMU driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index 395f3bd7de0a..e4c4c12236a7 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -14,8 +14,9 @@ config INV_MPU6050_I2C select INV_MPU6050_IIO select REGMAP_I2C help - This driver supports the Invensense MPU6050/6500/9150 and - ICM20608/20602 motion tracking devices over I2C. + This driver supports the Invensense MPU6000/6050/6500/6515, + MPU9150/9250/9255 and ICM20608/20602 motion tracking devices + over I2C. This driver can be built as a module. The module will be called inv-mpu6050-i2c. @@ -25,7 +26,8 @@ config INV_MPU6050_SPI select INV_MPU6050_IIO select REGMAP_SPI help - This driver supports the Invensense MPU6050/6500/9150 and - ICM20608/20602 motion tracking devices over SPI. + This driver supports the Invensense MPU6000/6050/6500/6515, + MPU9150/9250/9255 and ICM20608/20602 motion tracking devices + over SPI. This driver can be built as a module. The module will be called inv-mpu6050-spi. diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 8a704cd5bddb..b17f060b52fc 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -1137,10 +1137,9 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, if (result) return result; - result = devm_add_action(dev, inv_mpu_core_disable_regulator_action, + result = devm_add_action_or_reset(dev, inv_mpu_core_disable_regulator_action, st); if (result) { - inv_mpu_core_disable_regulator_action(st); dev_err(dev, "Failed to setup regulator cleanup action %d\n", result); return result; diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig index 002a423eae52..77aa0e77212d 100644 --- a/drivers/iio/imu/st_lsm6dsx/Kconfig +++ b/drivers/iio/imu/st_lsm6dsx/Kconfig @@ -2,15 +2,17 @@ config IIO_ST_LSM6DSX tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors" - depends on (I2C || SPI) + depends on (I2C || SPI || I3C) select IIO_BUFFER select IIO_KFIFO_BUF select IIO_ST_LSM6DSX_I2C if (I2C) select IIO_ST_LSM6DSX_SPI if (SPI_MASTER) + select IIO_ST_LSM6DSX_I3C if (I3C) help Say yes here to build support for STMicroelectronics LSM6DSx imu sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm, - ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr + ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr, lsm6ds3tr-c, + ism330dhcx and the accelerometer/gyroscope of lsm9ds1. To compile this driver as a module, choose M here: the module will be called st_lsm6dsx. @@ -24,3 +26,8 @@ config IIO_ST_LSM6DSX_SPI tristate depends on IIO_ST_LSM6DSX select REGMAP_SPI + +config IIO_ST_LSM6DSX_I3C + tristate + depends on IIO_ST_LSM6DSX + select REGMAP_I3C diff --git a/drivers/iio/imu/st_lsm6dsx/Makefile b/drivers/iio/imu/st_lsm6dsx/Makefile index 28cc67399d94..57cbcd67d64f 100644 --- a/drivers/iio/imu/st_lsm6dsx/Makefile +++ b/drivers/iio/imu/st_lsm6dsx/Makefile @@ -5,3 +5,4 @@ st_lsm6dsx-y := st_lsm6dsx_core.o st_lsm6dsx_buffer.o \ obj-$(CONFIG_IIO_ST_LSM6DSX) += st_lsm6dsx.o obj-$(CONFIG_IIO_ST_LSM6DSX_I2C) += st_lsm6dsx_i2c.o obj-$(CONFIG_IIO_ST_LSM6DSX_SPI) += st_lsm6dsx_spi.o +obj-$(CONFIG_IIO_ST_LSM6DSX_I3C) += st_lsm6dsx_i3c.o diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index c14bf533b66b..80e42c7dbcbe 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -22,6 +22,9 @@ #define ST_ASM330LHH_DEV_NAME "asm330lhh" #define ST_LSM6DSOX_DEV_NAME "lsm6dsox" #define ST_LSM6DSR_DEV_NAME "lsm6dsr" +#define ST_LSM6DS3TRC_DEV_NAME "lsm6ds3tr-c" +#define ST_ISM330DHCX_DEV_NAME "ism330dhcx" +#define ST_LSM9DS1_DEV_NAME "lsm9ds1-imu" enum st_lsm6dsx_hw_id { ST_LSM6DS3_ID, @@ -33,6 +36,9 @@ enum st_lsm6dsx_hw_id { ST_ASM330LHH_ID, ST_LSM6DSOX_ID, ST_LSM6DSR_ID, + ST_LSM6DS3TRC_ID, + ST_ISM330DHCX_ID, + ST_LSM9DS1_ID, ST_LSM6DSX_MAX_ID, }; @@ -54,8 +60,8 @@ enum st_lsm6dsx_hw_id { .address = addr, \ .modified = 1, \ .channel2 = mod, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ - BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index = scan_idx, \ .scan_type = { \ @@ -71,6 +77,7 @@ struct st_lsm6dsx_reg { u8 mask; }; +struct st_lsm6dsx_sensor; struct st_lsm6dsx_hw; struct st_lsm6dsx_odr { @@ -97,12 +104,14 @@ struct st_lsm6dsx_fs_table_entry { /** * struct st_lsm6dsx_fifo_ops - ST IMU FIFO settings + * @update_fifo: Update FIFO configuration callback. * @read_fifo: Read FIFO callback. * @fifo_th: FIFO threshold register info (addr + mask). * @fifo_diff: FIFO diff status register info (addr + mask). * @th_wl: FIFO threshold word length. */ struct st_lsm6dsx_fifo_ops { + int (*update_fifo)(struct st_lsm6dsx_sensor *sensor, bool enable); int (*read_fifo)(struct st_lsm6dsx_hw *hw); struct { u8 addr; @@ -196,8 +205,14 @@ struct st_lsm6dsx_ext_dev_settings { /** * struct st_lsm6dsx_settings - ST IMU sensor settings * @wai: Sensor WhoAmI default value. + * @int1_addr: Control Register address for INT1 + * @int2_addr: Control Register address for INT2 + * @reset_addr: register address for reset/reboot * @max_fifo_size: Sensor max fifo length in FIFO words. * @id: List of hw id/device name supported by the driver configuration. + * @channels: IIO channels supported by the device. + * @odr_table: Hw sensors odr table (Hz + val). + * @fs_table: Hw sensors gain table (gain + val). * @decimator: List of decimator register info (addr + mask). * @batch: List of FIFO batching register info (addr + mask). * @fifo_ops: Sensor hw FIFO parameters. @@ -206,11 +221,20 @@ struct st_lsm6dsx_ext_dev_settings { */ struct st_lsm6dsx_settings { u8 wai; + u8 int1_addr; + u8 int2_addr; + u8 reset_addr; u16 max_fifo_size; struct { enum st_lsm6dsx_hw_id hw_id; const char *name; } id[ST_LSM6DSX_MAX_ID]; + struct { + const struct iio_chan_spec *chan; + int len; + } channels[2]; + struct st_lsm6dsx_odr_table_entry odr_table[2]; + struct st_lsm6dsx_fs_table_entry fs_table[2]; struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID]; struct st_lsm6dsx_reg batch[ST_LSM6DSX_MAX_ID]; struct st_lsm6dsx_fifo_ops fifo_ops; @@ -314,6 +338,7 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw); int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val); 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); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index e4d8a79d557d..b0f3da1976e4 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -2,10 +2,10 @@ /* * STMicroelectronics st_lsm6dsx FIFO buffer library driver * - * LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC: The FIFO buffer can be - * configured to store data from gyroscope and accelerometer. Samples are - * queued without any tag according to a specific pattern based on - * 'FIFO data sets' (6 bytes each): + * LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: + * The FIFO buffer can be configured to store data from gyroscope and + * accelerometer. Samples are queued without any tag according to a + * specific pattern based on 'FIFO data sets' (6 bytes each): * - 1st data set is reserved for gyroscope data * - 2nd data set is reserved for accelerometer data * The FIFO pattern changes depending on the ODRs and decimation factors @@ -14,9 +14,10 @@ * (e.g. Gx, Gy, Gz, Ax, Ay, Az), then data are repeated depending on the * value of the decimation factor and ODR set for each FIFO data set. * - * LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR: The FIFO buffer can be configured to - * store data from gyroscope and accelerometer. Each sample is queued with - * a tag (1B) indicating data source (gyroscope, accelerometer, hw timer). + * LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: The FIFO buffer can be + * configured to store data from gyroscope and accelerometer. Each sample + * is queued with a tag (1B) indicating data source (gyroscope, accelerometer, + * hw timer). * * FIFO supported modes: * - BYPASS: FIFO disabled @@ -601,9 +602,8 @@ int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw) return err; } -static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable) +int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable) { - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); struct st_lsm6dsx_hw *hw = sensor->hw; int err; @@ -670,17 +670,29 @@ static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) count = hw->settings->fifo_ops.read_fifo(hw); mutex_unlock(&hw->fifo_lock); - return !count ? IRQ_NONE : IRQ_HANDLED; + return count ? IRQ_HANDLED : IRQ_NONE; } static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev) { - return st_lsm6dsx_update_fifo(iio_dev, true); + struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); + struct st_lsm6dsx_hw *hw = sensor->hw; + + if (!hw->settings->fifo_ops.update_fifo) + return -ENOTSUPP; + + return hw->settings->fifo_ops.update_fifo(sensor, true); } static int st_lsm6dsx_buffer_postdisable(struct iio_dev *iio_dev) { - return st_lsm6dsx_update_fifo(iio_dev, false); + struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); + struct st_lsm6dsx_hw *hw = sensor->hw; + + if (!hw->settings->fifo_ops.update_fifo) + return -ENOTSUPP; + + return hw->settings->fifo_ops.update_fifo(sensor, false); } static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = { diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index a6702a74570e..2d3495560136 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -10,6 +10,8 @@ * +-125/+-245/+-500/+-1000/+-2000 dps * LSM6DSx series has an integrated First-In-First-Out (FIFO) buffer * allowing dynamic batching of sensor data. + * LSM9DSx series is similar but includes an additional magnetometer, handled + * by a different driver. * * Supported sensors: * - LSM6DS3: @@ -18,18 +20,25 @@ * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - FIFO size: 8KB * - * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC: + * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - FIFO size: 4KB * - * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR + * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - FIFO size: 3KB * + * - LSM9DS1: + * - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 952 + * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 + * - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 952 + * - Gyroscope supported full-scale [dps]: +-245/+-500/+-2000 + * - FIFO size: 32 + * * Copyright 2016 STMicroelectronics Inc. * * Lorenzo Bianconi <lorenzo.bianconi@st.com> @@ -49,79 +58,110 @@ #include "st_lsm6dsx.h" -#define ST_LSM6DSX_REG_INT1_ADDR 0x0d -#define ST_LSM6DSX_REG_INT2_ADDR 0x0e #define ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK BIT(3) #define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f -#define ST_LSM6DSX_REG_RESET_ADDR 0x12 #define ST_LSM6DSX_REG_RESET_MASK BIT(0) #define ST_LSM6DSX_REG_BOOT_MASK BIT(7) #define ST_LSM6DSX_REG_BDU_ADDR 0x12 #define ST_LSM6DSX_REG_BDU_MASK BIT(6) -#define ST_LSM6DSX_REG_INT2_ON_INT1_ADDR 0x13 -#define ST_LSM6DSX_REG_INT2_ON_INT1_MASK BIT(5) - -#define ST_LSM6DSX_REG_ACC_OUT_X_L_ADDR 0x28 -#define ST_LSM6DSX_REG_ACC_OUT_Y_L_ADDR 0x2a -#define ST_LSM6DSX_REG_ACC_OUT_Z_L_ADDR 0x2c - -#define ST_LSM6DSX_REG_GYRO_OUT_X_L_ADDR 0x22 -#define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24 -#define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR 0x26 - -static const struct st_lsm6dsx_odr_table_entry st_lsm6dsx_odr_table[] = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 13, 0x01 }, - .odr_avl[1] = { 26, 0x02 }, - .odr_avl[2] = { 52, 0x03 }, - .odr_avl[3] = { 104, 0x04 }, - .odr_avl[4] = { 208, 0x05 }, - .odr_avl[5] = { 416, 0x06 }, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 13, 0x01 }, - .odr_avl[1] = { 26, 0x02 }, - .odr_avl[2] = { 52, 0x03 }, - .odr_avl[3] = { 104, 0x04 }, - .odr_avl[4] = { 208, 0x05 }, - .odr_avl[5] = { 416, 0x06 }, - } + +static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0), + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), }; -static const struct st_lsm6dsx_fs_table_entry st_lsm6dsx_fs_table[] = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, - } +static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x22, IIO_MOD_X, 0), + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x24, IIO_MOD_Y, 1), + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x26, IIO_MOD_Z, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), +}; + +static const struct iio_chan_spec st_lsm6ds0_gyro_channels[] = { + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x18, IIO_MOD_X, 0), + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1a, IIO_MOD_Y, 1), + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1c, IIO_MOD_Z, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), }; static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { { + .wai = 0x68, + .int1_addr = 0x0c, + .int2_addr = 0x0d, + .reset_addr = 0x22, + .max_fifo_size = 32, + .id = { + { + .hw_id = ST_LSM9DS1_ID, + .name = ST_LSM9DS1_DEV_NAME, + }, + }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6ds0_gyro_channels, + .len = ARRAY_SIZE(st_lsm6ds0_gyro_channels), + }, + }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x20, + .mask = GENMASK(7, 5), + }, + .odr_avl[0] = { 10, 0x01 }, + .odr_avl[1] = { 50, 0x02 }, + .odr_avl[2] = { 119, 0x03 }, + .odr_avl[3] = { 238, 0x04 }, + .odr_avl[4] = { 476, 0x05 }, + .odr_avl[5] = { 952, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 5), + }, + .odr_avl[0] = { 15, 0x01 }, + .odr_avl[1] = { 60, 0x02 }, + .odr_avl[2] = { 119, 0x03 }, + .odr_avl[3] = { 238, 0x04 }, + .odr_avl[4] = { 476, 0x05 }, + .odr_avl[5] = { 952, 0x06 }, + }, + }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x20, + .mask = GENMASK(4, 3), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(732), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(4, 3), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(245), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(2000), 0x3 }, + }, + }, + }, + { .wai = 0x69, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 1365, .id = { { @@ -129,6 +169,64 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DS3_DEV_NAME, }, }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + }, + }, .decimator = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x08, @@ -140,6 +238,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_fifo, .fifo_th = { .addr = 0x06, @@ -172,6 +271,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .wai = 0x69, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 682, .id = { { @@ -179,6 +281,64 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DS3H_DEV_NAME, }, }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + }, + }, .decimator = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x08, @@ -190,6 +350,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_fifo, .fifo_th = { .addr = 0x06, @@ -222,6 +383,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .wai = 0x6a, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 682, .id = { { @@ -233,6 +397,67 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .hw_id = ST_ISM330DLC_ID, .name = ST_ISM330DLC_DEV_NAME, + }, { + .hw_id = ST_LSM6DS3TRC_ID, + .name = ST_LSM6DS3TRC_DEV_NAME, + }, + }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, }, }, .decimator = { @@ -246,6 +471,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_fifo, .fifo_th = { .addr = 0x06, @@ -278,6 +504,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .wai = 0x6c, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 512, .id = { { @@ -288,6 +517,64 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_LSM6DSOX_DEV_NAME, }, }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + }, + }, .batch = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x09, @@ -299,6 +586,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_tagged_fifo, .fifo_th = { .addr = 0x07, @@ -306,7 +594,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, .fifo_diff = { .addr = 0x3a, - .mask = GENMASK(8, 0), + .mask = GENMASK(9, 0), }, .th_wl = 1, }, @@ -349,6 +637,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .wai = 0x6b, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 512, .id = { { @@ -356,6 +647,64 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .name = ST_ASM330LHH_DEV_NAME, }, }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + }, + }, .batch = { [ST_LSM6DSX_ID_ACC] = { .addr = 0x09, @@ -367,6 +716,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_tagged_fifo, .fifo_th = { .addr = 0x07, @@ -374,7 +724,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, .fifo_diff = { .addr = 0x3a, - .mask = GENMASK(8, 0), + .mask = GENMASK(9, 0), }, .th_wl = 1, }, @@ -391,11 +741,75 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .wai = 0x6b, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 512, .id = { { .hw_id = ST_LSM6DSR_ID, .name = ST_LSM6DSR_DEV_NAME, + }, { + .hw_id = ST_ISM330DHCX_ID, + .name = ST_ISM330DHCX_DEV_NAME, + }, + }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6dsx_gyro_channels, + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), + }, + }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(7, 4), + }, + .odr_avl[0] = { 13, 0x01 }, + .odr_avl[1] = { 26, 0x02 }, + .odr_avl[2] = { 52, 0x03 }, + .odr_avl[3] = { 104, 0x04 }, + .odr_avl[4] = { 208, 0x05 }, + .odr_avl[5] = { 416, 0x06 }, + }, + }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x11, + .mask = GENMASK(3, 2), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, }, }, .batch = { @@ -409,6 +823,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_tagged_fifo, .fifo_th = { .addr = 0x07, @@ -416,7 +831,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, .fifo_diff = { .addr = 0x3a, - .mask = GENMASK(8, 0), + .mask = GENMASK(9, 0), }, .th_wl = 1, }, @@ -459,26 +874,6 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }; -static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { - ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_X_L_ADDR, - IIO_MOD_X, 0), - ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_Y_L_ADDR, - IIO_MOD_Y, 1), - ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_Z_L_ADDR, - IIO_MOD_Z, 2), - IIO_CHAN_SOFT_TIMESTAMP(3), -}; - -static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_X_L_ADDR, - IIO_MOD_X, 0), - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR, - IIO_MOD_Y, 1), - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR, - IIO_MOD_Z, 2), - IIO_CHAN_SOFT_TIMESTAMP(3), -}; - int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable) { const struct st_lsm6dsx_shub_settings *hub_settings; @@ -533,23 +928,22 @@ static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id, static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, u32 gain) { - struct st_lsm6dsx_hw *hw = sensor->hw; - const struct st_lsm6dsx_reg *reg; + const struct st_lsm6dsx_fs_table_entry *fs_table; unsigned int data; int i, err; - u8 val; + fs_table = &sensor->hw->settings->fs_table[sensor->id]; for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) - if (st_lsm6dsx_fs_table[sensor->id].fs_avl[i].gain == gain) + if (fs_table->fs_avl[i].gain == gain) break; if (i == ST_LSM6DSX_FS_LIST_SIZE) return -EINVAL; - val = st_lsm6dsx_fs_table[sensor->id].fs_avl[i].val; - reg = &st_lsm6dsx_fs_table[sensor->id].reg; - data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); - err = st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); + data = ST_LSM6DSX_SHIFT_VAL(fs_table->fs_avl[i].val, + fs_table->reg.mask); + err = st_lsm6dsx_update_bits_locked(sensor->hw, fs_table->reg.addr, + fs_table->reg.mask, data); if (err < 0) return err; @@ -560,20 +954,22 @@ static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr, u8 *val) { + const struct st_lsm6dsx_odr_table_entry *odr_table; int i; + odr_table = &sensor->hw->settings->odr_table[sensor->id]; for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) /* * ext devices can run at different odr respect to * accel sensor */ - if (st_lsm6dsx_odr_table[sensor->id].odr_avl[i].hz >= odr) + if (odr_table->odr_avl[i].hz >= odr) break; if (i == ST_LSM6DSX_ODR_LIST_SIZE) return -EINVAL; - *val = st_lsm6dsx_odr_table[sensor->id].odr_avl[i].val; + *val = odr_table->odr_avl[i].val; return 0; } @@ -638,7 +1034,7 @@ static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 req_odr) return err; } - reg = &st_lsm6dsx_odr_table[ref_sensor->id].reg; + reg = &hw->settings->odr_table[ref_sensor->id].reg; data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); } @@ -783,11 +1179,12 @@ st_lsm6dsx_sysfs_sampling_frequency_avail(struct device *dev, { struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); enum st_lsm6dsx_sensor_id id = sensor->id; + struct st_lsm6dsx_hw *hw = sensor->hw; int i, len = 0; for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", - st_lsm6dsx_odr_table[id].odr_avl[i].hz); + hw->settings->odr_table[id].odr_avl[i].hz); buf[len - 1] = '\n'; return len; @@ -798,12 +1195,19 @@ static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev, char *buf) { struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); + const struct st_lsm6dsx_fs_table_entry *fs_table; enum st_lsm6dsx_sensor_id id = sensor->id; + struct st_lsm6dsx_hw *hw = sensor->hw; int i, len = 0; - for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) + fs_table = &hw->settings->fs_table[id]; + for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) { + if (!fs_table->fs_avl[i].gain) + break; + len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", - st_lsm6dsx_fs_table[id].fs_avl[i].gain); + fs_table->fs_avl[i].gain); + } buf[len - 1] = '\n'; return len; @@ -873,10 +1277,10 @@ static int st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, u8 *drdy_reg) switch (drdy_pin) { case 1: - *drdy_reg = ST_LSM6DSX_REG_INT1_ADDR; + *drdy_reg = hw->settings->int1_addr; break; case 2: - *drdy_reg = ST_LSM6DSX_REG_INT2_ADDR; + *drdy_reg = hw->settings->int2_addr; break; default: dev_err(hw->dev, "unsupported data ready pin\n"); @@ -976,7 +1380,7 @@ static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw) int err; /* device sw reset */ - err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_RESET_ADDR, + err = regmap_update_bits(hw->regmap, hw->settings->reset_addr, ST_LSM6DSX_REG_RESET_MASK, FIELD_PREP(ST_LSM6DSX_REG_RESET_MASK, 1)); if (err < 0) @@ -985,7 +1389,7 @@ static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw) msleep(50); /* reload trimming parameter */ - err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_RESET_ADDR, + err = regmap_update_bits(hw->regmap, hw->settings->reset_addr, ST_LSM6DSX_REG_BOOT_MASK, FIELD_PREP(ST_LSM6DSX_REG_BOOT_MASK, 1)); if (err < 0) @@ -1033,28 +1437,24 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, 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; sensor = iio_priv(iio_dev); sensor->id = id; sensor->hw = hw; - sensor->odr = st_lsm6dsx_odr_table[id].odr_avl[0].hz; - sensor->gain = st_lsm6dsx_fs_table[id].fs_avl[0].gain; + sensor->odr = hw->settings->odr_table[id].odr_avl[0].hz; + sensor->gain = hw->settings->fs_table[id].fs_avl[0].gain; sensor->watermark = 1; switch (id) { case ST_LSM6DSX_ID_ACC: - iio_dev->channels = st_lsm6dsx_acc_channels; - iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_acc_channels); iio_dev->info = &st_lsm6dsx_acc_info; - scnprintf(sensor->name, sizeof(sensor->name), "%s_accel", name); break; case ST_LSM6DSX_ID_GYRO: - iio_dev->channels = st_lsm6dsx_gyro_channels; - iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_gyro_channels); iio_dev->info = &st_lsm6dsx_gyro_info; - scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro", name); break; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index b3211e0ac07b..f52511059545 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -75,6 +75,18 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { .compatible = "st,lsm6dsr", .data = (void *)ST_LSM6DSR_ID, }, + { + .compatible = "st,lsm6ds3tr-c", + .data = (void *)ST_LSM6DS3TRC_ID, + }, + { + .compatible = "st,ism330dhcx", + .data = (void *)ST_ISM330DHCX_ID, + }, + { + .compatible = "st,lsm9ds1-imu", + .data = (void *)ST_LSM9DS1_ID, + }, {}, }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); @@ -89,6 +101,9 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, + { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, + { ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID }, + { ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID }, {}, }; MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c new file mode 100644 index 000000000000..57e633121bdc --- /dev/null +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. + * + * Author: Vitor Soares <vitor.soares@synopsys.com> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/i3c/device.h> +#include <linux/i3c/master.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/regmap.h> + +#include "st_lsm6dsx.h" + +static const struct i3c_device_id st_lsm6dsx_i3c_ids[] = { + I3C_DEVICE(0x0104, 0x006C, (void *)ST_LSM6DSO_ID), + I3C_DEVICE(0x0104, 0x006B, (void *)ST_LSM6DSR_ID), + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(i3c, st_lsm6dsx_i3c_ids); + +static int st_lsm6dsx_i3c_probe(struct i3c_device *i3cdev) +{ + struct regmap_config st_lsm6dsx_i3c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + }; + const struct i3c_device_id *id = i3c_device_match_id(i3cdev, + st_lsm6dsx_i3c_ids); + struct regmap *regmap; + + regmap = devm_regmap_init_i3c(i3cdev, &st_lsm6dsx_i3c_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&i3cdev->dev, "Failed to register i3c regmap %d\n", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return st_lsm6dsx_probe(&i3cdev->dev, 0, (uintptr_t)id->data, regmap); +} + +static struct i3c_driver st_lsm6dsx_driver = { + .driver = { + .name = "st_lsm6dsx_i3c", + .pm = &st_lsm6dsx_pm_ops, + }, + .probe = st_lsm6dsx_i3c_probe, + .id_table = st_lsm6dsx_i3c_ids, +}; +module_i3c_driver(st_lsm6dsx_driver); + +MODULE_AUTHOR("Vitor Soares <vitor.soares@synopsys.com>"); +MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx i3c driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c index c9d3c4711018..344b28dddebb 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c @@ -75,6 +75,18 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = { .compatible = "st,lsm6dsr", .data = (void *)ST_LSM6DSR_ID, }, + { + .compatible = "st,lsm6ds3tr-c", + .data = (void *)ST_LSM6DS3TRC_ID, + }, + { + .compatible = "st,ism330dhcx", + .data = (void *)ST_ISM330DHCX_ID, + }, + { + .compatible = "st,lsm9ds1-imu", + .data = (void *)ST_LSM9DS1_ID, + }, {}, }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match); @@ -89,6 +101,9 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = { { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, + { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, + { ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID }, + { ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID }, {}, }; MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table); diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index e3fd00b595d0..08d7e1ef2186 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -303,6 +303,7 @@ config MAX44000 config MAX44009 tristate "MAX44009 Ambient Light Sensor" depends on I2C + select REGMAP_I2C help Say Y here if you want to build support for Maxim Integrated's MAX44009 ambient light sensor device. @@ -310,6 +311,16 @@ config MAX44009 To compile this driver as a module, choose M here: the module will be called max44009. +config NOA1305 + tristate "ON Semiconductor NOA1305 ambient light sensor" + depends on I2C + help + Say Y here if you want to build support for the ON Semiconductor + NOA1305 ambient light sensor. + + To compile this driver as a module, choose M here: + The module will be called noa1305. + config OPT3001 tristate "Texas Instruments OPT3001 Light Sensor" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index e40794fbb435..00d1f9b98f39 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_LTR501) += ltr501.o obj-$(CONFIG_LV0104CS) += lv0104cs.o obj-$(CONFIG_MAX44000) += max44000.o obj-$(CONFIG_MAX44009) += max44009.o +obj-$(CONFIG_NOA1305) += noa1305.o obj-$(CONFIG_OPT3001) += opt3001.o obj-$(CONFIG_PA12203001) += pa12203001.o obj-$(CONFIG_RPR0521) += rpr0521.o diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c index b09b8b60bd83..c5dfb9a6b5a1 100644 --- a/drivers/iio/light/apds9960.c +++ b/drivers/iio/light/apds9960.c @@ -1135,5 +1135,5 @@ static struct i2c_driver apds9960_driver = { module_i2c_driver(apds9960_driver); MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>"); -MODULE_DESCRIPTION("ADPS9960 Gesture/RGB/ALS/Proximity sensor"); +MODULE_DESCRIPTION("APDS9960 Gesture/RGB/ALS/Proximity sensor"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c index 50f3438c2b49..0443861ba1ec 100644 --- a/drivers/iio/light/cm3323.c +++ b/drivers/iio/light/cm3323.c @@ -101,15 +101,16 @@ static int cm3323_init(struct iio_dev *indio_dev) return 0; } -static void cm3323_disable(struct iio_dev *indio_dev) +static void cm3323_disable(void *data) { int ret; - struct cm3323_data *data = iio_priv(indio_dev); + struct iio_dev *indio_dev = data; + struct cm3323_data *cm_data = iio_priv(indio_dev); - ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, + ret = i2c_smbus_write_word_data(cm_data->client, CM3323_CMD_CONF, CM3323_CONF_SD_BIT); if (ret < 0) - dev_err(&data->client->dev, "Error writing reg_conf\n"); + dev_err(&cm_data->client->dev, "Error writing reg_conf\n"); } static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2) @@ -243,26 +244,11 @@ static int cm3323_probe(struct i2c_client *client, return ret; } - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&client->dev, "failed to register iio dev\n"); - goto err_init; - } - - return 0; -err_init: - cm3323_disable(indio_dev); - return ret; -} - -static int cm3323_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - cm3323_disable(indio_dev); + ret = devm_add_action_or_reset(&client->dev, cm3323_disable, indio_dev); + if (ret < 0) + return ret; - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id cm3323_id[] = { @@ -276,7 +262,6 @@ static struct i2c_driver cm3323_driver = { .name = CM3323_DRV_NAME, }, .probe = cm3323_probe, - .remove = cm3323_remove, .id_table = cm3323_id, }; diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c index 7702c2bcbcfa..1019d625adb1 100644 --- a/drivers/iio/light/cm36651.c +++ b/drivers/iio/light/cm36651.c @@ -646,18 +646,18 @@ static int cm36651_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); cm36651->client = client; - cm36651->ps_client = i2c_new_dummy(client->adapter, + cm36651->ps_client = i2c_new_dummy_device(client->adapter, CM36651_I2C_ADDR_PS); - if (!cm36651->ps_client) { + if (IS_ERR(cm36651->ps_client)) { dev_err(&client->dev, "%s: new i2c device failed\n", __func__); - ret = -ENODEV; + ret = PTR_ERR(cm36651->ps_client); goto error_disable_reg; } - cm36651->ara_client = i2c_new_dummy(client->adapter, CM36651_ARA); - if (!cm36651->ara_client) { + cm36651->ara_client = i2c_new_dummy_device(client->adapter, CM36651_ARA); + if (IS_ERR(cm36651->ara_client)) { dev_err(&client->dev, "%s: new i2c device failed\n", __func__); - ret = -ENODEV; + ret = PTR_ERR(cm36651->ara_client); goto error_i2c_unregister_ps; } diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index 308ee6ff2e22..44313a009928 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -42,7 +42,7 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, struct cros_ec_light_prox_state *st = iio_priv(indio_dev); u16 data = 0; s64 val64; - int ret = IIO_VAL_INT; + int ret; int idx = chan->scan_index; mutex_lock(&st->core.cmd_lock); @@ -50,23 +50,22 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: if (chan->type == IIO_PROXIMITY) { - if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, - (s16 *)&data) < 0) { - ret = -EIO; + ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, + (s16 *)&data); + if (ret) break; - } *val = data; + ret = IIO_VAL_INT; } else { ret = -EINVAL; } break; case IIO_CHAN_INFO_PROCESSED: if (chan->type == IIO_LIGHT) { - if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, - (s16 *)&data) < 0) { - ret = -EIO; + ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, + (s16 *)&data); + if (ret) break; - } /* * The data coming from the light sensor is * pre-processed and represents the ambient light @@ -82,15 +81,16 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; st->core.param.sensor_offset.flags = 0; - if (cros_ec_motion_send_host_cmd(&st->core, 0)) { - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret) break; - } /* Save values */ - st->core.calib[0] = st->core.resp->sensor_offset.offset[0]; + st->core.calib[0].offset = + st->core.resp->sensor_offset.offset[0]; - *val = st->core.calib[idx]; + *val = st->core.calib[idx].offset; + ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_CALIBSCALE: /* @@ -101,10 +101,9 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE; - if (cros_ec_motion_send_host_cmd(&st->core, 0)) { - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret) break; - } val64 = st->core.resp->sensor_range.ret; *val = val64 >> 16; @@ -127,28 +126,27 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev, int val, int val2, long mask) { struct cros_ec_light_prox_state *st = iio_priv(indio_dev); - int ret = 0; + int ret; int idx = chan->scan_index; mutex_lock(&st->core.cmd_lock); switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: - st->core.calib[idx] = val; + st->core.calib[idx].offset = val; /* Send to EC for each axis, even if not complete */ st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; st->core.param.sensor_offset.flags = MOTION_SENSE_SET_OFFSET; - st->core.param.sensor_offset.offset[0] = st->core.calib[0]; + st->core.param.sensor_offset.offset[0] = + st->core.calib[0].offset; st->core.param.sensor_offset.temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - if (cros_ec_motion_send_host_cmd(&st->core, 0)) - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); break; case IIO_CHAN_INFO_CALIBSCALE: st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; st->core.param.sensor_range.data = (val << 16) | (val2 / 100); - if (cros_ec_motion_send_host_cmd(&st->core, 0)) - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); break; default: ret = cros_ec_sensors_core_write(&st->core, chan, val, val2, @@ -164,6 +162,7 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev, static const struct iio_info cros_ec_light_prox_info = { .read_raw = &cros_ec_light_prox_read, .write_raw = &cros_ec_light_prox_write, + .read_avail = &cros_ec_sensors_core_read_avail, }; static int cros_ec_light_prox_probe(struct platform_device *pdev) @@ -198,6 +197,8 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) channel->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | BIT(IIO_CHAN_INFO_FREQUENCY); + channel->info_mask_shared_by_all_available = + BIT(IIO_CHAN_INFO_SAMP_FREQ); channel->scan_type.realbits = CROS_EC_SENSOR_BITS; channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; channel->scan_type.shift = 0; @@ -205,8 +206,6 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) channel->ext_info = cros_ec_sensors_ext_info; channel->scan_type.sign = 'u'; - state->core.calib[0] = 0; - /* Sensor specific */ switch (state->core.type) { case MOTIONSENSE_TYPE_LIGHT: diff --git a/drivers/iio/light/noa1305.c b/drivers/iio/light/noa1305.c new file mode 100644 index 000000000000..5ebfbc52f541 --- /dev/null +++ b/drivers/iio/light/noa1305.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Support for ON Semiconductor NOA1305 ambient light sensor + * + * Copyright (C) 2016 Emcraft Systems + * Copyright (C) 2019 Collabora Ltd. + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> + +#define NOA1305_REG_POWER_CONTROL 0x0 +#define NOA1305_POWER_CONTROL_DOWN 0x00 +#define NOA1305_POWER_CONTROL_ON 0x08 +#define NOA1305_REG_RESET 0x1 +#define NOA1305_RESET_RESET 0x10 +#define NOA1305_REG_INTEGRATION_TIME 0x2 +#define NOA1305_INTEGR_TIME_800MS 0x00 +#define NOA1305_INTEGR_TIME_400MS 0x01 +#define NOA1305_INTEGR_TIME_200MS 0x02 +#define NOA1305_INTEGR_TIME_100MS 0x03 +#define NOA1305_INTEGR_TIME_50MS 0x04 +#define NOA1305_INTEGR_TIME_25MS 0x05 +#define NOA1305_INTEGR_TIME_12_5MS 0x06 +#define NOA1305_INTEGR_TIME_6_25MS 0x07 +#define NOA1305_REG_INT_SELECT 0x3 +#define NOA1305_INT_SEL_ACTIVE_HIGH 0x01 +#define NOA1305_INT_SEL_ACTIVE_LOW 0x02 +#define NOA1305_INT_SEL_INACTIVE 0x03 +#define NOA1305_REG_INT_THRESH_LSB 0x4 +#define NOA1305_REG_INT_THRESH_MSB 0x5 +#define NOA1305_REG_ALS_DATA_LSB 0x6 +#define NOA1305_REG_ALS_DATA_MSB 0x7 +#define NOA1305_REG_DEVICE_ID_LSB 0x8 +#define NOA1305_REG_DEVICE_ID_MSB 0x9 + +#define NOA1305_DEVICE_ID 0x0519 +#define NOA1305_DRIVER_NAME "noa1305" + +struct noa1305_priv { + struct i2c_client *client; + struct regmap *regmap; + struct regulator *vin_reg; +}; + +static int noa1305_measure(struct noa1305_priv *priv) +{ + __le16 data; + int ret; + + ret = regmap_bulk_read(priv->regmap, NOA1305_REG_ALS_DATA_LSB, &data, + 2); + if (ret < 0) + return ret; + + return le16_to_cpu(data); +} + +static int noa1305_scale(struct noa1305_priv *priv, int *val, int *val2) +{ + int data; + int ret; + + ret = regmap_read(priv->regmap, NOA1305_REG_INTEGRATION_TIME, &data); + if (ret < 0) + return ret; + + /* + * Lux = count / (<Integration Constant> * <Integration Time>) + * + * Integration Constant = 7.7 + * Integration Time in Seconds + */ + switch (data) { + case NOA1305_INTEGR_TIME_800MS: + *val = 100; + *val2 = 77 * 8; + break; + case NOA1305_INTEGR_TIME_400MS: + *val = 100; + *val2 = 77 * 4; + break; + case NOA1305_INTEGR_TIME_200MS: + *val = 100; + *val2 = 77 * 2; + break; + case NOA1305_INTEGR_TIME_100MS: + *val = 100; + *val2 = 77; + break; + case NOA1305_INTEGR_TIME_50MS: + *val = 1000; + *val2 = 77 * 5; + break; + case NOA1305_INTEGR_TIME_25MS: + *val = 10000; + *val2 = 77 * 25; + break; + case NOA1305_INTEGR_TIME_12_5MS: + *val = 100000; + *val2 = 77 * 125; + break; + case NOA1305_INTEGR_TIME_6_25MS: + *val = 1000000; + *val2 = 77 * 625; + break; + default: + return -EINVAL; + } + + return IIO_VAL_FRACTIONAL; +} + +static const struct iio_chan_spec noa1305_channels[] = { + { + .type = IIO_LIGHT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + } +}; + +static int noa1305_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret = -EINVAL; + struct noa1305_priv *priv = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_LIGHT: + ret = noa1305_measure(priv); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + default: + break; + } + break; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_LIGHT: + return noa1305_scale(priv, val, val2); + default: + break; + } + break; + default: + break; + } + + return ret; +} + +static const struct iio_info noa1305_info = { + .read_raw = noa1305_read_raw, +}; + +static bool noa1305_writable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case NOA1305_REG_POWER_CONTROL: + case NOA1305_REG_RESET: + case NOA1305_REG_INTEGRATION_TIME: + case NOA1305_REG_INT_SELECT: + case NOA1305_REG_INT_THRESH_LSB: + case NOA1305_REG_INT_THRESH_MSB: + return true; + default: + return false; + } +} + +static const struct regmap_config noa1305_regmap_config = { + .name = NOA1305_DRIVER_NAME, + .reg_bits = 8, + .val_bits = 8, + .max_register = NOA1305_REG_DEVICE_ID_MSB, + .writeable_reg = noa1305_writable_reg, +}; + +static void noa1305_reg_remove(void *data) +{ + struct noa1305_priv *priv = data; + + regulator_disable(priv->vin_reg); +} + +static int noa1305_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct noa1305_priv *priv; + struct iio_dev *indio_dev; + struct regmap *regmap; + __le16 data; + unsigned int dev_id; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + regmap = devm_regmap_init_i2c(client, &noa1305_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Regmap initialization failed.\n"); + return PTR_ERR(regmap); + } + + priv = iio_priv(indio_dev); + + priv->vin_reg = devm_regulator_get(&client->dev, "vin"); + if (IS_ERR(priv->vin_reg)) { + dev_err(&client->dev, "get regulator vin failed\n"); + return PTR_ERR(priv->vin_reg); + } + + ret = regulator_enable(priv->vin_reg); + if (ret) { + dev_err(&client->dev, "enable regulator vin failed\n"); + return ret; + } + + ret = devm_add_action_or_reset(&client->dev, noa1305_reg_remove, priv); + if (ret) { + dev_err(&client->dev, "addition of devm action failed\n"); + return ret; + } + + i2c_set_clientdata(client, indio_dev); + priv->client = client; + priv->regmap = regmap; + + ret = regmap_bulk_read(regmap, NOA1305_REG_DEVICE_ID_LSB, &data, 2); + if (ret < 0) { + dev_err(&client->dev, "ID reading failed: %d\n", ret); + return ret; + } + + dev_id = le16_to_cpu(data); + if (dev_id != NOA1305_DEVICE_ID) { + dev_err(&client->dev, "Unknown device ID: 0x%x\n", dev_id); + return -ENODEV; + } + + ret = regmap_write(regmap, NOA1305_REG_POWER_CONTROL, + NOA1305_POWER_CONTROL_ON); + if (ret < 0) { + dev_err(&client->dev, "Enabling power control failed\n"); + return ret; + } + + ret = regmap_write(regmap, NOA1305_REG_RESET, NOA1305_RESET_RESET); + if (ret < 0) { + dev_err(&client->dev, "Device reset failed\n"); + return ret; + } + + ret = regmap_write(regmap, NOA1305_REG_INTEGRATION_TIME, + NOA1305_INTEGR_TIME_800MS); + if (ret < 0) { + dev_err(&client->dev, "Setting integration time failed\n"); + 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); + indio_dev->name = NOA1305_DRIVER_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = devm_iio_device_register(&client->dev, indio_dev); + if (ret) + dev_err(&client->dev, "registering device failed\n"); + + return ret; +} + +static const struct of_device_id noa1305_of_match[] = { + { .compatible = "onnn,noa1305" }, + { } +}; +MODULE_DEVICE_TABLE(of, noa1305_of_match); + +static const struct i2c_device_id noa1305_ids[] = { + { "noa1305", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, noa1305_ids); + +static struct i2c_driver noa1305_driver = { + .driver = { + .name = NOA1305_DRIVER_NAME, + .of_match_table = noa1305_of_match, + }, + .probe = noa1305_probe, + .id_table = noa1305_ids, +}; + +module_i2c_driver(noa1305_driver); + +MODULE_AUTHOR("Sergei Miroshnichenko <sergeimir@emcraft.com>"); +MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.com"); +MODULE_DESCRIPTION("ON Semiconductor NOA1305 ambient light sensor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index 6579d2418814..982bba0c54e7 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -1261,7 +1261,7 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev) return ret; } - ret = iio_trigger_register(trig); + ret = devm_iio_trigger_register(&client->dev, trig); if (ret) return ret; @@ -1271,16 +1271,6 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev) return 0; } -static void si1145_remove_trigger(struct iio_dev *indio_dev) -{ - struct si1145_data *data = iio_priv(indio_dev); - - if (data->trig) { - iio_trigger_unregister(data->trig); - data->trig = NULL; - } -} - static int si1145_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1332,7 +1322,8 @@ static int si1145_probe(struct i2c_client *client, if (ret < 0) return ret; - ret = iio_triggered_buffer_setup(indio_dev, NULL, + ret = devm_iio_triggered_buffer_setup(&client->dev, + indio_dev, NULL, si1145_trigger_handler, &si1145_buffer_setup_ops); if (ret < 0) return ret; @@ -1340,23 +1331,12 @@ static int si1145_probe(struct i2c_client *client, if (client->irq) { ret = si1145_probe_trigger(indio_dev); if (ret < 0) - goto error_free_buffer; + return ret; } else { dev_info(&client->dev, "no irq, using polling\n"); } - ret = iio_device_register(indio_dev); - if (ret < 0) - goto error_free_trigger; - - return 0; - -error_free_trigger: - si1145_remove_trigger(indio_dev); -error_free_buffer: - iio_triggered_buffer_cleanup(indio_dev); - - return ret; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id si1145_ids[] = { @@ -1371,23 +1351,11 @@ static const struct i2c_device_id si1145_ids[] = { }; MODULE_DEVICE_TABLE(i2c, si1145_ids); -static int si1145_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - si1145_remove_trigger(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - return 0; -} - static struct i2c_driver si1145_driver = { .driver = { .name = "si1145", }, .probe = si1145_probe, - .remove = si1145_remove, .id_table = si1145_ids, }; diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index b955183edfe8..185c24a75ae6 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -679,9 +679,18 @@ static const struct acpi_device_id stk3310_acpi_id[] = { MODULE_DEVICE_TABLE(acpi, stk3310_acpi_id); +static const struct of_device_id stk3310_of_match[] = { + { .compatible = "sensortek,stk3310", }, + { .compatible = "sensortek,stk3311", }, + { .compatible = "sensortek,stk3335", }, + {} +}; +MODULE_DEVICE_TABLE(of, stk3310_of_match); + static struct i2c_driver stk3310_driver = { .driver = { .name = "stk3310", + .of_match_table = stk3310_of_match, .pm = STK3310_PM_OPS, .acpi_match_table = ACPI_PTR(stk3310_acpi_id), }, diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index 83cece921843..be37fcbd4654 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -134,6 +134,12 @@ enum { TSL2772_CHIP_SUSPENDED = 2 }; +enum { + TSL2772_SUPPLY_VDD = 0, + TSL2772_SUPPLY_VDDIO = 1, + TSL2772_NUM_SUPPLIES = 2 +}; + /* Per-device data */ struct tsl2772_als_info { u16 als_ch0; @@ -161,8 +167,7 @@ struct tsl2772_chip { struct mutex prox_mutex; struct mutex als_mutex; struct i2c_client *client; - struct regulator *vdd_supply; - struct regulator *vddio_supply; + struct regulator_bulk_data supplies[TSL2772_NUM_SUPPLIES]; u16 prox_data; struct tsl2772_als_info als_cur_info; struct tsl2772_settings settings; @@ -697,46 +702,7 @@ static void tsl2772_disable_regulators_action(void *_data) { struct tsl2772_chip *chip = _data; - regulator_disable(chip->vdd_supply); - regulator_disable(chip->vddio_supply); -} - -static int tsl2772_enable_regulator(struct tsl2772_chip *chip, - struct regulator *regulator) -{ - int ret; - - ret = regulator_enable(regulator); - if (ret < 0) { - dev_err(&chip->client->dev, "Failed to enable regulator: %d\n", - ret); - return ret; - } - - return 0; -} - -static struct regulator *tsl2772_get_regulator(struct tsl2772_chip *chip, - char *name) -{ - struct regulator *regulator; - int ret; - - regulator = devm_regulator_get(&chip->client->dev, name); - if (IS_ERR(regulator)) { - if (PTR_ERR(regulator) != -EPROBE_DEFER) - dev_err(&chip->client->dev, - "Failed to get %s regulator %d\n", - name, (int)PTR_ERR(regulator)); - - return regulator; - } - - ret = tsl2772_enable_regulator(chip, regulator); - if (ret < 0) - return ERR_PTR(ret); - - return regulator; + regulator_bulk_disable(ARRAY_SIZE(chip->supplies), chip->supplies); } static int tsl2772_chip_on(struct iio_dev *indio_dev) @@ -860,6 +826,13 @@ static int tsl2772_chip_off(struct iio_dev *indio_dev) return tsl2772_write_control_reg(chip, 0x00); } +static void tsl2772_chip_off_action(void *data) +{ + struct iio_dev *indio_dev = data; + + tsl2772_chip_off(indio_dev); +} + /** * tsl2772_invoke_change - power cycle the device to implement the user * parameters @@ -1797,20 +1770,32 @@ static int tsl2772_probe(struct i2c_client *clientp, chip->client = clientp; i2c_set_clientdata(clientp, indio_dev); - chip->vddio_supply = tsl2772_get_regulator(chip, "vddio"); - if (IS_ERR(chip->vddio_supply)) - return PTR_ERR(chip->vddio_supply); + chip->supplies[TSL2772_SUPPLY_VDD].supply = "vdd"; + chip->supplies[TSL2772_SUPPLY_VDDIO].supply = "vddio"; + + ret = devm_regulator_bulk_get(&clientp->dev, + ARRAY_SIZE(chip->supplies), + chip->supplies); + if (ret < 0) { + if (ret != -EPROBE_DEFER) + dev_err(&clientp->dev, + "Failed to get regulators: %d\n", + ret); + + return ret; + } - chip->vdd_supply = tsl2772_get_regulator(chip, "vdd"); - if (IS_ERR(chip->vdd_supply)) { - regulator_disable(chip->vddio_supply); - return PTR_ERR(chip->vdd_supply); + ret = regulator_bulk_enable(ARRAY_SIZE(chip->supplies), chip->supplies); + if (ret < 0) { + dev_err(&clientp->dev, "Failed to enable regulators: %d\n", + ret); + return ret; } - ret = devm_add_action(&clientp->dev, tsl2772_disable_regulators_action, - chip); + ret = devm_add_action_or_reset(&clientp->dev, + tsl2772_disable_regulators_action, + chip); if (ret < 0) { - tsl2772_disable_regulators_action(chip); dev_err(&clientp->dev, "Failed to setup regulator cleanup action %d\n", ret); return ret; @@ -1877,15 +1862,13 @@ static int tsl2772_probe(struct i2c_client *clientp, if (ret < 0) return ret; - ret = iio_device_register(indio_dev); - if (ret) { - tsl2772_chip_off(indio_dev); - dev_err(&clientp->dev, - "%s: iio registration failed\n", __func__); + ret = devm_add_action_or_reset(&clientp->dev, + tsl2772_chip_off_action, + indio_dev); + if (ret < 0) return ret; - } - return 0; + return devm_iio_device_register(&clientp->dev, indio_dev); } static int tsl2772_suspend(struct device *dev) @@ -1895,8 +1878,7 @@ static int tsl2772_suspend(struct device *dev) int ret; ret = tsl2772_chip_off(indio_dev); - regulator_disable(chip->vdd_supply); - regulator_disable(chip->vddio_supply); + regulator_bulk_disable(ARRAY_SIZE(chip->supplies), chip->supplies); return ret; } @@ -1907,32 +1889,15 @@ static int tsl2772_resume(struct device *dev) struct tsl2772_chip *chip = iio_priv(indio_dev); int ret; - ret = tsl2772_enable_regulator(chip, chip->vddio_supply); + ret = regulator_bulk_enable(ARRAY_SIZE(chip->supplies), chip->supplies); if (ret < 0) return ret; - ret = tsl2772_enable_regulator(chip, chip->vdd_supply); - if (ret < 0) { - regulator_disable(chip->vddio_supply); - return ret; - } - usleep_range(TSL2772_BOOT_MIN_SLEEP_TIME, TSL2772_BOOT_MAX_SLEEP_TIME); return tsl2772_chip_on(indio_dev); } -static int tsl2772_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - tsl2772_chip_off(indio_dev); - - iio_device_unregister(indio_dev); - - return 0; -} - static const struct i2c_device_id tsl2772_idtable[] = { { "tsl2571", tsl2571 }, { "tsl2671", tsl2671 }, @@ -1979,7 +1944,6 @@ static struct i2c_driver tsl2772_driver = { }, .id_table = tsl2772_idtable, .probe = tsl2772_probe, - .remove = tsl2772_remove, }; module_i2c_driver(tsl2772_driver); diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c index a3138e1b5803..0be553ad5989 100644 --- a/drivers/iio/light/veml6070.c +++ b/drivers/iio/light/veml6070.c @@ -158,10 +158,10 @@ static int veml6070_probe(struct i2c_client *client, indio_dev->name = VEML6070_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; - data->client2 = i2c_new_dummy(client->adapter, VEML6070_ADDR_DATA_LSB); - if (!data->client2) { + data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB); + if (IS_ERR(data->client2)) { dev_err(&client->dev, "i2c device for second chip address failed\n"); - return -ENODEV; + return PTR_ERR(data->client2); } data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD | diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index 7de10281ad9e..425cdd07b4e5 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -53,7 +53,7 @@ #define MMC35240_CTRL1_BW_SHIFT 0 #define MMC35240_WAIT_CHARGE_PUMP 50000 /* us */ -#define MMC53240_WAIT_SET_RESET 1000 /* us */ +#define MMC35240_WAIT_SET_RESET 1000 /* us */ /* * Memsic OTP process code piece is put here for reference: @@ -225,7 +225,7 @@ static int mmc35240_init(struct mmc35240_data *data) ret = mmc35240_hw_set(data, true); if (ret < 0) return ret; - usleep_range(MMC53240_WAIT_SET_RESET, MMC53240_WAIT_SET_RESET + 1); + usleep_range(MMC35240_WAIT_SET_RESET, MMC35240_WAIT_SET_RESET + 1); ret = mmc35240_hw_set(data, false); if (ret < 0) diff --git a/drivers/iio/magnetometer/st_magn.h b/drivers/iio/magnetometer/st_magn.h index d69ef9b2a731..204b285725c8 100644 --- a/drivers/iio/magnetometer/st_magn.h +++ b/drivers/iio/magnetometer/st_magn.h @@ -22,6 +22,7 @@ #define LIS2MDL_MAGN_DEV_NAME "lis2mdl" #define LSM9DS1_MAGN_DEV_NAME "lsm9ds1_magn" +const struct st_sensor_settings *st_magn_get_settings(const char *name); int st_magn_common_probe(struct iio_dev *indio_dev); void st_magn_common_remove(struct iio_dev *indio_dev); diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c index 11d7806655bc..bb425c167a96 100644 --- a/drivers/iio/magnetometer/st_magn_buffer.c +++ b/drivers/iio/magnetometer/st_magn_buffer.c @@ -32,39 +32,32 @@ 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; - struct st_sensor_data *mdata = iio_priv(indio_dev); - - mdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); - if (mdata->buffer_data == NULL) { - err = -ENOMEM; - goto allocate_memory_error; - } err = iio_triggered_buffer_postenable(indio_dev); if (err < 0) - goto st_magn_buffer_postenable_error; + return err; + + err = st_sensors_set_enable(indio_dev, true); + if (err < 0) + goto st_magn_buffer_predisable; - return st_sensors_set_enable(indio_dev, true); + return 0; -st_magn_buffer_postenable_error: - kfree(mdata->buffer_data); -allocate_memory_error: +st_magn_buffer_predisable: + iio_triggered_buffer_predisable(indio_dev); return err; } static int st_magn_buffer_predisable(struct iio_dev *indio_dev) { - int err; - struct st_sensor_data *mdata = iio_priv(indio_dev); + int err, err2; err = st_sensors_set_enable(indio_dev, false); - if (err < 0) - goto st_magn_buffer_predisable_error; - err = iio_triggered_buffer_predisable(indio_dev); + err2 = iio_triggered_buffer_predisable(indio_dev); + if (!err) + err = err2; -st_magn_buffer_predisable_error: - kfree(mdata->buffer_data); return err; } diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 2f7a1dbcdeb3..a3a268ee2896 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -12,7 +12,6 @@ #include <linux/slab.h> #include <linux/errno.h> #include <linux/types.h> -#include <linux/mutex.h> #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/gpio.h> @@ -470,28 +469,41 @@ static const struct iio_trigger_ops st_magn_trigger_ops = { #define ST_MAGN_TRIGGER_OPS NULL #endif +/* + * st_magn_get_settings() - get sensor settings from device name + * @name: device name buffer reference. + * + * Return: valid reference on success, NULL otherwise. + */ +const struct st_sensor_settings *st_magn_get_settings(const char *name) +{ + int index = st_sensors_get_settings_index(name, + st_magn_sensors_settings, + ARRAY_SIZE(st_magn_sensors_settings)); + if (index < 0) + return NULL; + + return &st_magn_sensors_settings[index]; +} +EXPORT_SYMBOL(st_magn_get_settings); + int st_magn_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *mdata = iio_priv(indio_dev); - int irq = mdata->get_irq_data_ready(indio_dev); int err; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &magn_info; - mutex_init(&mdata->tb.buf_lock); err = st_sensors_power_enable(indio_dev); if (err) return err; - err = st_sensors_check_device_support(indio_dev, - ARRAY_SIZE(st_magn_sensors_settings), - st_magn_sensors_settings); + err = st_sensors_verify_id(indio_dev); if (err < 0) goto st_magn_power_off; mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS; - mdata->multiread_bit = mdata->sensor_settings->multi_read_bit; indio_dev->channels = mdata->sensor_settings->ch; indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; @@ -507,7 +519,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev) if (err < 0) goto st_magn_power_off; - if (irq > 0) { + if (mdata->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, ST_MAGN_TRIGGER_OPS); if (err < 0) @@ -524,7 +536,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev) return 0; st_magn_device_register_error: - if (irq > 0) + if (mdata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_magn_probe_trigger_error: st_magn_deallocate_ring(indio_dev); @@ -542,7 +554,7 @@ void st_magn_common_remove(struct iio_dev *indio_dev) st_sensors_power_disable(indio_dev); iio_device_unregister(indio_dev); - if (mdata->get_irq_data_ready(indio_dev) > 0) + if (mdata->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_magn_deallocate_ring(indio_dev); diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index 4d014fd1aeb0..fdba480a12be 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -55,21 +55,33 @@ MODULE_DEVICE_TABLE(of, st_magn_of_match); #endif static int st_magn_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *mdata; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&client->dev, st_magn_of_match, + client->name, sizeof(client->name)); + + settings = st_magn_get_settings(client->name); + if (!settings) { + dev_err(&client->dev, "device name %s not recognized.\n", + client->name); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mdata)); if (!indio_dev) return -ENOMEM; mdata = iio_priv(indio_dev); - st_sensors_of_name_probe(&client->dev, st_magn_of_match, - client->name, sizeof(client->name)); + mdata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_i2c_configure(indio_dev, client, mdata); + err = st_sensors_i2c_configure(indio_dev, client); + if (err < 0) + return err; err = st_magn_common_probe(indio_dev); if (err < 0) diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index 0d47070611b1..fbf909bde841 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -51,19 +51,31 @@ MODULE_DEVICE_TABLE(of, st_magn_of_match); static int st_magn_spi_probe(struct spi_device *spi) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *mdata; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&spi->dev, st_magn_of_match, + spi->modalias, sizeof(spi->modalias)); + + settings = st_magn_get_settings(spi->modalias); + if (!settings) { + dev_err(&spi->dev, "device name %s not recognized.\n", + spi->modalias); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*mdata)); if (!indio_dev) return -ENOMEM; mdata = iio_priv(indio_dev); + mdata->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_of_name_probe(&spi->dev, st_magn_of_match, - spi->modalias, sizeof(spi->modalias)); - st_sensors_spi_configure(indio_dev, spi, mdata); + err = st_sensors_spi_configure(indio_dev, spi); + if (err < 0) + return err; err = st_magn_common_probe(indio_dev); if (err < 0) diff --git a/drivers/iio/potentiometer/Kconfig b/drivers/iio/potentiometer/Kconfig index ebc7c72a5e36..4cac0173db8b 100644 --- a/drivers/iio/potentiometer/Kconfig +++ b/drivers/iio/potentiometer/Kconfig @@ -26,6 +26,17 @@ config DS1803 To compile this driver as a module, choose M here: the module will be called ds1803. +config MAX5432 + tristate "Maxim MAX5432-MAX5435 Digital Potentiometer driver" + depends on I2C + help + Say yes here to build support for the Maxim + MAX5432, MAX5433, MAX5434 and MAX5435 digital + potentiometer chips. + + To compile this driver as a module, choose M here: the + module will be called max5432. + config MAX5481 tristate "Maxim MAX5481-MAX5484 Digital Potentiometer driver" depends on SPI diff --git a/drivers/iio/potentiometer/Makefile b/drivers/iio/potentiometer/Makefile index 8ff55138cf12..091adf3cdd0b 100644 --- a/drivers/iio/potentiometer/Makefile +++ b/drivers/iio/potentiometer/Makefile @@ -6,6 +6,7 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_AD5272) += ad5272.o obj-$(CONFIG_DS1803) += ds1803.o +obj-$(CONFIG_MAX5432) += max5432.o obj-$(CONFIG_MAX5481) += max5481.o obj-$(CONFIG_MAX5487) += max5487.o obj-$(CONFIG_MCP4018) += mcp4018.o diff --git a/drivers/iio/potentiometer/max5432.c b/drivers/iio/potentiometer/max5432.c new file mode 100644 index 000000000000..641b1821fdf6 --- /dev/null +++ b/drivers/iio/potentiometer/max5432.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Maxim Integrated MAX5432-MAX5435 digital potentiometer driver + * Copyright (C) 2019 Martin Kaiser <martin@kaiser.cx> + * + * Datasheet: + * https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf + */ + +#include <linux/i2c.h> +#include <linux/iio/iio.h> +#include <linux/limits.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> + +/* All chip variants have 32 wiper positions. */ +#define MAX5432_MAX_POS 31 + +#define MAX5432_OHM_50K (50 * 1000) +#define MAX5432_OHM_100K (100 * 1000) + +/* Update the volatile (currently active) setting. */ +#define MAX5432_CMD_VREG 0x11 + +struct max5432_data { + struct i2c_client *client; + unsigned long ohm; +}; + +static const struct iio_chan_spec max5432_channels[] = { + { + .type = IIO_RESISTANCE, + .indexed = 1, + .output = 1, + .channel = 0, + .address = MAX5432_CMD_VREG, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + } +}; + +static int max5432_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct max5432_data *data = iio_priv(indio_dev); + + if (mask != IIO_CHAN_INFO_SCALE) + return -EINVAL; + + if (unlikely(data->ohm > INT_MAX)) + return -ERANGE; + + *val = data->ohm; + *val2 = MAX5432_MAX_POS; + + return IIO_VAL_FRACTIONAL; +} + +static int max5432_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct max5432_data *data = iio_priv(indio_dev); + u8 data_byte; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + if (val < 0 || val > MAX5432_MAX_POS) + return -EINVAL; + + if (val2 != 0) + return -EINVAL; + + /* Wiper position is in bits D7-D3. (D2-D0 are don't care bits.) */ + data_byte = val << 3; + return i2c_smbus_write_byte_data(data->client, chan->address, + data_byte); +} + +static const struct iio_info max5432_info = { + .read_raw = max5432_read_raw, + .write_raw = max5432_write_raw, +}; + +static int max5432_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct iio_dev *indio_dev; + struct max5432_data *data; + + indio_dev = devm_iio_device_alloc(dev, sizeof(struct max5432_data)); + if (!indio_dev) + return -ENOMEM; + + i2c_set_clientdata(client, indio_dev); + + data = iio_priv(indio_dev); + 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); + indio_dev->name = client->name; + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct of_device_id max5432_dt_ids[] = { + { .compatible = "maxim,max5432", .data = (void *)MAX5432_OHM_50K }, + { .compatible = "maxim,max5433", .data = (void *)MAX5432_OHM_100K }, + { .compatible = "maxim,max5434", .data = (void *)MAX5432_OHM_50K }, + { .compatible = "maxim,max5435", .data = (void *)MAX5432_OHM_100K }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, max5432_dt_ids); + +static struct i2c_driver max5432_driver = { + .driver = { + .name = "max5432", + .of_match_table = of_match_ptr(max5432_dt_ids), + }, + .probe = max5432_probe, +}; + +module_i2c_driver(max5432_driver); + +MODULE_AUTHOR("Martin Kaiser <martin@kaiser.cx>"); +MODULE_DESCRIPTION("max5432-max5435 digital potentiometers"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c index 034ce98d6e97..70148624db64 100644 --- a/drivers/iio/pressure/cros_ec_baro.c +++ b/drivers/iio/pressure/cros_ec_baro.c @@ -39,26 +39,29 @@ static int cros_ec_baro_read(struct iio_dev *indio_dev, { struct cros_ec_baro_state *st = iio_priv(indio_dev); u16 data = 0; - int ret = IIO_VAL_INT; + int ret; int idx = chan->scan_index; mutex_lock(&st->core.cmd_lock); switch (mask) { case IIO_CHAN_INFO_RAW: - if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, - (s16 *)&data) < 0) - ret = -EIO; + ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, + (s16 *)&data); + if (ret) + break; + *val = data; + ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE; - if (cros_ec_motion_send_host_cmd(&st->core, 0)) { - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret) break; - } + *val = st->core.resp->sensor_range.ret; /* scale * in_pressure_raw --> kPa */ @@ -152,8 +155,6 @@ static int cros_ec_baro_probe(struct platform_device *pdev) channel->ext_info = cros_ec_sensors_ext_info; channel->scan_type.sign = 'u'; - state->core.calib[0] = 0; - /* Sensor specific */ switch (state->core.type) { case MOTIONSENSE_TYPE_BARO: diff --git a/drivers/iio/pressure/hp03.c b/drivers/iio/pressure/hp03.c index f00102577fd5..026ba15ef68f 100644 --- a/drivers/iio/pressure/hp03.c +++ b/drivers/iio/pressure/hp03.c @@ -243,10 +243,10 @@ static int hp03_probe(struct i2c_client *client, * which has it's dedicated I2C address and contains * the calibration constants for the sensor. */ - priv->eeprom_client = i2c_new_dummy(client->adapter, HP03_EEPROM_ADDR); - if (!priv->eeprom_client) { + priv->eeprom_client = i2c_new_dummy_device(client->adapter, HP03_EEPROM_ADDR); + if (IS_ERR(priv->eeprom_client)) { dev_err(dev, "New EEPROM I2C device failed\n"); - return -ENODEV; + return PTR_ERR(priv->eeprom_client); } priv->eeprom_regmap = regmap_init_i2c(priv->eeprom_client, diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h index 6a720cfb5686..c2e47a6c3118 100644 --- a/drivers/iio/pressure/st_pressure.h +++ b/drivers/iio/pressure/st_pressure.h @@ -41,6 +41,7 @@ static const struct st_sensors_platform_data default_press_pdata = { .drdy_int_pin = 1, }; +const struct st_sensor_settings *st_press_get_settings(const char *name); int st_press_common_probe(struct iio_dev *indio_dev); void st_press_common_remove(struct iio_dev *indio_dev); diff --git a/drivers/iio/pressure/st_pressure_buffer.c b/drivers/iio/pressure/st_pressure_buffer.c index 4566e08a64a1..418dbf9e6e1e 100644 --- a/drivers/iio/pressure/st_pressure_buffer.c +++ b/drivers/iio/pressure/st_pressure_buffer.c @@ -29,52 +29,39 @@ int st_press_trig_set_state(struct iio_trigger *trig, bool state) return st_sensors_set_dataready_irq(indio_dev, state); } -static int st_press_buffer_preenable(struct iio_dev *indio_dev) -{ - return st_sensors_set_enable(indio_dev, true); -} - static int st_press_buffer_postenable(struct iio_dev *indio_dev) { int err; - struct st_sensor_data *press_data = iio_priv(indio_dev); - - press_data->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); - if (press_data->buffer_data == NULL) { - err = -ENOMEM; - goto allocate_memory_error; - } err = iio_triggered_buffer_postenable(indio_dev); if (err < 0) - goto st_press_buffer_postenable_error; + return err; - return err; + err = st_sensors_set_enable(indio_dev, true); + if (err < 0) + goto st_press_buffer_predisable; -st_press_buffer_postenable_error: - kfree(press_data->buffer_data); -allocate_memory_error: + return 0; + +st_press_buffer_predisable: + iio_triggered_buffer_predisable(indio_dev); return err; } static int st_press_buffer_predisable(struct iio_dev *indio_dev) { - int err; - struct st_sensor_data *press_data = iio_priv(indio_dev); - - err = iio_triggered_buffer_predisable(indio_dev); - if (err < 0) - goto st_press_buffer_predisable_error; + int err, err2; err = st_sensors_set_enable(indio_dev, false); -st_press_buffer_predisable_error: - kfree(press_data->buffer_data); + err2 = iio_triggered_buffer_predisable(indio_dev); + if (!err) + err = err2; + return err; } static const struct iio_buffer_setup_ops st_press_buffer_setup_ops = { - .preenable = &st_press_buffer_preenable, .postenable = &st_press_buffer_postenable, .predisable = &st_press_buffer_predisable, }; diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index b960e76f7dfd..ca6863b32a5f 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -12,7 +12,6 @@ #include <linux/slab.h> #include <linux/errno.h> #include <linux/types.h> -#include <linux/mutex.h> #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/gpio.h> @@ -664,25 +663,39 @@ static const struct iio_trigger_ops st_press_trigger_ops = { #define ST_PRESS_TRIGGER_OPS NULL #endif +/* + * st_press_get_settings() - get sensor settings from device name + * @name: device name buffer reference. + * + * Return: valid reference on success, NULL otherwise. + */ +const struct st_sensor_settings *st_press_get_settings(const char *name) +{ + int index = st_sensors_get_settings_index(name, + st_press_sensors_settings, + ARRAY_SIZE(st_press_sensors_settings)); + if (index < 0) + return NULL; + + return &st_press_sensors_settings[index]; +} +EXPORT_SYMBOL(st_press_get_settings); + int st_press_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *press_data = iio_priv(indio_dev); struct st_sensors_platform_data *pdata = (struct st_sensors_platform_data *)press_data->dev->platform_data; - int irq = press_data->get_irq_data_ready(indio_dev); int err; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &press_info; - mutex_init(&press_data->tb.buf_lock); err = st_sensors_power_enable(indio_dev); if (err) return err; - err = st_sensors_check_device_support(indio_dev, - ARRAY_SIZE(st_press_sensors_settings), - st_press_sensors_settings); + err = st_sensors_verify_id(indio_dev); if (err < 0) goto st_press_power_off; @@ -693,7 +706,6 @@ int st_press_common_probe(struct iio_dev *indio_dev) * element. */ press_data->num_data_channels = press_data->sensor_settings->num_ch - 1; - press_data->multiread_bit = press_data->sensor_settings->multi_read_bit; indio_dev->channels = press_data->sensor_settings->ch; indio_dev->num_channels = press_data->sensor_settings->num_ch; @@ -716,7 +728,7 @@ int st_press_common_probe(struct iio_dev *indio_dev) if (err < 0) goto st_press_power_off; - if (irq > 0) { + if (press_data->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, ST_PRESS_TRIGGER_OPS); if (err < 0) @@ -733,7 +745,7 @@ int st_press_common_probe(struct iio_dev *indio_dev) return err; st_press_device_register_error: - if (irq > 0) + if (press_data->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_press_probe_trigger_error: st_press_deallocate_ring(indio_dev); @@ -751,7 +763,7 @@ void st_press_common_remove(struct iio_dev *indio_dev) st_sensors_power_disable(indio_dev); iio_device_unregister(indio_dev); - if (press_data->get_irq_data_ready(indio_dev) > 0) + if (press_data->irq > 0) st_sensors_deallocate_trigger(indio_dev); st_press_deallocate_ring(indio_dev); diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index b7d9ba706abc..71d2ed6b4948 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -78,18 +78,13 @@ static const struct i2c_device_id st_press_id_table[] = { MODULE_DEVICE_TABLE(i2c, st_press_id_table); static int st_press_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *press_data; + struct iio_dev *indio_dev; int ret; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*press_data)); - if (!indio_dev) - return -ENOMEM; - - press_data = iio_priv(indio_dev); - if (client->dev.of_node) { st_sensors_of_name_probe(&client->dev, st_press_of_match, client->name, sizeof(client->name)); @@ -99,11 +94,27 @@ static int st_press_i2c_probe(struct i2c_client *client, return -ENODEV; strlcpy(client->name, st_press_id_table[ret].name, - sizeof(client->name)); + sizeof(client->name)); } else if (!id) return -ENODEV; - st_sensors_i2c_configure(indio_dev, client, press_data); + settings = st_press_get_settings(client->name); + if (!settings) { + dev_err(&client->dev, "device name %s not recognized.\n", + client->name); + return -ENODEV; + } + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*press_data)); + if (!indio_dev) + return -ENOMEM; + + press_data = iio_priv(indio_dev); + press_data->sensor_settings = (struct st_sensor_settings *)settings; + + ret = st_sensors_i2c_configure(indio_dev, client); + if (ret < 0) + return ret; ret = st_press_common_probe(indio_dev); if (ret < 0) diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index ef61401c41d3..7c8b70221e70 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -61,19 +61,31 @@ MODULE_DEVICE_TABLE(of, st_press_of_match); static int st_press_spi_probe(struct spi_device *spi) { - struct iio_dev *indio_dev; + const struct st_sensor_settings *settings; struct st_sensor_data *press_data; + struct iio_dev *indio_dev; int err; + st_sensors_of_name_probe(&spi->dev, st_press_of_match, + spi->modalias, sizeof(spi->modalias)); + + settings = st_press_get_settings(spi->modalias); + if (!settings) { + dev_err(&spi->dev, "device name %s not recognized.\n", + spi->modalias); + return -ENODEV; + } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*press_data)); - if (indio_dev == NULL) + if (!indio_dev) return -ENOMEM; press_data = iio_priv(indio_dev); + press_data->sensor_settings = (struct st_sensor_settings *)settings; - st_sensors_of_name_probe(&spi->dev, st_press_of_match, - spi->modalias, sizeof(spi->modalias)); - st_sensors_spi_configure(indio_dev, spi, press_data); + err = st_sensors_spi_configure(indio_dev, spi); + if (err < 0) + return err; err = st_press_common_probe(indio_dev); if (err < 0) diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index 6b5cce6f1a7b..d53601447da4 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -62,7 +62,7 @@ config RFD77402 tristate "RFD77402 ToF sensor" depends on I2C help - Say Y to build a driver for the RFD77420 Time-of-Flight (distance) + Say Y to build a driver for the RFD77402 Time-of-Flight (distance) sensor module with I2C interface. To compile this driver as a module, choose M here: the diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c index c613a64c017f..2ab68282d0b6 100644 --- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -230,31 +230,13 @@ static int maxim_thermocouple_probe(struct spi_device *spi) data->spi = spi; data->chip = chip; - ret = iio_triggered_buffer_setup(indio_dev, NULL, + ret = devm_iio_triggered_buffer_setup(&spi->dev, + indio_dev, NULL, maxim_thermocouple_trigger_handler, NULL); if (ret) return ret; - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_buffer; - - return 0; - -error_unreg_buffer: - iio_triggered_buffer_cleanup(indio_dev); - - return ret; -} - -static int maxim_thermocouple_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id maxim_thermocouple_id[] = { @@ -277,7 +259,6 @@ static struct spi_driver maxim_thermocouple_driver = { .of_match_table = maxim_thermocouple_of_match, }, .probe = maxim_thermocouple_probe, - .remove = maxim_thermocouple_remove, .id_table = maxim_thermocouple_id, }; module_spi_driver(maxim_thermocouple_driver); diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index ccf1ce653b25..a5dfe65cd9b9 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -608,86 +608,6 @@ static const struct iio_enum stm32_enable_mode_enum = { .get = stm32_get_enable_mode }; -static const char *const stm32_quadrature_modes[] = { - "channel_A", - "channel_B", - "quadrature", -}; - -static int stm32_set_quadrature_mode(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - unsigned int mode) -{ - struct stm32_timer_trigger *priv = iio_priv(indio_dev); - - regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, mode + 1); - - return 0; -} - -static int stm32_get_quadrature_mode(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan) -{ - struct stm32_timer_trigger *priv = iio_priv(indio_dev); - u32 smcr; - int mode; - - regmap_read(priv->regmap, TIM_SMCR, &smcr); - mode = (smcr & TIM_SMCR_SMS) - 1; - if ((mode < 0) || (mode > ARRAY_SIZE(stm32_quadrature_modes))) - return -EINVAL; - - return mode; -} - -static const struct iio_enum stm32_quadrature_mode_enum = { - .items = stm32_quadrature_modes, - .num_items = ARRAY_SIZE(stm32_quadrature_modes), - .set = stm32_set_quadrature_mode, - .get = stm32_get_quadrature_mode -}; - -static const char *const stm32_count_direction_states[] = { - "up", - "down" -}; - -static int stm32_set_count_direction(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - unsigned int dir) -{ - struct stm32_timer_trigger *priv = iio_priv(indio_dev); - u32 val; - int mode; - - /* In encoder mode, direction is RO (given by TI1/TI2 signals) */ - regmap_read(priv->regmap, TIM_SMCR, &val); - mode = (val & TIM_SMCR_SMS) - 1; - if ((mode >= 0) || (mode < ARRAY_SIZE(stm32_quadrature_modes))) - return -EBUSY; - - return regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_DIR, - dir ? TIM_CR1_DIR : 0); -} - -static int stm32_get_count_direction(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan) -{ - struct stm32_timer_trigger *priv = iio_priv(indio_dev); - u32 cr1; - - regmap_read(priv->regmap, TIM_CR1, &cr1); - - return ((cr1 & TIM_CR1_DIR) ? 1 : 0); -} - -static const struct iio_enum stm32_count_direction_enum = { - .items = stm32_count_direction_states, - .num_items = ARRAY_SIZE(stm32_count_direction_states), - .set = stm32_set_count_direction, - .get = stm32_get_count_direction -}; - static ssize_t stm32_count_get_preset(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, @@ -728,10 +648,6 @@ static const struct iio_chan_spec_ext_info stm32_trigger_count_info[] = { .read = stm32_count_get_preset, .write = stm32_count_set_preset }, - IIO_ENUM("count_direction", IIO_SEPARATE, &stm32_count_direction_enum), - IIO_ENUM_AVAILABLE("count_direction", &stm32_count_direction_enum), - IIO_ENUM("quadrature_mode", IIO_SEPARATE, &stm32_quadrature_mode_enum), - IIO_ENUM_AVAILABLE("quadrature_mode", &stm32_quadrature_mode_enum), IIO_ENUM("enable_mode", IIO_SEPARATE, &stm32_enable_mode_enum), IIO_ENUM_AVAILABLE("enable_mode", &stm32_enable_mode_enum), IIO_ENUM("trigger_mode", IIO_SEPARATE, &stm32_trigger_mode_enum), diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index cf419d9c942d..b9c7f0dc653b 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -112,8 +112,6 @@ source "drivers/staging/gasket/Kconfig" source "drivers/staging/axis-fifo/Kconfig" -source "drivers/staging/erofs/Kconfig" - source "drivers/staging/fieldbus/Kconfig" source "drivers/staging/kpc2000/Kconfig" @@ -123,4 +121,6 @@ source "drivers/staging/isdn/Kconfig" source "drivers/staging/wusbcore/Kconfig" source "drivers/staging/uwb/Kconfig" +source "drivers/staging/exfat/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 38179bc842a8..4b5962006c4b 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -46,9 +46,9 @@ obj-$(CONFIG_DMA_RALINK) += ralink-gdma/ obj-$(CONFIG_SOC_MT7621) += mt7621-dts/ obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ -obj-$(CONFIG_EROFS_FS) += erofs/ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ obj-$(CONFIG_KPC2000) += kpc2000/ obj-$(CONFIG_ISDN_CAPI) += isdn/ obj-$(CONFIG_UWB) += uwb/ obj-$(CONFIG_USB_WUSB) += wusbcore/ +obj-$(CONFIG_EXFAT_FS) += exfat/ diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO index fbf015cc6d62..767dd98fd92d 100644 --- a/drivers/staging/android/TODO +++ b/drivers/staging/android/TODO @@ -6,8 +6,6 @@ TODO: ion/ - - Add dt-bindings for remaining heaps (chunk and carveout heaps). This would - involve putting appropriate bindings in a memory node for Ion to find. - Split /dev/ion up into multiple nodes (e.g. /dev/ion/heap0) - Better test framework (integration with VGEM was suggested) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 92c2914239e3..e6b1ca141b93 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -30,32 +30,6 @@ static struct ion_device *internal_dev; static int heap_id; /* this function should only be called while dev->lock is held */ -static void ion_buffer_add(struct ion_device *dev, - struct ion_buffer *buffer) -{ - struct rb_node **p = &dev->buffers.rb_node; - struct rb_node *parent = NULL; - struct ion_buffer *entry; - - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_buffer, node); - - if (buffer < entry) { - p = &(*p)->rb_left; - } else if (buffer > entry) { - p = &(*p)->rb_right; - } else { - pr_err("%s: buffer already found.", __func__); - BUG(); - } - } - - rb_link_node(&buffer->node, parent, p); - rb_insert_color(&buffer->node, &dev->buffers); -} - -/* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct ion_device *dev, unsigned long len, @@ -100,9 +74,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, INIT_LIST_HEAD(&buffer->attachments); mutex_init(&buffer->lock); - mutex_lock(&dev->buffer_lock); - ion_buffer_add(dev, buffer); - mutex_unlock(&dev->buffer_lock); return buffer; err1: @@ -131,11 +102,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer) static void _ion_buffer_destroy(struct ion_buffer *buffer) { struct ion_heap *heap = buffer->heap; - struct ion_device *dev = buffer->dev; - - mutex_lock(&dev->buffer_lock); - rb_erase(&buffer->node, &dev->buffers); - mutex_unlock(&dev->buffer_lock); if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) ion_heap_freelist_add(heap, buffer); @@ -694,8 +660,6 @@ static int ion_device_create(void) } idev->debug_root = debugfs_create_dir("ion", NULL); - idev->buffers = RB_ROOT; - mutex_init(&idev->buffer_lock); init_rwsem(&idev->lock); plist_head_init(&idev->heaps); internal_dev = idev; diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index e291299fd35f..74914a266e25 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -23,7 +23,6 @@ /** * struct ion_buffer - metadata for a particular buffer - * @node: node in the ion_device buffers tree * @list: element in list of deferred freeable buffers * @dev: back pointer to the ion_device * @heap: back pointer to the heap the buffer came from @@ -39,10 +38,7 @@ * @attachments: list of devices attached to this buffer */ struct ion_buffer { - union { - struct rb_node node; - struct list_head list; - }; + struct list_head list; struct ion_device *dev; struct ion_heap *heap; unsigned long flags; @@ -61,14 +57,10 @@ void ion_buffer_destroy(struct ion_buffer *buffer); /** * struct ion_device - the metadata of the ion device node * @dev: the actual misc device - * @buffers: an rb tree of all the existing buffers - * @buffer_lock: lock protecting the tree of buffers * @lock: rwsem protecting the tree of heaps and clients */ struct ion_device { struct miscdevice dev; - struct rb_root buffers; - struct mutex buffer_lock; struct rw_semaphore lock; struct plist_head heaps; struct dentry *debug_root; diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index aabcda3f9fc8..28603dfadce2 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -665,11 +665,6 @@ static void db2k_initialize_adc(struct comedi_device *dev) db2k_initialize_tmrs(dev); } -static void db2k_initialize_dac(struct comedi_device *dev) -{ - db2k_dac_disarm(dev); -} - static int db2k_8255_cb(struct comedi_device *dev, int dir, int port, int data, unsigned long iobase) { @@ -719,7 +714,7 @@ static int db2k_auto_attach(struct comedi_device *dev, unsigned long context) return result; db2k_initialize_adc(dev); - db2k_initialize_dac(dev); + db2k_dac_disarm(dev); s = &dev->subdevices[0]; /* ai subdevice */ diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index c175227009f1..f98e3ae27bff 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -596,7 +596,7 @@ static int ni_request_ao_mite_channel(struct comedi_device *dev) if (!mite_chan) { spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); dev_err(dev->class_dev, - "failed to reserve mite dma channel for analog outut\n"); + "failed to reserve mite dma channel for analog output\n"); return -EBUSY; } mite_chan->dir = COMEDI_OUTPUT; diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 3cc40d2544be..54d7605e909f 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1074,7 +1074,7 @@ static int usbduxsigma_pwm_period(struct comedi_device *dev, unsigned int period) { struct usbduxsigma_private *devpriv = dev->private; - int fx2delay = 255; + int fx2delay; if (period < MIN_PWM_PERIOD) return -EAGAIN; diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index 4f3c2c13a225..147481bf680c 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -165,7 +165,7 @@ static void _nbu2ss_create_ep0_packet(struct nbu2ss_udc *udc, udc->ep0_req.req.buf = p_buf; udc->ep0_req.req.length = length; udc->ep0_req.req.dma = 0; - udc->ep0_req.req.zero = TRUE; + udc->ep0_req.req.zero = true; udc->ep0_req.req.complete = _nbu2ss_ep0_complete; udc->ep0_req.req.status = -EINPROGRESS; udc->ep0_req.req.context = udc; @@ -668,7 +668,7 @@ static int _nbu2ss_ep0_in_transfer(struct nbu2ss_udc *udc, if ((req->req.actual % EP0_PACKETSIZE) == 0) { if (req->zero) { req->zero = false; - EP0_send_NULL(udc, FALSE); + EP0_send_NULL(udc, false); return 1; } } @@ -695,7 +695,7 @@ static int _nbu2ss_ep0_in_transfer(struct nbu2ss_udc *udc, i_remain_size -= result; if (i_remain_size == 0) { - EP0_send_NULL(udc, FALSE); + EP0_send_NULL(udc, false); return result; } @@ -754,7 +754,7 @@ static int _nbu2ss_ep0_out_transfer(struct nbu2ss_udc *udc, if ((req->req.actual % EP0_PACKETSIZE) == 0) { if (req->zero) { req->zero = false; - EP0_receive_NULL(udc, FALSE); + EP0_receive_NULL(udc, false); return 1; } } @@ -799,7 +799,7 @@ static int _nbu2ss_out_dma(struct nbu2ss_udc *udc, struct nbu2ss_req *req, if (req->dma_flag) return 1; /* DMA is forwarded */ - req->dma_flag = TRUE; + req->dma_flag = true; p_buffer = req->req.dma; p_buffer += req->req.actual; @@ -997,7 +997,7 @@ static int _nbu2ss_in_dma(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep, if (req->req.actual == 0) _nbu2ss_dma_map_single(udc, ep, req, USB_DIR_IN); #endif - req->dma_flag = TRUE; + req->dma_flag = true; /* MAX Packet Size */ mpkt = _nbu2ss_readl(&preg->EP_REGS[num].EP_PCKT_ADRS) & EPN_MPKT; @@ -1166,7 +1166,7 @@ static int _nbu2ss_start_transfer(struct nbu2ss_udc *udc, { int nret = -EINVAL; - req->dma_flag = FALSE; + req->dma_flag = false; req->div_len = 0; if (req->req.length == 0) { @@ -1190,7 +1190,7 @@ static int _nbu2ss_start_transfer(struct nbu2ss_udc *udc, break; case EP0_IN_STATUS_PHASE: - nret = EP0_send_NULL(udc, TRUE); + nret = EP0_send_NULL(udc, true); break; default: @@ -1216,7 +1216,7 @@ static int _nbu2ss_start_transfer(struct nbu2ss_udc *udc, static void _nbu2ss_restert_transfer(struct nbu2ss_ep *ep) { u32 length; - bool bflag = FALSE; + bool bflag = false; struct nbu2ss_req *req; req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); @@ -1229,7 +1229,7 @@ static void _nbu2ss_restert_transfer(struct nbu2ss_ep *ep) length &= EPN_LDATA; if (length < ep->ep.maxpacket) - bflag = TRUE; + bflag = true; } _nbu2ss_start_transfer(ep->udc, ep, req, bflag); @@ -1280,7 +1280,7 @@ static void _nbu2ss_set_endpoint_stall(struct nbu2ss_udc *udc, if (bstall) { /* Set STALL */ - ep->halted = TRUE; + ep->halted = true; if (ep_adrs & USB_DIR_IN) data = EPN_BCLR | EPN_ISTL; @@ -1290,7 +1290,7 @@ static void _nbu2ss_set_endpoint_stall(struct nbu2ss_udc *udc, _nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, data); } else { /* Clear STALL */ - ep->stalled = FALSE; + ep->stalled = false; if (ep_adrs & USB_DIR_IN) { _nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL , EPN_ISTL); @@ -1305,9 +1305,9 @@ static void _nbu2ss_set_endpoint_stall(struct nbu2ss_udc *udc, , data); } - ep->stalled = FALSE; + ep->stalled = false; if (ep->halted) { - ep->halted = FALSE; + ep->halted = false; _nbu2ss_restert_transfer(ep); } } @@ -1533,13 +1533,13 @@ static int std_req_get_status(struct nbu2ss_udc *udc) /*-------------------------------------------------------------------------*/ static int std_req_clear_feature(struct nbu2ss_udc *udc) { - return _nbu2ss_req_feature(udc, FALSE); + return _nbu2ss_req_feature(udc, false); } /*-------------------------------------------------------------------------*/ static int std_req_set_feature(struct nbu2ss_udc *udc) { - return _nbu2ss_req_feature(udc, TRUE); + return _nbu2ss_req_feature(udc, true); } /*-------------------------------------------------------------------------*/ @@ -1601,7 +1601,7 @@ static inline void _nbu2ss_read_request_data(struct nbu2ss_udc *udc, u32 *pdata) /*-------------------------------------------------------------------------*/ static inline int _nbu2ss_decode_request(struct nbu2ss_udc *udc) { - bool bcall_back = TRUE; + bool bcall_back = true; int nret = -EINVAL; struct usb_ctrlrequest *p_ctrl; @@ -1623,22 +1623,22 @@ static inline int _nbu2ss_decode_request(struct nbu2ss_udc *udc) switch (p_ctrl->bRequest) { case USB_REQ_GET_STATUS: nret = std_req_get_status(udc); - bcall_back = FALSE; + bcall_back = false; break; case USB_REQ_CLEAR_FEATURE: nret = std_req_clear_feature(udc); - bcall_back = FALSE; + bcall_back = false; break; case USB_REQ_SET_FEATURE: nret = std_req_set_feature(udc); - bcall_back = FALSE; + bcall_back = false; break; case USB_REQ_SET_ADDRESS: nret = std_req_set_address(udc); - bcall_back = FALSE; + bcall_back = false; break; case USB_REQ_SET_CONFIGURATION: @@ -1655,7 +1655,7 @@ static inline int _nbu2ss_decode_request(struct nbu2ss_udc *udc) if (nret >= 0) { /*--------------------------------------*/ /* Status Stage */ - nret = EP0_send_NULL(udc, TRUE); + nret = EP0_send_NULL(udc, true); } } @@ -1688,7 +1688,7 @@ static inline int _nbu2ss_ep0_in_data_stage(struct nbu2ss_udc *udc) nret = _nbu2ss_ep0_in_transfer(udc, req); if (nret == 0) { udc->ep0state = EP0_OUT_STATUS_PAHSE; - EP0_receive_NULL(udc, TRUE); + EP0_receive_NULL(udc, true); } return 0; @@ -1708,7 +1708,7 @@ static inline int _nbu2ss_ep0_out_data_stage(struct nbu2ss_udc *udc) nret = _nbu2ss_ep0_out_transfer(udc, req); if (nret == 0) { udc->ep0state = EP0_IN_STATUS_PHASE; - EP0_send_NULL(udc, TRUE); + EP0_send_NULL(udc, true); } else if (nret < 0) { _nbu2ss_bitset(&udc->p_regs->EP0_CONTROL, EP0_BCLR); @@ -1817,7 +1817,7 @@ static inline void _nbu2ss_ep0_int(struct nbu2ss_udc *udc) if (nret < 0) { /* Send Stall */ - _nbu2ss_set_endpoint_stall(udc, 0, TRUE); + _nbu2ss_set_endpoint_stall(udc, 0, true); } } @@ -1925,7 +1925,7 @@ static inline void _nbu2ss_epn_in_dma_int(struct nbu2ss_udc *udc, preq->actual += req->div_len; req->div_len = 0; - req->dma_flag = FALSE; + req->dma_flag = false; #ifdef USE_DMA _nbu2ss_dma_unmap_single(udc, ep, req, USB_DIR_IN); @@ -1961,7 +1961,7 @@ static inline void _nbu2ss_epn_out_dma_int(struct nbu2ss_udc *udc, if (req->req.actual == req->req.length) { if ((req->req.length % ep->ep.maxpacket) && !req->zero) { req->div_len = 0; - req->dma_flag = FALSE; + req->dma_flag = false; _nbu2ss_ep_done(ep, req, 0); return; } @@ -1990,7 +1990,7 @@ static inline void _nbu2ss_epn_out_dma_int(struct nbu2ss_udc *udc, if ((req->req.actual % ep->ep.maxpacket) > 0) { if (req->req.actual == req->div_len) { req->div_len = 0; - req->dma_flag = FALSE; + req->dma_flag = false; _nbu2ss_ep_done(ep, req, 0); return; } @@ -1998,7 +1998,7 @@ static inline void _nbu2ss_epn_out_dma_int(struct nbu2ss_udc *udc, req->req.actual += req->div_len; req->div_len = 0; - req->dma_flag = FALSE; + req->dma_flag = false; _nbu2ss_epn_out_int(udc, ep, req); } @@ -2187,7 +2187,7 @@ static int _nbu2ss_enable_controller(struct nbu2ss_udc *udc) /* USB Interrupt Enable */ _nbu2ss_bitset(&udc->p_regs->USB_INT_ENA, USB_INT_EN_BIT); - udc->udc_enabled = TRUE; + udc->udc_enabled = true; return 0; } @@ -2203,7 +2203,7 @@ static void _nbu2ss_reset_controller(struct nbu2ss_udc *udc) static void _nbu2ss_disable_controller(struct nbu2ss_udc *udc) { if (udc->udc_enabled) { - udc->udc_enabled = FALSE; + udc->udc_enabled = false; _nbu2ss_reset_controller(udc); _nbu2ss_bitset(&udc->p_regs->EPCTR, (DIRPD | EPC_RST)); } @@ -2456,8 +2456,8 @@ static int nbu2ss_ep_enable(struct usb_ep *_ep, ep->direct = desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK; ep->ep_type = ep_type; ep->wedged = 0; - ep->halted = FALSE; - ep->stalled = FALSE; + ep->halted = false; + ep->stalled = false; ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); @@ -2588,9 +2588,9 @@ static int nbu2ss_ep_queue(struct usb_ep *_ep, #ifdef USE_DMA if ((uintptr_t)req->req.buf & 0x3) - req->unaligned = TRUE; + req->unaligned = true; else - req->unaligned = FALSE; + req->unaligned = false; if (req->unaligned) { if (!ep->virt_buf) @@ -2616,7 +2616,7 @@ static int nbu2ss_ep_queue(struct usb_ep *_ep, list_add_tail(&req->queue, &ep->queue); if (bflag && !ep->stalled) { - result = _nbu2ss_start_transfer(udc, ep, req, FALSE); + result = _nbu2ss_start_transfer(udc, ep, req, false); if (result < 0) { dev_err(udc->dev, " *** %s, result = %d\n", __func__, result); @@ -2704,12 +2704,12 @@ static int nbu2ss_ep_set_halt(struct usb_ep *_ep, int value) ep_adrs = ep->epnum | ep->direct; if (value == 0) { _nbu2ss_set_endpoint_stall(udc, ep_adrs, value); - ep->stalled = FALSE; + ep->stalled = false; } else { if (list_empty(&ep->queue)) _nbu2ss_epn_set_stall(udc, ep); else - ep->stalled = TRUE; + ep->stalled = true; } if (value == 0) @@ -3094,10 +3094,8 @@ static int nbu2ss_drv_probe(struct platform_device *pdev) return PTR_ERR(mmio_base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ\n"); + if (irq < 0) return irq; - } status = devm_request_irq(&pdev->dev, irq, _nbu2ss_udc_irq, 0, driver_name, udc); diff --git a/drivers/staging/emxx_udc/emxx_udc.h b/drivers/staging/emxx_udc/emxx_udc.h index b8c3dee5626c..9c2671cb32f7 100644 --- a/drivers/staging/emxx_udc/emxx_udc.h +++ b/drivers/staging/emxx_udc/emxx_udc.h @@ -19,11 +19,6 @@ #define USE_DMA 1 #define USE_SUSPEND_WAIT 1 -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - /*------------ Board dependence(Resource) */ #define VBUS_VALUE GPIO_VBUS diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig deleted file mode 100644 index d04b798a8efb..000000000000 --- a/drivers/staging/erofs/Kconfig +++ /dev/null @@ -1,151 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -config EROFS_FS - tristate "EROFS filesystem support" - depends on BLOCK - help - EROFS(Enhanced Read-Only File System) is a lightweight - read-only file system with modern designs (eg. page-sized - blocks, inline xattrs/data, etc.) for scenarios which need - high-performance read-only requirements, eg. firmwares in - mobile phone or LIVECDs. - - It also provides VLE compression support, focusing on - random read improvements, keeping relatively lower - compression ratios, which is useful for high-performance - devices with limited memory and ROM space. - - If unsure, say N. - -config EROFS_FS_DEBUG - bool "EROFS debugging feature" - depends on EROFS_FS - help - Print EROFS debugging messages and enable more BUG_ONs - which check the filesystem consistency aggressively. - - For daily use, say N. - -config EROFS_FS_XATTR - bool "EROFS extended attributes" - depends on EROFS_FS - default y - help - Extended attributes are name:value pairs associated with inodes by - the kernel or by users (see the attr(5) manual page, or visit - <http://acl.bestbits.at/> for details). - - If unsure, say N. - -config EROFS_FS_POSIX_ACL - bool "EROFS Access Control Lists" - depends on EROFS_FS_XATTR - select FS_POSIX_ACL - default y - help - Posix Access Control Lists (ACLs) support permissions for users and - groups beyond the owner/group/world scheme. - - To learn more about Access Control Lists, visit the POSIX ACLs for - Linux website <http://acl.bestbits.at/>. - - If you don't know what Access Control Lists are, say N. - -config EROFS_FS_SECURITY - bool "EROFS Security Labels" - depends on EROFS_FS_XATTR - help - Security labels provide an access control facility to support Linux - Security Models (LSMs) accepted by AppArmor, SELinux, Smack and TOMOYO - Linux. This option enables an extended attribute handler for file - security labels in the erofs filesystem, so that it requires enabling - the extended attribute support in advance. - - If you are not using a security module, say N. - -config EROFS_FS_USE_VM_MAP_RAM - bool "EROFS VM_MAP_RAM Support" - depends on EROFS_FS - help - use vm_map_ram/vm_unmap_ram instead of vmap/vunmap. - - If you don't know what these are, say N. - -config EROFS_FAULT_INJECTION - bool "EROFS fault injection facility" - depends on EROFS_FS - help - Test EROFS to inject faults such as ENOMEM, EIO, and so on. - If unsure, say N. - -config EROFS_FS_IO_MAX_RETRIES - int "EROFS IO Maximum Retries" - depends on EROFS_FS - default "5" - help - Maximum retry count of IO Errors. - - If unsure, leave the default value (5 retries, 6 IOs at most). - -config EROFS_FS_ZIP - bool "EROFS Data Compresssion Support" - depends on EROFS_FS - select LZ4_DECOMPRESS - help - Currently we support LZ4 VLE Compression only. - Play at your own risk. - - If you don't want to use compression feature, say N. - -config EROFS_FS_CLUSTER_PAGE_LIMIT - int "EROFS Cluster Pages Hard Limit" - depends on EROFS_FS_ZIP - range 1 256 - default "1" - help - Indicates VLE compressed pages hard limit of a - compressed cluster. - - For example, if files of a image are compressed - into 8k-unit, the hard limit should not be less - than 2. Otherwise, the image cannot be mounted - correctly on this kernel. - -choice - prompt "EROFS VLE Data Decompression mode" - depends on EROFS_FS_ZIP - default EROFS_FS_ZIP_CACHE_BIPOLAR - help - EROFS supports three options for VLE decompression. - "In-place Decompression Only" consumes the minimum memory - with lowest random read. - - "Bipolar Cached Decompression" consumes the maximum memory - with highest random read. - - If unsure, select "Bipolar Cached Decompression" - -config EROFS_FS_ZIP_NO_CACHE - bool "In-place Decompression Only" - help - Read compressed data into page cache and do in-place - decompression directly. - -config EROFS_FS_ZIP_CACHE_UNIPOLAR - bool "Unipolar Cached Decompression" - help - For each request, it caches the last compressed page - for further reading. - It still decompresses in place for the rest compressed pages. - -config EROFS_FS_ZIP_CACHE_BIPOLAR - bool "Bipolar Cached Decompression" - help - For each request, it caches the both end compressed pages - for further reading. - It still decompresses in place for the rest compressed pages. - - Recommended for performance priority. - -endchoice - diff --git a/drivers/staging/erofs/Makefile b/drivers/staging/erofs/Makefile deleted file mode 100644 index e704d9e51514..000000000000 --- a/drivers/staging/erofs/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -EROFS_VERSION = "1.0pre1" - -ccflags-y += -DEROFS_VERSION=\"$(EROFS_VERSION)\" - -obj-$(CONFIG_EROFS_FS) += erofs.o -# staging requirement: to be self-contained in its own directory -ccflags-y += -I $(srctree)/$(src)/include -erofs-objs := super.o inode.o data.o namei.o dir.o utils.o -erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o -erofs-$(CONFIG_EROFS_FS_ZIP) += unzip_vle.o zmap.o decompressor.o - diff --git a/drivers/staging/erofs/TODO b/drivers/staging/erofs/TODO deleted file mode 100644 index a8608b2f72bd..000000000000 --- a/drivers/staging/erofs/TODO +++ /dev/null @@ -1,46 +0,0 @@ - -EROFS is still working in progress, thus it is not suitable -for all productive uses. play at your own risk :) - -TODO List: - - add the missing error handling code - (mainly existed in xattr and decompression submodules); - - - finalize erofs ondisk format design (which means that - minor on-disk revisions could happen later); - - - documentation and detailed technical analysis; - - - general code review and clean up - (including confusing variable names and code snippets); - - - support larger compressed clustersizes for selection - (currently erofs only works as expected with the page-sized - compressed cluster configuration, usually 4KB); - - - support more lossless data compression algorithms - in addition to LZ4 algorithms in VLE approach; - - - data deduplication and other useful features. - -The following git tree provides the file system user-space -tools under development (ex, formatting tool mkfs.erofs): ->> git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git - -The open-source development of erofs-utils is at the early stage. -Contact the original author Li Guifu <bluce.liguifu@huawei.com> and -the co-maintainer Fang Wei <fangwei1@huawei.com> for the latest news -and more details. - -Code, suggestions, etc, are welcome. Please feel free to -ask and send patches, - -To: - linux-erofs mailing list <linux-erofs@lists.ozlabs.org> - Gao Xiang <gaoxiang25@huawei.com> - Chao Yu <yuchao0@huawei.com> - -Cc: (for linux-kernel upstream patches) - Greg Kroah-Hartman <gregkh@linuxfoundation.org> - linux-staging mailing list <devel@driverdev.osuosl.org> - diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c deleted file mode 100644 index 4c3d8bf8d249..000000000000 --- a/drivers/staging/erofs/inode.c +++ /dev/null @@ -1,332 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/drivers/staging/erofs/inode.c - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. - */ -#include "xattr.h" - -#include <trace/events/erofs.h> - -/* no locking */ -static int read_inode(struct inode *inode, void *data) -{ - struct erofs_vnode *vi = EROFS_V(inode); - struct erofs_inode_v1 *v1 = data; - const unsigned int advise = le16_to_cpu(v1->i_advise); - erofs_blk_t nblks = 0; - - vi->datamode = __inode_data_mapping(advise); - - if (unlikely(vi->datamode >= EROFS_INODE_LAYOUT_MAX)) { - errln("unsupported data mapping %u of nid %llu", - vi->datamode, vi->nid); - DBG_BUGON(1); - return -EIO; - } - - if (__inode_version(advise) == EROFS_INODE_LAYOUT_V2) { - struct erofs_inode_v2 *v2 = data; - - vi->inode_isize = sizeof(struct erofs_inode_v2); - vi->xattr_isize = ondisk_xattr_ibody_size(v2->i_xattr_icount); - - inode->i_mode = le16_to_cpu(v2->i_mode); - if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) { - vi->raw_blkaddr = le32_to_cpu(v2->i_u.raw_blkaddr); - } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { - inode->i_rdev = - new_decode_dev(le32_to_cpu(v2->i_u.rdev)); - } else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - inode->i_rdev = 0; - } else { - return -EIO; - } - - i_uid_write(inode, le32_to_cpu(v2->i_uid)); - i_gid_write(inode, le32_to_cpu(v2->i_gid)); - set_nlink(inode, le32_to_cpu(v2->i_nlink)); - - /* ns timestamp */ - inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = - le64_to_cpu(v2->i_ctime); - inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = - le32_to_cpu(v2->i_ctime_nsec); - - inode->i_size = le64_to_cpu(v2->i_size); - - /* total blocks for compressed files */ - if (is_inode_layout_compression(inode)) - nblks = le32_to_cpu(v2->i_u.compressed_blocks); - } else if (__inode_version(advise) == EROFS_INODE_LAYOUT_V1) { - struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); - - vi->inode_isize = sizeof(struct erofs_inode_v1); - vi->xattr_isize = ondisk_xattr_ibody_size(v1->i_xattr_icount); - - inode->i_mode = le16_to_cpu(v1->i_mode); - if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) { - vi->raw_blkaddr = le32_to_cpu(v1->i_u.raw_blkaddr); - } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { - inode->i_rdev = - new_decode_dev(le32_to_cpu(v1->i_u.rdev)); - } else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - inode->i_rdev = 0; - } else { - return -EIO; - } - - i_uid_write(inode, le16_to_cpu(v1->i_uid)); - i_gid_write(inode, le16_to_cpu(v1->i_gid)); - set_nlink(inode, le16_to_cpu(v1->i_nlink)); - - /* use build time to derive all file time */ - inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = - sbi->build_time; - inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = - sbi->build_time_nsec; - - inode->i_size = le32_to_cpu(v1->i_size); - if (is_inode_layout_compression(inode)) - nblks = le32_to_cpu(v1->i_u.compressed_blocks); - } else { - errln("unsupported on-disk inode version %u of nid %llu", - __inode_version(advise), vi->nid); - DBG_BUGON(1); - return -EIO; - } - - if (!nblks) - /* measure inode.i_blocks as generic filesystems */ - inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9; - else - inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK; - return 0; -} - -/* - * try_lock can be required since locking order is: - * file data(fs_inode) - * meta(bd_inode) - * but the majority of the callers is "iget", - * in that case we are pretty sure no deadlock since - * no data operations exist. However I tend to - * try_lock since it takes no much overhead and - * will success immediately. - */ -static int fill_inline_data(struct inode *inode, void *data, - unsigned int m_pofs) -{ - struct erofs_vnode *vi = EROFS_V(inode); - struct erofs_sb_info *sbi = EROFS_I_SB(inode); - - /* should be inode inline C */ - if (!is_inode_flat_inline(inode)) - return 0; - - /* fast symlink (following ext4) */ - if (S_ISLNK(inode->i_mode) && inode->i_size < PAGE_SIZE) { - char *lnk = erofs_kmalloc(sbi, inode->i_size + 1, GFP_KERNEL); - - if (unlikely(!lnk)) - return -ENOMEM; - - m_pofs += vi->inode_isize + vi->xattr_isize; - - /* inline symlink data shouldn't across page boundary as well */ - if (unlikely(m_pofs + inode->i_size > PAGE_SIZE)) { - DBG_BUGON(1); - kfree(lnk); - return -EIO; - } - - /* get in-page inline data */ - memcpy(lnk, data + m_pofs, inode->i_size); - lnk[inode->i_size] = '\0'; - - inode->i_link = lnk; - set_inode_fast_symlink(inode); - } - return 0; -} - -static int fill_inode(struct inode *inode, int isdir) -{ - struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); - struct erofs_vnode *vi = EROFS_V(inode); - struct page *page; - void *data; - int err; - erofs_blk_t blkaddr; - unsigned int ofs; - - trace_erofs_fill_inode(inode, isdir); - - blkaddr = erofs_blknr(iloc(sbi, vi->nid)); - ofs = erofs_blkoff(iloc(sbi, vi->nid)); - - debugln("%s, reading inode nid %llu at %u of blkaddr %u", - __func__, vi->nid, ofs, blkaddr); - - page = erofs_get_meta_page(inode->i_sb, blkaddr, isdir); - - if (IS_ERR(page)) { - errln("failed to get inode (nid: %llu) page, err %ld", - vi->nid, PTR_ERR(page)); - return PTR_ERR(page); - } - - DBG_BUGON(!PageUptodate(page)); - data = page_address(page); - - err = read_inode(inode, data + ofs); - if (!err) { - /* setup the new inode */ - if (S_ISREG(inode->i_mode)) { - inode->i_op = &erofs_generic_iops; - inode->i_fop = &generic_ro_fops; - } else if (S_ISDIR(inode->i_mode)) { - inode->i_op = &erofs_dir_iops; - inode->i_fop = &erofs_dir_fops; - } else if (S_ISLNK(inode->i_mode)) { - /* by default, page_get_link is used for symlink */ - inode->i_op = &erofs_symlink_iops; - inode_nohighmem(inode); - } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || - S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - inode->i_op = &erofs_generic_iops; - init_special_inode(inode, inode->i_mode, inode->i_rdev); - goto out_unlock; - } else { - err = -EIO; - goto out_unlock; - } - - if (is_inode_layout_compression(inode)) { - err = z_erofs_fill_inode(inode); - goto out_unlock; - } - - inode->i_mapping->a_ops = &erofs_raw_access_aops; - - /* fill last page if inline data is available */ - err = fill_inline_data(inode, data, ofs); - } - -out_unlock: - unlock_page(page); - put_page(page); - return err; -} - -/* - * erofs nid is 64bits, but i_ino is 'unsigned long', therefore - * we should do more for 32-bit platform to find the right inode. - */ -#if BITS_PER_LONG == 32 -static int erofs_ilookup_test_actor(struct inode *inode, void *opaque) -{ - const erofs_nid_t nid = *(erofs_nid_t *)opaque; - - return EROFS_V(inode)->nid == nid; -} - -static int erofs_iget_set_actor(struct inode *inode, void *opaque) -{ - const erofs_nid_t nid = *(erofs_nid_t *)opaque; - - inode->i_ino = erofs_inode_hash(nid); - return 0; -} -#endif - -static inline struct inode *erofs_iget_locked(struct super_block *sb, - erofs_nid_t nid) -{ - const unsigned long hashval = erofs_inode_hash(nid); - -#if BITS_PER_LONG >= 64 - /* it is safe to use iget_locked for >= 64-bit platform */ - return iget_locked(sb, hashval); -#else - return iget5_locked(sb, hashval, erofs_ilookup_test_actor, - erofs_iget_set_actor, &nid); -#endif -} - -struct inode *erofs_iget(struct super_block *sb, - erofs_nid_t nid, - bool isdir) -{ - struct inode *inode = erofs_iget_locked(sb, nid); - - if (unlikely(!inode)) - return ERR_PTR(-ENOMEM); - - if (inode->i_state & I_NEW) { - int err; - struct erofs_vnode *vi = EROFS_V(inode); - - vi->nid = nid; - - err = fill_inode(inode, isdir); - if (likely(!err)) - unlock_new_inode(inode); - else { - iget_failed(inode); - inode = ERR_PTR(err); - } - } - return inode; -} - -int erofs_getattr(const struct path *path, struct kstat *stat, - u32 request_mask, unsigned int query_flags) -{ - struct inode *const inode = d_inode(path->dentry); - - if (is_inode_layout_compression(inode)) - stat->attributes |= STATX_ATTR_COMPRESSED; - - stat->attributes |= STATX_ATTR_IMMUTABLE; - stat->attributes_mask |= (STATX_ATTR_COMPRESSED | - STATX_ATTR_IMMUTABLE); - - generic_fillattr(inode, stat); - return 0; -} - -const struct inode_operations erofs_generic_iops = { - .getattr = erofs_getattr, -#ifdef CONFIG_EROFS_FS_XATTR - .listxattr = erofs_listxattr, -#endif - .get_acl = erofs_get_acl, -}; - -const struct inode_operations erofs_symlink_iops = { - .get_link = page_get_link, - .getattr = erofs_getattr, -#ifdef CONFIG_EROFS_FS_XATTR - .listxattr = erofs_listxattr, -#endif - .get_acl = erofs_get_acl, -}; - -const struct inode_operations erofs_fast_symlink_iops = { - .get_link = simple_get_link, - .getattr = erofs_getattr, -#ifdef CONFIG_EROFS_FS_XATTR - .listxattr = erofs_listxattr, -#endif - .get_acl = erofs_get_acl, -}; - diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c deleted file mode 100644 index 54494412eba4..000000000000 --- a/drivers/staging/erofs/super.c +++ /dev/null @@ -1,701 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/drivers/staging/erofs/super.c - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. - */ -#include <linux/module.h> -#include <linux/buffer_head.h> -#include <linux/statfs.h> -#include <linux/parser.h> -#include <linux/seq_file.h> -#include "internal.h" -#include "xattr.h" - -#define CREATE_TRACE_POINTS -#include <trace/events/erofs.h> - -static struct kmem_cache *erofs_inode_cachep __read_mostly; - -static void init_once(void *ptr) -{ - struct erofs_vnode *vi = ptr; - - inode_init_once(&vi->vfs_inode); -} - -static int __init erofs_init_inode_cache(void) -{ - erofs_inode_cachep = kmem_cache_create("erofs_inode", - sizeof(struct erofs_vnode), 0, - SLAB_RECLAIM_ACCOUNT, - init_once); - - return erofs_inode_cachep ? 0 : -ENOMEM; -} - -static void erofs_exit_inode_cache(void) -{ - kmem_cache_destroy(erofs_inode_cachep); -} - -static struct inode *alloc_inode(struct super_block *sb) -{ - struct erofs_vnode *vi = - kmem_cache_alloc(erofs_inode_cachep, GFP_KERNEL); - - if (!vi) - return NULL; - - /* zero out everything except vfs_inode */ - memset(vi, 0, offsetof(struct erofs_vnode, vfs_inode)); - return &vi->vfs_inode; -} - -static void free_inode(struct inode *inode) -{ - struct erofs_vnode *vi = EROFS_V(inode); - - /* be careful RCU symlink path (see ext4_inode_info->i_data)! */ - if (is_inode_fast_symlink(inode)) - kfree(inode->i_link); - - kfree(vi->xattr_shared_xattrs); - - kmem_cache_free(erofs_inode_cachep, vi); -} - -static bool check_layout_compatibility(struct super_block *sb, - struct erofs_super_block *layout) -{ - const unsigned int requirements = le32_to_cpu(layout->requirements); - - EROFS_SB(sb)->requirements = requirements; - - /* check if current kernel meets all mandatory requirements */ - if (requirements & (~EROFS_ALL_REQUIREMENTS)) { - errln("unidentified requirements %x, please upgrade kernel version", - requirements & ~EROFS_ALL_REQUIREMENTS); - return false; - } - return true; -} - -static int superblock_read(struct super_block *sb) -{ - struct erofs_sb_info *sbi; - struct buffer_head *bh; - struct erofs_super_block *layout; - unsigned int blkszbits; - int ret; - - bh = sb_bread(sb, 0); - - if (!bh) { - errln("cannot read erofs superblock"); - return -EIO; - } - - sbi = EROFS_SB(sb); - layout = (struct erofs_super_block *)((u8 *)bh->b_data - + EROFS_SUPER_OFFSET); - - ret = -EINVAL; - if (le32_to_cpu(layout->magic) != EROFS_SUPER_MAGIC_V1) { - errln("cannot find valid erofs superblock"); - goto out; - } - - blkszbits = layout->blkszbits; - /* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */ - if (unlikely(blkszbits != LOG_BLOCK_SIZE)) { - errln("blksize %u isn't supported on this platform", - 1 << blkszbits); - goto out; - } - - if (!check_layout_compatibility(sb, layout)) - goto out; - - sbi->blocks = le32_to_cpu(layout->blocks); - sbi->meta_blkaddr = le32_to_cpu(layout->meta_blkaddr); -#ifdef CONFIG_EROFS_FS_XATTR - sbi->xattr_blkaddr = le32_to_cpu(layout->xattr_blkaddr); -#endif - sbi->islotbits = ffs(sizeof(struct erofs_inode_v1)) - 1; -#ifdef CONFIG_EROFS_FS_ZIP - /* TODO: clusterbits should be related to inode */ - sbi->clusterbits = blkszbits; - - if (1 << (sbi->clusterbits - PAGE_SHIFT) > Z_EROFS_CLUSTER_MAX_PAGES) - errln("clusterbits %u is not supported on this kernel", - sbi->clusterbits); -#endif - - sbi->root_nid = le16_to_cpu(layout->root_nid); - sbi->inos = le64_to_cpu(layout->inos); - - sbi->build_time = le64_to_cpu(layout->build_time); - sbi->build_time_nsec = le32_to_cpu(layout->build_time_nsec); - - memcpy(&sb->s_uuid, layout->uuid, sizeof(layout->uuid)); - memcpy(sbi->volume_name, layout->volume_name, - sizeof(layout->volume_name)); - - ret = 0; -out: - brelse(bh); - return ret; -} - -#ifdef CONFIG_EROFS_FAULT_INJECTION -const char *erofs_fault_name[FAULT_MAX] = { - [FAULT_KMALLOC] = "kmalloc", - [FAULT_READ_IO] = "read IO error", -}; - -static void __erofs_build_fault_attr(struct erofs_sb_info *sbi, - unsigned int rate) -{ - struct erofs_fault_info *ffi = &sbi->fault_info; - - if (rate) { - atomic_set(&ffi->inject_ops, 0); - ffi->inject_rate = rate; - ffi->inject_type = (1 << FAULT_MAX) - 1; - } else { - memset(ffi, 0, sizeof(struct erofs_fault_info)); - } - - set_opt(sbi, FAULT_INJECTION); -} - -static int erofs_build_fault_attr(struct erofs_sb_info *sbi, - substring_t *args) -{ - int rate = 0; - - if (args->from && match_int(args, &rate)) - return -EINVAL; - - __erofs_build_fault_attr(sbi, rate); - return 0; -} - -static unsigned int erofs_get_fault_rate(struct erofs_sb_info *sbi) -{ - return sbi->fault_info.inject_rate; -} -#else -static void __erofs_build_fault_attr(struct erofs_sb_info *sbi, - unsigned int rate) -{ -} - -static int erofs_build_fault_attr(struct erofs_sb_info *sbi, - substring_t *args) -{ - infoln("fault_injection options not supported"); - return 0; -} - -static unsigned int erofs_get_fault_rate(struct erofs_sb_info *sbi) -{ - return 0; -} -#endif - -static void default_options(struct erofs_sb_info *sbi) -{ - /* set up some FS parameters */ -#ifdef CONFIG_EROFS_FS_ZIP - sbi->max_sync_decompress_pages = DEFAULT_MAX_SYNC_DECOMPRESS_PAGES; -#endif - -#ifdef CONFIG_EROFS_FS_XATTR - set_opt(sbi, XATTR_USER); -#endif - -#ifdef CONFIG_EROFS_FS_POSIX_ACL - set_opt(sbi, POSIX_ACL); -#endif -} - -enum { - Opt_user_xattr, - Opt_nouser_xattr, - Opt_acl, - Opt_noacl, - Opt_fault_injection, - Opt_err -}; - -static match_table_t erofs_tokens = { - {Opt_user_xattr, "user_xattr"}, - {Opt_nouser_xattr, "nouser_xattr"}, - {Opt_acl, "acl"}, - {Opt_noacl, "noacl"}, - {Opt_fault_injection, "fault_injection=%u"}, - {Opt_err, NULL} -}; - -static int parse_options(struct super_block *sb, char *options) -{ - substring_t args[MAX_OPT_ARGS]; - char *p; - int err; - - if (!options) - return 0; - - while ((p = strsep(&options, ","))) { - int token; - - if (!*p) - continue; - - args[0].to = args[0].from = NULL; - token = match_token(p, erofs_tokens, args); - - switch (token) { -#ifdef CONFIG_EROFS_FS_XATTR - case Opt_user_xattr: - set_opt(EROFS_SB(sb), XATTR_USER); - break; - case Opt_nouser_xattr: - clear_opt(EROFS_SB(sb), XATTR_USER); - break; -#else - case Opt_user_xattr: - infoln("user_xattr options not supported"); - break; - case Opt_nouser_xattr: - infoln("nouser_xattr options not supported"); - break; -#endif -#ifdef CONFIG_EROFS_FS_POSIX_ACL - case Opt_acl: - set_opt(EROFS_SB(sb), POSIX_ACL); - break; - case Opt_noacl: - clear_opt(EROFS_SB(sb), POSIX_ACL); - break; -#else - case Opt_acl: - infoln("acl options not supported"); - break; - case Opt_noacl: - infoln("noacl options not supported"); - break; -#endif - case Opt_fault_injection: - err = erofs_build_fault_attr(EROFS_SB(sb), args); - if (err) - return err; - break; - - default: - errln("Unrecognized mount option \"%s\" " - "or missing value", p); - return -EINVAL; - } - } - return 0; -} - -#ifdef EROFS_FS_HAS_MANAGED_CACHE - -static const struct address_space_operations managed_cache_aops; - -static int managed_cache_releasepage(struct page *page, gfp_t gfp_mask) -{ - int ret = 1; /* 0 - busy */ - struct address_space *const mapping = page->mapping; - - DBG_BUGON(!PageLocked(page)); - DBG_BUGON(mapping->a_ops != &managed_cache_aops); - - if (PagePrivate(page)) - ret = erofs_try_to_free_cached_page(mapping, page); - - return ret; -} - -static void managed_cache_invalidatepage(struct page *page, - unsigned int offset, - unsigned int length) -{ - const unsigned int stop = length + offset; - - DBG_BUGON(!PageLocked(page)); - - /* Check for potential overflow in debug mode */ - DBG_BUGON(stop > PAGE_SIZE || stop < length); - - if (offset == 0 && stop == PAGE_SIZE) - while (!managed_cache_releasepage(page, GFP_NOFS)) - cond_resched(); -} - -static const struct address_space_operations managed_cache_aops = { - .releasepage = managed_cache_releasepage, - .invalidatepage = managed_cache_invalidatepage, -}; - -static struct inode *erofs_init_managed_cache(struct super_block *sb) -{ - struct inode *inode = new_inode(sb); - - if (unlikely(!inode)) - return ERR_PTR(-ENOMEM); - - set_nlink(inode, 1); - inode->i_size = OFFSET_MAX; - - inode->i_mapping->a_ops = &managed_cache_aops; - mapping_set_gfp_mask(inode->i_mapping, - GFP_NOFS | __GFP_HIGHMEM | - __GFP_MOVABLE | __GFP_NOFAIL); - return inode; -} - -#endif - -static int erofs_read_super(struct super_block *sb, - const char *dev_name, - void *data, int silent) -{ - struct inode *inode; - struct erofs_sb_info *sbi; - int err = -EINVAL; - - infoln("read_super, device -> %s", dev_name); - infoln("options -> %s", (char *)data); - - if (unlikely(!sb_set_blocksize(sb, EROFS_BLKSIZ))) { - errln("failed to set erofs blksize"); - goto err; - } - - sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (unlikely(!sbi)) { - err = -ENOMEM; - goto err; - } - sb->s_fs_info = sbi; - - err = superblock_read(sb); - if (err) - goto err_sbread; - - sb->s_magic = EROFS_SUPER_MAGIC; - sb->s_flags |= SB_RDONLY | SB_NOATIME; - sb->s_maxbytes = MAX_LFS_FILESIZE; - sb->s_time_gran = 1; - - sb->s_op = &erofs_sops; - -#ifdef CONFIG_EROFS_FS_XATTR - sb->s_xattr = erofs_xattr_handlers; -#endif - - /* set erofs default mount options */ - default_options(sbi); - - err = parse_options(sb, data); - if (err) - goto err_parseopt; - - if (!silent) - infoln("root inode @ nid %llu", ROOT_NID(sbi)); - - if (test_opt(sbi, POSIX_ACL)) - sb->s_flags |= SB_POSIXACL; - else - sb->s_flags &= ~SB_POSIXACL; - -#ifdef CONFIG_EROFS_FS_ZIP - INIT_RADIX_TREE(&sbi->workstn_tree, GFP_ATOMIC); -#endif - -#ifdef EROFS_FS_HAS_MANAGED_CACHE - sbi->managed_cache = erofs_init_managed_cache(sb); - if (IS_ERR(sbi->managed_cache)) { - err = PTR_ERR(sbi->managed_cache); - goto err_init_managed_cache; - } -#endif - - /* get the root inode */ - inode = erofs_iget(sb, ROOT_NID(sbi), true); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto err_iget; - } - - if (!S_ISDIR(inode->i_mode)) { - errln("rootino(nid %llu) is not a directory(i_mode %o)", - ROOT_NID(sbi), inode->i_mode); - err = -EINVAL; - iput(inode); - goto err_iget; - } - - sb->s_root = d_make_root(inode); - if (!sb->s_root) { - err = -ENOMEM; - goto err_iget; - } - - /* save the device name to sbi */ - sbi->dev_name = __getname(); - if (!sbi->dev_name) { - err = -ENOMEM; - goto err_devname; - } - - snprintf(sbi->dev_name, PATH_MAX, "%s", dev_name); - sbi->dev_name[PATH_MAX - 1] = '\0'; - - erofs_register_super(sb); - - if (!silent) - infoln("mounted on %s with opts: %s.", dev_name, - (char *)data); - return 0; - /* - * please add a label for each exit point and use - * the following name convention, thus new features - * can be integrated easily without renaming labels. - */ -err_devname: - dput(sb->s_root); - sb->s_root = NULL; -err_iget: -#ifdef EROFS_FS_HAS_MANAGED_CACHE - iput(sbi->managed_cache); -err_init_managed_cache: -#endif -err_parseopt: -err_sbread: - sb->s_fs_info = NULL; - kfree(sbi); -err: - return err; -} - -/* - * could be triggered after deactivate_locked_super() - * is called, thus including umount and failed to initialize. - */ -static void erofs_put_super(struct super_block *sb) -{ - struct erofs_sb_info *sbi = EROFS_SB(sb); - - /* for cases which are failed in "read_super" */ - if (!sbi) - return; - - WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); - - infoln("unmounted for %s", sbi->dev_name); - __putname(sbi->dev_name); - -#ifdef EROFS_FS_HAS_MANAGED_CACHE - iput(sbi->managed_cache); -#endif - - mutex_lock(&sbi->umount_mutex); - -#ifdef CONFIG_EROFS_FS_ZIP - /* clean up the compression space of this sb */ - erofs_shrink_workstation(EROFS_SB(sb), ~0UL, true); -#endif - - erofs_unregister_super(sb); - mutex_unlock(&sbi->umount_mutex); - - kfree(sbi); - sb->s_fs_info = NULL; -} - - -struct erofs_mount_private { - const char *dev_name; - char *options; -}; - -/* support mount_bdev() with options */ -static int erofs_fill_super(struct super_block *sb, - void *_priv, int silent) -{ - struct erofs_mount_private *priv = _priv; - - return erofs_read_super(sb, priv->dev_name, - priv->options, silent); -} - -static struct dentry *erofs_mount( - struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) -{ - struct erofs_mount_private priv = { - .dev_name = dev_name, - .options = data - }; - - return mount_bdev(fs_type, flags, dev_name, - &priv, erofs_fill_super); -} - -static void erofs_kill_sb(struct super_block *sb) -{ - kill_block_super(sb); -} - -static struct file_system_type erofs_fs_type = { - .owner = THIS_MODULE, - .name = "erofs", - .mount = erofs_mount, - .kill_sb = erofs_kill_sb, - .fs_flags = FS_REQUIRES_DEV, -}; -MODULE_ALIAS_FS("erofs"); - -static int __init erofs_module_init(void) -{ - int err; - - erofs_check_ondisk_layout_definitions(); - infoln("initializing erofs " EROFS_VERSION); - - err = erofs_init_inode_cache(); - if (err) - goto icache_err; - - err = register_shrinker(&erofs_shrinker_info); - if (err) - goto shrinker_err; - - err = z_erofs_init_zip_subsystem(); - if (err) - goto zip_err; - - err = register_filesystem(&erofs_fs_type); - if (err) - goto fs_err; - - infoln("successfully to initialize erofs"); - return 0; - -fs_err: - z_erofs_exit_zip_subsystem(); -zip_err: - unregister_shrinker(&erofs_shrinker_info); -shrinker_err: - erofs_exit_inode_cache(); -icache_err: - return err; -} - -static void __exit erofs_module_exit(void) -{ - unregister_filesystem(&erofs_fs_type); - z_erofs_exit_zip_subsystem(); - unregister_shrinker(&erofs_shrinker_info); - erofs_exit_inode_cache(); - infoln("successfully finalize erofs"); -} - -/* get filesystem statistics */ -static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - struct super_block *sb = dentry->d_sb; - struct erofs_sb_info *sbi = EROFS_SB(sb); - u64 id = huge_encode_dev(sb->s_bdev->bd_dev); - - buf->f_type = sb->s_magic; - buf->f_bsize = EROFS_BLKSIZ; - buf->f_blocks = sbi->blocks; - buf->f_bfree = buf->f_bavail = 0; - - buf->f_files = ULLONG_MAX; - buf->f_ffree = ULLONG_MAX - sbi->inos; - - buf->f_namelen = EROFS_NAME_LEN; - - buf->f_fsid.val[0] = (u32)id; - buf->f_fsid.val[1] = (u32)(id >> 32); - return 0; -} - -static int erofs_show_options(struct seq_file *seq, struct dentry *root) -{ - struct erofs_sb_info *sbi __maybe_unused = EROFS_SB(root->d_sb); - -#ifdef CONFIG_EROFS_FS_XATTR - if (test_opt(sbi, XATTR_USER)) - seq_puts(seq, ",user_xattr"); - else - seq_puts(seq, ",nouser_xattr"); -#endif -#ifdef CONFIG_EROFS_FS_POSIX_ACL - if (test_opt(sbi, POSIX_ACL)) - seq_puts(seq, ",acl"); - else - seq_puts(seq, ",noacl"); -#endif - if (test_opt(sbi, FAULT_INJECTION)) - seq_printf(seq, ",fault_injection=%u", - erofs_get_fault_rate(sbi)); - return 0; -} - -static int erofs_remount(struct super_block *sb, int *flags, char *data) -{ - struct erofs_sb_info *sbi = EROFS_SB(sb); - unsigned int org_mnt_opt = sbi->mount_opt; - unsigned int org_inject_rate = erofs_get_fault_rate(sbi); - int err; - - DBG_BUGON(!sb_rdonly(sb)); - err = parse_options(sb, data); - if (err) - goto out; - - if (test_opt(sbi, POSIX_ACL)) - sb->s_flags |= SB_POSIXACL; - else - sb->s_flags &= ~SB_POSIXACL; - - *flags |= SB_RDONLY; - return 0; -out: - __erofs_build_fault_attr(sbi, org_inject_rate); - sbi->mount_opt = org_mnt_opt; - - return err; -} - -const struct super_operations erofs_sops = { - .put_super = erofs_put_super, - .alloc_inode = alloc_inode, - .free_inode = free_inode, - .statfs = erofs_statfs, - .show_options = erofs_show_options, - .remount_fs = erofs_remount, -}; - -module_init(erofs_module_init); -module_exit(erofs_module_exit); - -MODULE_DESCRIPTION("Enhanced ROM File System"); -MODULE_AUTHOR("Gao Xiang, Yu Chao, Miao Xie, CONSUMER BG, HUAWEI Inc."); -MODULE_LICENSE("GPL"); - diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c deleted file mode 100644 index f0dab81ff816..000000000000 --- a/drivers/staging/erofs/unzip_vle.c +++ /dev/null @@ -1,1591 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/drivers/staging/erofs/unzip_vle.c - * - * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. - */ -#include "unzip_vle.h" -#include "compress.h" -#include <linux/prefetch.h> - -#include <trace/events/erofs.h> - -/* - * a compressed_pages[] placeholder in order to avoid - * being filled with file pages for in-place decompression. - */ -#define PAGE_UNALLOCATED ((void *)0x5F0E4B1D) - -/* how to allocate cached pages for a workgroup */ -enum z_erofs_cache_alloctype { - DONTALLOC, /* don't allocate any cached pages */ - DELAYEDALLOC, /* delayed allocation (at the time of submitting io) */ -}; - -/* - * tagged pointer with 1-bit tag for all compressed pages - * tag 0 - the page is just found with an extra page reference - */ -typedef tagptr1_t compressed_page_t; - -#define tag_compressed_page_justfound(page) \ - tagptr_fold(compressed_page_t, page, 1) - -static struct workqueue_struct *z_erofs_workqueue __read_mostly; -static struct kmem_cache *z_erofs_workgroup_cachep __read_mostly; - -void z_erofs_exit_zip_subsystem(void) -{ - destroy_workqueue(z_erofs_workqueue); - kmem_cache_destroy(z_erofs_workgroup_cachep); -} - -static inline int init_unzip_workqueue(void) -{ - const unsigned int onlinecpus = num_possible_cpus(); - - /* - * we don't need too many threads, limiting threads - * could improve scheduling performance. - */ - z_erofs_workqueue = - alloc_workqueue("erofs_unzipd", - WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE, - onlinecpus + onlinecpus / 4); - - return z_erofs_workqueue ? 0 : -ENOMEM; -} - -static void init_once(void *ptr) -{ - struct z_erofs_vle_workgroup *grp = ptr; - struct z_erofs_vle_work *const work = - z_erofs_vle_grab_primary_work(grp); - unsigned int i; - - mutex_init(&work->lock); - work->nr_pages = 0; - work->vcnt = 0; - for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i) - grp->compressed_pages[i] = NULL; -} - -static void init_always(struct z_erofs_vle_workgroup *grp) -{ - struct z_erofs_vle_work *const work = - z_erofs_vle_grab_primary_work(grp); - - atomic_set(&grp->obj.refcount, 1); - grp->flags = 0; - - DBG_BUGON(work->nr_pages); - DBG_BUGON(work->vcnt); -} - -int __init z_erofs_init_zip_subsystem(void) -{ - z_erofs_workgroup_cachep = - kmem_cache_create("erofs_compress", - Z_EROFS_WORKGROUP_SIZE, 0, - SLAB_RECLAIM_ACCOUNT, init_once); - - if (z_erofs_workgroup_cachep) { - if (!init_unzip_workqueue()) - return 0; - - kmem_cache_destroy(z_erofs_workgroup_cachep); - } - return -ENOMEM; -} - -enum z_erofs_vle_work_role { - Z_EROFS_VLE_WORK_SECONDARY, - Z_EROFS_VLE_WORK_PRIMARY, - /* - * The current work was the tail of an exist chain, and the previous - * processed chained works are all decided to be hooked up to it. - * A new chain should be created for the remaining unprocessed works, - * therefore different from Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED, - * the next work cannot reuse the whole page in the following scenario: - * ________________________________________________________________ - * | tail (partial) page | head (partial) page | - * | (belongs to the next work) | (belongs to the current work) | - * |_______PRIMARY_FOLLOWED_______|________PRIMARY_HOOKED___________| - */ - Z_EROFS_VLE_WORK_PRIMARY_HOOKED, - /* - * The current work has been linked with the processed chained works, - * and could be also linked with the potential remaining works, which - * means if the processing page is the tail partial page of the work, - * the current work can safely use the whole page (since the next work - * is under control) for in-place decompression, as illustrated below: - * ________________________________________________________________ - * | tail (partial) page | head (partial) page | - * | (of the current work) | (of the previous work) | - * | PRIMARY_FOLLOWED or | | - * |_____PRIMARY_HOOKED____|____________PRIMARY_FOLLOWED____________| - * - * [ (*) the above page can be used for the current work itself. ] - */ - Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED, - Z_EROFS_VLE_WORK_MAX -}; - -struct z_erofs_vle_work_builder { - enum z_erofs_vle_work_role role; - /* - * 'hosted = false' means that the current workgroup doesn't belong to - * the owned chained workgroups. In the other words, it is none of our - * business to submit this workgroup. - */ - bool hosted; - - struct z_erofs_vle_workgroup *grp; - struct z_erofs_vle_work *work; - struct z_erofs_pagevec_ctor vector; - - /* pages used for reading the compressed data */ - struct page **compressed_pages; - unsigned int compressed_deficit; -}; - -#define VLE_WORK_BUILDER_INIT() \ - { .work = NULL, .role = Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED } - -#ifdef EROFS_FS_HAS_MANAGED_CACHE -static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, - struct address_space *mc, - pgoff_t index, - unsigned int clusterpages, - enum z_erofs_cache_alloctype type, - struct list_head *pagepool, - gfp_t gfp) -{ - struct page **const pages = bl->compressed_pages; - const unsigned int remaining = bl->compressed_deficit; - bool standalone = true; - unsigned int i, j = 0; - - if (bl->role < Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED) - return; - - gfp = mapping_gfp_constraint(mc, gfp) & ~__GFP_RECLAIM; - - index += clusterpages - remaining; - - for (i = 0; i < remaining; ++i) { - struct page *page; - compressed_page_t t; - - /* the compressed page was loaded before */ - if (READ_ONCE(pages[i])) - continue; - - page = find_get_page(mc, index + i); - - if (page) { - t = tag_compressed_page_justfound(page); - } else if (type == DELAYEDALLOC) { - t = tagptr_init(compressed_page_t, PAGE_UNALLOCATED); - } else { /* DONTALLOC */ - if (standalone) - j = i; - standalone = false; - continue; - } - - if (!cmpxchg_relaxed(&pages[i], NULL, tagptr_cast_ptr(t))) - continue; - - if (page) - put_page(page); - } - bl->compressed_pages += j; - bl->compressed_deficit = remaining - j; - - if (standalone) - bl->role = Z_EROFS_VLE_WORK_PRIMARY; -} - -/* called by erofs_shrinker to get rid of all compressed_pages */ -int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, - struct erofs_workgroup *egrp) -{ - struct z_erofs_vle_workgroup *const grp = - container_of(egrp, struct z_erofs_vle_workgroup, obj); - struct address_space *const mapping = MNGD_MAPPING(sbi); - const int clusterpages = erofs_clusterpages(sbi); - int i; - - /* - * refcount of workgroup is now freezed as 1, - * therefore no need to worry about available decompression users. - */ - for (i = 0; i < clusterpages; ++i) { - struct page *page = grp->compressed_pages[i]; - - if (!page || page->mapping != mapping) - continue; - - /* block other users from reclaiming or migrating the page */ - if (!trylock_page(page)) - return -EBUSY; - - /* barrier is implied in the following 'unlock_page' */ - WRITE_ONCE(grp->compressed_pages[i], NULL); - - set_page_private(page, 0); - ClearPagePrivate(page); - - unlock_page(page); - put_page(page); - } - return 0; -} - -int erofs_try_to_free_cached_page(struct address_space *mapping, - struct page *page) -{ - struct erofs_sb_info *const sbi = EROFS_SB(mapping->host->i_sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - struct z_erofs_vle_workgroup *const grp = (void *)page_private(page); - int ret = 0; /* 0 - busy */ - - if (erofs_workgroup_try_to_freeze(&grp->obj, 1)) { - unsigned int i; - - for (i = 0; i < clusterpages; ++i) { - if (grp->compressed_pages[i] == page) { - WRITE_ONCE(grp->compressed_pages[i], NULL); - ret = 1; - break; - } - } - erofs_workgroup_unfreeze(&grp->obj, 1); - - if (ret) { - ClearPagePrivate(page); - put_page(page); - } - } - return ret; -} -#else -static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, - struct address_space *mc, - pgoff_t index, - unsigned int clusterpages, - enum z_erofs_cache_alloctype type, - struct list_head *pagepool, - gfp_t gfp) -{ - /* nowhere to load compressed pages from */ -} -#endif - -/* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ -static inline bool try_to_reuse_as_compressed_page( - struct z_erofs_vle_work_builder *b, - struct page *page) -{ - while (b->compressed_deficit) { - --b->compressed_deficit; - if (!cmpxchg(b->compressed_pages++, NULL, page)) - return true; - } - - return false; -} - -/* callers must be with work->lock held */ -static int z_erofs_vle_work_add_page( - struct z_erofs_vle_work_builder *builder, - struct page *page, - enum z_erofs_page_type type) -{ - int ret; - bool occupied; - - /* give priority for the compressed data storage */ - if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY && - type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && - try_to_reuse_as_compressed_page(builder, page)) - return 0; - - ret = z_erofs_pagevec_ctor_enqueue(&builder->vector, - page, type, &occupied); - builder->work->vcnt += (unsigned int)ret; - - return ret ? 0 : -EAGAIN; -} - -static enum z_erofs_vle_work_role -try_to_claim_workgroup(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t *owned_head, - bool *hosted) -{ - DBG_BUGON(*hosted); - - /* let's claim these following types of workgroup */ -retry: - if (grp->next == Z_EROFS_VLE_WORKGRP_NIL) { - /* type 1, nil workgroup */ - if (cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_NIL, - *owned_head) != Z_EROFS_VLE_WORKGRP_NIL) - goto retry; - - *owned_head = &grp->next; - *hosted = true; - /* lucky, I am the followee :) */ - return Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED; - - } else if (grp->next == Z_EROFS_VLE_WORKGRP_TAIL) { - /* - * type 2, link to the end of a existing open chain, - * be careful that its submission itself is governed - * by the original owned chain. - */ - if (cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_TAIL, - *owned_head) != Z_EROFS_VLE_WORKGRP_TAIL) - goto retry; - *owned_head = Z_EROFS_VLE_WORKGRP_TAIL; - return Z_EROFS_VLE_WORK_PRIMARY_HOOKED; - } - - return Z_EROFS_VLE_WORK_PRIMARY; /* :( better luck next time */ -} - -struct z_erofs_vle_work_finder { - struct super_block *sb; - pgoff_t idx; - unsigned int pageofs; - - struct z_erofs_vle_workgroup **grp_ret; - enum z_erofs_vle_work_role *role; - z_erofs_vle_owned_workgrp_t *owned_head; - bool *hosted; -}; - -static struct z_erofs_vle_work * -z_erofs_vle_work_lookup(const struct z_erofs_vle_work_finder *f) -{ - bool tag, primary; - struct erofs_workgroup *egrp; - struct z_erofs_vle_workgroup *grp; - struct z_erofs_vle_work *work; - - egrp = erofs_find_workgroup(f->sb, f->idx, &tag); - if (!egrp) { - *f->grp_ret = NULL; - return NULL; - } - - grp = container_of(egrp, struct z_erofs_vle_workgroup, obj); - *f->grp_ret = grp; - - work = z_erofs_vle_grab_work(grp, f->pageofs); - /* if multiref is disabled, `primary' is always true */ - primary = true; - - DBG_BUGON(work->pageofs != f->pageofs); - - /* - * lock must be taken first to avoid grp->next == NIL between - * claiming workgroup and adding pages: - * grp->next != NIL - * grp->next = NIL - * mutex_unlock_all - * mutex_lock(&work->lock) - * add all pages to pagevec - * - * [correct locking case 1]: - * mutex_lock(grp->work[a]) - * ... - * mutex_lock(grp->work[b]) mutex_lock(grp->work[c]) - * ... *role = SECONDARY - * add all pages to pagevec - * ... - * mutex_unlock(grp->work[c]) - * mutex_lock(grp->work[c]) - * ... - * grp->next = NIL - * mutex_unlock_all - * - * [correct locking case 2]: - * mutex_lock(grp->work[b]) - * ... - * mutex_lock(grp->work[a]) - * ... - * mutex_lock(grp->work[c]) - * ... - * grp->next = NIL - * mutex_unlock_all - * mutex_lock(grp->work[a]) - * *role = PRIMARY_OWNER - * add all pages to pagevec - * ... - */ - mutex_lock(&work->lock); - - *f->hosted = false; - if (!primary) - *f->role = Z_EROFS_VLE_WORK_SECONDARY; - else /* claim the workgroup if possible */ - *f->role = try_to_claim_workgroup(grp, f->owned_head, - f->hosted); - return work; -} - -static struct z_erofs_vle_work * -z_erofs_vle_work_register(const struct z_erofs_vle_work_finder *f, - struct erofs_map_blocks *map) -{ - bool gnew = false; - struct z_erofs_vle_workgroup *grp = *f->grp_ret; - struct z_erofs_vle_work *work; - - /* if multiref is disabled, grp should never be nullptr */ - if (unlikely(grp)) { - DBG_BUGON(1); - return ERR_PTR(-EINVAL); - } - - /* no available workgroup, let's allocate one */ - grp = kmem_cache_alloc(z_erofs_workgroup_cachep, GFP_NOFS); - if (unlikely(!grp)) - return ERR_PTR(-ENOMEM); - - init_always(grp); - grp->obj.index = f->idx; - grp->llen = map->m_llen; - - z_erofs_vle_set_workgrp_fmt(grp, (map->m_flags & EROFS_MAP_ZIPPED) ? - Z_EROFS_VLE_WORKGRP_FMT_LZ4 : - Z_EROFS_VLE_WORKGRP_FMT_PLAIN); - - if (map->m_flags & EROFS_MAP_FULL_MAPPED) - grp->flags |= Z_EROFS_VLE_WORKGRP_FULL_LENGTH; - - /* new workgrps have been claimed as type 1 */ - WRITE_ONCE(grp->next, *f->owned_head); - /* primary and followed work for all new workgrps */ - *f->role = Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED; - /* it should be submitted by ourselves */ - *f->hosted = true; - - gnew = true; - work = z_erofs_vle_grab_primary_work(grp); - work->pageofs = f->pageofs; - - /* - * lock all primary followed works before visible to others - * and mutex_trylock *never* fails for a new workgroup. - */ - mutex_trylock(&work->lock); - - if (gnew) { - int err = erofs_register_workgroup(f->sb, &grp->obj, 0); - - if (err) { - mutex_unlock(&work->lock); - kmem_cache_free(z_erofs_workgroup_cachep, grp); - return ERR_PTR(-EAGAIN); - } - } - - *f->owned_head = &grp->next; - *f->grp_ret = grp; - return work; -} - -#define builder_is_hooked(builder) \ - ((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_HOOKED) - -#define builder_is_followed(builder) \ - ((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED) - -static int z_erofs_vle_work_iter_begin(struct z_erofs_vle_work_builder *builder, - struct super_block *sb, - struct erofs_map_blocks *map, - z_erofs_vle_owned_workgrp_t *owned_head) -{ - const unsigned int clusterpages = erofs_clusterpages(EROFS_SB(sb)); - struct z_erofs_vle_workgroup *grp; - const struct z_erofs_vle_work_finder finder = { - .sb = sb, - .idx = erofs_blknr(map->m_pa), - .pageofs = map->m_la & ~PAGE_MASK, - .grp_ret = &grp, - .role = &builder->role, - .owned_head = owned_head, - .hosted = &builder->hosted - }; - struct z_erofs_vle_work *work; - - DBG_BUGON(builder->work); - - /* must be Z_EROFS_WORK_TAIL or the next chained work */ - DBG_BUGON(*owned_head == Z_EROFS_VLE_WORKGRP_NIL); - DBG_BUGON(*owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - - DBG_BUGON(erofs_blkoff(map->m_pa)); - -repeat: - work = z_erofs_vle_work_lookup(&finder); - if (work) { - unsigned int orig_llen; - - /* increase workgroup `llen' if needed */ - while ((orig_llen = READ_ONCE(grp->llen)) < map->m_llen && - orig_llen != cmpxchg_relaxed(&grp->llen, - orig_llen, map->m_llen)) - cpu_relax(); - goto got_it; - } - - work = z_erofs_vle_work_register(&finder, map); - if (unlikely(work == ERR_PTR(-EAGAIN))) - goto repeat; - - if (IS_ERR(work)) - return PTR_ERR(work); -got_it: - z_erofs_pagevec_ctor_init(&builder->vector, Z_EROFS_NR_INLINE_PAGEVECS, - work->pagevec, work->vcnt); - - if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY) { - /* enable possibly in-place decompression */ - builder->compressed_pages = grp->compressed_pages; - builder->compressed_deficit = clusterpages; - } else { - builder->compressed_pages = NULL; - builder->compressed_deficit = 0; - } - - builder->grp = grp; - builder->work = work; - return 0; -} - -/* - * keep in mind that no referenced workgroups will be freed - * only after a RCU grace period, so rcu_read_lock() could - * prevent a workgroup from being freed. - */ -static void z_erofs_rcu_callback(struct rcu_head *head) -{ - struct z_erofs_vle_work *work = container_of(head, - struct z_erofs_vle_work, rcu); - struct z_erofs_vle_workgroup *grp = - z_erofs_vle_work_workgroup(work, true); - - kmem_cache_free(z_erofs_workgroup_cachep, grp); -} - -void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) -{ - struct z_erofs_vle_workgroup *const vgrp = container_of(grp, - struct z_erofs_vle_workgroup, obj); - struct z_erofs_vle_work *const work = &vgrp->work; - - call_rcu(&work->rcu, z_erofs_rcu_callback); -} - -static void -__z_erofs_vle_work_release(struct z_erofs_vle_workgroup *grp, - struct z_erofs_vle_work *work __maybe_unused) -{ - erofs_workgroup_put(&grp->obj); -} - -static void z_erofs_vle_work_release(struct z_erofs_vle_work *work) -{ - struct z_erofs_vle_workgroup *grp = - z_erofs_vle_work_workgroup(work, true); - - __z_erofs_vle_work_release(grp, work); -} - -static inline bool -z_erofs_vle_work_iter_end(struct z_erofs_vle_work_builder *builder) -{ - struct z_erofs_vle_work *work = builder->work; - - if (!work) - return false; - - z_erofs_pagevec_ctor_exit(&builder->vector, false); - mutex_unlock(&work->lock); - - /* - * if all pending pages are added, don't hold work reference - * any longer if the current work isn't hosted by ourselves. - */ - if (!builder->hosted) - __z_erofs_vle_work_release(builder->grp, work); - - builder->work = NULL; - builder->grp = NULL; - return true; -} - -static inline struct page *__stagingpage_alloc(struct list_head *pagepool, - gfp_t gfp) -{ - struct page *page = erofs_allocpage(pagepool, gfp); - - if (unlikely(!page)) - return NULL; - - page->mapping = Z_EROFS_MAPPING_STAGING; - return page; -} - -struct z_erofs_vle_frontend { - struct inode *const inode; - - struct z_erofs_vle_work_builder builder; - struct erofs_map_blocks map; - - z_erofs_vle_owned_workgrp_t owned_head; - - /* used for applying cache strategy on the fly */ - bool backmost; - erofs_off_t headoffset; -}; - -#define VLE_FRONTEND_INIT(__i) { \ - .inode = __i, \ - .map = { \ - .m_llen = 0, \ - .m_plen = 0, \ - .mpage = NULL \ - }, \ - .builder = VLE_WORK_BUILDER_INIT(), \ - .owned_head = Z_EROFS_VLE_WORKGRP_TAIL, \ - .backmost = true, } - -#ifdef EROFS_FS_HAS_MANAGED_CACHE -static inline bool -should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) -{ - if (fe->backmost) - return true; - - if (EROFS_FS_ZIP_CACHE_LVL >= 2) - return la < fe->headoffset; - - return false; -} -#else -static inline bool -should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) -{ - return false; -} -#endif - -static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, - struct page *page, - struct list_head *page_pool) -{ - struct super_block *const sb = fe->inode->i_sb; - struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); - struct erofs_map_blocks *const map = &fe->map; - struct z_erofs_vle_work_builder *const builder = &fe->builder; - const loff_t offset = page_offset(page); - - bool tight = builder_is_hooked(builder); - struct z_erofs_vle_work *work = builder->work; - - enum z_erofs_cache_alloctype cache_strategy; - enum z_erofs_page_type page_type; - unsigned int cur, end, spiltted, index; - int err = 0; - - /* register locked file pages as online pages in pack */ - z_erofs_onlinepage_init(page); - - spiltted = 0; - end = PAGE_SIZE; -repeat: - cur = end - 1; - - /* lucky, within the range of the current map_blocks */ - if (offset + cur >= map->m_la && - offset + cur < map->m_la + map->m_llen) { - /* didn't get a valid unzip work previously (very rare) */ - if (!builder->work) - goto restart_now; - goto hitted; - } - - /* go ahead the next map_blocks */ - debugln("%s: [out-of-range] pos %llu", __func__, offset + cur); - - if (z_erofs_vle_work_iter_end(builder)) - fe->backmost = false; - - map->m_la = offset + cur; - map->m_llen = 0; - err = z_erofs_map_blocks_iter(fe->inode, map, 0); - if (unlikely(err)) - goto err_out; - -restart_now: - if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) - goto hitted; - - DBG_BUGON(map->m_plen != 1 << sbi->clusterbits); - DBG_BUGON(erofs_blkoff(map->m_pa)); - - err = z_erofs_vle_work_iter_begin(builder, sb, map, &fe->owned_head); - if (unlikely(err)) - goto err_out; - - /* preload all compressed pages (maybe downgrade role if necessary) */ - if (should_alloc_managed_pages(fe, map->m_la)) - cache_strategy = DELAYEDALLOC; - else - cache_strategy = DONTALLOC; - - preload_compressed_pages(builder, MNGD_MAPPING(sbi), - map->m_pa / PAGE_SIZE, - map->m_plen / PAGE_SIZE, - cache_strategy, page_pool, GFP_KERNEL); - - tight &= builder_is_hooked(builder); - work = builder->work; -hitted: - cur = end - min_t(unsigned int, offset + end - map->m_la, end); - if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) { - zero_user_segment(page, cur, end); - goto next_part; - } - - /* let's derive page type */ - page_type = cur ? Z_EROFS_VLE_PAGE_TYPE_HEAD : - (!spiltted ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : - (tight ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : - Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED)); - - if (cur) - tight &= builder_is_followed(builder); - -retry: - err = z_erofs_vle_work_add_page(builder, page, page_type); - /* should allocate an additional staging page for pagevec */ - if (err == -EAGAIN) { - struct page *const newpage = - __stagingpage_alloc(page_pool, GFP_NOFS); - - err = z_erofs_vle_work_add_page(builder, newpage, - Z_EROFS_PAGE_TYPE_EXCLUSIVE); - if (likely(!err)) - goto retry; - } - - if (unlikely(err)) - goto err_out; - - index = page->index - map->m_la / PAGE_SIZE; - - /* FIXME! avoid the last relundant fixup & endio */ - z_erofs_onlinepage_fixup(page, index, true); - - /* bump up the number of spiltted parts of a page */ - ++spiltted; - /* also update nr_pages */ - work->nr_pages = max_t(pgoff_t, work->nr_pages, index + 1); -next_part: - /* can be used for verification */ - map->m_llen = offset + cur - map->m_la; - - end = cur; - if (end > 0) - goto repeat; - -out: - /* FIXME! avoid the last relundant fixup & endio */ - z_erofs_onlinepage_endio(page); - - debugln("%s, finish page: %pK spiltted: %u map->m_llen %llu", - __func__, page, spiltted, map->m_llen); - return err; - - /* if some error occurred while processing this page */ -err_out: - SetPageError(page); - goto out; -} - -static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) -{ - tagptr1_t t = tagptr_init(tagptr1_t, ptr); - struct z_erofs_vle_unzip_io *io = tagptr_unfold_ptr(t); - bool background = tagptr_unfold_tags(t); - - if (!background) { - unsigned long flags; - - spin_lock_irqsave(&io->u.wait.lock, flags); - if (!atomic_add_return(bios, &io->pending_bios)) - wake_up_locked(&io->u.wait); - spin_unlock_irqrestore(&io->u.wait.lock, flags); - return; - } - - if (!atomic_add_return(bios, &io->pending_bios)) - queue_work(z_erofs_workqueue, &io->u.work); -} - -static inline void z_erofs_vle_read_endio(struct bio *bio) -{ - struct erofs_sb_info *sbi = NULL; - blk_status_t err = bio->bi_status; - struct bio_vec *bvec; - struct bvec_iter_all iter_all; - - bio_for_each_segment_all(bvec, bio, iter_all) { - struct page *page = bvec->bv_page; - bool cachemngd = false; - - DBG_BUGON(PageUptodate(page)); - DBG_BUGON(!page->mapping); - - if (unlikely(!sbi && !z_erofs_page_is_staging(page))) { - sbi = EROFS_SB(page->mapping->host->i_sb); - - if (time_to_inject(sbi, FAULT_READ_IO)) { - erofs_show_injection_info(FAULT_READ_IO); - err = BLK_STS_IOERR; - } - } - - /* sbi should already be gotten if the page is managed */ - if (sbi) - cachemngd = erofs_page_is_managed(sbi, page); - - if (unlikely(err)) - SetPageError(page); - else if (cachemngd) - SetPageUptodate(page); - - if (cachemngd) - unlock_page(page); - } - - z_erofs_vle_unzip_kickoff(bio->bi_private, -1); - bio_put(bio); -} - -static struct page *z_pagemap_global[Z_EROFS_VLE_VMAP_GLOBAL_PAGES]; -static DEFINE_MUTEX(z_pagemap_global_lock); - -static int z_erofs_vle_unzip(struct super_block *sb, - struct z_erofs_vle_workgroup *grp, - struct list_head *page_pool) -{ - struct erofs_sb_info *const sbi = EROFS_SB(sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - - struct z_erofs_pagevec_ctor ctor; - unsigned int nr_pages; - unsigned int sparsemem_pages = 0; - struct page *pages_onstack[Z_EROFS_VLE_VMAP_ONSTACK_PAGES]; - struct page **pages, **compressed_pages, *page; - unsigned int algorithm; - unsigned int i, outputsize; - - enum z_erofs_page_type page_type; - bool overlapped, partial; - struct z_erofs_vle_work *work; - int err; - - might_sleep(); - work = z_erofs_vle_grab_primary_work(grp); - DBG_BUGON(!READ_ONCE(work->nr_pages)); - - mutex_lock(&work->lock); - nr_pages = work->nr_pages; - - if (likely(nr_pages <= Z_EROFS_VLE_VMAP_ONSTACK_PAGES)) - pages = pages_onstack; - else if (nr_pages <= Z_EROFS_VLE_VMAP_GLOBAL_PAGES && - mutex_trylock(&z_pagemap_global_lock)) - pages = z_pagemap_global; - else { -repeat: - pages = kvmalloc_array(nr_pages, sizeof(struct page *), - GFP_KERNEL); - - /* fallback to global pagemap for the lowmem scenario */ - if (unlikely(!pages)) { - if (nr_pages > Z_EROFS_VLE_VMAP_GLOBAL_PAGES) - goto repeat; - else { - mutex_lock(&z_pagemap_global_lock); - pages = z_pagemap_global; - } - } - } - - for (i = 0; i < nr_pages; ++i) - pages[i] = NULL; - - z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_NR_INLINE_PAGEVECS, - work->pagevec, 0); - - for (i = 0; i < work->vcnt; ++i) { - unsigned int pagenr; - - page = z_erofs_pagevec_ctor_dequeue(&ctor, &page_type); - - /* all pages in pagevec ought to be valid */ - DBG_BUGON(!page); - DBG_BUGON(!page->mapping); - - if (z_erofs_put_stagingpage(page_pool, page)) - continue; - - if (page_type == Z_EROFS_VLE_PAGE_TYPE_HEAD) - pagenr = 0; - else - pagenr = z_erofs_onlinepage_index(page); - - DBG_BUGON(pagenr >= nr_pages); - DBG_BUGON(pages[pagenr]); - - pages[pagenr] = page; - } - sparsemem_pages = i; - - z_erofs_pagevec_ctor_exit(&ctor, true); - - overlapped = false; - compressed_pages = grp->compressed_pages; - - err = 0; - for (i = 0; i < clusterpages; ++i) { - unsigned int pagenr; - - page = compressed_pages[i]; - - /* all compressed pages ought to be valid */ - DBG_BUGON(!page); - DBG_BUGON(!page->mapping); - - if (!z_erofs_page_is_staging(page)) { - if (erofs_page_is_managed(sbi, page)) { - if (unlikely(!PageUptodate(page))) - err = -EIO; - continue; - } - - /* - * only if non-head page can be selected - * for inplace decompression - */ - pagenr = z_erofs_onlinepage_index(page); - - DBG_BUGON(pagenr >= nr_pages); - DBG_BUGON(pages[pagenr]); - ++sparsemem_pages; - pages[pagenr] = page; - - overlapped = true; - } - - /* PG_error needs checking for inplaced and staging pages */ - if (unlikely(PageError(page))) { - DBG_BUGON(PageUptodate(page)); - err = -EIO; - } - } - - if (unlikely(err)) - goto out; - - if (nr_pages << PAGE_SHIFT >= work->pageofs + grp->llen) { - outputsize = grp->llen; - partial = !(grp->flags & Z_EROFS_VLE_WORKGRP_FULL_LENGTH); - } else { - outputsize = (nr_pages << PAGE_SHIFT) - work->pageofs; - partial = true; - } - - if (z_erofs_vle_workgrp_fmt(grp) == Z_EROFS_VLE_WORKGRP_FMT_PLAIN) - algorithm = Z_EROFS_COMPRESSION_SHIFTED; - else - algorithm = Z_EROFS_COMPRESSION_LZ4; - - err = z_erofs_decompress(&(struct z_erofs_decompress_req) { - .sb = sb, - .in = compressed_pages, - .out = pages, - .pageofs_out = work->pageofs, - .inputsize = PAGE_SIZE, - .outputsize = outputsize, - .alg = algorithm, - .inplace_io = overlapped, - .partial_decoding = partial - }, page_pool); - -out: - /* must handle all compressed pages before endding pages */ - for (i = 0; i < clusterpages; ++i) { - page = compressed_pages[i]; - - if (erofs_page_is_managed(sbi, page)) - continue; - - /* recycle all individual staging pages */ - (void)z_erofs_put_stagingpage(page_pool, page); - - WRITE_ONCE(compressed_pages[i], NULL); - } - - for (i = 0; i < nr_pages; ++i) { - page = pages[i]; - if (!page) - continue; - - DBG_BUGON(!page->mapping); - - /* recycle all individual staging pages */ - if (z_erofs_put_stagingpage(page_pool, page)) - continue; - - if (unlikely(err < 0)) - SetPageError(page); - - z_erofs_onlinepage_endio(page); - } - - if (pages == z_pagemap_global) - mutex_unlock(&z_pagemap_global_lock); - else if (unlikely(pages != pages_onstack)) - kvfree(pages); - - work->nr_pages = 0; - work->vcnt = 0; - - /* all work locks MUST be taken before the following line */ - - WRITE_ONCE(grp->next, Z_EROFS_VLE_WORKGRP_NIL); - - /* all work locks SHOULD be released right now */ - mutex_unlock(&work->lock); - - z_erofs_vle_work_release(work); - return err; -} - -static void z_erofs_vle_unzip_all(struct super_block *sb, - struct z_erofs_vle_unzip_io *io, - struct list_head *page_pool) -{ - z_erofs_vle_owned_workgrp_t owned = io->head; - - while (owned != Z_EROFS_VLE_WORKGRP_TAIL_CLOSED) { - struct z_erofs_vle_workgroup *grp; - - /* no possible that 'owned' equals Z_EROFS_WORK_TPTR_TAIL */ - DBG_BUGON(owned == Z_EROFS_VLE_WORKGRP_TAIL); - - /* no possible that 'owned' equals NULL */ - DBG_BUGON(owned == Z_EROFS_VLE_WORKGRP_NIL); - - grp = container_of(owned, struct z_erofs_vle_workgroup, next); - owned = READ_ONCE(grp->next); - - z_erofs_vle_unzip(sb, grp, page_pool); - } -} - -static void z_erofs_vle_unzip_wq(struct work_struct *work) -{ - struct z_erofs_vle_unzip_io_sb *iosb = container_of(work, - struct z_erofs_vle_unzip_io_sb, io.u.work); - LIST_HEAD(page_pool); - - DBG_BUGON(iosb->io.head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &page_pool); - - put_pages_list(&page_pool); - kvfree(iosb); -} - -static struct page * -pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, - unsigned int nr, - struct list_head *pagepool, - struct address_space *mc, - gfp_t gfp) -{ - /* determined at compile time to avoid too many #ifdefs */ - const bool nocache = __builtin_constant_p(mc) ? !mc : false; - const pgoff_t index = grp->obj.index; - bool tocache = false; - - struct address_space *mapping; - struct page *oldpage, *page; - - compressed_page_t t; - int justfound; - -repeat: - page = READ_ONCE(grp->compressed_pages[nr]); - oldpage = page; - - if (!page) - goto out_allocpage; - - /* - * the cached page has not been allocated and - * an placeholder is out there, prepare it now. - */ - if (!nocache && page == PAGE_UNALLOCATED) { - tocache = true; - goto out_allocpage; - } - - /* process the target tagged pointer */ - t = tagptr_init(compressed_page_t, page); - justfound = tagptr_unfold_tags(t); - page = tagptr_unfold_ptr(t); - - mapping = READ_ONCE(page->mapping); - - /* - * if managed cache is disabled, it's no way to - * get such a cached-like page. - */ - if (nocache) { - /* if managed cache is disabled, it is impossible `justfound' */ - DBG_BUGON(justfound); - - /* and it should be locked, not uptodate, and not truncated */ - DBG_BUGON(!PageLocked(page)); - DBG_BUGON(PageUptodate(page)); - DBG_BUGON(!mapping); - goto out; - } - - /* - * unmanaged (file) pages are all locked solidly, - * therefore it is impossible for `mapping' to be NULL. - */ - if (mapping && mapping != mc) - /* ought to be unmanaged pages */ - goto out; - - lock_page(page); - - /* only true if page reclaim goes wrong, should never happen */ - DBG_BUGON(justfound && PagePrivate(page)); - - /* the page is still in manage cache */ - if (page->mapping == mc) { - WRITE_ONCE(grp->compressed_pages[nr], page); - - ClearPageError(page); - if (!PagePrivate(page)) { - /* - * impossible to be !PagePrivate(page) for - * the current restriction as well if - * the page is already in compressed_pages[]. - */ - DBG_BUGON(!justfound); - - justfound = 0; - set_page_private(page, (unsigned long)grp); - SetPagePrivate(page); - } - - /* no need to submit io if it is already up-to-date */ - if (PageUptodate(page)) { - unlock_page(page); - page = NULL; - } - goto out; - } - - /* - * the managed page has been truncated, it's unsafe to - * reuse this one, let's allocate a new cache-managed page. - */ - DBG_BUGON(page->mapping); - DBG_BUGON(!justfound); - - tocache = true; - unlock_page(page); - put_page(page); -out_allocpage: - page = __stagingpage_alloc(pagepool, gfp); - if (oldpage != cmpxchg(&grp->compressed_pages[nr], oldpage, page)) { - list_add(&page->lru, pagepool); - cpu_relax(); - goto repeat; - } - if (nocache || !tocache) - goto out; - if (add_to_page_cache_lru(page, mc, index + nr, gfp)) { - page->mapping = Z_EROFS_MAPPING_STAGING; - goto out; - } - - set_page_private(page, (unsigned long)grp); - SetPagePrivate(page); -out: /* the only exit (for tracing and debugging) */ - return page; -} - -static struct z_erofs_vle_unzip_io * -jobqueue_init(struct super_block *sb, - struct z_erofs_vle_unzip_io *io, - bool foreground) -{ - struct z_erofs_vle_unzip_io_sb *iosb; - - if (foreground) { - /* waitqueue available for foreground io */ - DBG_BUGON(!io); - - init_waitqueue_head(&io->u.wait); - atomic_set(&io->pending_bios, 0); - goto out; - } - - iosb = kvzalloc(sizeof(*iosb), GFP_KERNEL | __GFP_NOFAIL); - DBG_BUGON(!iosb); - - /* initialize fields in the allocated descriptor */ - io = &iosb->io; - iosb->sb = sb; - INIT_WORK(&io->u.work, z_erofs_vle_unzip_wq); -out: - io->head = Z_EROFS_VLE_WORKGRP_TAIL_CLOSED; - return io; -} - -/* define workgroup jobqueue types */ -enum { -#ifdef EROFS_FS_HAS_MANAGED_CACHE - JQ_BYPASS, -#endif - JQ_SUBMIT, - NR_JOBQUEUES, -}; - -static void *jobqueueset_init(struct super_block *sb, - z_erofs_vle_owned_workgrp_t qtail[], - struct z_erofs_vle_unzip_io *q[], - struct z_erofs_vle_unzip_io *fgq, - bool forcefg) -{ -#ifdef EROFS_FS_HAS_MANAGED_CACHE - /* - * if managed cache is enabled, bypass jobqueue is needed, - * no need to read from device for all workgroups in this queue. - */ - q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); - qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; -#endif - - q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg); - qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; - - return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg)); -} - -#ifdef EROFS_FS_HAS_MANAGED_CACHE -static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t qtail[], - z_erofs_vle_owned_workgrp_t owned_head) -{ - z_erofs_vle_owned_workgrp_t *const submit_qtail = qtail[JQ_SUBMIT]; - z_erofs_vle_owned_workgrp_t *const bypass_qtail = qtail[JQ_BYPASS]; - - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - if (owned_head == Z_EROFS_VLE_WORKGRP_TAIL) - owned_head = Z_EROFS_VLE_WORKGRP_TAIL_CLOSED; - - WRITE_ONCE(grp->next, Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - - WRITE_ONCE(*submit_qtail, owned_head); - WRITE_ONCE(*bypass_qtail, &grp->next); - - qtail[JQ_BYPASS] = &grp->next; -} - -static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], - unsigned int nr_bios, - bool force_fg) -{ - /* - * although background is preferred, no one is pending for submission. - * don't issue workqueue for decompression but drop it directly instead. - */ - if (force_fg || nr_bios) - return false; - - kvfree(container_of(q[JQ_SUBMIT], - struct z_erofs_vle_unzip_io_sb, - io)); - return true; -} -#else -static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t qtail[], - z_erofs_vle_owned_workgrp_t owned_head) -{ - /* impossible to bypass submission for managed cache disabled */ - DBG_BUGON(1); -} - -static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], - unsigned int nr_bios, - bool force_fg) -{ - /* bios should be >0 if managed cache is disabled */ - DBG_BUGON(!nr_bios); - return false; -} -#endif - -static bool z_erofs_vle_submit_all(struct super_block *sb, - z_erofs_vle_owned_workgrp_t owned_head, - struct list_head *pagepool, - struct z_erofs_vle_unzip_io *fgq, - bool force_fg) -{ - struct erofs_sb_info *const sbi = EROFS_SB(sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - const gfp_t gfp = GFP_NOFS; - - z_erofs_vle_owned_workgrp_t qtail[NR_JOBQUEUES]; - struct z_erofs_vle_unzip_io *q[NR_JOBQUEUES]; - struct bio *bio; - void *bi_private; - /* since bio will be NULL, no need to initialize last_index */ - pgoff_t uninitialized_var(last_index); - bool force_submit = false; - unsigned int nr_bios; - - if (unlikely(owned_head == Z_EROFS_VLE_WORKGRP_TAIL)) - return false; - - force_submit = false; - bio = NULL; - nr_bios = 0; - bi_private = jobqueueset_init(sb, qtail, q, fgq, force_fg); - - /* by default, all need io submission */ - q[JQ_SUBMIT]->head = owned_head; - - do { - struct z_erofs_vle_workgroup *grp; - pgoff_t first_index; - struct page *page; - unsigned int i = 0, bypass = 0; - int err; - - /* no possible 'owned_head' equals the following */ - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_NIL); - - grp = container_of(owned_head, - struct z_erofs_vle_workgroup, next); - - /* close the main owned chain at first */ - owned_head = cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_TAIL, - Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - - first_index = grp->obj.index; - force_submit |= (first_index != last_index + 1); - -repeat: - page = pickup_page_for_submission(grp, i, pagepool, - MNGD_MAPPING(sbi), gfp); - if (!page) { - force_submit = true; - ++bypass; - goto skippage; - } - - if (bio && force_submit) { -submit_bio_retry: - __submit_bio(bio, REQ_OP_READ, 0); - bio = NULL; - } - - if (!bio) { - bio = erofs_grab_bio(sb, first_index + i, - BIO_MAX_PAGES, bi_private, - z_erofs_vle_read_endio, true); - ++nr_bios; - } - - err = bio_add_page(bio, page, PAGE_SIZE, 0); - if (err < PAGE_SIZE) - goto submit_bio_retry; - - force_submit = false; - last_index = first_index + i; -skippage: - if (++i < clusterpages) - goto repeat; - - if (bypass < clusterpages) - qtail[JQ_SUBMIT] = &grp->next; - else - move_to_bypass_jobqueue(grp, qtail, owned_head); - } while (owned_head != Z_EROFS_VLE_WORKGRP_TAIL); - - if (bio) - __submit_bio(bio, REQ_OP_READ, 0); - - if (postsubmit_is_all_bypassed(q, nr_bios, force_fg)) - return true; - - z_erofs_vle_unzip_kickoff(bi_private, nr_bios); - return true; -} - -static void z_erofs_submit_and_unzip(struct z_erofs_vle_frontend *f, - struct list_head *pagepool, - bool force_fg) -{ - struct super_block *sb = f->inode->i_sb; - struct z_erofs_vle_unzip_io io[NR_JOBQUEUES]; - - if (!z_erofs_vle_submit_all(sb, f->owned_head, pagepool, io, force_fg)) - return; - -#ifdef EROFS_FS_HAS_MANAGED_CACHE - z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); -#endif - if (!force_fg) - return; - - /* wait until all bios are completed */ - wait_event(io[JQ_SUBMIT].u.wait, - !atomic_read(&io[JQ_SUBMIT].pending_bios)); - - /* let's synchronous decompression */ - z_erofs_vle_unzip_all(sb, &io[JQ_SUBMIT], pagepool); -} - -static int z_erofs_vle_normalaccess_readpage(struct file *file, - struct page *page) -{ - struct inode *const inode = page->mapping->host; - struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); - int err; - LIST_HEAD(pagepool); - - trace_erofs_readpage(page, false); - - f.headoffset = (erofs_off_t)page->index << PAGE_SHIFT; - - err = z_erofs_do_read_page(&f, page, &pagepool); - (void)z_erofs_vle_work_iter_end(&f.builder); - - if (err) { - errln("%s, failed to read, err [%d]", __func__, err); - goto out; - } - - z_erofs_submit_and_unzip(&f, &pagepool, true); -out: - if (f.map.mpage) - put_page(f.map.mpage); - - /* clean up the remaining free pages */ - put_pages_list(&pagepool); - return 0; -} - -static int z_erofs_vle_normalaccess_readpages(struct file *filp, - struct address_space *mapping, - struct list_head *pages, - unsigned int nr_pages) -{ - struct inode *const inode = mapping->host; - struct erofs_sb_info *const sbi = EROFS_I_SB(inode); - - bool sync = __should_decompress_synchronously(sbi, nr_pages); - struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); - gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL); - struct page *head = NULL; - LIST_HEAD(pagepool); - - trace_erofs_readpages(mapping->host, lru_to_page(pages), - nr_pages, false); - - f.headoffset = (erofs_off_t)lru_to_page(pages)->index << PAGE_SHIFT; - - for (; nr_pages; --nr_pages) { - struct page *page = lru_to_page(pages); - - prefetchw(&page->flags); - list_del(&page->lru); - - /* - * A pure asynchronous readahead is indicated if - * a PG_readahead marked page is hitted at first. - * Let's also do asynchronous decompression for this case. - */ - sync &= !(PageReadahead(page) && !head); - - if (add_to_page_cache_lru(page, mapping, page->index, gfp)) { - list_add(&page->lru, &pagepool); - continue; - } - - set_page_private(page, (unsigned long)head); - head = page; - } - - while (head) { - struct page *page = head; - int err; - - /* traversal in reverse order */ - head = (void *)page_private(page); - - err = z_erofs_do_read_page(&f, page, &pagepool); - if (err) { - struct erofs_vnode *vi = EROFS_V(inode); - - errln("%s, readahead error at page %lu of nid %llu", - __func__, page->index, vi->nid); - } - - put_page(page); - } - - (void)z_erofs_vle_work_iter_end(&f.builder); - - z_erofs_submit_and_unzip(&f, &pagepool, sync); - - if (f.map.mpage) - put_page(f.map.mpage); - - /* clean up the remaining free pages */ - put_pages_list(&pagepool); - return 0; -} - -const struct address_space_operations z_erofs_vle_normalaccess_aops = { - .readpage = z_erofs_vle_normalaccess_readpage, - .readpages = z_erofs_vle_normalaccess_readpages, -}; - diff --git a/drivers/staging/exfat/Kconfig b/drivers/staging/exfat/Kconfig new file mode 100644 index 000000000000..290dbfc7ace1 --- /dev/null +++ b/drivers/staging/exfat/Kconfig @@ -0,0 +1,49 @@ +config EXFAT_FS + tristate "exFAT fs support" + depends on BLOCK + select NLS + help + This adds support for the exFAT file system. + +config EXFAT_DONT_MOUNT_VFAT + bool "Prohibit mounting of fat/vfat filesysems by exFAT" + depends on EXFAT_FS + default y + help + By default, the exFAT driver will only mount exFAT filesystems, and refuse + to mount fat/vfat filesystems. Set this to 'n' to allow the exFAT driver + to mount these filesystems. + +config EXFAT_DISCARD + bool "enable discard support" + depends on EXFAT_FS + default y + +config EXFAT_DELAYED_SYNC + bool "enable delayed sync" + depends on EXFAT_FS + default n + +config EXFAT_KERNEL_DEBUG + bool "enable kernel debug features via ioctl" + depends on EXFAT_FS + default n + +config EXFAT_DEBUG_MSG + bool "print debug messages" + depends on EXFAT_FS + default n + +config EXFAT_DEFAULT_CODEPAGE + int "Default codepage for exFAT" + default 437 + depends on EXFAT_FS + help + This option should be set to the codepage of your exFAT filesystems. + +config EXFAT_DEFAULT_IOCHARSET + string "Default iocharset for exFAT" + default "utf8" + depends on EXFAT_FS + help + Set this to the default input/output character set you'd like exFAT to use. diff --git a/drivers/staging/exfat/Makefile b/drivers/staging/exfat/Makefile new file mode 100644 index 000000000000..84944dfbae28 --- /dev/null +++ b/drivers/staging/exfat/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_EXFAT_FS) += exfat.o + +exfat-y := exfat_core.o \ + exfat_super.o \ + exfat_blkdev.o \ + exfat_cache.o \ + exfat_nls.o \ + exfat_upcase.o diff --git a/drivers/staging/exfat/TODO b/drivers/staging/exfat/TODO new file mode 100644 index 000000000000..a3eb282f9efc --- /dev/null +++ b/drivers/staging/exfat/TODO @@ -0,0 +1,12 @@ +exfat_core.c - ffsReadFile - the goto err_out seem to leak a brelse(). +same for ffsWriteFile. + +exfat_core.c - fs_sync(sb,0) all over the place looks fishy as hell. +There's only one place that calls it with a non-zero argument. + +ffsTruncateFile - if (old_size <= new_size) { +That doesn't look right. How did it ever work? Are they relying on lazy +block allocation when actual writes happen? If nothing else, it never +does the 'fid->size = new_size' and do the inode update.... + +ffsSetAttr() is just dangling in the breeze, not wired up at all... diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h new file mode 100644 index 000000000000..6c12f2d79f4d --- /dev/null +++ b/drivers/staging/exfat/exfat.h @@ -0,0 +1,971 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#ifndef _EXFAT_H +#define _EXFAT_H + +#include <linux/types.h> +#include <linux/buffer_head.h> + +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + /* For Debugging Purpose */ + /* IOCTL code 'f' used by + * - file systems typically #0~0x1F + * - embedded terminal devices #128~ + * - exts for debugging purpose #99 + * number 100 and 101 is available now but has possible conflicts + */ +#define EXFAT_IOC_GET_DEBUGFLAGS _IOR('f', 100, long) +#define EXFAT_IOC_SET_DEBUGFLAGS _IOW('f', 101, long) + +#define EXFAT_DEBUGFLAGS_INVALID_UMOUNT 0x01 +#define EXFAT_DEBUGFLAGS_ERROR_RW 0x02 +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + +#ifdef CONFIG_EXFAT_DEBUG_MSG +#define DEBUG 1 +#else +#undef DEBUG +#endif + +#define DENTRY_SIZE 32 /* dir entry size */ +#define DENTRY_SIZE_BITS 5 + +/* PBR entries */ +#define PBR_SIGNATURE 0xAA55 +#define EXT_SIGNATURE 0xAA550000 +#define VOL_LABEL "NO NAME " /* size should be 11 */ +#define OEM_NAME "MSWIN4.1" /* size should be 8 */ +#define STR_FAT12 "FAT12 " /* size should be 8 */ +#define STR_FAT16 "FAT16 " /* size should be 8 */ +#define STR_FAT32 "FAT32 " /* size should be 8 */ +#define STR_EXFAT "EXFAT " /* size should be 8 */ +#define VOL_CLEAN 0x0000 +#define VOL_DIRTY 0x0002 + +/* max number of clusters */ +#define FAT12_THRESHOLD 4087 /* 2^12 - 1 + 2 (clu 0 & 1) */ +#define FAT16_THRESHOLD 65527 /* 2^16 - 1 + 2 */ +#define FAT32_THRESHOLD 268435457 /* 2^28 - 1 + 2 */ +#define EXFAT_THRESHOLD 268435457 /* 2^28 - 1 + 2 */ + +/* file types */ +#define TYPE_UNUSED 0x0000 +#define TYPE_DELETED 0x0001 +#define TYPE_INVALID 0x0002 +#define TYPE_CRITICAL_PRI 0x0100 +#define TYPE_BITMAP 0x0101 +#define TYPE_UPCASE 0x0102 +#define TYPE_VOLUME 0x0103 +#define TYPE_DIR 0x0104 +#define TYPE_FILE 0x011F +#define TYPE_SYMLINK 0x015F +#define TYPE_CRITICAL_SEC 0x0200 +#define TYPE_STREAM 0x0201 +#define TYPE_EXTEND 0x0202 +#define TYPE_ACL 0x0203 +#define TYPE_BENIGN_PRI 0x0400 +#define TYPE_GUID 0x0401 +#define TYPE_PADDING 0x0402 +#define TYPE_ACLTAB 0x0403 +#define TYPE_BENIGN_SEC 0x0800 +#define TYPE_ALL 0x0FFF + +/* time modes */ +#define TM_CREATE 0 +#define TM_MODIFY 1 +#define TM_ACCESS 2 + +/* checksum types */ +#define CS_DIR_ENTRY 0 +#define CS_PBR_SECTOR 1 +#define CS_DEFAULT 2 + +#define CLUSTER_16(x) ((u16)(x)) +#define CLUSTER_32(x) ((u32)(x)) + +#define START_SECTOR(x) \ + ((((sector_t)((x) - 2)) << p_fs->sectors_per_clu_bits) + \ + p_fs->data_start_sector) + +#define IS_LAST_SECTOR_IN_CLUSTER(sec) \ + ((((sec) - p_fs->data_start_sector + 1) & \ + ((1 << p_fs->sectors_per_clu_bits) - 1)) == 0) + +#define GET_CLUSTER_FROM_SECTOR(sec) \ + ((u32)((((sec) - p_fs->data_start_sector) >> \ + p_fs->sectors_per_clu_bits) + 2)) + +#define GET16(p_src) \ + (((u16)(p_src)[0]) | (((u16)(p_src)[1]) << 8)) +#define GET32(p_src) \ + (((u32)(p_src)[0]) | (((u32)(p_src)[1]) << 8) | \ + (((u32)(p_src)[2]) << 16) | (((u32)(p_src)[3]) << 24)) +#define GET64(p_src) \ + (((u64)(p_src)[0]) | (((u64)(p_src)[1]) << 8) | \ + (((u64)(p_src)[2]) << 16) | (((u64)(p_src)[3]) << 24) | \ + (((u64)(p_src)[4]) << 32) | (((u64)(p_src)[5]) << 40) | \ + (((u64)(p_src)[6]) << 48) | (((u64)(p_src)[7]) << 56)) + +#define SET16(p_dst, src) \ + do { \ + (p_dst)[0] = (u8)(src); \ + (p_dst)[1] = (u8)(((u16)(src)) >> 8); \ + } while (0) +#define SET32(p_dst, src) \ + do { \ + (p_dst)[0] = (u8)(src); \ + (p_dst)[1] = (u8)(((u32)(src)) >> 8); \ + (p_dst)[2] = (u8)(((u32)(src)) >> 16); \ + (p_dst)[3] = (u8)(((u32)(src)) >> 24); \ + } while (0) +#define SET64(p_dst, src) \ + do { \ + (p_dst)[0] = (u8)(src); \ + (p_dst)[1] = (u8)(((u64)(src)) >> 8); \ + (p_dst)[2] = (u8)(((u64)(src)) >> 16); \ + (p_dst)[3] = (u8)(((u64)(src)) >> 24); \ + (p_dst)[4] = (u8)(((u64)(src)) >> 32); \ + (p_dst)[5] = (u8)(((u64)(src)) >> 40); \ + (p_dst)[6] = (u8)(((u64)(src)) >> 48); \ + (p_dst)[7] = (u8)(((u64)(src)) >> 56); \ + } while (0) + +#ifdef __LITTLE_ENDIAN +#define GET16_A(p_src) (*((u16 *)(p_src))) +#define GET32_A(p_src) (*((u32 *)(p_src))) +#define GET64_A(p_src) (*((u64 *)(p_src))) +#define SET16_A(p_dst, src) (*((u16 *)(p_dst)) = (u16)(src)) +#define SET32_A(p_dst, src) (*((u32 *)(p_dst)) = (u32)(src)) +#define SET64_A(p_dst, src) (*((u64 *)(p_dst)) = (u64)(src)) +#else /* BIG_ENDIAN */ +#define GET16_A(p_src) GET16(p_src) +#define GET32_A(p_src) GET32(p_src) +#define GET64_A(p_src) GET64(p_src) +#define SET16_A(p_dst, src) SET16(p_dst, src) +#define SET32_A(p_dst, src) SET32(p_dst, src) +#define SET64_A(p_dst, src) SET64(p_dst, src) +#endif + +/* cache size (in number of sectors) */ +/* (should be an exponential value of 2) */ +#define FAT_CACHE_SIZE 128 +#define FAT_CACHE_HASH_SIZE 64 +#define BUF_CACHE_SIZE 256 +#define BUF_CACHE_HASH_SIZE 64 + +/* Upcase table macro */ +#define HIGH_INDEX_BIT (8) +#define HIGH_INDEX_MASK (0xFF00) +#define LOW_INDEX_BIT (16 - HIGH_INDEX_BIT) +#define UTBL_ROW_COUNT BIT(LOW_INDEX_BIT) +#define UTBL_COL_COUNT BIT(HIGH_INDEX_BIT) + +static inline u16 get_col_index(u16 i) +{ + return i >> LOW_INDEX_BIT; +} + +static inline u16 get_row_index(u16 i) +{ + return i & ~HIGH_INDEX_MASK; +} + +#define EXFAT_SUPER_MAGIC (0x2011BAB0L) +#define EXFAT_ROOT_INO 1 + +/* FAT types */ +#define FAT12 0x01 /* FAT12 */ +#define FAT16 0x0E /* Win95 FAT16 (LBA) */ +#define FAT32 0x0C /* Win95 FAT32 (LBA) */ +#define EXFAT 0x07 /* exFAT */ + +/* file name lengths */ +#define MAX_CHARSET_SIZE 3 /* max size of multi-byte character */ +#define MAX_PATH_DEPTH 15 /* max depth of path name */ +#define MAX_NAME_LENGTH 256 /* max len of filename including NULL */ +#define MAX_PATH_LENGTH 260 /* max len of pathname including NULL */ +#define DOS_NAME_LENGTH 11 /* DOS filename length excluding NULL */ +#define DOS_PATH_LENGTH 80 /* DOS pathname length excluding NULL */ + +/* file attributes */ +#define ATTR_NORMAL 0x0000 +#define ATTR_READONLY 0x0001 +#define ATTR_HIDDEN 0x0002 +#define ATTR_SYSTEM 0x0004 +#define ATTR_VOLUME 0x0008 +#define ATTR_SUBDIR 0x0010 +#define ATTR_ARCHIVE 0x0020 +#define ATTR_SYMLINK 0x0040 +#define ATTR_EXTEND 0x000F +#define ATTR_RWMASK 0x007E + +/* file creation modes */ +#define FM_REGULAR 0x00 +#define FM_SYMLINK 0x40 + +/* return values */ +#define FFS_SUCCESS 0 +#define FFS_MEDIAERR 1 +#define FFS_FORMATERR 2 +#define FFS_MOUNTED 3 +#define FFS_NOTMOUNTED 4 +#define FFS_ALIGNMENTERR 5 +#define FFS_SEMAPHOREERR 6 +#define FFS_INVALIDPATH 7 +#define FFS_INVALIDFID 8 +#define FFS_NOTFOUND 9 +#define FFS_FILEEXIST 10 +#define FFS_PERMISSIONERR 11 +#define FFS_NOTOPENED 12 +#define FFS_MAXOPENED 13 +#define FFS_FULL 14 +#define FFS_EOF 15 +#define FFS_DIRBUSY 16 +#define FFS_MEMORYERR 17 +#define FFS_NAMETOOLONG 18 +#define FFS_ERROR 19 + +#define NUM_UPCASE 2918 + +#define DOS_CUR_DIR_NAME ". " +#define DOS_PAR_DIR_NAME ".. " + +#ifdef __LITTLE_ENDIAN +#define UNI_CUR_DIR_NAME ".\0" +#define UNI_PAR_DIR_NAME ".\0.\0" +#else +#define UNI_CUR_DIR_NAME "\0." +#define UNI_PAR_DIR_NAME "\0.\0." +#endif + +struct date_time_t { + u16 Year; + u16 Month; + u16 Day; + u16 Hour; + u16 Minute; + u16 Second; + u16 MilliSecond; +}; + +struct part_info_t { + u32 Offset; /* start sector number of the partition */ + u32 Size; /* in sectors */ +}; + +struct dev_info_t { + u32 SecSize; /* sector size in bytes */ + u32 DevSize; /* block device size in sectors */ +}; + +struct vol_info_t { + u32 FatType; + u32 ClusterSize; + u32 NumClusters; + u32 FreeClusters; + u32 UsedClusters; +}; + +/* directory structure */ +struct chain_t { + u32 dir; + s32 size; + u8 flags; +}; + +struct file_id_t { + struct chain_t dir; + s32 entry; + u32 type; + u32 attr; + u32 start_clu; + u64 size; + u8 flags; + s64 rwoffset; + s32 hint_last_off; + u32 hint_last_clu; +}; + +struct dir_entry_t { + char Name[MAX_NAME_LENGTH * MAX_CHARSET_SIZE]; + + /* used only for FAT12/16/32, not used for exFAT */ + char ShortName[DOS_NAME_LENGTH + 2]; + + u32 Attr; + u64 Size; + u32 NumSubdirs; + struct date_time_t CreateTimestamp; + struct date_time_t ModifyTimestamp; + struct date_time_t AccessTimestamp; +}; + +struct timestamp_t { + u16 sec; /* 0 ~ 59 */ + u16 min; /* 0 ~ 59 */ + u16 hour; /* 0 ~ 23 */ + u16 day; /* 1 ~ 31 */ + u16 mon; /* 1 ~ 12 */ + u16 year; /* 0 ~ 127 (since 1980) */ +}; + +/* MS_DOS FAT partition boot record (512 bytes) */ +struct pbr_sector_t { + u8 jmp_boot[3]; + u8 oem_name[8]; + u8 bpb[109]; + u8 boot_code[390]; + u8 signature[2]; +}; + +/* MS-DOS FAT12/16 BIOS parameter block (51 bytes) */ +struct bpb16_t { + u8 sector_size[2]; + u8 sectors_per_clu; + u8 num_reserved[2]; + u8 num_fats; + u8 num_root_entries[2]; + u8 num_sectors[2]; + u8 media_type; + u8 num_fat_sectors[2]; + u8 sectors_in_track[2]; + u8 num_heads[2]; + u8 num_hid_sectors[4]; + u8 num_huge_sectors[4]; + + u8 phy_drv_no; + u8 reserved; + u8 ext_signature; + u8 vol_serial[4]; + u8 vol_label[11]; + u8 vol_type[8]; +}; + +/* MS-DOS FAT32 BIOS parameter block (79 bytes) */ +struct bpb32_t { + u8 sector_size[2]; + u8 sectors_per_clu; + u8 num_reserved[2]; + u8 num_fats; + u8 num_root_entries[2]; + u8 num_sectors[2]; + u8 media_type; + u8 num_fat_sectors[2]; + u8 sectors_in_track[2]; + u8 num_heads[2]; + u8 num_hid_sectors[4]; + u8 num_huge_sectors[4]; + u8 num_fat32_sectors[4]; + u8 ext_flags[2]; + u8 fs_version[2]; + u8 root_cluster[4]; + u8 fsinfo_sector[2]; + u8 backup_sector[2]; + u8 reserved[12]; + + u8 phy_drv_no; + u8 ext_reserved; + u8 ext_signature; + u8 vol_serial[4]; + u8 vol_label[11]; + u8 vol_type[8]; +}; + +/* MS-DOS EXFAT BIOS parameter block (109 bytes) */ +struct bpbex_t { + u8 reserved1[53]; + u8 vol_offset[8]; + u8 vol_length[8]; + u8 fat_offset[4]; + u8 fat_length[4]; + u8 clu_offset[4]; + u8 clu_count[4]; + u8 root_cluster[4]; + u8 vol_serial[4]; + u8 fs_version[2]; + u8 vol_flags[2]; + u8 sector_size_bits; + u8 sectors_per_clu_bits; + u8 num_fats; + u8 phy_drv_no; + u8 perc_in_use; + u8 reserved2[7]; +}; + +/* MS-DOS FAT file system information sector (512 bytes) */ +struct fsi_sector_t { + u8 signature1[4]; + u8 reserved1[480]; + u8 signature2[4]; + u8 free_cluster[4]; + u8 next_cluster[4]; + u8 reserved2[14]; + u8 signature3[2]; +}; + +/* MS-DOS FAT directory entry (32 bytes) */ +struct dentry_t { + u8 dummy[32]; +}; + +struct dos_dentry_t { + u8 name[DOS_NAME_LENGTH]; + u8 attr; + u8 lcase; + u8 create_time_ms; + u8 create_time[2]; + u8 create_date[2]; + u8 access_date[2]; + u8 start_clu_hi[2]; + u8 modify_time[2]; + u8 modify_date[2]; + u8 start_clu_lo[2]; + u8 size[4]; +}; + +/* MS-DOS FAT extended directory entry (32 bytes) */ +struct ext_dentry_t { + u8 order; + u8 unicode_0_4[10]; + u8 attr; + u8 sysid; + u8 checksum; + u8 unicode_5_10[12]; + u8 start_clu[2]; + u8 unicode_11_12[4]; +}; + +/* MS-DOS EXFAT file directory entry (32 bytes) */ +struct file_dentry_t { + u8 type; + u8 num_ext; + u8 checksum[2]; + u8 attr[2]; + u8 reserved1[2]; + u8 create_time[2]; + u8 create_date[2]; + u8 modify_time[2]; + u8 modify_date[2]; + u8 access_time[2]; + u8 access_date[2]; + u8 create_time_ms; + u8 modify_time_ms; + u8 access_time_ms; + u8 reserved2[9]; +}; + +/* MS-DOS EXFAT stream extension directory entry (32 bytes) */ +struct strm_dentry_t { + u8 type; + u8 flags; + u8 reserved1; + u8 name_len; + u8 name_hash[2]; + u8 reserved2[2]; + u8 valid_size[8]; + u8 reserved3[4]; + u8 start_clu[4]; + u8 size[8]; +}; + +/* MS-DOS EXFAT file name directory entry (32 bytes) */ +struct name_dentry_t { + u8 type; + u8 flags; + u8 unicode_0_14[30]; +}; + +/* MS-DOS EXFAT allocation bitmap directory entry (32 bytes) */ +struct bmap_dentry_t { + u8 type; + u8 flags; + u8 reserved[18]; + u8 start_clu[4]; + u8 size[8]; +}; + +/* MS-DOS EXFAT up-case table directory entry (32 bytes) */ +struct case_dentry_t { + u8 type; + u8 reserved1[3]; + u8 checksum[4]; + u8 reserved2[12]; + u8 start_clu[4]; + u8 size[8]; +}; + +/* MS-DOS EXFAT volume label directory entry (32 bytes) */ +struct volm_dentry_t { + u8 type; + u8 label_len; + u8 unicode_0_10[22]; + u8 reserved[8]; +}; + +/* unused entry hint information */ +struct uentry_t { + u32 dir; + s32 entry; + struct chain_t clu; +}; + +/* DOS name structure */ +struct dos_name_t { + u8 name[DOS_NAME_LENGTH]; + u8 name_case; +}; + +/* unicode name structure */ +struct uni_name_t { + u16 name[MAX_NAME_LENGTH]; + u16 name_hash; + u8 name_len; +}; + +struct buf_cache_t { + struct buf_cache_t *next; + struct buf_cache_t *prev; + struct buf_cache_t *hash_next; + struct buf_cache_t *hash_prev; + s32 drv; + sector_t sec; + u32 flag; + struct buffer_head *buf_bh; +}; + +struct fs_func { + s32 (*alloc_cluster)(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain); + void (*free_cluster)(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse); + s32 (*count_used_clusters)(struct super_block *sb); + + s32 (*init_dir_entry)(struct super_block *sb, struct chain_t *p_dir, + s32 entry, u32 type, u32 start_clu, u64 size); + s32 (*init_ext_entry)(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 num_entries, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname); + s32 (*find_dir_entry)(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type); + void (*delete_dir_entry)(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + s32 offset, s32 num_entries); + void (*get_uni_name_from_ext_entry)(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname); + s32 (*count_ext_entries)(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + struct dentry_t *p_entry); + s32 (*calc_num_entries)(struct uni_name_t *p_uniname); + + u32 (*get_entry_type)(struct dentry_t *p_entry); + void (*set_entry_type)(struct dentry_t *p_entry, u32 type); + u32 (*get_entry_attr)(struct dentry_t *p_entry); + void (*set_entry_attr)(struct dentry_t *p_entry, u32 attr); + u8 (*get_entry_flag)(struct dentry_t *p_entry); + void (*set_entry_flag)(struct dentry_t *p_entry, u8 flag); + u32 (*get_entry_clu0)(struct dentry_t *p_entry); + void (*set_entry_clu0)(struct dentry_t *p_entry, u32 clu0); + u64 (*get_entry_size)(struct dentry_t *p_entry); + void (*set_entry_size)(struct dentry_t *p_entry, u64 size); + void (*get_entry_time)(struct dentry_t *p_entry, + struct timestamp_t *tp, u8 mode); + void (*set_entry_time)(struct dentry_t *p_entry, + struct timestamp_t *tp, u8 mode); +}; + +struct fs_info_t { + u32 drv; /* drive ID */ + u32 vol_type; /* volume FAT type */ + u32 vol_id; /* volume serial number */ + + u64 num_sectors; /* num of sectors in volume */ + u32 num_clusters; /* num of clusters in volume */ + u32 cluster_size; /* cluster size in bytes */ + u32 cluster_size_bits; + u32 sectors_per_clu; /* cluster size in sectors */ + u32 sectors_per_clu_bits; + + u32 PBR_sector; /* PBR sector */ + u32 FAT1_start_sector; /* FAT1 start sector */ + u32 FAT2_start_sector; /* FAT2 start sector */ + u32 root_start_sector; /* root dir start sector */ + u32 data_start_sector; /* data area start sector */ + u32 num_FAT_sectors; /* num of FAT sectors */ + + u32 root_dir; /* root dir cluster */ + u32 dentries_in_root; /* num of dentries in root dir */ + u32 dentries_per_clu; /* num of dentries per cluster */ + + u32 vol_flag; /* volume dirty flag */ + struct buffer_head *pbr_bh; /* PBR sector */ + + u32 map_clu; /* allocation bitmap start cluster */ + u32 map_sectors; /* num of allocation bitmap sectors */ + struct buffer_head **vol_amap; /* allocation bitmap */ + + u16 **vol_utbl; /* upcase table */ + + u32 clu_srch_ptr; /* cluster search pointer */ + u32 used_clusters; /* number of used clusters */ + struct uentry_t hint_uentry; /* unused entry hint information */ + + u32 dev_ejected; /* block device operation error flag */ + + struct fs_func *fs_func; + struct semaphore v_sem; + + /* FAT cache */ + struct buf_cache_t FAT_cache_array[FAT_CACHE_SIZE]; + struct buf_cache_t FAT_cache_lru_list; + struct buf_cache_t FAT_cache_hash_list[FAT_CACHE_HASH_SIZE]; + + /* buf cache */ + struct buf_cache_t buf_cache_array[BUF_CACHE_SIZE]; + struct buf_cache_t buf_cache_lru_list; + struct buf_cache_t buf_cache_hash_list[BUF_CACHE_HASH_SIZE]; +}; + +#define ES_2_ENTRIES 2 +#define ES_3_ENTRIES 3 +#define ES_ALL_ENTRIES 0 + +struct entry_set_cache_t { + /* sector number that contains file_entry */ + sector_t sector; + + /* byte offset in the sector */ + s32 offset; + + /* + * flag in stream entry. + * 01 for cluster chain, + * 03 for contig. clusteres. + */ + s32 alloc_flag; + + u32 num_entries; + + /* __buf should be the last member */ + void *__buf; +}; + +#define EXFAT_ERRORS_CONT 1 /* ignore error and continue */ +#define EXFAT_ERRORS_PANIC 2 /* panic on error */ +#define EXFAT_ERRORS_RO 3 /* remount r/o on error */ + +/* ioctl command */ +#define EXFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32) + +struct exfat_mount_options { + kuid_t fs_uid; + kgid_t fs_gid; + unsigned short fs_fmask; + unsigned short fs_dmask; + + /* permission for setting the [am]time */ + unsigned short allow_utime; + + /* codepage for shortname conversions */ + unsigned short codepage; + + /* charset for filename input/display */ + char *iocharset; + + unsigned char casesensitive; + + /* on error: continue, panic, remount-ro */ + unsigned char errors; +#ifdef CONFIG_EXFAT_DISCARD + /* flag on if -o dicard specified and device support discard() */ + unsigned char discard; +#endif /* CONFIG_EXFAT_DISCARD */ +}; + +#define EXFAT_HASH_BITS 8 +#define EXFAT_HASH_SIZE BIT(EXFAT_HASH_BITS) + +/* + * EXFAT file system in-core superblock data + */ +struct bd_info_t { + s32 sector_size; /* in bytes */ + s32 sector_size_bits; + s32 sector_size_mask; + + /* total number of sectors in this block device */ + s32 num_sectors; + + /* opened or not */ + bool opened; +}; + +struct exfat_sb_info { + struct fs_info_t fs_info; + struct bd_info_t bd_info; + + struct exfat_mount_options options; + + int s_dirt; + struct mutex s_lock; + struct nls_table *nls_disk; /* Codepage used on disk */ + struct nls_table *nls_io; /* Charset used for input and display */ + + struct inode *fat_inode; + + spinlock_t inode_hash_lock; + struct hlist_head inode_hashtable[EXFAT_HASH_SIZE]; +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + long debug_flags; +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ +}; + +/* + * EXFAT file system inode data in memory + */ +struct exfat_inode_info { + struct file_id_t fid; + char *target; + /* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */ + loff_t mmu_private; /* physically allocated size */ + loff_t i_pos; /* on-disk position of directory entry or 0 */ + struct hlist_node i_hash_fat; /* hash by i_location */ + struct rw_semaphore truncate_lock; + struct inode vfs_inode; + struct rw_semaphore i_alloc_sem; /* protect bmap against truncate */ +}; + +#define EXFAT_SB(sb) ((struct exfat_sb_info *)((sb)->s_fs_info)) + +static inline struct exfat_inode_info *EXFAT_I(struct inode *inode) +{ + return container_of(inode, struct exfat_inode_info, vfs_inode); +} + +/* NLS management function */ +u16 nls_upper(struct super_block *sb, u16 a); +int nls_dosname_cmp(struct super_block *sb, u8 *a, u8 *b); +int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b); +void nls_uniname_to_dosname(struct super_block *sb, + struct dos_name_t *p_dosname, + struct uni_name_t *p_uniname, bool *p_lossy); +void nls_dosname_to_uniname(struct super_block *sb, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname); +void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring, + struct uni_name_t *p_uniname); +void nls_cstring_to_uniname(struct super_block *sb, + struct uni_name_t *p_uniname, u8 *p_cstring, + bool *p_lossy); + +/* buffer cache management */ +void buf_init(struct super_block *sb); +void buf_shutdown(struct super_block *sb); +int FAT_read(struct super_block *sb, u32 loc, u32 *content); +s32 FAT_write(struct super_block *sb, u32 loc, u32 content); +u8 *FAT_getblk(struct super_block *sb, sector_t sec); +void FAT_modify(struct super_block *sb, sector_t sec); +void FAT_release_all(struct super_block *sb); +void FAT_sync(struct super_block *sb); +u8 *buf_getblk(struct super_block *sb, sector_t sec); +void buf_modify(struct super_block *sb, sector_t sec); +void buf_lock(struct super_block *sb, sector_t sec); +void buf_unlock(struct super_block *sb, sector_t sec); +void buf_release(struct super_block *sb, sector_t sec); +void buf_release_all(struct super_block *sb); +void buf_sync(struct super_block *sb); + +/* fs management functions */ +void fs_set_vol_flags(struct super_block *sb, u32 new_flag); +void fs_error(struct super_block *sb); + +/* cluster management functions */ +s32 clear_cluster(struct super_block *sb, u32 clu); +s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain); +s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain); +void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse); +void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse); +u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain); +s32 count_num_clusters(struct super_block *sb, struct chain_t *dir); +s32 fat_count_used_clusters(struct super_block *sb); +s32 exfat_count_used_clusters(struct super_block *sb); +void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len); + +/* allocation bitmap management functions */ +s32 load_alloc_bitmap(struct super_block *sb); +void free_alloc_bitmap(struct super_block *sb); +s32 set_alloc_bitmap(struct super_block *sb, u32 clu); +s32 clr_alloc_bitmap(struct super_block *sb, u32 clu); +u32 test_alloc_bitmap(struct super_block *sb, u32 clu); +void sync_alloc_bitmap(struct super_block *sb); + +/* upcase table management functions */ +s32 load_upcase_table(struct super_block *sb); +void free_upcase_table(struct super_block *sb); + +/* dir entry management functions */ +u32 fat_get_entry_type(struct dentry_t *p_entry); +u32 exfat_get_entry_type(struct dentry_t *p_entry); +void fat_set_entry_type(struct dentry_t *p_entry, u32 type); +void exfat_set_entry_type(struct dentry_t *p_entry, u32 type); +u32 fat_get_entry_attr(struct dentry_t *p_entry); +u32 exfat_get_entry_attr(struct dentry_t *p_entry); +void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr); +void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr); +u8 fat_get_entry_flag(struct dentry_t *p_entry); +u8 exfat_get_entry_flag(struct dentry_t *p_entry); +void fat_set_entry_flag(struct dentry_t *p_entry, u8 flag); +void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flag); +u32 fat_get_entry_clu0(struct dentry_t *p_entry); +u32 exfat_get_entry_clu0(struct dentry_t *p_entry); +void fat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu); +void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu); +u64 fat_get_entry_size(struct dentry_t *p_entry); +u64 exfat_get_entry_size(struct dentry_t *p_entry); +void fat_set_entry_size(struct dentry_t *p_entry, u64 size); +void exfat_set_entry_size(struct dentry_t *p_entry, u64 size); +struct timestamp_t *tm_current(struct timestamp_t *tm); +void fat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode); +void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode); +void fat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode); +void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode); +s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry, + u32 type, u32 start_clu, u64 size); +s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, u32 type, u32 start_clu, u64 size); +s32 fat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 num_entries, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname); +s32 exfat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 num_entries, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname); +void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu); +void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, + u16 *uniname); +void init_file_entry(struct file_dentry_t *ep, u32 type); +void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu, + u64 size); +void init_name_entry(struct name_dentry_t *ep, u16 *uniname); +void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 order, s32 num_entries); +void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 order, s32 num_entries); + +s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry, + sector_t *sector, s32 *offset); +struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector, + s32 offset); +struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir, + s32 entry, sector_t *sector); +struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u32 type, + struct dentry_t **file_ep); +void release_entry_set(struct entry_set_cache_t *es); +s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es); +s32 write_partial_entries_in_entry_set(struct super_block *sb, + struct entry_set_cache_t *es, + struct dentry_t *ep, u32 count); +s32 search_deleted_or_unused_entry(struct super_block *sb, + struct chain_t *p_dir, s32 num_entries); +s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, + s32 num_entries); +s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type); +s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type); +s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, + s32 entry, struct dentry_t *p_entry); +s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, + s32 entry, struct dentry_t *p_entry); +s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir, + u32 type); +void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir, + s32 entry); +void update_dir_checksum_with_entry_set(struct super_block *sb, + struct entry_set_cache_t *es); +bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir); + +/* name conversion functions */ +s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 *entries, + struct dos_name_t *p_dosname); +void get_uni_name_from_dos_entry(struct super_block *sb, + struct dos_dentry_t *ep, + struct uni_name_t *p_uniname, u8 mode); +void fat_get_uni_name_from_ext_entry(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname); +void exfat_get_uni_name_from_ext_entry(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname); +s32 extract_uni_name_from_ext_entry(struct ext_dentry_t *ep, + u16 *uniname, s32 order); +s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, + u16 *uniname, s32 order); +s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir, + struct dos_name_t *p_dosname); +void fat_attach_count_to_dos_name(u8 *dosname, s32 count); +s32 fat_calc_num_entries(struct uni_name_t *p_uniname); +s32 exfat_calc_num_entries(struct uni_name_t *p_uniname); +u8 calc_checksum_1byte(void *data, s32 len, u8 chksum); +u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type); +u32 calc_checksum_4byte(void *data, s32 len, u32 chksum, s32 type); + +/* name resolution functions */ +s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir, + struct uni_name_t *p_uniname); +s32 resolve_name(u8 *name, u8 **arg); + +/* file operation functions */ +s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr); +s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr); +s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr); +s32 create_dir(struct inode *inode, struct chain_t *p_dir, + struct uni_name_t *p_uniname, struct file_id_t *fid); +s32 create_file(struct inode *inode, struct chain_t *p_dir, + struct uni_name_t *p_uniname, u8 mode, struct file_id_t *fid); +void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry); +s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 old_entry, + struct uni_name_t *p_uniname, struct file_id_t *fid); +s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry, + struct chain_t *p_newdir, struct uni_name_t *p_uniname, + struct file_id_t *fid); + +/* sector read/write functions */ +int sector_read(struct super_block *sb, sector_t sec, + struct buffer_head **bh, bool read); +int sector_write(struct super_block *sb, sector_t sec, + struct buffer_head *bh, bool sync); +int multi_sector_read(struct super_block *sb, sector_t sec, + struct buffer_head **bh, s32 num_secs, bool read); +int multi_sector_write(struct super_block *sb, sector_t sec, + struct buffer_head *bh, s32 num_secs, bool sync); + +void bdev_open(struct super_block *sb); +void bdev_close(struct super_block *sb); +int bdev_read(struct super_block *sb, sector_t secno, + struct buffer_head **bh, u32 num_secs, bool read); +int bdev_write(struct super_block *sb, sector_t secno, + struct buffer_head *bh, u32 num_secs, bool sync); +int bdev_sync(struct super_block *sb); + +extern const u8 uni_upcase[]; +#endif /* _EXFAT_H */ diff --git a/drivers/staging/exfat/exfat_blkdev.c b/drivers/staging/exfat/exfat_blkdev.c new file mode 100644 index 000000000000..f086c75e7076 --- /dev/null +++ b/drivers/staging/exfat/exfat_blkdev.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include <linux/blkdev.h> +#include <linux/buffer_head.h> +#include <linux/fs.h> +#include "exfat.h" + +void bdev_open(struct super_block *sb) +{ + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bd->opened) + return; + + p_bd->sector_size = bdev_logical_block_size(sb->s_bdev); + p_bd->sector_size_bits = ilog2(p_bd->sector_size); + p_bd->sector_size_mask = p_bd->sector_size - 1; + p_bd->num_sectors = i_size_read(sb->s_bdev->bd_inode) >> + p_bd->sector_size_bits; + p_bd->opened = true; +} + +void bdev_close(struct super_block *sb) +{ + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + p_bd->opened = false; +} + +int bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh, + u32 num_secs, bool read) +{ + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) + return FFS_MEDIAERR; +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + + if (!p_bd->opened) + return FFS_MEDIAERR; + + if (*bh) + __brelse(*bh); + + if (read) + *bh = __bread(sb->s_bdev, secno, + num_secs << p_bd->sector_size_bits); + else + *bh = __getblk(sb->s_bdev, secno, + num_secs << p_bd->sector_size_bits); + + if (*bh) + return 0; + + WARN(!p_fs->dev_ejected, + "[EXFAT] No bh, device seems wrong or to be ejected.\n"); + + return FFS_MEDIAERR; +} + +int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh, + u32 num_secs, bool sync) +{ + s32 count; + struct buffer_head *bh2; + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) + return FFS_MEDIAERR; +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + + if (!p_bd->opened) + return FFS_MEDIAERR; + + if (secno == bh->b_blocknr) { + lock_buffer(bh); + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + unlock_buffer(bh); + if (sync && (sync_dirty_buffer(bh) != 0)) + return FFS_MEDIAERR; + } else { + count = num_secs << p_bd->sector_size_bits; + + bh2 = __getblk(sb->s_bdev, secno, count); + if (!bh2) + goto no_bh; + + lock_buffer(bh2); + memcpy(bh2->b_data, bh->b_data, count); + set_buffer_uptodate(bh2); + mark_buffer_dirty(bh2); + unlock_buffer(bh2); + if (sync && (sync_dirty_buffer(bh2) != 0)) { + __brelse(bh2); + goto no_bh; + } + __brelse(bh2); + } + + return 0; + +no_bh: + WARN(!p_fs->dev_ejected, + "[EXFAT] No bh, device seems wrong or to be ejected.\n"); + + return FFS_MEDIAERR; +} + +int bdev_sync(struct super_block *sb) +{ + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) + return FFS_MEDIAERR; +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + + if (!p_bd->opened) + return FFS_MEDIAERR; + + return sync_blockdev(sb->s_bdev); +} diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c new file mode 100644 index 000000000000..1565ce65d39f --- /dev/null +++ b/drivers/staging/exfat/exfat_cache.c @@ -0,0 +1,724 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include <linux/buffer_head.h> +#include <linux/fs.h> +#include <linux/mutex.h> +#include "exfat.h" + +#define LOCKBIT 0x01 +#define DIRTYBIT 0x02 + +/* Local variables */ +static DEFINE_SEMAPHORE(f_sem); +static DEFINE_SEMAPHORE(b_sem); + +static struct buf_cache_t *FAT_cache_find(struct super_block *sb, sector_t sec) +{ + s32 off; + struct buf_cache_t *bp, *hp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + off = (sec + + (sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE - 1); + + hp = &p_fs->FAT_cache_hash_list[off]; + for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { + if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { + WARN(!bp->buf_bh, + "[EXFAT] FAT_cache has no bh. It will make system panic.\n"); + + touch_buffer(bp->buf_bh); + return bp; + } + } + return NULL; +} + +static void push_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list) +{ + bp->next = list->next; + bp->prev = list; + list->next->prev = bp; + list->next = bp; +} + +static void push_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list) +{ + bp->prev = list->prev; + bp->next = list; + list->prev->next = bp; + list->prev = bp; +} + +static void move_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list) +{ + bp->prev->next = bp->next; + bp->next->prev = bp->prev; + push_to_mru(bp, list); +} + +static void move_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list) +{ + bp->prev->next = bp->next; + bp->next->prev = bp->prev; + push_to_lru(bp, list); +} + +static struct buf_cache_t *FAT_cache_get(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = p_fs->FAT_cache_lru_list.prev; + + move_to_mru(bp, &p_fs->FAT_cache_lru_list); + return bp; +} + +static void FAT_cache_insert_hash(struct super_block *sb, + struct buf_cache_t *bp) +{ + s32 off; + struct buf_cache_t *hp; + struct fs_info_t *p_fs; + + p_fs = &(EXFAT_SB(sb)->fs_info); + off = (bp->sec + + (bp->sec >> p_fs->sectors_per_clu_bits)) & + (FAT_CACHE_HASH_SIZE - 1); + + hp = &p_fs->FAT_cache_hash_list[off]; + bp->hash_next = hp->hash_next; + bp->hash_prev = hp; + hp->hash_next->hash_prev = bp; + hp->hash_next = bp; +} + +static void FAT_cache_remove_hash(struct buf_cache_t *bp) +{ + (bp->hash_prev)->hash_next = bp->hash_next; + (bp->hash_next)->hash_prev = bp->hash_prev; +} + +static void buf_cache_insert_hash(struct super_block *sb, + struct buf_cache_t *bp) +{ + s32 off; + struct buf_cache_t *hp; + struct fs_info_t *p_fs; + + p_fs = &(EXFAT_SB(sb)->fs_info); + off = (bp->sec + + (bp->sec >> p_fs->sectors_per_clu_bits)) & + (BUF_CACHE_HASH_SIZE - 1); + + hp = &p_fs->buf_cache_hash_list[off]; + bp->hash_next = hp->hash_next; + bp->hash_prev = hp; + hp->hash_next->hash_prev = bp; + hp->hash_next = bp; +} + +static void buf_cache_remove_hash(struct buf_cache_t *bp) +{ + (bp->hash_prev)->hash_next = bp->hash_next; + (bp->hash_next)->hash_prev = bp->hash_prev; +} + +void buf_init(struct super_block *sb) +{ + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + int i; + + /* LRU list */ + p_fs->FAT_cache_lru_list.next = &p_fs->FAT_cache_lru_list; + p_fs->FAT_cache_lru_list.prev = &p_fs->FAT_cache_lru_list; + + for (i = 0; i < FAT_CACHE_SIZE; i++) { + p_fs->FAT_cache_array[i].drv = -1; + p_fs->FAT_cache_array[i].sec = ~0; + p_fs->FAT_cache_array[i].flag = 0; + p_fs->FAT_cache_array[i].buf_bh = NULL; + p_fs->FAT_cache_array[i].prev = NULL; + p_fs->FAT_cache_array[i].next = NULL; + push_to_mru(&p_fs->FAT_cache_array[i], + &p_fs->FAT_cache_lru_list); + } + + p_fs->buf_cache_lru_list.next = &p_fs->buf_cache_lru_list; + p_fs->buf_cache_lru_list.prev = &p_fs->buf_cache_lru_list; + + for (i = 0; i < BUF_CACHE_SIZE; i++) { + p_fs->buf_cache_array[i].drv = -1; + p_fs->buf_cache_array[i].sec = ~0; + p_fs->buf_cache_array[i].flag = 0; + p_fs->buf_cache_array[i].buf_bh = NULL; + p_fs->buf_cache_array[i].prev = NULL; + p_fs->buf_cache_array[i].next = NULL; + push_to_mru(&p_fs->buf_cache_array[i], + &p_fs->buf_cache_lru_list); + } + + /* HASH list */ + for (i = 0; i < FAT_CACHE_HASH_SIZE; i++) { + p_fs->FAT_cache_hash_list[i].drv = -1; + p_fs->FAT_cache_hash_list[i].sec = ~0; + p_fs->FAT_cache_hash_list[i].hash_next = + &p_fs->FAT_cache_hash_list[i]; + p_fs->FAT_cache_hash_list[i].hash_prev = + &p_fs->FAT_cache_hash_list[i]; + } + + for (i = 0; i < FAT_CACHE_SIZE; i++) + FAT_cache_insert_hash(sb, &p_fs->FAT_cache_array[i]); + + for (i = 0; i < BUF_CACHE_HASH_SIZE; i++) { + p_fs->buf_cache_hash_list[i].drv = -1; + p_fs->buf_cache_hash_list[i].sec = ~0; + p_fs->buf_cache_hash_list[i].hash_next = + &p_fs->buf_cache_hash_list[i]; + p_fs->buf_cache_hash_list[i].hash_prev = + &p_fs->buf_cache_hash_list[i]; + } + + for (i = 0; i < BUF_CACHE_SIZE; i++) + buf_cache_insert_hash(sb, &p_fs->buf_cache_array[i]); +} + +void buf_shutdown(struct super_block *sb) +{ +} + +static int __FAT_read(struct super_block *sb, u32 loc, u32 *content) +{ + s32 off; + u32 _content; + sector_t sec; + u8 *fat_sector, *fat_entry; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_fs->vol_type == FAT12) { + sec = p_fs->FAT1_start_sector + + ((loc + (loc >> 1)) >> p_bd->sector_size_bits); + off = (loc + (loc >> 1)) & p_bd->sector_size_mask; + + if (off == (p_bd->sector_size - 1)) { + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + _content = (u32)fat_sector[off]; + + fat_sector = FAT_getblk(sb, ++sec); + if (!fat_sector) + return -1; + + _content |= (u32)fat_sector[0] << 8; + } else { + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + _content = GET16(fat_entry); + } + + if (loc & 1) + _content >>= 4; + + _content &= 0x00000FFF; + + if (_content >= CLUSTER_16(0x0FF8)) { + *content = CLUSTER_32(~0); + return 0; + } + *content = CLUSTER_32(_content); + return 0; + } else if (p_fs->vol_type == FAT16) { + sec = p_fs->FAT1_start_sector + + (loc >> (p_bd->sector_size_bits - 1)); + off = (loc << 1) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + + _content = GET16_A(fat_entry); + + _content &= 0x0000FFFF; + + if (_content >= CLUSTER_16(0xFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } + *content = CLUSTER_32(_content); + return 0; + } else if (p_fs->vol_type == FAT32) { + sec = p_fs->FAT1_start_sector + + (loc >> (p_bd->sector_size_bits - 2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + + _content = GET32_A(fat_entry); + + _content &= 0x0FFFFFFF; + + if (_content >= CLUSTER_32(0x0FFFFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } + *content = CLUSTER_32(_content); + return 0; + } else if (p_fs->vol_type == EXFAT) { + sec = p_fs->FAT1_start_sector + + (loc >> (p_bd->sector_size_bits - 2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + _content = GET32_A(fat_entry); + + if (_content >= CLUSTER_32(0xFFFFFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } + *content = CLUSTER_32(_content); + return 0; + } + + /* Unknown volume type, throw in the towel and go home */ + *content = CLUSTER_32(~0); + return 0; +} + +/* in : sb, loc + * out: content + * returns 0 on success + * -1 on error + */ +int FAT_read(struct super_block *sb, u32 loc, u32 *content) +{ + s32 ret; + + down(&f_sem); + ret = __FAT_read(sb, loc, content); + up(&f_sem); + + return ret; +} + +static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content) +{ + s32 off; + sector_t sec; + u8 *fat_sector, *fat_entry; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_fs->vol_type == FAT12) { + content &= 0x00000FFF; + + sec = p_fs->FAT1_start_sector + + ((loc + (loc >> 1)) >> p_bd->sector_size_bits); + off = (loc + (loc >> 1)) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + if (loc & 1) { /* odd */ + content <<= 4; + + if (off == (p_bd->sector_size - 1)) { + fat_sector[off] = (u8)(content | + (fat_sector[off] & + 0x0F)); + FAT_modify(sb, sec); + + fat_sector = FAT_getblk(sb, ++sec); + if (!fat_sector) + return -1; + + fat_sector[0] = (u8)(content >> 8); + } else { + fat_entry = &fat_sector[off]; + content |= GET16(fat_entry) & 0x000F; + + SET16(fat_entry, content); + } + } else { /* even */ + fat_sector[off] = (u8)(content); + + if (off == (p_bd->sector_size - 1)) { + fat_sector[off] = (u8)(content); + FAT_modify(sb, sec); + + fat_sector = FAT_getblk(sb, ++sec); + if (!fat_sector) + return -1; + fat_sector[0] = (u8)((fat_sector[0] & 0xF0) | + (content >> 8)); + } else { + fat_entry = &fat_sector[off]; + content |= GET16(fat_entry) & 0xF000; + + SET16(fat_entry, content); + } + } + } + + else if (p_fs->vol_type == FAT16) { + content &= 0x0000FFFF; + + sec = p_fs->FAT1_start_sector + (loc >> + (p_bd->sector_size_bits - 1)); + off = (loc << 1) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + + SET16_A(fat_entry, content); + } else if (p_fs->vol_type == FAT32) { + content &= 0x0FFFFFFF; + + sec = p_fs->FAT1_start_sector + (loc >> + (p_bd->sector_size_bits - 2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + + content |= GET32_A(fat_entry) & 0xF0000000; + + SET32_A(fat_entry, content); + } else { /* p_fs->vol_type == EXFAT */ + sec = p_fs->FAT1_start_sector + (loc >> + (p_bd->sector_size_bits - 2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + + SET32_A(fat_entry, content); + } + + FAT_modify(sb, sec); + return 0; +} + +int FAT_write(struct super_block *sb, u32 loc, u32 content) +{ + s32 ret; + + down(&f_sem); + ret = __FAT_write(sb, loc, content); + up(&f_sem); + + return ret; +} + +u8 *FAT_getblk(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = FAT_cache_find(sb, sec); + if (bp) { + move_to_mru(bp, &p_fs->FAT_cache_lru_list); + return bp->buf_bh->b_data; + } + + bp = FAT_cache_get(sb, sec); + + FAT_cache_remove_hash(bp); + + bp->drv = p_fs->drv; + bp->sec = sec; + bp->flag = 0; + + FAT_cache_insert_hash(sb, bp); + + if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) { + FAT_cache_remove_hash(bp); + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + bp->buf_bh = NULL; + + move_to_lru(bp, &p_fs->FAT_cache_lru_list); + return NULL; + } + + return bp->buf_bh->b_data; +} + +void FAT_modify(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + + bp = FAT_cache_find(sb, sec); + if (bp) + sector_write(sb, sec, bp->buf_bh, 0); +} + +void FAT_release_all(struct super_block *sb) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + down(&f_sem); + + bp = p_fs->FAT_cache_lru_list.next; + while (bp != &p_fs->FAT_cache_lru_list) { + if (bp->drv == p_fs->drv) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if (bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + } + bp = bp->next; + } + + up(&f_sem); +} + +void FAT_sync(struct super_block *sb) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + down(&f_sem); + + bp = p_fs->FAT_cache_lru_list.next; + while (bp != &p_fs->FAT_cache_lru_list) { + if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) { + sync_dirty_buffer(bp->buf_bh); + bp->flag &= ~(DIRTYBIT); + } + bp = bp->next; + } + + up(&f_sem); +} + +static struct buf_cache_t *buf_cache_find(struct super_block *sb, sector_t sec) +{ + s32 off; + struct buf_cache_t *bp, *hp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + off = (sec + (sec >> p_fs->sectors_per_clu_bits)) & + (BUF_CACHE_HASH_SIZE - 1); + + hp = &p_fs->buf_cache_hash_list[off]; + for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { + if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { + touch_buffer(bp->buf_bh); + return bp; + } + } + return NULL; +} + +static struct buf_cache_t *buf_cache_get(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = p_fs->buf_cache_lru_list.prev; + while (bp->flag & LOCKBIT) + bp = bp->prev; + + move_to_mru(bp, &p_fs->buf_cache_lru_list); + return bp; +} + +static u8 *__buf_getblk(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = buf_cache_find(sb, sec); + if (bp) { + move_to_mru(bp, &p_fs->buf_cache_lru_list); + return bp->buf_bh->b_data; + } + + bp = buf_cache_get(sb, sec); + + buf_cache_remove_hash(bp); + + bp->drv = p_fs->drv; + bp->sec = sec; + bp->flag = 0; + + buf_cache_insert_hash(sb, bp); + + if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) { + buf_cache_remove_hash(bp); + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + bp->buf_bh = NULL; + + move_to_lru(bp, &p_fs->buf_cache_lru_list); + return NULL; + } + + return bp->buf_bh->b_data; +} + +u8 *buf_getblk(struct super_block *sb, sector_t sec) +{ + u8 *buf; + + down(&b_sem); + buf = __buf_getblk(sb, sec); + up(&b_sem); + + return buf; +} + +void buf_modify(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + + down(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp)) + sector_write(sb, sec, bp->buf_bh, 0); + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n", + (unsigned long long)sec); + + up(&b_sem); +} + +void buf_lock(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + + down(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp)) + bp->flag |= LOCKBIT; + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n", + (unsigned long long)sec); + + up(&b_sem); +} + +void buf_unlock(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + + down(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp)) + bp->flag &= ~(LOCKBIT); + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n", + (unsigned long long)sec); + + up(&b_sem); +} + +void buf_release(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + down(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp)) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if (bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + + move_to_lru(bp, &p_fs->buf_cache_lru_list); + } + + up(&b_sem); +} + +void buf_release_all(struct super_block *sb) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + down(&b_sem); + + bp = p_fs->buf_cache_lru_list.next; + while (bp != &p_fs->buf_cache_lru_list) { + if (bp->drv == p_fs->drv) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if (bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + } + bp = bp->next; + } + + up(&b_sem); +} + +void buf_sync(struct super_block *sb) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + down(&b_sem); + + bp = p_fs->buf_cache_lru_list.next; + while (bp != &p_fs->buf_cache_lru_list) { + if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) { + sync_dirty_buffer(bp->buf_bh); + bp->flag &= ~(DIRTYBIT); + } + bp = bp->next; + } + + up(&b_sem); +} diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c new file mode 100644 index 000000000000..b3e9cf725cf5 --- /dev/null +++ b/drivers/staging/exfat/exfat_core.c @@ -0,0 +1,3701 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include <linux/types.h> +#include <linux/buffer_head.h> +#include <linux/fs.h> +#include <linux/mutex.h> +#include <linux/blkdev.h> +#include <linux/slab.h> +#include "exfat.h" + +static void __set_sb_dirty(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + sbi->s_dirt = 1; +} + +static u8 name_buf[MAX_PATH_LENGTH * MAX_CHARSET_SIZE]; + +static char *reserved_names[] = { + "AUX ", "CON ", "NUL ", "PRN ", + "COM1 ", "COM2 ", "COM3 ", "COM4 ", + "COM5 ", "COM6 ", "COM7 ", "COM8 ", "COM9 ", + "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ", + "LPT5 ", "LPT6 ", "LPT7 ", "LPT8 ", "LPT9 ", + NULL +}; + +static u8 free_bit[] = { + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 0 ~ 19 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, /* 20 ~ 39 */ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 40 ~ 59 */ + 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 60 ~ 79 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, /* 80 ~ 99 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, /* 100 ~ 119 */ + 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 120 ~ 139 */ + 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, /* 140 ~ 159 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 160 ~ 179 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, /* 180 ~ 199 */ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 200 ~ 219 */ + 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 220 ~ 239 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 240 ~ 254 */ +}; + +static u8 used_bit[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, /* 0 ~ 19 */ + 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, /* 20 ~ 39 */ + 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, /* 40 ~ 59 */ + 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 60 ~ 79 */ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, /* 80 ~ 99 */ + 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, /* 100 ~ 119 */ + 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, /* 120 ~ 139 */ + 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 140 ~ 159 */ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, /* 160 ~ 179 */ + 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, /* 180 ~ 199 */ + 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, /* 200 ~ 219 */ + 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 220 ~ 239 */ + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /* 240 ~ 255 */ +}; + +#define BITMAP_LOC(v) ((v) >> 3) +#define BITMAP_SHIFT(v) ((v) & 0x07) + +static inline s32 exfat_bitmap_test(u8 *bitmap, int i) +{ + u8 data; + + data = bitmap[BITMAP_LOC(i)]; + if ((data >> BITMAP_SHIFT(i)) & 0x01) + return 1; + return 0; +} + +static inline void exfat_bitmap_set(u8 *bitmap, int i) +{ + bitmap[BITMAP_LOC(i)] |= (0x01 << BITMAP_SHIFT(i)); +} + +static inline void exfat_bitmap_clear(u8 *bitmap, int i) +{ + bitmap[BITMAP_LOC(i)] &= ~(0x01 << BITMAP_SHIFT(i)); +} + +/* + * File System Management Functions + */ + +void fs_set_vol_flags(struct super_block *sb, u32 new_flag) +{ + struct pbr_sector_t *p_pbr; + struct bpbex_t *p_bpb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_fs->vol_flag == new_flag) + return; + + p_fs->vol_flag = new_flag; + + if (p_fs->vol_type == EXFAT) { + if (!p_fs->pbr_bh) { + if (sector_read(sb, p_fs->PBR_sector, + &p_fs->pbr_bh, 1) != FFS_SUCCESS) + return; + } + + p_pbr = (struct pbr_sector_t *)p_fs->pbr_bh->b_data; + p_bpb = (struct bpbex_t *)p_pbr->bpb; + SET16(p_bpb->vol_flags, (u16)new_flag); + + /* XXX duyoung + * what can we do here? (cuz fs_set_vol_flags() is void) + */ + if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh))) + sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1); + else + sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0); + } +} + +void fs_error(struct super_block *sb) +{ + struct exfat_mount_options *opts = &EXFAT_SB(sb)->options; + + if (opts->errors == EXFAT_ERRORS_PANIC) { + panic("[EXFAT] Filesystem panic from previous error\n"); + } else if ((opts->errors == EXFAT_ERRORS_RO) && !sb_rdonly(sb)) { + sb->s_flags |= SB_RDONLY; + pr_err("[EXFAT] Filesystem has been set read-only\n"); + } +} + +/* + * Cluster Management Functions + */ + +s32 clear_cluster(struct super_block *sb, u32 clu) +{ + sector_t s, n; + s32 ret = FFS_SUCCESS; + struct buffer_head *tmp_bh = NULL; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (clu == CLUSTER_32(0)) { /* FAT16 root_dir */ + s = p_fs->root_start_sector; + n = p_fs->data_start_sector; + } else { + s = START_SECTOR(clu); + n = s + p_fs->sectors_per_clu; + } + + for (; s < n; s++) { + ret = sector_read(sb, s, &tmp_bh, 0); + if (ret != FFS_SUCCESS) + return ret; + + memset((char *)tmp_bh->b_data, 0x0, p_bd->sector_size); + ret = sector_write(sb, s, tmp_bh, 0); + if (ret != FFS_SUCCESS) + break; + } + + brelse(tmp_bh); + return ret; +} + +s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain) +{ + int i, num_clusters = 0; + u32 new_clu, last_clu = CLUSTER_32(~0), read_clu; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + new_clu = p_chain->dir; + if (new_clu == CLUSTER_32(~0)) + new_clu = p_fs->clu_srch_ptr; + else if (new_clu >= p_fs->num_clusters) + new_clu = 2; + + __set_sb_dirty(sb); + + p_chain->dir = CLUSTER_32(~0); + + for (i = 2; i < p_fs->num_clusters; i++) { + if (FAT_read(sb, new_clu, &read_clu) != 0) + return -1; + + if (read_clu == CLUSTER_32(0)) { + if (FAT_write(sb, new_clu, CLUSTER_32(~0)) < 0) + return -1; + num_clusters++; + + if (p_chain->dir == CLUSTER_32(~0)) { + p_chain->dir = new_clu; + } else { + if (FAT_write(sb, last_clu, new_clu) < 0) + return -1; + } + + last_clu = new_clu; + + if ((--num_alloc) == 0) { + p_fs->clu_srch_ptr = new_clu; + if (p_fs->used_clusters != UINT_MAX) + p_fs->used_clusters += num_clusters; + + return num_clusters; + } + } + if ((++new_clu) >= p_fs->num_clusters) + new_clu = 2; + } + + p_fs->clu_srch_ptr = new_clu; + if (p_fs->used_clusters != UINT_MAX) + p_fs->used_clusters += num_clusters; + + return num_clusters; +} + +s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain) +{ + s32 num_clusters = 0; + u32 hint_clu, new_clu, last_clu = CLUSTER_32(~0); + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + hint_clu = p_chain->dir; + if (hint_clu == CLUSTER_32(~0)) { + hint_clu = test_alloc_bitmap(sb, p_fs->clu_srch_ptr - 2); + if (hint_clu == CLUSTER_32(~0)) + return 0; + } else if (hint_clu >= p_fs->num_clusters) { + hint_clu = 2; + p_chain->flags = 0x01; + } + + __set_sb_dirty(sb); + + p_chain->dir = CLUSTER_32(~0); + + while ((new_clu = test_alloc_bitmap(sb, hint_clu - 2)) != CLUSTER_32(~0)) { + if (new_clu != hint_clu) { + if (p_chain->flags == 0x03) { + exfat_chain_cont_cluster(sb, p_chain->dir, + num_clusters); + p_chain->flags = 0x01; + } + } + + if (set_alloc_bitmap(sb, new_clu - 2) != FFS_SUCCESS) + return -1; + + num_clusters++; + + if (p_chain->flags == 0x01) { + if (FAT_write(sb, new_clu, CLUSTER_32(~0)) < 0) + return -1; + } + + if (p_chain->dir == CLUSTER_32(~0)) { + p_chain->dir = new_clu; + } else { + if (p_chain->flags == 0x01) { + if (FAT_write(sb, last_clu, new_clu) < 0) + return -1; + } + } + last_clu = new_clu; + + if ((--num_alloc) == 0) { + p_fs->clu_srch_ptr = hint_clu; + if (p_fs->used_clusters != UINT_MAX) + p_fs->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return num_clusters; + } + + hint_clu = new_clu + 1; + if (hint_clu >= p_fs->num_clusters) { + hint_clu = 2; + + if (p_chain->flags == 0x03) { + exfat_chain_cont_cluster(sb, p_chain->dir, + num_clusters); + p_chain->flags = 0x01; + } + } + } + + p_fs->clu_srch_ptr = hint_clu; + if (p_fs->used_clusters != UINT_MAX) + p_fs->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return num_clusters; +} + +void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse) +{ + s32 num_clusters = 0; + u32 clu, prev; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + int i; + sector_t sector; + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return; + __set_sb_dirty(sb); + clu = p_chain->dir; + + if (p_chain->size <= 0) + return; + + do { + if (p_fs->dev_ejected) + break; + + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) + buf_release(sb, sector + i); + } + + prev = clu; + if (FAT_read(sb, clu, &clu) == -1) + break; + + if (FAT_write(sb, prev, CLUSTER_32(0)) < 0) + break; + num_clusters++; + + } while (clu != CLUSTER_32(~0)); + + if (p_fs->used_clusters != UINT_MAX) + p_fs->used_clusters -= num_clusters; +} + +void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse) +{ + s32 num_clusters = 0; + u32 clu; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + int i; + sector_t sector; + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return; + + if (p_chain->size <= 0) { + pr_err("[EXFAT] free_cluster : skip free-req clu:%u, because of zero-size truncation\n", + p_chain->dir); + return; + } + + __set_sb_dirty(sb); + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + do { + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) + buf_release(sb, sector + i); + } + + if (clr_alloc_bitmap(sb, clu - 2) != FFS_SUCCESS) + break; + clu++; + + num_clusters++; + } while (num_clusters < p_chain->size); + } else { + do { + if (p_fs->dev_ejected) + break; + + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) + buf_release(sb, sector + i); + } + + if (clr_alloc_bitmap(sb, clu - 2) != FFS_SUCCESS) + break; + + if (FAT_read(sb, clu, &clu) == -1) + break; + num_clusters++; + } while ((clu != CLUSTER_32(0)) && (clu != CLUSTER_32(~0))); + } + + if (p_fs->used_clusters != UINT_MAX) + p_fs->used_clusters -= num_clusters; +} + +u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain) +{ + u32 clu, next; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + clu += p_chain->size - 1; + } else { + while ((FAT_read(sb, clu, &next) == 0) && + (next != CLUSTER_32(~0))) { + if (p_fs->dev_ejected) + break; + clu = next; + } + } + + return clu; +} + +s32 count_num_clusters(struct super_block *sb, struct chain_t *p_chain) +{ + int i, count = 0; + u32 clu; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return 0; + + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + count = p_chain->size; + } else { + for (i = 2; i < p_fs->num_clusters; i++) { + count++; + if (FAT_read(sb, clu, &clu) != 0) + return 0; + if (clu == CLUSTER_32(~0)) + break; + } + } + + return count; +} + +s32 fat_count_used_clusters(struct super_block *sb) +{ + int i, count = 0; + u32 clu; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = 2; i < p_fs->num_clusters; i++) { + if (FAT_read(sb, i, &clu) != 0) + break; + if (clu != CLUSTER_32(0)) + count++; + } + + return count; +} + +s32 exfat_count_used_clusters(struct super_block *sb) +{ + int i, map_i, map_b, count = 0; + u8 k; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + map_i = map_b = 0; + + for (i = 2; i < p_fs->num_clusters; i += 8) { + k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b); + count += used_bit[k]; + + if ((++map_b) >= p_bd->sector_size) { + map_i++; + map_b = 0; + } + } + + return count; +} + +void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len) +{ + if (len == 0) + return; + + while (len > 1) { + if (FAT_write(sb, chain, chain + 1) < 0) + break; + chain++; + len--; + } + FAT_write(sb, chain, CLUSTER_32(~0)); +} + +/* + * Allocation Bitmap Management Functions + */ + +s32 load_alloc_bitmap(struct super_block *sb) +{ + int i, j, ret; + u32 map_size; + u32 type; + sector_t sector; + struct chain_t clu; + struct bmap_dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu.dir = p_fs->root_dir; + clu.flags = 0x01; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < p_fs->dentries_per_clu; i++) { + ep = (struct bmap_dentry_t *)get_entry_in_dir(sb, &clu, + i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep); + + if (type == TYPE_UNUSED) + break; + if (type != TYPE_BITMAP) + continue; + + if (ep->flags == 0x0) { + p_fs->map_clu = GET32_A(ep->start_clu); + map_size = (u32)GET64_A(ep->size); + + p_fs->map_sectors = ((map_size - 1) >> p_bd->sector_size_bits) + 1; + + p_fs->vol_amap = kmalloc_array(p_fs->map_sectors, + sizeof(struct buffer_head *), + GFP_KERNEL); + if (!p_fs->vol_amap) + return FFS_MEMORYERR; + + sector = START_SECTOR(p_fs->map_clu); + + for (j = 0; j < p_fs->map_sectors; j++) { + p_fs->vol_amap[j] = NULL; + ret = sector_read(sb, sector + j, &(p_fs->vol_amap[j]), 1); + if (ret != FFS_SUCCESS) { + /* release all buffers and free vol_amap */ + i = 0; + while (i < j) + brelse(p_fs->vol_amap[i++]); + + kfree(p_fs->vol_amap); + p_fs->vol_amap = NULL; + return ret; + } + } + + p_fs->pbr_bh = NULL; + return FFS_SUCCESS; + } + } + + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return FFS_MEDIAERR; + } + + return FFS_FORMATERR; +} + +void free_alloc_bitmap(struct super_block *sb) +{ + int i; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + brelse(p_fs->pbr_bh); + + for (i = 0; i < p_fs->map_sectors; i++) + __brelse(p_fs->vol_amap[i]); + + kfree(p_fs->vol_amap); + p_fs->vol_amap = NULL; +} + +s32 set_alloc_bitmap(struct super_block *sb, u32 clu) +{ + int i, b; + sector_t sector; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + i = clu >> (p_bd->sector_size_bits + 3); + b = clu & ((p_bd->sector_size << 3) - 1); + + sector = START_SECTOR(p_fs->map_clu) + i; + + exfat_bitmap_set((u8 *)p_fs->vol_amap[i]->b_data, b); + + return sector_write(sb, sector, p_fs->vol_amap[i], 0); +} + +s32 clr_alloc_bitmap(struct super_block *sb, u32 clu) +{ + int i, b; + sector_t sector; +#ifdef CONFIG_EXFAT_DISCARD + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_mount_options *opts = &sbi->options; + int ret; +#endif /* CONFIG_EXFAT_DISCARD */ + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + i = clu >> (p_bd->sector_size_bits + 3); + b = clu & ((p_bd->sector_size << 3) - 1); + + sector = START_SECTOR(p_fs->map_clu) + i; + + exfat_bitmap_clear((u8 *)p_fs->vol_amap[i]->b_data, b); + + return sector_write(sb, sector, p_fs->vol_amap[i], 0); + +#ifdef CONFIG_EXFAT_DISCARD + if (opts->discard) { + ret = sb_issue_discard(sb, START_SECTOR(clu), + (1 << p_fs->sectors_per_clu_bits), + GFP_NOFS, 0); + if (ret == -EOPNOTSUPP) { + pr_warn("discard not supported by device, disabling"); + opts->discard = 0; + } + } +#endif /* CONFIG_EXFAT_DISCARD */ +} + +u32 test_alloc_bitmap(struct super_block *sb, u32 clu) +{ + int i, map_i, map_b; + u32 clu_base, clu_free; + u8 k, clu_mask; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu_base = (clu & ~(0x7)) + 2; + clu_mask = (1 << (clu - clu_base + 2)) - 1; + + map_i = clu >> (p_bd->sector_size_bits + 3); + map_b = (clu >> 3) & p_bd->sector_size_mask; + + for (i = 2; i < p_fs->num_clusters; i += 8) { + k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b); + if (clu_mask > 0) { + k |= clu_mask; + clu_mask = 0; + } + if (k < 0xFF) { + clu_free = clu_base + free_bit[k]; + if (clu_free < p_fs->num_clusters) + return clu_free; + } + clu_base += 8; + + if (((++map_b) >= p_bd->sector_size) || + (clu_base >= p_fs->num_clusters)) { + if ((++map_i) >= p_fs->map_sectors) { + clu_base = 2; + map_i = 0; + } + map_b = 0; + } + } + + return CLUSTER_32(~0); +} + +void sync_alloc_bitmap(struct super_block *sb) +{ + int i; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (!p_fs->vol_amap) + return; + + for (i = 0; i < p_fs->map_sectors; i++) + sync_dirty_buffer(p_fs->vol_amap[i]); +} + +/* + * Upcase table Management Functions + */ +static s32 __load_upcase_table(struct super_block *sb, sector_t sector, + u32 num_sectors, u32 utbl_checksum) +{ + int i, ret = FFS_ERROR; + u32 j; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct buffer_head *tmp_bh = NULL; + sector_t end_sector = num_sectors + sector; + + bool skip = false; + u32 index = 0; + u16 uni = 0; + u16 **upcase_table; + + u32 checksum = 0; + + upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *), + GFP_KERNEL); + if (!upcase_table) + return FFS_MEMORYERR; + memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *)); + + while (sector < end_sector) { + ret = sector_read(sb, sector, &tmp_bh, 1); + if (ret != FFS_SUCCESS) { + pr_debug("sector read (0x%llX)fail\n", + (unsigned long long)sector); + goto error; + } + sector++; + + for (i = 0; i < p_bd->sector_size && index <= 0xFFFF; i += 2) { + uni = GET16(((u8 *)tmp_bh->b_data) + i); + + checksum = ((checksum & 1) ? 0x80000000 : 0) + + (checksum >> 1) + *(((u8 *)tmp_bh->b_data) + + i); + checksum = ((checksum & 1) ? 0x80000000 : 0) + + (checksum >> 1) + *(((u8 *)tmp_bh->b_data) + + (i + 1)); + + if (skip) { + pr_debug("skip from 0x%X ", index); + index += uni; + pr_debug("to 0x%X (amount of 0x%X)\n", + index, uni); + skip = false; + } else if (uni == index) { + index++; + } else if (uni == 0xFFFF) { + skip = true; + } else { /* uni != index , uni != 0xFFFF */ + u16 col_index = get_col_index(index); + + if (!upcase_table[col_index]) { + pr_debug("alloc = 0x%X\n", col_index); + upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT, + sizeof(u16), GFP_KERNEL); + if (!upcase_table[col_index]) { + ret = FFS_MEMORYERR; + goto error; + } + + for (j = 0; j < UTBL_ROW_COUNT; j++) + upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; + } + + upcase_table[col_index][get_row_index(index)] = uni; + index++; + } + } + } + if (index >= 0xFFFF && utbl_checksum == checksum) { + if (tmp_bh) + brelse(tmp_bh); + return FFS_SUCCESS; + } + ret = FFS_ERROR; +error: + if (tmp_bh) + brelse(tmp_bh); + free_upcase_table(sb); + return ret; +} + +static s32 __load_default_upcase_table(struct super_block *sb) +{ + int i, ret = FFS_ERROR; + u32 j; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + bool skip = false; + u32 index = 0; + u16 uni = 0; + u16 **upcase_table; + + upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *), + GFP_KERNEL); + if (!upcase_table) + return FFS_MEMORYERR; + memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *)); + + for (i = 0; index <= 0xFFFF && i < NUM_UPCASE * 2; i += 2) { + uni = GET16(uni_upcase + i); + if (skip) { + pr_debug("skip from 0x%X ", index); + index += uni; + pr_debug("to 0x%X (amount of 0x%X)\n", index, uni); + skip = false; + } else if (uni == index) { + index++; + } else if (uni == 0xFFFF) { + skip = true; + } else { /* uni != index , uni != 0xFFFF */ + u16 col_index = get_col_index(index); + + if (!upcase_table[col_index]) { + pr_debug("alloc = 0x%X\n", col_index); + upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT, + sizeof(u16), + GFP_KERNEL); + if (!upcase_table[col_index]) { + ret = FFS_MEMORYERR; + goto error; + } + + for (j = 0; j < UTBL_ROW_COUNT; j++) + upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; + } + + upcase_table[col_index][get_row_index(index)] = uni; + index++; + } + } + + if (index >= 0xFFFF) + return FFS_SUCCESS; + +error: + /* FATAL error: default upcase table has error */ + free_upcase_table(sb); + return ret; +} + +s32 load_upcase_table(struct super_block *sb) +{ + int i; + u32 tbl_clu, tbl_size; + sector_t sector; + u32 type, num_sectors; + struct chain_t clu; + struct case_dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu.dir = p_fs->root_dir; + clu.flags = 0x01; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + while (clu.dir != CLUSTER_32(~0)) { + for (i = 0; i < p_fs->dentries_per_clu; i++) { + ep = (struct case_dentry_t *)get_entry_in_dir(sb, &clu, + i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep); + + if (type == TYPE_UNUSED) + break; + if (type != TYPE_UPCASE) + continue; + + tbl_clu = GET32_A(ep->start_clu); + tbl_size = (u32)GET64_A(ep->size); + + sector = START_SECTOR(tbl_clu); + num_sectors = ((tbl_size - 1) >> p_bd->sector_size_bits) + 1; + if (__load_upcase_table(sb, sector, num_sectors, + GET32_A(ep->checksum)) != FFS_SUCCESS) + break; + return FFS_SUCCESS; + } + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return FFS_MEDIAERR; + } + /* load default upcase table */ + return __load_default_upcase_table(sb); +} + +void free_upcase_table(struct super_block *sb) +{ + u32 i; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + u16 **upcase_table; + + upcase_table = p_fs->vol_utbl; + for (i = 0; i < UTBL_COL_COUNT; i++) + kfree(upcase_table[i]); + + kfree(p_fs->vol_utbl); + p_fs->vol_utbl = NULL; +} + +/* + * Directory Entry Management Functions + */ + +u32 fat_get_entry_type(struct dentry_t *p_entry) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + if (*(ep->name) == 0x0) + return TYPE_UNUSED; + + else if (*(ep->name) == 0xE5) + return TYPE_DELETED; + + else if (ep->attr == ATTR_EXTEND) + return TYPE_EXTEND; + + else if ((ep->attr & (ATTR_SUBDIR | ATTR_VOLUME)) == ATTR_VOLUME) + return TYPE_VOLUME; + + else if ((ep->attr & (ATTR_SUBDIR | ATTR_VOLUME)) == ATTR_SUBDIR) + return TYPE_DIR; + + return TYPE_FILE; +} + +u32 exfat_get_entry_type(struct dentry_t *p_entry) +{ + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; + + if (ep->type == 0x0) { + return TYPE_UNUSED; + } else if (ep->type < 0x80) { + return TYPE_DELETED; + } else if (ep->type == 0x80) { + return TYPE_INVALID; + } else if (ep->type < 0xA0) { + if (ep->type == 0x81) { + return TYPE_BITMAP; + } else if (ep->type == 0x82) { + return TYPE_UPCASE; + } else if (ep->type == 0x83) { + return TYPE_VOLUME; + } else if (ep->type == 0x85) { + if (GET16_A(ep->attr) & ATTR_SUBDIR) + return TYPE_DIR; + else + return TYPE_FILE; + } + return TYPE_CRITICAL_PRI; + } else if (ep->type < 0xC0) { + if (ep->type == 0xA0) + return TYPE_GUID; + else if (ep->type == 0xA1) + return TYPE_PADDING; + else if (ep->type == 0xA2) + return TYPE_ACLTAB; + return TYPE_BENIGN_PRI; + } else if (ep->type < 0xE0) { + if (ep->type == 0xC0) + return TYPE_STREAM; + else if (ep->type == 0xC1) + return TYPE_EXTEND; + else if (ep->type == 0xC2) + return TYPE_ACL; + return TYPE_CRITICAL_SEC; + } + + return TYPE_BENIGN_SEC; +} + +void fat_set_entry_type(struct dentry_t *p_entry, u32 type) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + if (type == TYPE_UNUSED) + *(ep->name) = 0x0; + + else if (type == TYPE_DELETED) + *(ep->name) = 0xE5; + + else if (type == TYPE_EXTEND) + ep->attr = ATTR_EXTEND; + + else if (type == TYPE_DIR) + ep->attr = ATTR_SUBDIR; + + else if (type == TYPE_FILE) + ep->attr = ATTR_ARCHIVE; + + else if (type == TYPE_SYMLINK) + ep->attr = ATTR_ARCHIVE | ATTR_SYMLINK; +} + +void exfat_set_entry_type(struct dentry_t *p_entry, u32 type) +{ + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; + + if (type == TYPE_UNUSED) { + ep->type = 0x0; + } else if (type == TYPE_DELETED) { + ep->type &= ~0x80; + } else if (type == TYPE_STREAM) { + ep->type = 0xC0; + } else if (type == TYPE_EXTEND) { + ep->type = 0xC1; + } else if (type == TYPE_BITMAP) { + ep->type = 0x81; + } else if (type == TYPE_UPCASE) { + ep->type = 0x82; + } else if (type == TYPE_VOLUME) { + ep->type = 0x83; + } else if (type == TYPE_DIR) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_SUBDIR); + } else if (type == TYPE_FILE) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_ARCHIVE); + } else if (type == TYPE_SYMLINK) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_ARCHIVE | ATTR_SYMLINK); + } +} + +u32 fat_get_entry_attr(struct dentry_t *p_entry) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + return (u32)ep->attr; +} + +u32 exfat_get_entry_attr(struct dentry_t *p_entry) +{ + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; + + return (u32)GET16_A(ep->attr); +} + +void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + ep->attr = (u8)attr; +} + +void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr) +{ + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; + + SET16_A(ep->attr, (u16)attr); +} + +u8 fat_get_entry_flag(struct dentry_t *p_entry) +{ + return 0x01; +} + +u8 exfat_get_entry_flag(struct dentry_t *p_entry) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; + + return ep->flags; +} + +void fat_set_entry_flag(struct dentry_t *p_entry, u8 flags) +{ +} + +void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; + + ep->flags = flags; +} + +u32 fat_get_entry_clu0(struct dentry_t *p_entry) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + return ((u32)GET16_A(ep->start_clu_hi) << 16) | + GET16_A(ep->start_clu_lo); +} + +u32 exfat_get_entry_clu0(struct dentry_t *p_entry) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; + + return GET32_A(ep->start_clu); +} + +void fat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu)); + SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16)); +} + +void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; + + SET32_A(ep->start_clu, start_clu); +} + +u64 fat_get_entry_size(struct dentry_t *p_entry) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + return (u64)GET32_A(ep->size); +} + +u64 exfat_get_entry_size(struct dentry_t *p_entry) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; + + return GET64_A(ep->valid_size); +} + +void fat_set_entry_size(struct dentry_t *p_entry, u64 size) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + SET32_A(ep->size, (u32)size); +} + +void exfat_set_entry_size(struct dentry_t *p_entry, u64 size) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; + + SET64_A(ep->valid_size, size); + SET64_A(ep->size, size); +} + +void fat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode) +{ + u16 t = 0x00, d = 0x21; + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + switch (mode) { + case TM_CREATE: + t = GET16_A(ep->create_time); + d = GET16_A(ep->create_date); + break; + case TM_MODIFY: + t = GET16_A(ep->modify_time); + d = GET16_A(ep->modify_date); + break; + } + + tp->sec = (t & 0x001F) << 1; + tp->min = (t >> 5) & 0x003F; + tp->hour = (t >> 11); + tp->day = (d & 0x001F); + tp->mon = (d >> 5) & 0x000F; + tp->year = (d >> 9); +} + +void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode) +{ + u16 t = 0x00, d = 0x21; + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; + + switch (mode) { + case TM_CREATE: + t = GET16_A(ep->create_time); + d = GET16_A(ep->create_date); + break; + case TM_MODIFY: + t = GET16_A(ep->modify_time); + d = GET16_A(ep->modify_date); + break; + case TM_ACCESS: + t = GET16_A(ep->access_time); + d = GET16_A(ep->access_date); + break; + } + + tp->sec = (t & 0x001F) << 1; + tp->min = (t >> 5) & 0x003F; + tp->hour = (t >> 11); + tp->day = (d & 0x001F); + tp->mon = (d >> 5) & 0x000F; + tp->year = (d >> 9); +} + +void fat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode) +{ + u16 t, d; + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1); + d = (tp->year << 9) | (tp->mon << 5) | tp->day; + + switch (mode) { + case TM_CREATE: + SET16_A(ep->create_time, t); + SET16_A(ep->create_date, d); + break; + case TM_MODIFY: + SET16_A(ep->modify_time, t); + SET16_A(ep->modify_date, d); + break; + } +} + +void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode) +{ + u16 t, d; + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; + + t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1); + d = (tp->year << 9) | (tp->mon << 5) | tp->day; + + switch (mode) { + case TM_CREATE: + SET16_A(ep->create_time, t); + SET16_A(ep->create_date, d); + break; + case TM_MODIFY: + SET16_A(ep->modify_time, t); + SET16_A(ep->modify_date, d); + break; + case TM_ACCESS: + SET16_A(ep->access_time, t); + SET16_A(ep->access_date, d); + break; + } +} + +s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry, + u32 type, u32 start_clu, u64 size) +{ + sector_t sector; + struct dos_dentry_t *dos_ep; + + dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + §or); + if (!dos_ep) + return FFS_MEDIAERR; + + init_dos_entry(dos_ep, type, start_clu); + buf_modify(sb, sector); + + return FFS_SUCCESS; +} + +s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, u32 type, u32 start_clu, u64 size) +{ + sector_t sector; + u8 flags; + struct file_dentry_t *file_ep; + struct strm_dentry_t *strm_ep; + + flags = (type == TYPE_FILE) ? 0x01 : 0x03; + + /* we cannot use get_entry_set_in_dir here because file ep is not initialized yet */ + file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + §or); + if (!file_ep) + return FFS_MEDIAERR; + + strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry + 1, + §or); + if (!strm_ep) + return FFS_MEDIAERR; + + init_file_entry(file_ep, type); + buf_modify(sb, sector); + + init_strm_entry(strm_ep, flags, start_clu, size); + buf_modify(sb, sector); + + return FFS_SUCCESS; +} + +static s32 fat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 num_entries, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname) +{ + int i; + sector_t sector; + u8 chksum; + u16 *uniname = p_uniname->name; + struct dos_dentry_t *dos_ep; + struct ext_dentry_t *ext_ep; + + dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + §or); + if (!dos_ep) + return FFS_MEDIAERR; + + dos_ep->lcase = p_dosname->name_case; + memcpy(dos_ep->name, p_dosname->name, DOS_NAME_LENGTH); + buf_modify(sb, sector); + + if ((--num_entries) > 0) { + chksum = calc_checksum_1byte((void *)dos_ep->name, + DOS_NAME_LENGTH, 0); + + for (i = 1; i < num_entries; i++) { + ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, + p_dir, + entry - i, + §or); + if (!ext_ep) + return FFS_MEDIAERR; + + init_ext_entry(ext_ep, i, chksum, uniname); + buf_modify(sb, sector); + uniname += 13; + } + + ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir, + entry - i, + §or); + if (!ext_ep) + return FFS_MEDIAERR; + + init_ext_entry(ext_ep, i + 0x40, chksum, uniname); + buf_modify(sb, sector); + } + + return FFS_SUCCESS; +} + +static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 num_entries, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname) +{ + int i; + sector_t sector; + u16 *uniname = p_uniname->name; + struct file_dentry_t *file_ep; + struct strm_dentry_t *strm_ep; + struct name_dentry_t *name_ep; + + file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + §or); + if (!file_ep) + return FFS_MEDIAERR; + + file_ep->num_ext = (u8)(num_entries - 1); + buf_modify(sb, sector); + + strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry + 1, + §or); + if (!strm_ep) + return FFS_MEDIAERR; + + strm_ep->name_len = p_uniname->name_len; + SET16_A(strm_ep->name_hash, p_uniname->name_hash); + buf_modify(sb, sector); + + for (i = 2; i < num_entries; i++) { + name_ep = (struct name_dentry_t *)get_entry_in_dir(sb, p_dir, + entry + i, + §or); + if (!name_ep) + return FFS_MEDIAERR; + + init_name_entry(name_ep, uniname); + buf_modify(sb, sector); + uniname += 15; + } + + update_dir_checksum(sb, p_dir, entry); + + return FFS_SUCCESS; +} + +void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu) +{ + struct timestamp_t tm, *tp; + + fat_set_entry_type((struct dentry_t *)ep, type); + SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu)); + SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16)); + SET32_A(ep->size, 0); + + tp = tm_current(&tm); + fat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE); + fat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY); + SET16_A(ep->access_date, 0); + ep->create_time_ms = 0; +} + +void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, u16 *uniname) +{ + int i; + bool end = false; + + fat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND); + ep->order = (u8)order; + ep->sysid = 0; + ep->checksum = chksum; + SET16_A(ep->start_clu, 0); + + for (i = 0; i < 10; i += 2) { + if (!end) { + SET16(ep->unicode_0_4 + i, *uniname); + if (*uniname == 0x0) + end = true; + else + uniname++; + } else { + SET16(ep->unicode_0_4 + i, 0xFFFF); + } + } + + for (i = 0; i < 12; i += 2) { + if (!end) { + SET16_A(ep->unicode_5_10 + i, *uniname); + if (*uniname == 0x0) + end = true; + else + uniname++; + } else { + SET16_A(ep->unicode_5_10 + i, 0xFFFF); + } + } + + for (i = 0; i < 4; i += 2) { + if (!end) { + SET16_A(ep->unicode_11_12 + i, *uniname); + if (*uniname == 0x0) + end = true; + else + uniname++; + } else { + SET16_A(ep->unicode_11_12 + i, 0xFFFF); + } + } +} + +void init_file_entry(struct file_dentry_t *ep, u32 type) +{ + struct timestamp_t tm, *tp; + + exfat_set_entry_type((struct dentry_t *)ep, type); + + tp = tm_current(&tm); + exfat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE); + exfat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY); + exfat_set_entry_time((struct dentry_t *)ep, tp, TM_ACCESS); + ep->create_time_ms = 0; + ep->modify_time_ms = 0; + ep->access_time_ms = 0; +} + +void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu, u64 size) +{ + exfat_set_entry_type((struct dentry_t *)ep, TYPE_STREAM); + ep->flags = flags; + SET32_A(ep->start_clu, start_clu); + SET64_A(ep->valid_size, size); + SET64_A(ep->size, size); +} + +void init_name_entry(struct name_dentry_t *ep, u16 *uniname) +{ + int i; + + exfat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND); + ep->flags = 0x0; + + for (i = 0; i < 30; i++, i++) { + SET16_A(ep->unicode_0_14 + i, *uniname); + if (*uniname == 0x0) + break; + uniname++; + } +} + +void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 order, s32 num_entries) +{ + int i; + sector_t sector; + struct dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = num_entries - 1; i >= order; i--) { + ep = get_entry_in_dir(sb, p_dir, entry - i, §or); + if (!ep) + return; + + p_fs->fs_func->set_entry_type(ep, TYPE_DELETED); + buf_modify(sb, sector); + } +} + +void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 order, s32 num_entries) +{ + int i; + sector_t sector; + struct dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = order; i < num_entries; i++) { + ep = get_entry_in_dir(sb, p_dir, entry + i, §or); + if (!ep) + return; + + p_fs->fs_func->set_entry_type(ep, TYPE_DELETED); + buf_modify(sb, sector); + } +} + +void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir, + s32 entry) +{ + int i, num_entries; + sector_t sector; + u16 chksum; + struct file_dentry_t *file_ep; + struct dentry_t *ep; + + file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + §or); + if (!file_ep) + return; + + buf_lock(sb, sector); + + num_entries = (s32)file_ep->num_ext + 1; + chksum = calc_checksum_2byte((void *)file_ep, DENTRY_SIZE, 0, + CS_DIR_ENTRY); + + for (i = 1; i < num_entries; i++) { + ep = get_entry_in_dir(sb, p_dir, entry + i, NULL); + if (!ep) { + buf_unlock(sb, sector); + return; + } + + chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum, + CS_DEFAULT); + } + + SET16_A(file_ep->checksum, chksum); + buf_modify(sb, sector); + buf_unlock(sb, sector); +} + +void update_dir_checksum_with_entry_set(struct super_block *sb, + struct entry_set_cache_t *es) +{ + struct dentry_t *ep; + u16 chksum = 0; + s32 chksum_type = CS_DIR_ENTRY, i; + + ep = (struct dentry_t *)&(es->__buf); + for (i = 0; i < es->num_entries; i++) { + pr_debug("%s ep %p\n", __func__, ep); + chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum, + chksum_type); + ep++; + chksum_type = CS_DEFAULT; + } + + ep = (struct dentry_t *)&(es->__buf); + SET16_A(((struct file_dentry_t *)ep)->checksum, chksum); + write_whole_entry_set(sb, es); +} + +static s32 _walk_fat_chain(struct super_block *sb, struct chain_t *p_dir, + s32 byte_offset, u32 *clu) +{ + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + s32 clu_offset; + u32 cur_clu; + + clu_offset = byte_offset >> p_fs->cluster_size_bits; + cur_clu = p_dir->dir; + + if (p_dir->flags == 0x03) { + cur_clu += clu_offset; + } else { + while (clu_offset > 0) { + if (FAT_read(sb, cur_clu, &cur_clu) == -1) + return FFS_MEDIAERR; + clu_offset--; + } + } + + if (clu) + *clu = cur_clu; + return FFS_SUCCESS; +} + +s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry, + sector_t *sector, s32 *offset) +{ + s32 off, ret; + u32 clu = 0; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + off = entry << DENTRY_SIZE_BITS; + + if (p_dir->dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + *offset = off & p_bd->sector_size_mask; + *sector = off >> p_bd->sector_size_bits; + *sector += p_fs->root_start_sector; + } else { + ret = _walk_fat_chain(sb, p_dir, off, &clu); + if (ret != FFS_SUCCESS) + return ret; + + /* byte offset in cluster */ + off &= p_fs->cluster_size - 1; + + /* byte offset in sector */ + *offset = off & p_bd->sector_size_mask; + + /* sector offset in cluster */ + *sector = off >> p_bd->sector_size_bits; + *sector += START_SECTOR(clu); + } + return FFS_SUCCESS; +} + +struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector, + s32 offset) +{ + u8 *buf; + + buf = buf_getblk(sb, sector); + + if (!buf) + return NULL; + + return (struct dentry_t *)(buf + offset); +} + +struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir, + s32 entry, sector_t *sector) +{ + s32 off; + sector_t sec; + u8 *buf; + + if (find_location(sb, p_dir, entry, &sec, &off) != FFS_SUCCESS) + return NULL; + + buf = buf_getblk(sb, sec); + + if (!buf) + return NULL; + + if (sector) + *sector = sec; + return (struct dentry_t *)(buf + off); +} + +/* returns a set of dentries for a file or dir. + * Note that this is a copy (dump) of dentries so that user should call write_entry_set() + * to apply changes made in this entry set to the real device. + * in: + * sb+p_dir+entry: indicates a file/dir + * type: specifies how many dentries should be included. + * out: + * file_ep: will point the first dentry(= file dentry) on success + * return: + * pointer of entry set on success, + * NULL on failure. + */ + +#define ES_MODE_STARTED 0 +#define ES_MODE_GET_FILE_ENTRY 1 +#define ES_MODE_GET_STRM_ENTRY 2 +#define ES_MODE_GET_NAME_ENTRY 3 +#define ES_MODE_GET_CRITICAL_SEC_ENTRY 4 +struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u32 type, + struct dentry_t **file_ep) +{ + s32 off, ret, byte_offset; + u32 clu = 0; + sector_t sec; + u32 entry_type; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct entry_set_cache_t *es = NULL; + struct dentry_t *ep, *pos; + u8 *buf; + u8 num_entries; + s32 mode = ES_MODE_STARTED; + size_t bufsize; + + pr_debug("%s entered p_dir dir %u flags %x size %d\n", + __func__, p_dir->dir, p_dir->flags, p_dir->size); + + byte_offset = entry << DENTRY_SIZE_BITS; + ret = _walk_fat_chain(sb, p_dir, byte_offset, &clu); + if (ret != FFS_SUCCESS) + return NULL; + + /* byte offset in cluster */ + byte_offset &= p_fs->cluster_size - 1; + + /* byte offset in sector */ + off = byte_offset & p_bd->sector_size_mask; + + /* sector offset in cluster */ + sec = byte_offset >> p_bd->sector_size_bits; + sec += START_SECTOR(clu); + + buf = buf_getblk(sb, sec); + if (!buf) + goto err_out; + + ep = (struct dentry_t *)(buf + off); + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type != TYPE_FILE) + && (entry_type != TYPE_DIR)) + goto err_out; + + if (type == ES_ALL_ENTRIES) + num_entries = ((struct file_dentry_t *)ep)->num_ext + 1; + else + num_entries = type; + + bufsize = offsetof(struct entry_set_cache_t, __buf) + (num_entries) * + sizeof(struct dentry_t); + pr_debug("%s: trying to kmalloc %zx bytes for %d entries\n", __func__, + bufsize, num_entries); + es = kmalloc(bufsize, GFP_KERNEL); + if (!es) + goto err_out; + + es->num_entries = num_entries; + es->sector = sec; + es->offset = off; + es->alloc_flag = p_dir->flags; + + pos = (struct dentry_t *)&es->__buf; + + while (num_entries) { + /* + * instead of copying whole sector, we will check every entry. + * this will provide minimum stablity and consistency. + */ + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) + goto err_out; + + switch (mode) { + case ES_MODE_STARTED: + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) + mode = ES_MODE_GET_FILE_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_FILE_ENTRY: + if (entry_type == TYPE_STREAM) + mode = ES_MODE_GET_STRM_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_STRM_ENTRY: + if (entry_type == TYPE_EXTEND) + mode = ES_MODE_GET_NAME_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_NAME_ENTRY: + if (entry_type == TYPE_EXTEND) + break; + else if (entry_type == TYPE_STREAM) + goto err_out; + else if (entry_type & TYPE_CRITICAL_SEC) + mode = ES_MODE_GET_CRITICAL_SEC_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_CRITICAL_SEC_ENTRY: + if ((entry_type == TYPE_EXTEND) || + (entry_type == TYPE_STREAM)) + goto err_out; + else if ((entry_type & TYPE_CRITICAL_SEC) != + TYPE_CRITICAL_SEC) + goto err_out; + break; + } + + memcpy(pos, ep, sizeof(struct dentry_t)); + + if (--num_entries == 0) + break; + + if (((off + DENTRY_SIZE) & p_bd->sector_size_mask) < + (off & p_bd->sector_size_mask)) { + /* get the next sector */ + if (IS_LAST_SECTOR_IN_CLUSTER(sec)) { + if (es->alloc_flag == 0x03) { + clu++; + } else { + if (FAT_read(sb, clu, &clu) == -1) + goto err_out; + } + sec = START_SECTOR(clu); + } else { + sec++; + } + buf = buf_getblk(sb, sec); + if (!buf) + goto err_out; + off = 0; + ep = (struct dentry_t *)(buf); + } else { + ep++; + off += DENTRY_SIZE; + } + pos++; + } + + if (file_ep) + *file_ep = (struct dentry_t *)&(es->__buf); + + pr_debug("%s exiting es %p sec %llu offset %d flags %d, num_entries %u buf ptr %p\n", + __func__, es, (unsigned long long)es->sector, es->offset, + es->alloc_flag, es->num_entries, &es->__buf); + return es; +err_out: + pr_debug("%s exited NULL (es %p)\n", __func__, es); + kfree(es); + return NULL; +} + +void release_entry_set(struct entry_set_cache_t *es) +{ + pr_debug("%s es=%p\n", __func__, es); + kfree(es); +} + +static s32 __write_partial_entries_in_entry_set(struct super_block *sb, + struct entry_set_cache_t *es, + sector_t sec, s32 off, u32 count) +{ + s32 num_entries, buf_off = (off - es->offset); + u32 remaining_byte_in_sector, copy_entries; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + u32 clu; + u8 *buf, *esbuf = (u8 *)&(es->__buf); + + pr_debug("%s entered es %p sec %llu off %d count %d\n", + __func__, es, (unsigned long long)sec, off, count); + num_entries = count; + + while (num_entries) { + /* white per sector base */ + remaining_byte_in_sector = (1 << p_bd->sector_size_bits) - off; + copy_entries = min_t(s32, + remaining_byte_in_sector >> DENTRY_SIZE_BITS, + num_entries); + buf = buf_getblk(sb, sec); + if (!buf) + goto err_out; + pr_debug("es->buf %p buf_off %u\n", esbuf, buf_off); + pr_debug("copying %d entries from %p to sector %llu\n", + copy_entries, (esbuf + buf_off), + (unsigned long long)sec); + memcpy(buf + off, esbuf + buf_off, + copy_entries << DENTRY_SIZE_BITS); + buf_modify(sb, sec); + num_entries -= copy_entries; + + if (num_entries) { + /* get next sector */ + if (IS_LAST_SECTOR_IN_CLUSTER(sec)) { + clu = GET_CLUSTER_FROM_SECTOR(sec); + if (es->alloc_flag == 0x03) { + clu++; + } else { + if (FAT_read(sb, clu, &clu) == -1) + goto err_out; + } + sec = START_SECTOR(clu); + } else { + sec++; + } + off = 0; + buf_off += copy_entries << DENTRY_SIZE_BITS; + } + } + + pr_debug("%s exited successfully\n", __func__); + return FFS_SUCCESS; +err_out: + pr_debug("%s failed\n", __func__); + return FFS_ERROR; +} + +/* write back all entries in entry set */ +s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es) +{ + return __write_partial_entries_in_entry_set(sb, es, es->sector, + es->offset, + es->num_entries); +} + +/* write back some entries in entry set */ +s32 write_partial_entries_in_entry_set(struct super_block *sb, + struct entry_set_cache_t *es, struct dentry_t *ep, u32 count) +{ + s32 ret, byte_offset, off; + u32 clu = 0; + sector_t sec; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct chain_t dir; + + /* vaidity check */ + if (ep + count > ((struct dentry_t *)&(es->__buf)) + es->num_entries) + return FFS_ERROR; + + dir.dir = GET_CLUSTER_FROM_SECTOR(es->sector); + dir.flags = es->alloc_flag; + dir.size = 0xffffffff; /* XXX */ + + byte_offset = (es->sector - START_SECTOR(dir.dir)) << + p_bd->sector_size_bits; + byte_offset += ((void **)ep - &(es->__buf)) + es->offset; + + ret = _walk_fat_chain(sb, &dir, byte_offset, &clu); + if (ret != FFS_SUCCESS) + return ret; + + /* byte offset in cluster */ + byte_offset &= p_fs->cluster_size - 1; + + /* byte offset in sector */ + off = byte_offset & p_bd->sector_size_mask; + + /* sector offset in cluster */ + sec = byte_offset >> p_bd->sector_size_bits; + sec += START_SECTOR(clu); + return __write_partial_entries_in_entry_set(sb, es, sec, off, count); +} + +/* search EMPTY CONTINUOUS "num_entries" entries */ +s32 search_deleted_or_unused_entry(struct super_block *sb, + struct chain_t *p_dir, s32 num_entries) +{ + int i, dentry, num_empty = 0; + s32 dentries_per_clu; + u32 type; + struct chain_t clu; + struct dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + if (p_fs->hint_uentry.dir == p_dir->dir) { + if (p_fs->hint_uentry.entry == -1) + return -1; + + clu.dir = p_fs->hint_uentry.clu.dir; + clu.size = p_fs->hint_uentry.clu.size; + clu.flags = p_fs->hint_uentry.clu.flags; + + dentry = p_fs->hint_uentry.entry; + } else { + p_fs->hint_uentry.entry = -1; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + dentry = 0; + } + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + i = dentry % dentries_per_clu; + else + i = dentry & (dentries_per_clu - 1); + + for (; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -1; + + type = p_fs->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) { + num_empty++; + if (p_fs->hint_uentry.entry == -1) { + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = dentry; + + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = clu.size; + p_fs->hint_uentry.clu.flags = clu.flags; + } + } else if (type == TYPE_DELETED) { + num_empty++; + } else { + num_empty = 0; + } + + if (num_empty >= num_entries) { + p_fs->hint_uentry.dir = CLUSTER_32(~0); + p_fs->hint_uentry.entry = -1; + + if (p_fs->vol_type == EXFAT) + return dentry - (num_entries - 1); + else + return dentry; + } + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return -1; + } + } + + return -1; +} + +s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries) +{ + s32 ret, dentry; + u32 last_clu; + sector_t sector; + u64 size = 0; + struct chain_t clu; + struct dentry_t *ep = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + return search_deleted_or_unused_entry(sb, p_dir, num_entries); + + while ((dentry = search_deleted_or_unused_entry(sb, p_dir, num_entries)) < 0) { + if (p_fs->dev_ejected) + break; + + if (p_fs->vol_type == EXFAT) { + if (p_dir->dir != p_fs->root_dir) + size = i_size_read(inode); + } + + last_clu = find_last_cluster(sb, p_dir); + clu.dir = last_clu + 1; + clu.size = 0; + clu.flags = p_dir->flags; + + /* (1) allocate a cluster */ + ret = p_fs->fs_func->alloc_cluster(sb, 1, &clu); + if (ret < 1) + return -1; + + if (clear_cluster(sb, clu.dir) != FFS_SUCCESS) + return -1; + + /* (2) append to the FAT chain */ + if (clu.flags != p_dir->flags) { + exfat_chain_cont_cluster(sb, p_dir->dir, p_dir->size); + p_dir->flags = 0x01; + p_fs->hint_uentry.clu.flags = 0x01; + } + if (clu.flags == 0x01) + if (FAT_write(sb, last_clu, clu.dir) < 0) + return -1; + + if (p_fs->hint_uentry.entry == -1) { + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = p_dir->size << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS); + + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = 0; + p_fs->hint_uentry.clu.flags = clu.flags; + } + p_fs->hint_uentry.clu.size++; + p_dir->size++; + + /* (3) update the directory entry */ + if (p_fs->vol_type == EXFAT) { + if (p_dir->dir != p_fs->root_dir) { + size += p_fs->cluster_size; + + ep = get_entry_in_dir(sb, &fid->dir, + fid->entry + 1, §or); + if (!ep) + return -1; + p_fs->fs_func->set_entry_size(ep, size); + p_fs->fs_func->set_entry_flag(ep, p_dir->flags); + buf_modify(sb, sector); + + update_dir_checksum(sb, &(fid->dir), + fid->entry); + } + } + + i_size_write(inode, i_size_read(inode) + p_fs->cluster_size); + EXFAT_I(inode)->mmu_private += p_fs->cluster_size; + EXFAT_I(inode)->fid.size += p_fs->cluster_size; + EXFAT_I(inode)->fid.flags = p_dir->flags; + inode->i_blocks += 1 << (p_fs->cluster_size_bits - 9); + } + + return dentry; +} + +/* return values of fat_find_dir_entry() + * >= 0 : return dir entiry position with the name in dir + * -1 : (root dir, ".") it is the root dir itself + * -2 : entry with the name does not exist + */ +s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type) +{ + int i, dentry = 0, len; + s32 order = 0; + bool is_feasible_entry = true, has_ext_entry = false; + s32 dentries_per_clu; + u32 entry_type; + u16 entry_uniname[14], *uniname = NULL, unichar; + struct chain_t clu; + struct dentry_t *ep; + struct dos_dentry_t *dos_ep; + struct ext_dentry_t *ext_ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == p_fs->root_dir) { + if ((!nls_uniname_cmp(sb, p_uniname->name, + (u16 *)UNI_CUR_DIR_NAME)) || + (!nls_uniname_cmp(sb, p_uniname->name, + (u16 *)UNI_PAR_DIR_NAME))) + return -1; // special case, root directory itself + } + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -2; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { + if ((type == TYPE_ALL) || (type == entry_type)) { + if (is_feasible_entry && has_ext_entry) + return dentry; + + dos_ep = (struct dos_dentry_t *)ep; + if (!nls_dosname_cmp(sb, p_dosname->name, dos_ep->name)) + return dentry; + } + is_feasible_entry = true; + has_ext_entry = false; + } else if (entry_type == TYPE_EXTEND) { + if (is_feasible_entry) { + ext_ep = (struct ext_dentry_t *)ep; + if (ext_ep->order > 0x40) { + order = (s32)(ext_ep->order - 0x40); + uniname = p_uniname->name + 13 * (order - 1); + } else { + order = (s32)ext_ep->order; + uniname -= 13; + } + + len = extract_uni_name_from_ext_entry(ext_ep, entry_uniname, order); + + unichar = *(uniname + len); + *(uniname + len) = 0x0; + + if (nls_uniname_cmp(sb, uniname, entry_uniname)) + is_feasible_entry = false; + + *(uniname + len) = unichar; + } + has_ext_entry = true; + } else if (entry_type == TYPE_UNUSED) { + return -2; + } + is_feasible_entry = true; + has_ext_entry = false; + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return -2; + } + + return -2; +} + +/* return values of exfat_find_dir_entry() + * >= 0 : return dir entiry position with the name in dir + * -1 : (root dir, ".") it is the root dir itself + * -2 : entry with the name does not exist + */ +s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type) +{ + int i = 0, dentry = 0, num_ext_entries = 0, len, step; + s32 order = 0; + bool is_feasible_entry = false; + s32 dentries_per_clu, num_empty = 0; + u32 entry_type; + u16 entry_uniname[16], *uniname = NULL, unichar; + struct chain_t clu; + struct dentry_t *ep; + struct file_dentry_t *file_ep; + struct strm_dentry_t *strm_ep; + struct name_dentry_t *name_ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == p_fs->root_dir) { + if ((!nls_uniname_cmp(sb, p_uniname->name, + (u16 *)UNI_CUR_DIR_NAME)) || + (!nls_uniname_cmp(sb, p_uniname->name, + (u16 *)UNI_PAR_DIR_NAME))) + return -1; // special case, root directory itself + } + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = -1; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + while (i < dentries_per_clu) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -2; + + entry_type = p_fs->fs_func->get_entry_type(ep); + step = 1; + + if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) { + is_feasible_entry = false; + + if (p_fs->hint_uentry.entry == -1) { + num_empty++; + + if (num_empty == 1) { + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = clu.size; + p_fs->hint_uentry.clu.flags = clu.flags; + } + if ((num_empty >= num_entries) || (entry_type == TYPE_UNUSED)) + p_fs->hint_uentry.entry = dentry - (num_empty - 1); + } + + if (entry_type == TYPE_UNUSED) + return -2; + } else { + num_empty = 0; + + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { + file_ep = (struct file_dentry_t *)ep; + if ((type == TYPE_ALL) || (type == entry_type)) { + num_ext_entries = file_ep->num_ext; + is_feasible_entry = true; + } else { + is_feasible_entry = false; + step = file_ep->num_ext + 1; + } + } else if (entry_type == TYPE_STREAM) { + if (is_feasible_entry) { + strm_ep = (struct strm_dentry_t *)ep; + if (p_uniname->name_hash == GET16_A(strm_ep->name_hash) && + p_uniname->name_len == strm_ep->name_len) { + order = 1; + } else { + is_feasible_entry = false; + step = num_ext_entries; + } + } + } else if (entry_type == TYPE_EXTEND) { + if (is_feasible_entry) { + name_ep = (struct name_dentry_t *)ep; + + if ((++order) == 2) + uniname = p_uniname->name; + else + uniname += 15; + + len = extract_uni_name_from_name_entry(name_ep, + entry_uniname, order); + + unichar = *(uniname + len); + *(uniname + len) = 0x0; + + if (nls_uniname_cmp(sb, uniname, entry_uniname)) { + is_feasible_entry = false; + step = num_ext_entries - order + 1; + } else if (order == num_ext_entries) { + p_fs->hint_uentry.dir = CLUSTER_32(~0); + p_fs->hint_uentry.entry = -1; + return dentry - (num_ext_entries); + } + + *(uniname + len) = unichar; + } + } else { + is_feasible_entry = false; + } + } + + i += step; + dentry += step; + } + + i -= dentries_per_clu; + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return -2; + } + } + + return -2; +} + +s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, + s32 entry, struct dentry_t *p_entry) +{ + s32 count = 0; + u8 chksum; + struct dos_dentry_t *dos_ep = (struct dos_dentry_t *)p_entry; + struct ext_dentry_t *ext_ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + chksum = calc_checksum_1byte((void *)dos_ep->name, DOS_NAME_LENGTH, 0); + + for (entry--; entry >= 0; entry--) { + ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir, + entry, NULL); + if (!ext_ep) + return -1; + + if ((p_fs->fs_func->get_entry_type((struct dentry_t *)ext_ep) == + TYPE_EXTEND) && (ext_ep->checksum == chksum)) { + count++; + if (ext_ep->order > 0x40) + return count; + } else { + return count; + } + } + + return count; +} + +s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, + s32 entry, struct dentry_t *p_entry) +{ + int i, count = 0; + u32 type; + struct file_dentry_t *file_ep = (struct file_dentry_t *)p_entry; + struct dentry_t *ext_ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = 0, entry++; i < file_ep->num_ext; i++, entry++) { + ext_ep = get_entry_in_dir(sb, p_dir, entry, NULL); + if (!ext_ep) + return -1; + + type = p_fs->fs_func->get_entry_type(ext_ep); + if ((type == TYPE_EXTEND) || (type == TYPE_STREAM)) + count++; + else + return count; + } + + return count; +} + +s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir, + u32 type) +{ + int i, count = 0; + s32 dentries_per_clu; + u32 entry_type; + struct chain_t clu; + struct dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -1; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if (entry_type == TYPE_UNUSED) + return count; + if (!(type & TYPE_CRITICAL_PRI) && + !(type & TYPE_BENIGN_PRI)) + continue; + + if ((type == TYPE_ALL) || (type == entry_type)) + count++; + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return -1; + } + } + + return count; +} + +bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir) +{ + int i, count = 0; + s32 dentries_per_clu; + u32 type; + struct chain_t clu; + struct dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + break; + + type = p_fs->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) + return true; + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + return false; + + if (p_fs->vol_type == EXFAT) + return false; + if ((p_dir->dir == p_fs->root_dir) || ((++count) > 2)) + return false; + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + break; + } + + return true; +} + +/* + * Name Conversion Functions + */ + +/* input : dir, uni_name + * output : num_of_entry, dos_name(format : aaaaaa~1.bbb) + */ +s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 *entries, + struct dos_name_t *p_dosname) +{ + s32 ret, num_entries; + bool lossy = false; + char **r; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + num_entries = p_fs->fs_func->calc_num_entries(p_uniname); + if (num_entries == 0) + return FFS_INVALIDPATH; + + if (p_fs->vol_type != EXFAT) { + nls_uniname_to_dosname(sb, p_dosname, p_uniname, &lossy); + + if (lossy) { + ret = fat_generate_dos_name(sb, p_dir, p_dosname); + if (ret) + return ret; + } else { + for (r = reserved_names; *r; r++) { + if (!strncmp((void *)p_dosname->name, *r, 8)) + return FFS_INVALIDPATH; + } + + if (p_dosname->name_case != 0xFF) + num_entries = 1; + } + + if (num_entries > 1) + p_dosname->name_case = 0x0; + } + + *entries = num_entries; + + return FFS_SUCCESS; +} + +void get_uni_name_from_dos_entry(struct super_block *sb, + struct dos_dentry_t *ep, + struct uni_name_t *p_uniname, u8 mode) +{ + struct dos_name_t dos_name; + + if (mode == 0x0) + dos_name.name_case = 0x0; + else + dos_name.name_case = ep->lcase; + + memcpy(dos_name.name, ep->name, DOS_NAME_LENGTH); + nls_dosname_to_uniname(sb, p_uniname, &dos_name); +} + +void fat_get_uni_name_from_ext_entry(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname) +{ + int i; + struct ext_dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (entry--, i = 1; entry >= 0; entry--, i++) { + ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + NULL); + if (!ep) + return; + + if (p_fs->fs_func->get_entry_type((struct dentry_t *)ep) == + TYPE_EXTEND) { + extract_uni_name_from_ext_entry(ep, uniname, i); + if (ep->order > 0x40) + return; + } else { + return; + } + + uniname += 13; + } +} + +void exfat_get_uni_name_from_ext_entry(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname) +{ + int i; + struct dentry_t *ep; + struct entry_set_cache_t *es; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + es = get_entry_set_in_dir(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); + if (!es || es->num_entries < 3) { + if (es) + release_entry_set(es); + return; + } + + ep += 2; + + /* + * First entry : file entry + * Second entry : stream-extension entry + * Third entry : first file-name entry + * So, the index of first file-name dentry should start from 2. + */ + for (i = 2; i < es->num_entries; i++, ep++) { + if (p_fs->fs_func->get_entry_type(ep) == TYPE_EXTEND) + extract_uni_name_from_name_entry((struct name_dentry_t *) + ep, uniname, i); + else + goto out; + uniname += 15; + } + +out: + release_entry_set(es); +} + +s32 extract_uni_name_from_ext_entry(struct ext_dentry_t *ep, u16 *uniname, + s32 order) +{ + int i, len = 0; + + for (i = 0; i < 10; i += 2) { + *uniname = GET16(ep->unicode_0_4 + i); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + + if (order < 20) { + for (i = 0; i < 12; i += 2) { + *uniname = GET16_A(ep->unicode_5_10 + i); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + } else { + for (i = 0; i < 8; i += 2) { + *uniname = GET16_A(ep->unicode_5_10 + i); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + *uniname = 0x0; /* uniname[MAX_NAME_LENGTH-1] */ + return len; + } + + for (i = 0; i < 4; i += 2) { + *uniname = GET16_A(ep->unicode_11_12 + i); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + + *uniname = 0x0; + return len; +} + +s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname, + s32 order) +{ + int i, len = 0; + + for (i = 0; i < 30; i += 2) { + *uniname = GET16_A(ep->unicode_0_14 + i); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + + *uniname = 0x0; + return len; +} + +s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir, + struct dos_name_t *p_dosname) +{ + int i, j, count = 0; + bool count_begin = false; + s32 dentries_per_clu; + u32 type; + u8 bmap[128/* 1 ~ 1023 */]; + struct chain_t clu; + struct dos_dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + memset(bmap, 0, sizeof(bmap)); + exfat_bitmap_set(bmap, 0); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = (struct dos_dentry_t *)get_entry_in_dir(sb, &clu, + i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((struct dentry_t *) + ep); + + if (type == TYPE_UNUSED) + break; + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + count = 0; + count_begin = false; + + for (j = 0; j < 8; j++) { + if (ep->name[j] == ' ') + break; + + if (ep->name[j] == '~') { + count_begin = true; + } else if (count_begin) { + if ((ep->name[j] >= '0') && + (ep->name[j] <= '9')) { + count = count * 10 + + (ep->name[j] - '0'); + } else { + count = 0; + count_begin = false; + } + } + } + + if ((count > 0) && (count < 1024)) + exfat_bitmap_set(bmap, count); + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return FFS_MEDIAERR; + } + + count = 0; + for (i = 0; i < 128; i++) { + if (bmap[i] != 0xFF) { + for (j = 0; j < 8; j++) { + if (exfat_bitmap_test(&bmap[i], j) == 0) { + count = (i << 3) + j; + break; + } + } + if (count != 0) + break; + } + } + + if ((count == 0) || (count >= 1024)) + return FFS_FILEEXIST; + fat_attach_count_to_dos_name(p_dosname->name, count); + + /* Now dos_name has DOS~????.EXT */ + return FFS_SUCCESS; +} + +void fat_attach_count_to_dos_name(u8 *dosname, s32 count) +{ + int i, j, length; + char str_count[6]; + + snprintf(str_count, sizeof(str_count), "~%d", count); + length = strlen(str_count); + + i = 0; + j = 0; + while (j <= (8 - length)) { + i = j; + if (dosname[j] == ' ') + break; + if (dosname[j] & 0x80) + j += 2; + else + j++; + } + + for (j = 0; j < length; i++, j++) + dosname[i] = (u8)str_count[j]; + + if (i == 7) + dosname[7] = ' '; +} + +s32 fat_calc_num_entries(struct uni_name_t *p_uniname) +{ + s32 len; + + len = p_uniname->name_len; + if (len == 0) + return 0; + + /* 1 dos name entry + extended entries */ + return (len - 1) / 13 + 2; +} + +s32 exfat_calc_num_entries(struct uni_name_t *p_uniname) +{ + s32 len; + + len = p_uniname->name_len; + if (len == 0) + return 0; + + /* 1 file entry + 1 stream entry + name entries */ + return (len - 1) / 15 + 3; +} + +u8 calc_checksum_1byte(void *data, s32 len, u8 chksum) +{ + int i; + u8 *c = (u8 *)data; + + for (i = 0; i < len; i++, c++) + chksum = (((chksum & 1) << 7) | ((chksum & 0xFE) >> 1)) + *c; + + return chksum; +} + +u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type) +{ + int i; + u8 *c = (u8 *)data; + + switch (type) { + case CS_DIR_ENTRY: + for (i = 0; i < len; i++, c++) { + if ((i == 2) || (i == 3)) + continue; + chksum = (((chksum & 1) << 15) | + ((chksum & 0xFFFE) >> 1)) + (u16)*c; + } + break; + default + : + for (i = 0; i < len; i++, c++) + chksum = (((chksum & 1) << 15) | + ((chksum & 0xFFFE) >> 1)) + (u16)*c; + } + + return chksum; +} + +u32 calc_checksum_4byte(void *data, s32 len, u32 chksum, s32 type) +{ + int i; + u8 *c = (u8 *)data; + + switch (type) { + case CS_PBR_SECTOR: + for (i = 0; i < len; i++, c++) { + if ((i == 106) || (i == 107) || (i == 112)) + continue; + chksum = (((chksum & 1) << 31) | + ((chksum & 0xFFFFFFFE) >> 1)) + (u32)*c; + } + break; + default + : + for (i = 0; i < len; i++, c++) + chksum = (((chksum & 1) << 31) | + ((chksum & 0xFFFFFFFE) >> 1)) + (u32)*c; + } + + return chksum; +} + +/* + * Name Resolution Functions + */ + +/* return values of resolve_path() + * > 0 : return the length of the path + * < 0 : return error + */ +s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir, + struct uni_name_t *p_uniname) +{ + bool lossy = false; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + + if (strscpy(name_buf, path, sizeof(name_buf)) < 0) + return FFS_INVALIDPATH; + + nls_cstring_to_uniname(sb, p_uniname, name_buf, &lossy); + if (lossy) + return FFS_INVALIDPATH; + + fid->size = i_size_read(inode); + + p_dir->dir = fid->start_clu; + p_dir->size = (s32)(fid->size >> p_fs->cluster_size_bits); + p_dir->flags = fid->flags; + + return FFS_SUCCESS; +} + +/* + * File Operation Functions + */ +static struct fs_func fat_fs_func = { + .alloc_cluster = fat_alloc_cluster, + .free_cluster = fat_free_cluster, + .count_used_clusters = fat_count_used_clusters, + + .init_dir_entry = fat_init_dir_entry, + .init_ext_entry = fat_init_ext_entry, + .find_dir_entry = fat_find_dir_entry, + .delete_dir_entry = fat_delete_dir_entry, + .get_uni_name_from_ext_entry = fat_get_uni_name_from_ext_entry, + .count_ext_entries = fat_count_ext_entries, + .calc_num_entries = fat_calc_num_entries, + + .get_entry_type = fat_get_entry_type, + .set_entry_type = fat_set_entry_type, + .get_entry_attr = fat_get_entry_attr, + .set_entry_attr = fat_set_entry_attr, + .get_entry_flag = fat_get_entry_flag, + .set_entry_flag = fat_set_entry_flag, + .get_entry_clu0 = fat_get_entry_clu0, + .set_entry_clu0 = fat_set_entry_clu0, + .get_entry_size = fat_get_entry_size, + .set_entry_size = fat_set_entry_size, + .get_entry_time = fat_get_entry_time, + .set_entry_time = fat_set_entry_time, +}; + +s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) +{ + s32 num_reserved, num_root_sectors; + struct bpb16_t *p_bpb = (struct bpb16_t *)p_pbr->bpb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + num_root_sectors = GET16(p_bpb->num_root_entries) << DENTRY_SIZE_BITS; + num_root_sectors = ((num_root_sectors - 1) >> + p_bd->sector_size_bits) + 1; + + p_fs->sectors_per_clu = p_bpb->sectors_per_clu; + p_fs->sectors_per_clu_bits = ilog2(p_bpb->sectors_per_clu); + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET16(p_bpb->num_fat_sectors); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->FAT2_start_sector + + p_fs->num_FAT_sectors; + p_fs->data_start_sector = p_fs->root_start_sector + num_root_sectors; + + p_fs->num_sectors = GET16(p_bpb->num_sectors); + if (p_fs->num_sectors == 0) + p_fs->num_sectors = GET32(p_bpb->num_huge_sectors); + + num_reserved = p_fs->data_start_sector - p_fs->PBR_sector; + p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >> + p_fs->sectors_per_clu_bits) + 2; + /* because the cluster index starts with 2 */ + + if (p_fs->num_clusters < FAT12_THRESHOLD) + p_fs->vol_type = FAT12; + else + p_fs->vol_type = FAT16; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = 0; + p_fs->dentries_in_root = GET16(p_bpb->num_root_entries); + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - + DENTRY_SIZE_BITS); + + p_fs->vol_flag = VOL_CLEAN; + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = UINT_MAX; + + p_fs->fs_func = &fat_fs_func; + + return FFS_SUCCESS; +} + +s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) +{ + s32 num_reserved; + struct bpb32_t *p_bpb = (struct bpb32_t *)p_pbr->bpb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + p_fs->sectors_per_clu = p_bpb->sectors_per_clu; + p_fs->sectors_per_clu_bits = ilog2(p_bpb->sectors_per_clu); + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET32(p_bpb->num_fat32_sectors); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->FAT2_start_sector + + p_fs->num_FAT_sectors; + p_fs->data_start_sector = p_fs->root_start_sector; + + p_fs->num_sectors = GET32(p_bpb->num_huge_sectors); + num_reserved = p_fs->data_start_sector - p_fs->PBR_sector; + + p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >> + p_fs->sectors_per_clu_bits) + 2; + /* because the cluster index starts with 2 */ + + p_fs->vol_type = FAT32; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = GET32(p_bpb->root_cluster); + p_fs->dentries_in_root = 0; + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - + DENTRY_SIZE_BITS); + + p_fs->vol_flag = VOL_CLEAN; + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = UINT_MAX; + + p_fs->fs_func = &fat_fs_func; + + return FFS_SUCCESS; +} + +static struct fs_func exfat_fs_func = { + .alloc_cluster = exfat_alloc_cluster, + .free_cluster = exfat_free_cluster, + .count_used_clusters = exfat_count_used_clusters, + + .init_dir_entry = exfat_init_dir_entry, + .init_ext_entry = exfat_init_ext_entry, + .find_dir_entry = exfat_find_dir_entry, + .delete_dir_entry = exfat_delete_dir_entry, + .get_uni_name_from_ext_entry = exfat_get_uni_name_from_ext_entry, + .count_ext_entries = exfat_count_ext_entries, + .calc_num_entries = exfat_calc_num_entries, + + .get_entry_type = exfat_get_entry_type, + .set_entry_type = exfat_set_entry_type, + .get_entry_attr = exfat_get_entry_attr, + .set_entry_attr = exfat_set_entry_attr, + .get_entry_flag = exfat_get_entry_flag, + .set_entry_flag = exfat_set_entry_flag, + .get_entry_clu0 = exfat_get_entry_clu0, + .set_entry_clu0 = exfat_set_entry_clu0, + .get_entry_size = exfat_get_entry_size, + .set_entry_size = exfat_set_entry_size, + .get_entry_time = exfat_get_entry_time, + .set_entry_time = exfat_set_entry_time, +}; + +s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) +{ + struct bpbex_t *p_bpb = (struct bpbex_t *)p_pbr->bpb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + p_fs->sectors_per_clu = 1 << p_bpb->sectors_per_clu_bits; + p_fs->sectors_per_clu_bits = p_bpb->sectors_per_clu_bits; + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET32(p_bpb->fat_length); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET32(p_bpb->fat_offset); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->PBR_sector + GET32(p_bpb->clu_offset); + p_fs->data_start_sector = p_fs->root_start_sector; + + p_fs->num_sectors = GET64(p_bpb->vol_length); + p_fs->num_clusters = GET32(p_bpb->clu_count) + 2; + /* because the cluster index starts with 2 */ + + p_fs->vol_type = EXFAT; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = GET32(p_bpb->root_cluster); + p_fs->dentries_in_root = 0; + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - + DENTRY_SIZE_BITS); + + p_fs->vol_flag = (u32)GET16(p_bpb->vol_flags); + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = UINT_MAX; + + p_fs->fs_func = &exfat_fs_func; + + return FFS_SUCCESS; +} + +s32 create_dir(struct inode *inode, struct chain_t *p_dir, + struct uni_name_t *p_uniname, struct file_id_t *fid) +{ + s32 ret, dentry, num_entries; + u64 size; + struct chain_t clu; + struct dos_name_t dos_name, dot_name; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, + &dos_name); + if (ret) + return ret; + + /* find_empty_entry must be called before alloc_cluster */ + dentry = find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) + return FFS_FULL; + + clu.dir = CLUSTER_32(~0); + clu.size = 0; + clu.flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + + /* (1) allocate a cluster */ + ret = fs_func->alloc_cluster(sb, 1, &clu); + if (ret < 0) + return FFS_MEDIAERR; + else if (ret == 0) + return FFS_FULL; + + ret = clear_cluster(sb, clu.dir); + if (ret != FFS_SUCCESS) + return ret; + + if (p_fs->vol_type == EXFAT) { + size = p_fs->cluster_size; + } else { + size = 0; + + /* initialize the . and .. entry + * Information for . points to itself + * Information for .. points to parent dir + */ + + dot_name.name_case = 0x0; + memcpy(dot_name.name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH); + + ret = fs_func->init_dir_entry(sb, &clu, 0, TYPE_DIR, clu.dir, + 0); + if (ret != FFS_SUCCESS) + return ret; + + ret = fs_func->init_ext_entry(sb, &clu, 0, 1, NULL, &dot_name); + if (ret != FFS_SUCCESS) + return ret; + + memcpy(dot_name.name, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH); + + if (p_dir->dir == p_fs->root_dir) + ret = fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, + CLUSTER_32(0), 0); + else + ret = fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, + p_dir->dir, 0); + + if (ret != FFS_SUCCESS) + return ret; + + ret = p_fs->fs_func->init_ext_entry(sb, &clu, 1, 1, NULL, + &dot_name); + if (ret != FFS_SUCCESS) + return ret; + } + + /* (2) update the directory entry */ + /* make sub-dir entry in parent directory */ + ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir, + size); + if (ret != FFS_SUCCESS) + return ret; + + ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, + &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fid->dir.dir = p_dir->dir; + fid->dir.size = p_dir->size; + fid->dir.flags = p_dir->flags; + fid->entry = dentry; + + fid->attr = ATTR_SUBDIR; + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->size = size; + fid->start_clu = clu.dir; + + fid->type = TYPE_DIR; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + return FFS_SUCCESS; +} + +s32 create_file(struct inode *inode, struct chain_t *p_dir, + struct uni_name_t *p_uniname, u8 mode, struct file_id_t *fid) +{ + s32 ret, dentry, num_entries; + struct dos_name_t dos_name; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, + &dos_name); + if (ret) + return ret; + + /* find_empty_entry must be called before alloc_cluster() */ + dentry = find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) + return FFS_FULL; + + /* (1) update the directory entry */ + /* fill the dos name directory entry information of the created file. + * the first cluster is not determined yet. (0) + */ + ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode, + CLUSTER_32(0), 0); + if (ret != FFS_SUCCESS) + return ret; + + ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, + &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fid->dir.dir = p_dir->dir; + fid->dir.size = p_dir->size; + fid->dir.flags = p_dir->flags; + fid->entry = dentry; + + fid->attr = ATTR_ARCHIVE | mode; + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + + fid->type = TYPE_FILE; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + return FFS_SUCCESS; +} + +void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry) +{ + s32 num_entries; + sector_t sector; + struct dentry_t *ep; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + + ep = get_entry_in_dir(sb, p_dir, entry, §or); + if (!ep) + return; + + buf_lock(sb, sector); + + /* buf_lock() before call count_ext_entries() */ + num_entries = fs_func->count_ext_entries(sb, p_dir, entry, ep); + if (num_entries < 0) { + buf_unlock(sb, sector); + return; + } + num_entries++; + + buf_unlock(sb, sector); + + /* (1) update the directory entry */ + fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries); +} + +s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry, + struct uni_name_t *p_uniname, struct file_id_t *fid) +{ + s32 ret, newentry = -1, num_old_entries, num_new_entries; + sector_t sector_old, sector_new; + struct dos_name_t dos_name; + struct dentry_t *epold, *epnew; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + + epold = get_entry_in_dir(sb, p_dir, oldentry, §or_old); + if (!epold) + return FFS_MEDIAERR; + + buf_lock(sb, sector_old); + + /* buf_lock() before call count_ext_entries() */ + num_old_entries = fs_func->count_ext_entries(sb, p_dir, oldentry, + epold); + if (num_old_entries < 0) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + num_old_entries++; + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, + &num_new_entries, &dos_name); + if (ret) { + buf_unlock(sb, sector_old); + return ret; + } + + if (num_old_entries < num_new_entries) { + newentry = find_empty_entry(inode, p_dir, num_new_entries); + if (newentry < 0) { + buf_unlock(sb, sector_old); + return FFS_FULL; + } + + epnew = get_entry_in_dir(sb, p_dir, newentry, §or_new); + if (!epnew) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + + memcpy((void *)epnew, (void *)epold, DENTRY_SIZE); + if (fs_func->get_entry_type(epnew) == TYPE_FILE) { + fs_func->set_entry_attr(epnew, + fs_func->get_entry_attr(epnew) | + ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_new); + buf_unlock(sb, sector_old); + + if (p_fs->vol_type == EXFAT) { + epold = get_entry_in_dir(sb, p_dir, oldentry + 1, + §or_old); + buf_lock(sb, sector_old); + epnew = get_entry_in_dir(sb, p_dir, newentry + 1, + §or_new); + + if (!epold || !epnew) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + + memcpy((void *)epnew, (void *)epold, DENTRY_SIZE); + buf_modify(sb, sector_new); + buf_unlock(sb, sector_old); + } + + ret = fs_func->init_ext_entry(sb, p_dir, newentry, + num_new_entries, p_uniname, + &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fs_func->delete_dir_entry(sb, p_dir, oldentry, 0, + num_old_entries); + fid->entry = newentry; + } else { + if (fs_func->get_entry_type(epold) == TYPE_FILE) { + fs_func->set_entry_attr(epold, + fs_func->get_entry_attr(epold) | + ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_old); + buf_unlock(sb, sector_old); + + ret = fs_func->init_ext_entry(sb, p_dir, oldentry, + num_new_entries, p_uniname, + &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fs_func->delete_dir_entry(sb, p_dir, oldentry, num_new_entries, + num_old_entries); + } + + return FFS_SUCCESS; +} + +s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry, + struct chain_t *p_newdir, struct uni_name_t *p_uniname, + struct file_id_t *fid) +{ + s32 ret, newentry, num_new_entries, num_old_entries; + sector_t sector_mov, sector_new; + struct chain_t clu; + struct dos_name_t dos_name; + struct dentry_t *epmov, *epnew; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + + epmov = get_entry_in_dir(sb, p_olddir, oldentry, §or_mov); + if (!epmov) + return FFS_MEDIAERR; + + /* check if the source and target directory is the same */ + if (fs_func->get_entry_type(epmov) == TYPE_DIR && + fs_func->get_entry_clu0(epmov) == p_newdir->dir) + return FFS_INVALIDPATH; + + buf_lock(sb, sector_mov); + + /* buf_lock() before call count_ext_entries() */ + num_old_entries = fs_func->count_ext_entries(sb, p_olddir, oldentry, + epmov); + if (num_old_entries < 0) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + num_old_entries++; + + ret = get_num_entries_and_dos_name(sb, p_newdir, p_uniname, + &num_new_entries, &dos_name); + if (ret) { + buf_unlock(sb, sector_mov); + return ret; + } + + newentry = find_empty_entry(inode, p_newdir, num_new_entries); + if (newentry < 0) { + buf_unlock(sb, sector_mov); + return FFS_FULL; + } + + epnew = get_entry_in_dir(sb, p_newdir, newentry, §or_new); + if (!epnew) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + + memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE); + if (fs_func->get_entry_type(epnew) == TYPE_FILE) { + fs_func->set_entry_attr(epnew, fs_func->get_entry_attr(epnew) | + ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_new); + buf_unlock(sb, sector_mov); + + if (p_fs->vol_type == EXFAT) { + epmov = get_entry_in_dir(sb, p_olddir, oldentry + 1, + §or_mov); + buf_lock(sb, sector_mov); + epnew = get_entry_in_dir(sb, p_newdir, newentry + 1, + §or_new); + if (!epmov || !epnew) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + + memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE); + buf_modify(sb, sector_new); + buf_unlock(sb, sector_mov); + } else if (fs_func->get_entry_type(epnew) == TYPE_DIR) { + /* change ".." pointer to new parent dir */ + clu.dir = fs_func->get_entry_clu0(epnew); + clu.flags = 0x01; + + epnew = get_entry_in_dir(sb, &clu, 1, §or_new); + if (!epnew) + return FFS_MEDIAERR; + + if (p_newdir->dir == p_fs->root_dir) + fs_func->set_entry_clu0(epnew, CLUSTER_32(0)); + else + fs_func->set_entry_clu0(epnew, p_newdir->dir); + buf_modify(sb, sector_new); + } + + ret = fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries, + p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fs_func->delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries); + + fid->dir.dir = p_newdir->dir; + fid->dir.size = p_newdir->size; + fid->dir.flags = p_newdir->flags; + + fid->entry = newentry; + + return FFS_SUCCESS; +} + +/* + * Sector Read/Write Functions + */ + +int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh, + bool read) +{ + s32 ret = FFS_MEDIAERR; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((sec >= (p_fs->PBR_sector + p_fs->num_sectors)) && + (p_fs->num_sectors > 0)) { + pr_err("[EXFAT] %s: out of range error! (sec = %llu)\n", + __func__, (unsigned long long)sec); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_read(sb, sec, bh, 1, read); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = 1; + } + + return ret; +} + +int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh, + bool sync) +{ + s32 ret = FFS_MEDIAERR; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (sec >= (p_fs->PBR_sector + p_fs->num_sectors) && + (p_fs->num_sectors > 0)) { + pr_err("[EXFAT] %s: out of range error! (sec = %llu)\n", + __func__, (unsigned long long)sec); + fs_error(sb); + return ret; + } + + if (!bh) { + pr_err("[EXFAT] %s: bh is NULL!\n", __func__); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_write(sb, sec, bh, 1, sync); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = 1; + } + + return ret; +} + +int multi_sector_read(struct super_block *sb, sector_t sec, + struct buffer_head **bh, s32 num_secs, bool read) +{ + s32 ret = FFS_MEDIAERR; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors)) && + (p_fs->num_sectors > 0)) { + pr_err("[EXFAT] %s: out of range error! (sec = %llu, num_secs = %d)\n", + __func__, (unsigned long long)sec, num_secs); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_read(sb, sec, bh, num_secs, read); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = 1; + } + + return ret; +} + +int multi_sector_write(struct super_block *sb, sector_t sec, + struct buffer_head *bh, s32 num_secs, bool sync) +{ + s32 ret = FFS_MEDIAERR; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors) && + (p_fs->num_sectors > 0)) { + pr_err("[EXFAT] %s: out of range error! (sec = %llu, num_secs = %d)\n", + __func__, (unsigned long long)sec, num_secs); + fs_error(sb); + return ret; + } + if (!bh) { + pr_err("[EXFAT] %s: bh is NULL!\n", __func__); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_write(sb, sec, bh, num_secs, sync); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = 1; + } + + return ret; +} diff --git a/drivers/staging/exfat/exfat_nls.c b/drivers/staging/exfat/exfat_nls.c new file mode 100644 index 000000000000..03cb8290b5d2 --- /dev/null +++ b/drivers/staging/exfat/exfat_nls.c @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include <linux/string.h> +#include <linux/nls.h> +#include "exfat.h" + +static u16 bad_dos_chars[] = { + /* + , ; = [ ] */ + 0x002B, 0x002C, 0x003B, 0x003D, 0x005B, 0x005D, + 0xFF0B, 0xFF0C, 0xFF1B, 0xFF1D, 0xFF3B, 0xFF3D, + 0 +}; + +static u16 bad_uni_chars[] = { + /* " * / : < > ? \ | */ + 0x0022, 0x002A, 0x002F, 0x003A, + 0x003C, 0x003E, 0x003F, 0x005C, 0x007C, + 0 +}; + +static int convert_ch_to_uni(struct nls_table *nls, u16 *uni, u8 *ch, + bool *lossy) +{ + int len; + + *uni = 0x0; + + if (ch[0] < 0x80) { + *uni = (u16)ch[0]; + return 1; + } + + len = nls->char2uni(ch, NLS_MAX_CHARSET_SIZE, uni); + if (len < 0) { + /* conversion failed */ + pr_info("%s: fail to use nls\n", __func__); + if (lossy) + *lossy = true; + *uni = (u16)'_'; + if (!strcmp(nls->charset, "utf8")) + return 1; + else + return 2; + } + + return len; +} + +static int convert_uni_to_ch(struct nls_table *nls, u8 *ch, u16 uni, + bool *lossy) +{ + int len; + + ch[0] = 0x0; + + if (uni < 0x0080) { + ch[0] = (u8)uni; + return 1; + } + + len = nls->uni2char(uni, ch, NLS_MAX_CHARSET_SIZE); + if (len < 0) { + /* conversion failed */ + pr_info("%s: fail to use nls\n", __func__); + if (lossy) + *lossy = true; + ch[0] = '_'; + return 1; + } + + return len; +} + +u16 nls_upper(struct super_block *sb, u16 a) +{ + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (EXFAT_SB(sb)->options.casesensitive) + return a; + if (p_fs->vol_utbl && p_fs->vol_utbl[get_col_index(a)]) + return p_fs->vol_utbl[get_col_index(a)][get_row_index(a)]; + else + return a; +} + +static u16 *nls_wstrchr(u16 *str, u16 wchar) +{ + while (*str) { + if (*(str++) == wchar) + return str; + } + + return NULL; +} + +int nls_dosname_cmp(struct super_block *sb, u8 *a, u8 *b) +{ + return strncmp(a, b, DOS_NAME_LENGTH); +} + +int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b) +{ + int i; + + for (i = 0; i < MAX_NAME_LENGTH; i++, a++, b++) { + if (nls_upper(sb, *a) != nls_upper(sb, *b)) + return 1; + if (*a == 0x0) + return 0; + } + return 0; +} + +void nls_uniname_to_dosname(struct super_block *sb, + struct dos_name_t *p_dosname, + struct uni_name_t *p_uniname, bool *p_lossy) +{ + int i, j, len; + bool lossy = false; + u8 buf[MAX_CHARSET_SIZE]; + u8 lower = 0, upper = 0; + u8 *dosname = p_dosname->name; + u16 *uniname = p_uniname->name; + u16 *p, *last_period; + struct nls_table *nls = EXFAT_SB(sb)->nls_disk; + + for (i = 0; i < DOS_NAME_LENGTH; i++) + *(dosname + i) = ' '; + + if (!nls_uniname_cmp(sb, uniname, (u16 *)UNI_CUR_DIR_NAME)) { + *(dosname) = '.'; + p_dosname->name_case = 0x0; + if (p_lossy) + *p_lossy = false; + return; + } + + if (!nls_uniname_cmp(sb, uniname, (u16 *)UNI_PAR_DIR_NAME)) { + *(dosname) = '.'; + *(dosname + 1) = '.'; + p_dosname->name_case = 0x0; + if (p_lossy) + *p_lossy = false; + return; + } + + /* search for the last embedded period */ + last_period = NULL; + for (p = uniname; *p; p++) { + if (*p == (u16)'.') + last_period = p; + } + + i = 0; + while (i < DOS_NAME_LENGTH) { + if (i == 8) { + if (!last_period) + break; + + if (uniname <= last_period) { + if (uniname < last_period) + lossy = true; + uniname = last_period + 1; + } + } + + if (*uniname == (u16)'\0') { + break; + } else if (*uniname == (u16)' ') { + lossy = true; + } else if (*uniname == (u16)'.') { + if (uniname < last_period) + lossy = true; + else + i = 8; + } else if (nls_wstrchr(bad_dos_chars, *uniname)) { + lossy = true; + *(dosname + i) = '_'; + i++; + } else { + len = convert_uni_to_ch(nls, buf, *uniname, &lossy); + + if (len > 1) { + if ((i >= 8) && ((i + len) > DOS_NAME_LENGTH)) + break; + + if ((i < 8) && ((i + len) > 8)) { + i = 8; + continue; + } + + lower = 0xFF; + + for (j = 0; j < len; j++, i++) + *(dosname + i) = *(buf + j); + } else { /* len == 1 */ + if ((*buf >= 'a') && (*buf <= 'z')) { + *(dosname + i) = *buf - ('a' - 'A'); + + if (i < 8) + lower |= 0x08; + else + lower |= 0x10; + } else if ((*buf >= 'A') && (*buf <= 'Z')) { + *(dosname + i) = *buf; + + if (i < 8) + upper |= 0x08; + else + upper |= 0x10; + } else { + *(dosname + i) = *buf; + } + i++; + } + } + + uniname++; + } + + if (*dosname == 0xE5) + *dosname = 0x05; + + if (*uniname != 0x0) + lossy = true; + + if (upper & lower) + p_dosname->name_case = 0xFF; + else + p_dosname->name_case = lower; + + if (p_lossy) + *p_lossy = lossy; +} + +void nls_dosname_to_uniname(struct super_block *sb, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname) +{ + int i = 0, j, n = 0; + u8 buf[DOS_NAME_LENGTH + 2]; + u8 *dosname = p_dosname->name; + u16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_disk; + + if (*dosname == 0x05) { + *buf = 0xE5; + i++; + n++; + } + + for (; i < 8; i++, n++) { + if (*(dosname + i) == ' ') + break; + + if ((*(dosname + i) >= 'A') && (*(dosname + i) <= 'Z') && + (p_dosname->name_case & 0x08)) + *(buf + n) = *(dosname + i) + ('a' - 'A'); + else + *(buf + n) = *(dosname + i); + } + if (*(dosname + 8) != ' ') { + *(buf + n) = '.'; + n++; + } + + for (i = 8; i < DOS_NAME_LENGTH; i++, n++) { + if (*(dosname + i) == ' ') + break; + + if ((*(dosname + i) >= 'A') && (*(dosname + i) <= 'Z') && + (p_dosname->name_case & 0x10)) + *(buf + n) = *(dosname + i) + ('a' - 'A'); + else + *(buf + n) = *(dosname + i); + } + *(buf + n) = '\0'; + + i = 0; + j = 0; + while (j < (MAX_NAME_LENGTH - 1)) { + if (*(buf + i) == '\0') + break; + + i += convert_ch_to_uni(nls, uniname, (buf + i), NULL); + + uniname++; + j++; + } + + *uniname = (u16)'\0'; +} + +void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring, + struct uni_name_t *p_uniname) +{ + int i, j, len; + u8 buf[MAX_CHARSET_SIZE]; + u16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + if (!nls) { + len = utf16s_to_utf8s(uniname, MAX_NAME_LENGTH, + UTF16_HOST_ENDIAN, p_cstring, + MAX_NAME_LENGTH); + p_cstring[len] = 0; + return; + } + + i = 0; + while (i < (MAX_NAME_LENGTH - 1)) { + if (*uniname == (u16)'\0') + break; + + len = convert_uni_to_ch(nls, buf, *uniname, NULL); + + if (len > 1) { + for (j = 0; j < len; j++) + *p_cstring++ = (char)*(buf + j); + } else { /* len == 1 */ + *p_cstring++ = (char)*buf; + } + + uniname++; + i++; + } + + *p_cstring = '\0'; +} + +void nls_cstring_to_uniname(struct super_block *sb, + struct uni_name_t *p_uniname, u8 *p_cstring, + bool *p_lossy) +{ + int i, j; + bool lossy = false; + u8 *end_of_name; + u8 upname[MAX_NAME_LENGTH * 2]; + u16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + /* strip all trailing spaces */ + end_of_name = p_cstring + strlen(p_cstring); + + while (*(--end_of_name) == ' ') { + if (end_of_name < p_cstring) + break; + } + *(++end_of_name) = '\0'; + + if (strcmp(p_cstring, ".") && strcmp(p_cstring, "..")) { + /* strip all trailing periods */ + while (*(--end_of_name) == '.') { + if (end_of_name < p_cstring) + break; + } + *(++end_of_name) = '\0'; + } + + if (*p_cstring == '\0') + lossy = true; + + if (!nls) { + i = utf8s_to_utf16s(p_cstring, MAX_NAME_LENGTH, + UTF16_HOST_ENDIAN, uniname, + MAX_NAME_LENGTH); + for (j = 0; j < i; j++) + SET16_A(upname + j * 2, nls_upper(sb, uniname[j])); + uniname[i] = '\0'; + } else { + i = 0; + j = 0; + while (j < (MAX_NAME_LENGTH - 1)) { + if (*(p_cstring + i) == '\0') + break; + + i += convert_ch_to_uni(nls, uniname, + (u8 *)(p_cstring + i), &lossy); + + if ((*uniname < 0x0020) || + nls_wstrchr(bad_uni_chars, *uniname)) + lossy = true; + + SET16_A(upname + j * 2, nls_upper(sb, *uniname)); + + uniname++; + j++; + } + + if (*(p_cstring + i) != '\0') + lossy = true; + *uniname = (u16)'\0'; + } + + p_uniname->name_len = j; + p_uniname->name_hash = calc_checksum_2byte(upname, j << 1, 0, + CS_DEFAULT); + + if (p_lossy) + *p_lossy = lossy; +} diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c new file mode 100644 index 000000000000..5f6caee819a6 --- /dev/null +++ b/drivers/staging/exfat/exfat_super.c @@ -0,0 +1,4049 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/time.h> +#include <linux/slab.h> +#include <linux/seq_file.h> +#include <linux/pagemap.h> +#include <linux/mpage.h> +#include <linux/buffer_head.h> +#include <linux/exportfs.h> +#include <linux/mount.h> +#include <linux/vfs.h> +#include <linux/aio.h> +#include <linux/iversion.h> +#include <linux/parser.h> +#include <linux/uio.h> +#include <linux/writeback.h> +#include <linux/log2.h> +#include <linux/hash.h> +#include <linux/backing-dev.h> +#include <linux/sched.h> +#include <linux/fs_struct.h> +#include <linux/namei.h> + +#include <linux/string.h> +#include <linux/nls.h> +#include <linux/mutex.h> +#include <linux/swap.h> + +#define EXFAT_VERSION "1.3.0" + +#include "exfat.h" + +static struct kmem_cache *exfat_inode_cachep; + +static int exfat_default_codepage = CONFIG_EXFAT_DEFAULT_CODEPAGE; +static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; + +#define INC_IVERSION(x) (inode_inc_iversion(x)) +#define GET_IVERSION(x) (inode_peek_iversion_raw(x)) +#define SET_IVERSION(x, y) (inode_set_iversion(x, y)) + +static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos); +static int exfat_sync_inode(struct inode *inode); +static struct inode *exfat_build_inode(struct super_block *sb, + struct file_id_t *fid, loff_t i_pos); +static int exfat_write_inode(struct inode *inode, + struct writeback_control *wbc); +static void exfat_write_super(struct super_block *sb); + +#define UNIX_SECS_1980 315532800L +#define UNIX_SECS_2108 4354819200L + +/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ +static void exfat_time_fat2unix(struct timespec64 *ts, struct date_time_t *tp) +{ + ts->tv_sec = mktime64(tp->Year + 1980, tp->Month + 1, tp->Day, + tp->Hour, tp->Minute, tp->Second); + + ts->tv_nsec = tp->MilliSecond * NSEC_PER_MSEC; +} + +/* Convert linear UNIX date to a FAT time/date pair. */ +static void exfat_time_unix2fat(struct timespec64 *ts, struct date_time_t *tp) +{ + time64_t second = ts->tv_sec; + struct tm tm; + + time64_to_tm(second, 0, &tm); + + if (second < UNIX_SECS_1980) { + tp->MilliSecond = 0; + tp->Second = 0; + tp->Minute = 0; + tp->Hour = 0; + tp->Day = 1; + tp->Month = 1; + tp->Year = 0; + return; + } + + if (second >= UNIX_SECS_2108) { + tp->MilliSecond = 999; + tp->Second = 59; + tp->Minute = 59; + tp->Hour = 23; + tp->Day = 31; + tp->Month = 12; + tp->Year = 127; + return; + } + + tp->MilliSecond = ts->tv_nsec / NSEC_PER_MSEC; + tp->Second = tm.tm_sec; + tp->Minute = tm.tm_min; + tp->Hour = tm.tm_hour; + tp->Day = tm.tm_mday; + tp->Month = tm.tm_mon + 1; + tp->Year = tm.tm_year + 1900 - 1980; +} + +struct timestamp_t *tm_current(struct timestamp_t *tp) +{ + time64_t second = ktime_get_real_seconds(); + struct tm tm; + + time64_to_tm(second, 0, &tm); + + if (second < UNIX_SECS_1980) { + tp->sec = 0; + tp->min = 0; + tp->hour = 0; + tp->day = 1; + tp->mon = 1; + tp->year = 0; + return tp; + } + + if (second >= UNIX_SECS_2108) { + tp->sec = 59; + tp->min = 59; + tp->hour = 23; + tp->day = 31; + tp->mon = 12; + tp->year = 127; + return tp; + } + + tp->sec = tm.tm_sec; + tp->min = tm.tm_min; + tp->hour = tm.tm_hour; + tp->day = tm.tm_mday; + tp->mon = tm.tm_mon + 1; + tp->year = tm.tm_year + 1900 - 1980; + + return tp; +} + +static void __lock_super(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + mutex_lock(&sbi->s_lock); +} + +static void __unlock_super(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + mutex_unlock(&sbi->s_lock); +} + +static int __is_sb_dirty(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + return sbi->s_dirt; +} + +static void __set_sb_clean(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + sbi->s_dirt = 0; +} + +static int __exfat_revalidate(struct dentry *dentry) +{ + return 0; +} + +static int exfat_revalidate(struct dentry *dentry, unsigned int flags) +{ + if (flags & LOOKUP_RCU) + return -ECHILD; + + if (dentry->d_inode) + return 1; + return __exfat_revalidate(dentry); +} + +static int exfat_revalidate_ci(struct dentry *dentry, unsigned int flags) +{ + if (flags & LOOKUP_RCU) + return -ECHILD; + + if (dentry->d_inode) + return 1; + + if (!flags) + return 0; + + if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) + return 0; + + return __exfat_revalidate(dentry); +} + +static unsigned int __exfat_striptail_len(unsigned int len, const char *name) +{ + while (len && name[len - 1] == '.') + len--; + return len; +} + +static unsigned int exfat_striptail_len(const struct qstr *qstr) +{ + return __exfat_striptail_len(qstr->len, qstr->name); +} + +static int exfat_d_hash(const struct dentry *dentry, struct qstr *qstr) +{ + qstr->hash = full_name_hash(dentry, qstr->name, + exfat_striptail_len(qstr)); + return 0; +} + +static int exfat_d_hashi(const struct dentry *dentry, struct qstr *qstr) +{ + struct super_block *sb = dentry->d_sb; + const unsigned char *name; + unsigned int len; + unsigned long hash; + + name = qstr->name; + len = exfat_striptail_len(qstr); + + hash = init_name_hash(dentry); + while (len--) + hash = partial_name_hash(nls_upper(sb, *name++), hash); + qstr->hash = end_name_hash(hash); + + return 0; +} + +static int exfat_cmpi(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + struct nls_table *t = EXFAT_SB(dentry->d_sb)->nls_io; + unsigned int alen, blen; + + alen = exfat_striptail_len(name); + blen = __exfat_striptail_len(len, str); + if (alen == blen) { + if (!t) { + if (strncasecmp(name->name, str, alen) == 0) + return 0; + } else { + if (nls_strnicmp(t, name->name, str, alen) == 0) + return 0; + } + } + return 1; +} + +static int exfat_cmp(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + unsigned int alen, blen; + + alen = exfat_striptail_len(name); + blen = __exfat_striptail_len(len, str); + if (alen == blen) { + if (strncmp(name->name, str, alen) == 0) + return 0; + } + return 1; +} + +static const struct dentry_operations exfat_ci_dentry_ops = { + .d_revalidate = exfat_revalidate_ci, + .d_hash = exfat_d_hashi, + .d_compare = exfat_cmpi, +}; + +static const struct dentry_operations exfat_dentry_ops = { + .d_revalidate = exfat_revalidate, + .d_hash = exfat_d_hash, + .d_compare = exfat_cmp, +}; + +static DEFINE_SEMAPHORE(z_sem); + +static inline void fs_sync(struct super_block *sb, bool do_sync) +{ + if (do_sync) + bdev_sync(sb); +} + +/* + * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to + * save ATTR_RO instead of ->i_mode. + * + * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only + * bit, it's just used as flag for app. + */ +static inline int exfat_mode_can_hold_ro(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + if (S_ISDIR(inode->i_mode)) + return 0; + + if ((~sbi->options.fs_fmask) & 0222) + return 1; + return 0; +} + +/* Convert attribute bits and a mask to the UNIX mode. */ +static inline mode_t exfat_make_mode(struct exfat_sb_info *sbi, u32 attr, + mode_t mode) +{ + if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR)) + mode &= ~0222; + + if (attr & ATTR_SUBDIR) + return (mode & ~sbi->options.fs_dmask) | S_IFDIR; + else if (attr & ATTR_SYMLINK) + return (mode & ~sbi->options.fs_dmask) | S_IFLNK; + else + return (mode & ~sbi->options.fs_fmask) | S_IFREG; +} + +/* Return the FAT attribute byte for this inode */ +static inline u32 exfat_make_attr(struct inode *inode) +{ + if (exfat_mode_can_hold_ro(inode) && !(inode->i_mode & 0222)) + return (EXFAT_I(inode)->fid.attr) | ATTR_READONLY; + else + return EXFAT_I(inode)->fid.attr; +} + +static inline void exfat_save_attr(struct inode *inode, u32 attr) +{ + if (exfat_mode_can_hold_ro(inode)) + EXFAT_I(inode)->fid.attr = attr & ATTR_RWMASK; + else + EXFAT_I(inode)->fid.attr = attr & (ATTR_RWMASK | ATTR_READONLY); +} + +static int ffsMountVol(struct super_block *sb) +{ + int i, ret; + struct pbr_sector_t *p_pbr; + struct buffer_head *tmp_bh = NULL; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + pr_info("[EXFAT] trying to mount...\n"); + + down(&z_sem); + + buf_init(sb); + + sema_init(&p_fs->v_sem, 1); + p_fs->dev_ejected = 0; + + /* open the block device */ + bdev_open(sb); + + if (p_bd->sector_size < sb->s_blocksize) { + ret = FFS_MEDIAERR; + goto out; + } + if (p_bd->sector_size > sb->s_blocksize) + sb_set_blocksize(sb, p_bd->sector_size); + + /* read Sector 0 */ + if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS) { + ret = FFS_MEDIAERR; + goto out; + } + + p_fs->PBR_sector = 0; + + p_pbr = (struct pbr_sector_t *)tmp_bh->b_data; + + /* check the validity of PBR */ + if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) { + brelse(tmp_bh); + bdev_close(sb); + ret = FFS_FORMATERR; + goto out; + } + + /* fill fs_struct */ + for (i = 0; i < 53; i++) + if (p_pbr->bpb[i]) + break; + + if (i < 53) { +#ifdef CONFIG_EXFAT_DONT_MOUNT_VFAT + ret = -EINVAL; + printk(KERN_INFO "EXFAT: Attempted to mount VFAT filesystem\n"); + goto out; +#else + if (GET16(p_pbr->bpb + 11)) /* num_fat_sectors */ + ret = fat16_mount(sb, p_pbr); + else + ret = fat32_mount(sb, p_pbr); +#endif + } else { + ret = exfat_mount(sb, p_pbr); + } + + brelse(tmp_bh); + + if (ret) { + bdev_close(sb); + goto out; + } + + if (p_fs->vol_type == EXFAT) { + ret = load_alloc_bitmap(sb); + if (ret) { + bdev_close(sb); + goto out; + } + ret = load_upcase_table(sb); + if (ret) { + free_alloc_bitmap(sb); + bdev_close(sb); + goto out; + } + } + + if (p_fs->dev_ejected) { + if (p_fs->vol_type == EXFAT) { + free_upcase_table(sb); + free_alloc_bitmap(sb); + } + bdev_close(sb); + ret = FFS_MEDIAERR; + goto out; + } + + pr_info("[EXFAT] mounted successfully\n"); + +out: + up(&z_sem); + + return ret; +} + +static int ffsUmountVol(struct super_block *sb) +{ + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + int err = FFS_SUCCESS; + + pr_info("[EXFAT] trying to unmount...\n"); + + down(&z_sem); + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); + + if (p_fs->vol_type == EXFAT) { + free_upcase_table(sb); + free_alloc_bitmap(sb); + } + + FAT_release_all(sb); + buf_release_all(sb); + + /* close the block device */ + bdev_close(sb); + + if (p_fs->dev_ejected) { + pr_info("[EXFAT] unmounted with media errors. Device is already ejected.\n"); + err = FFS_MEDIAERR; + } + + buf_shutdown(sb); + + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + up(&z_sem); + + pr_info("[EXFAT] unmounted successfully\n"); + + return err; +} + +static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info) +{ + int err = FFS_SUCCESS; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if (!info) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + if (p_fs->used_clusters == UINT_MAX) + p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb); + + info->FatType = p_fs->vol_type; + info->ClusterSize = p_fs->cluster_size; + info->NumClusters = p_fs->num_clusters - 2; /* clu 0 & 1 */ + info->UsedClusters = p_fs->used_clusters; + info->FreeClusters = info->NumClusters - info->UsedClusters; + + if (p_fs->dev_ejected) + err = FFS_MEDIAERR; + + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return err; +} + +static int ffsSyncVol(struct super_block *sb, bool do_sync) +{ + int err = FFS_SUCCESS; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* synchronize the file system */ + fs_sync(sb, do_sync); + fs_set_vol_flags(sb, VOL_CLEAN); + + if (p_fs->dev_ejected) + err = FFS_MEDIAERR; + + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return err; +} + +/*----------------------------------------------------------------------*/ +/* File Operation Functions */ +/*----------------------------------------------------------------------*/ + +static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) +{ + int ret, dentry, num_entries; + struct chain_t dir; + struct uni_name_t uni_name; + struct dos_name_t dos_name; + struct dentry_t *ep, *ep2; + struct entry_set_cache_t *es = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + pr_debug("%s entered\n", __func__); + + /* check the validity of pointer parameters */ + if (!fid || !path || (*path == '\0')) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check the validity of directory name in the given pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + goto out; + + ret = get_num_entries_and_dos_name(sb, &dir, &uni_name, &num_entries, + &dos_name); + if (ret) + goto out; + + /* search the file name for directories */ + dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries, + &dos_name, TYPE_ALL); + if (dentry < -1) { + ret = FFS_NOTFOUND; + goto out; + } + + fid->dir.dir = dir.dir; + fid->dir.size = dir.size; + fid->dir.flags = dir.flags; + fid->entry = dentry; + + if (dentry == -1) { + fid->type = TYPE_DIR; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + fid->attr = ATTR_SUBDIR; + fid->flags = 0x01; + fid->size = 0; + fid->start_clu = p_fs->root_dir; + } else { + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &dir, dentry, + ES_2_ENTRIES, &ep); + if (!es) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep + 1; + } else { + ep = get_entry_in_dir(sb, &dir, dentry, NULL); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep; + } + + fid->type = p_fs->fs_func->get_entry_type(ep); + fid->rwoffset = 0; + fid->hint_last_off = -1; + fid->attr = p_fs->fs_func->get_entry_attr(ep); + + fid->size = p_fs->fs_func->get_entry_size(ep2); + if ((fid->type == TYPE_FILE) && (fid->size == 0)) { + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->start_clu = CLUSTER_32(~0); + } else { + fid->flags = p_fs->fs_func->get_entry_flag(ep2); + fid->start_clu = p_fs->fs_func->get_entry_clu0(ep2); + } + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + } + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsCreateFile(struct inode *inode, char *path, u8 mode, + struct file_id_t *fid) +{ + struct chain_t dir; + struct uni_name_t uni_name; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + int ret; + + /* check the validity of pointer parameters */ + if (!fid || !path || (*path == '\0')) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check the validity of directory name in the given pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + goto out; + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* create a new file */ + ret = create_file(inode, &dir, &uni_name, mode, fid); + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer, + u64 count, u64 *rcount) +{ + s32 offset, sec_offset, clu_offset; + u32 clu; + int ret = 0; + sector_t LogSector; + u64 oneblkread, read_bytes; + struct buffer_head *tmp_bh = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + /* check the validity of the given file id */ + if (!fid) + return FFS_INVALIDFID; + + /* check the validity of pointer parameters */ + if (!buffer) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) { + ret = FFS_PERMISSIONERR; + goto out; + } + + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + + if (count > (fid->size - fid->rwoffset)) + count = fid->size - fid->rwoffset; + + if (count == 0) { + if (rcount) + *rcount = 0; + ret = FFS_EOF; + goto out; + } + + read_bytes = 0; + + while (count > 0) { + clu_offset = (s32)(fid->rwoffset >> p_fs->cluster_size_bits); + clu = fid->start_clu; + + if (fid->flags == 0x03) { + clu += clu_offset; + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu = fid->hint_last_clu; + } + + while (clu_offset > 0) { + /* clu = FAT_read(sb, clu); */ + if (FAT_read(sb, clu, &clu) == -1) + return FFS_MEDIAERR; + + clu_offset--; + } + } + + /* hint information */ + fid->hint_last_off = (s32)(fid->rwoffset >> + p_fs->cluster_size_bits); + fid->hint_last_clu = clu; + + /* byte offset in cluster */ + offset = (s32)(fid->rwoffset & (p_fs->cluster_size - 1)); + + /* sector offset in cluster */ + sec_offset = offset >> p_bd->sector_size_bits; + + /* byte offset in sector */ + offset &= p_bd->sector_size_mask; + + LogSector = START_SECTOR(clu) + sec_offset; + + oneblkread = (u64)(p_bd->sector_size - offset); + if (oneblkread > count) + oneblkread = count; + + if ((offset == 0) && (oneblkread == p_bd->sector_size)) { + if (sector_read(sb, LogSector, &tmp_bh, 1) != + FFS_SUCCESS) + goto err_out; + memcpy((char *)buffer + read_bytes, + (char *)tmp_bh->b_data, (s32)oneblkread); + } else { + if (sector_read(sb, LogSector, &tmp_bh, 1) != + FFS_SUCCESS) + goto err_out; + memcpy((char *)buffer + read_bytes, + (char *)tmp_bh->b_data + offset, + (s32)oneblkread); + } + count -= oneblkread; + read_bytes += oneblkread; + fid->rwoffset += oneblkread; + } + brelse(tmp_bh); + +/* How did this ever work and not leak a brlse()?? */ +err_out: + /* set the size of read bytes */ + if (rcount) + *rcount = read_bytes; + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, + void *buffer, u64 count, u64 *wcount) +{ + bool modified = false; + s32 offset, sec_offset, clu_offset; + s32 num_clusters, num_alloc, num_alloced = (s32)~0; + int ret = 0; + u32 clu, last_clu; + sector_t LogSector, sector = 0; + u64 oneblkwrite, write_bytes; + struct chain_t new_clu; + struct timestamp_t tm; + struct dentry_t *ep, *ep2; + struct entry_set_cache_t *es = NULL; + struct buffer_head *tmp_bh = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + /* check the validity of the given file id */ + if (!fid) + return FFS_INVALIDFID; + + /* check the validity of pointer parameters */ + if (!buffer) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) { + ret = FFS_PERMISSIONERR; + goto out; + } + + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + + if (count == 0) { + if (wcount) + *wcount = 0; + ret = FFS_SUCCESS; + goto out; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + if (fid->size == 0) + num_clusters = 0; + else + num_clusters = (s32)((fid->size - 1) >> + p_fs->cluster_size_bits) + 1; + + write_bytes = 0; + + while (count > 0) { + clu_offset = (s32)(fid->rwoffset >> p_fs->cluster_size_bits); + clu = last_clu = fid->start_clu; + + if (fid->flags == 0x03) { + if ((clu_offset > 0) && (clu != CLUSTER_32(~0))) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + clu = CLUSTER_32(~0); + else + clu += clu_offset; + } + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu = fid->hint_last_clu; + } + + while ((clu_offset > 0) && (clu != CLUSTER_32(~0))) { + last_clu = clu; + /* clu = FAT_read(sb, clu); */ + if (FAT_read(sb, clu, &clu) == -1) { + ret = FFS_MEDIAERR; + goto out; + } + clu_offset--; + } + } + + if (clu == CLUSTER_32(~0)) { + num_alloc = (s32)((count - 1) >> + p_fs->cluster_size_bits) + 1; + new_clu.dir = (last_clu == CLUSTER_32(~0)) ? + CLUSTER_32(~0) : last_clu + 1; + new_clu.size = 0; + new_clu.flags = fid->flags; + + /* (1) allocate a chain of clusters */ + num_alloced = p_fs->fs_func->alloc_cluster(sb, + num_alloc, + &new_clu); + if (num_alloced == 0) + break; + if (num_alloced < 0) { + ret = FFS_MEDIAERR; + goto out; + } + + /* (2) append to the FAT chain */ + if (last_clu == CLUSTER_32(~0)) { + if (new_clu.flags == 0x01) + fid->flags = 0x01; + fid->start_clu = new_clu.dir; + modified = true; + } else { + if (new_clu.flags != fid->flags) { + exfat_chain_cont_cluster(sb, + fid->start_clu, + num_clusters); + fid->flags = 0x01; + modified = true; + } + if (new_clu.flags == 0x01) + FAT_write(sb, last_clu, new_clu.dir); + } + + num_clusters += num_alloced; + clu = new_clu.dir; + } + + /* hint information */ + fid->hint_last_off = (s32)(fid->rwoffset >> + p_fs->cluster_size_bits); + fid->hint_last_clu = clu; + + /* byte offset in cluster */ + offset = (s32)(fid->rwoffset & (p_fs->cluster_size - 1)); + + /* sector offset in cluster */ + sec_offset = offset >> p_bd->sector_size_bits; + + /* byte offset in sector */ + offset &= p_bd->sector_size_mask; + + LogSector = START_SECTOR(clu) + sec_offset; + + oneblkwrite = (u64)(p_bd->sector_size - offset); + if (oneblkwrite > count) + oneblkwrite = count; + + if ((offset == 0) && (oneblkwrite == p_bd->sector_size)) { + if (sector_read(sb, LogSector, &tmp_bh, 0) != + FFS_SUCCESS) + goto err_out; + memcpy((char *)tmp_bh->b_data, + (char *)buffer + write_bytes, (s32)oneblkwrite); + if (sector_write(sb, LogSector, tmp_bh, 0) != + FFS_SUCCESS) { + brelse(tmp_bh); + goto err_out; + } + } else { + if ((offset > 0) || + ((fid->rwoffset + oneblkwrite) < fid->size)) { + if (sector_read(sb, LogSector, &tmp_bh, 1) != + FFS_SUCCESS) + goto err_out; + } else { + if (sector_read(sb, LogSector, &tmp_bh, 0) != + FFS_SUCCESS) + goto err_out; + } + + memcpy((char *)tmp_bh->b_data + offset, + (char *)buffer + write_bytes, (s32)oneblkwrite); + if (sector_write(sb, LogSector, tmp_bh, 0) != + FFS_SUCCESS) { + brelse(tmp_bh); + goto err_out; + } + } + + count -= oneblkwrite; + write_bytes += oneblkwrite; + fid->rwoffset += oneblkwrite; + + fid->attr |= ATTR_ARCHIVE; + + if (fid->size < fid->rwoffset) { + fid->size = fid->rwoffset; + modified = true; + } + } + + brelse(tmp_bh); + + /* (3) update the direcoty entry */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, + ES_ALL_ENTRIES, &ep); + if (!es) + goto err_out; + ep2 = ep + 1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + goto err_out; + ep2 = ep; + } + + p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); + p_fs->fs_func->set_entry_attr(ep, fid->attr); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + + if (modified) { + if (p_fs->fs_func->get_entry_flag(ep2) != fid->flags) + p_fs->fs_func->set_entry_flag(ep2, fid->flags); + + if (p_fs->fs_func->get_entry_size(ep2) != fid->size) + p_fs->fs_func->set_entry_size(ep2, fid->size); + + if (p_fs->fs_func->get_entry_clu0(ep2) != fid->start_clu) + p_fs->fs_func->set_entry_clu0(ep2, fid->start_clu); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + } + + if (p_fs->vol_type == EXFAT) { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + +err_out: + /* set the size of written bytes */ + if (wcount) + *wcount = write_bytes; + + if (num_alloced == 0) + ret = FFS_FULL; + + else if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) +{ + s32 num_clusters; + u32 last_clu = CLUSTER_32(0); + int ret = 0; + sector_t sector = 0; + struct chain_t clu; + struct timestamp_t tm; + struct dentry_t *ep, *ep2; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + struct entry_set_cache_t *es = NULL; + + pr_debug("%s entered (inode %p size %llu)\n", __func__, inode, + new_size); + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) { + ret = FFS_PERMISSIONERR; + goto out; + } + + if (fid->size != old_size) { + pr_err("[EXFAT] truncate : can't skip it because of size-mismatch(old:%lld->fid:%lld).\n", + old_size, fid->size); + } + + if (old_size <= new_size) { + ret = FFS_SUCCESS; + goto out; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + clu.dir = fid->start_clu; + clu.size = (s32)((old_size - 1) >> p_fs->cluster_size_bits) + 1; + clu.flags = fid->flags; + + if (new_size > 0) { + num_clusters = (s32)((new_size - 1) >> + p_fs->cluster_size_bits) + 1; + + if (clu.flags == 0x03) { + clu.dir += num_clusters; + } else { + while (num_clusters > 0) { + last_clu = clu.dir; + if (FAT_read(sb, clu.dir, &clu.dir) == -1) { + ret = FFS_MEDIAERR; + goto out; + } + num_clusters--; + } + } + + clu.size -= num_clusters; + } + + fid->size = new_size; + fid->attr |= ATTR_ARCHIVE; + if (new_size == 0) { + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->start_clu = CLUSTER_32(~0); + } + + /* (1) update the directory entry */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, + ES_ALL_ENTRIES, &ep); + if (!es) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep + 1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep; + } + + p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); + p_fs->fs_func->set_entry_attr(ep, fid->attr); + + p_fs->fs_func->set_entry_size(ep2, new_size); + if (new_size == 0) { + p_fs->fs_func->set_entry_flag(ep2, 0x01); + p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0)); + } + + if (p_fs->vol_type != EXFAT) { + buf_modify(sb, sector); + } else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + /* (2) cut off from the FAT chain */ + if (last_clu != CLUSTER_32(0)) { + if (fid->flags == 0x01) + FAT_write(sb, last_clu, CLUSTER_32(~0)); + } + + /* (3) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu, 0); + + /* hint information */ + fid->hint_last_off = -1; + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + pr_debug("%s exited (%d)\n", __func__, ret); + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static void update_parent_info(struct file_id_t *fid, + struct inode *parent_inode) +{ + struct fs_info_t *p_fs = &(EXFAT_SB(parent_inode->i_sb)->fs_info); + struct file_id_t *parent_fid = &(EXFAT_I(parent_inode)->fid); + + if (unlikely((parent_fid->flags != fid->dir.flags) || + (parent_fid->size != + (fid->dir.size << p_fs->cluster_size_bits)) || + (parent_fid->start_clu != fid->dir.dir))) { + fid->dir.dir = parent_fid->start_clu; + fid->dir.flags = parent_fid->flags; + fid->dir.size = ((parent_fid->size + (p_fs->cluster_size - 1)) + >> p_fs->cluster_size_bits); + } +} + +static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, + struct inode *new_parent_inode, struct dentry *new_dentry) +{ + s32 ret; + s32 dentry; + struct chain_t olddir, newdir; + struct chain_t *p_dir = NULL; + struct uni_name_t uni_name; + struct dentry_t *ep; + struct super_block *sb = old_parent_inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + u8 *new_path = (u8 *)new_dentry->d_name.name; + struct inode *new_inode = new_dentry->d_inode; + int num_entries; + struct file_id_t *new_fid = NULL; + s32 new_entry = 0; + + /* check the validity of the given file id */ + if (!fid) + return FFS_INVALIDFID; + + /* check the validity of pointer parameters */ + if (!new_path || (*new_path == '\0')) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + update_parent_info(fid, old_parent_inode); + + olddir.dir = fid->dir.dir; + olddir.size = fid->dir.size; + olddir.flags = fid->dir.flags; + + dentry = fid->entry; + + /* check if the old file is "." or ".." */ + if (p_fs->vol_type != EXFAT) { + if ((olddir.dir != p_fs->root_dir) && (dentry < 2)) { + ret = FFS_PERMISSIONERR; + goto out2; + } + } + + ep = get_entry_in_dir(sb, &olddir, dentry, NULL); + if (!ep) { + ret = FFS_MEDIAERR; + goto out2; + } + + if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) { + ret = FFS_PERMISSIONERR; + goto out2; + } + + /* check whether new dir is existing directory and empty */ + if (new_inode) { + u32 entry_type; + + ret = FFS_MEDIAERR; + new_fid = &EXFAT_I(new_inode)->fid; + + update_parent_info(new_fid, new_parent_inode); + + p_dir = &(new_fid->dir); + new_entry = new_fid->entry; + ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); + if (!ep) + goto out; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if (entry_type == TYPE_DIR) { + struct chain_t new_clu; + + new_clu.dir = new_fid->start_clu; + new_clu.size = (s32)((new_fid->size - 1) >> + p_fs->cluster_size_bits) + 1; + new_clu.flags = new_fid->flags; + + if (!is_dir_empty(sb, &new_clu)) { + ret = FFS_FILEEXIST; + goto out; + } + } + } + + /* check the validity of directory name in the given new pathname */ + ret = resolve_path(new_parent_inode, new_path, &newdir, &uni_name); + if (ret) + goto out2; + + fs_set_vol_flags(sb, VOL_DIRTY); + + if (olddir.dir == newdir.dir) + ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name, + fid); + else + ret = move_file(new_parent_inode, &olddir, dentry, &newdir, + &uni_name, fid); + + if ((ret == FFS_SUCCESS) && new_inode) { + /* delete entries of new_dir */ + ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); + if (!ep) + goto out; + + num_entries = p_fs->fs_func->count_ext_entries(sb, p_dir, + new_entry, ep); + if (num_entries < 0) + goto out; + p_fs->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0, + num_entries + 1); + } +out: +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; +out2: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) +{ + s32 dentry; + int ret = FFS_SUCCESS; + struct chain_t dir, clu_to_free; + struct dentry_t *ep; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (!fid) + return FFS_INVALIDFID; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + dir.dir = fid->dir.dir; + dir.size = fid->dir.size; + dir.flags = fid->dir.flags; + + dentry = fid->entry; + + ep = get_entry_in_dir(sb, &dir, dentry, NULL); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + + if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) { + ret = FFS_PERMISSIONERR; + goto out; + } + fs_set_vol_flags(sb, VOL_DIRTY); + + /* (1) update the directory entry */ + remove_file(inode, &dir, dentry); + + clu_to_free.dir = fid->start_clu; + clu_to_free.size = (s32)((fid->size - 1) >> p_fs->cluster_size_bits) + 1; + clu_to_free.flags = fid->flags; + + /* (2) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu_to_free, 0); + + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +#if 0 +/* Not currently wired up */ +static int ffsSetAttr(struct inode *inode, u32 attr) +{ + u32 type; + int ret = FFS_SUCCESS; + sector_t sector = 0; + struct dentry_t *ep; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + struct entry_set_cache_t *es = NULL; + + if (fid->attr == attr) { + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + } + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* get the directory entry of given file */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, + ES_ALL_ENTRIES, &ep); + if (!es) { + ret = FFS_MEDIAERR; + goto out; + } + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + } + + type = p_fs->fs_func->get_entry_type(ep); + + if (((type == TYPE_FILE) && (attr & ATTR_SUBDIR)) || + ((type == TYPE_DIR) && (!(attr & ATTR_SUBDIR)))) { + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + else + ret = FFS_ERROR; + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + goto out; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* set the file attribute */ + fid->attr = attr; + p_fs->fs_func->set_entry_attr(ep, attr); + + if (p_fs->vol_type != EXFAT) { + buf_modify(sb, sector); + } else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} +#endif + +static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) +{ + sector_t sector = 0; + s32 count; + int ret = FFS_SUCCESS; + struct chain_t dir; + struct uni_name_t uni_name; + struct timestamp_t tm; + struct dentry_t *ep, *ep2; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + struct entry_set_cache_t *es = NULL; + u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + + pr_debug("%s entered\n", __func__); + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + info->Attr = ATTR_SUBDIR; + memset((char *)&info->CreateTimestamp, 0, + sizeof(struct date_time_t)); + memset((char *)&info->ModifyTimestamp, 0, + sizeof(struct date_time_t)); + memset((char *)&info->AccessTimestamp, 0, + sizeof(struct date_time_t)); + strcpy(info->ShortName, "."); + strcpy(info->Name, "."); + + dir.dir = p_fs->root_dir; + dir.flags = 0x01; + + if (p_fs->root_dir == CLUSTER_32(0)) { + /* FAT16 root_dir */ + info->Size = p_fs->dentries_in_root << + DENTRY_SIZE_BITS; + } else { + info->Size = count_num_clusters(sb, &dir) << + p_fs->cluster_size_bits; + } + + count = count_dos_name_entries(sb, &dir, TYPE_DIR); + if (count < 0) { + ret = FFS_MEDIAERR; + goto out; + } + info->NumSubdirs = count; + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + goto out; + } + } + + /* get the directory entry of given file or directory */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, + ES_2_ENTRIES, &ep); + if (!es) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep + 1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep; + buf_lock(sb, sector); + } + + /* set FILE_INFO structure using the acquired struct dentry_t */ + info->Attr = p_fs->fs_func->get_entry_attr(ep); + + p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE); + info->CreateTimestamp.Year = tm.year; + info->CreateTimestamp.Month = tm.mon; + info->CreateTimestamp.Day = tm.day; + info->CreateTimestamp.Hour = tm.hour; + info->CreateTimestamp.Minute = tm.min; + info->CreateTimestamp.Second = tm.sec; + info->CreateTimestamp.MilliSecond = 0; + + p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY); + info->ModifyTimestamp.Year = tm.year; + info->ModifyTimestamp.Month = tm.mon; + info->ModifyTimestamp.Day = tm.day; + info->ModifyTimestamp.Hour = tm.hour; + info->ModifyTimestamp.Minute = tm.min; + info->ModifyTimestamp.Second = tm.sec; + info->ModifyTimestamp.MilliSecond = 0; + + memset((char *)&info->AccessTimestamp, 0, sizeof(struct date_time_t)); + + *(uni_name.name) = 0x0; + /* XXX this is very bad for exfat cuz name is already included in es. + * API should be revised + */ + p_fs->fs_func->get_uni_name_from_ext_entry(sb, &(fid->dir), fid->entry, + uni_name.name); + if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT) + get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep, + &uni_name, 0x1); + nls_uniname_to_cstring(sb, info->Name, &uni_name); + + if (p_fs->vol_type == EXFAT) { + info->NumSubdirs = 2; + } else { + buf_unlock(sb, sector); + get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep, + &uni_name, 0x0); + nls_uniname_to_cstring(sb, info->ShortName, &uni_name); + info->NumSubdirs = 0; + } + + info->Size = p_fs->fs_func->get_entry_size(ep2); + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + + if (is_dir) { + dir.dir = fid->start_clu; + dir.flags = 0x01; + + if (info->Size == 0) + info->Size = (u64)count_num_clusters(sb, &dir) << + p_fs->cluster_size_bits; + + count = count_dos_name_entries(sb, &dir, TYPE_DIR); + if (count < 0) { + ret = FFS_MEDIAERR; + goto out; + } + info->NumSubdirs += count; + } + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + pr_debug("%s exited successfully\n", __func__); + return ret; +} + +static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) +{ + sector_t sector = 0; + int ret = FFS_SUCCESS; + struct timestamp_t tm; + struct dentry_t *ep, *ep2; + struct entry_set_cache_t *es = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + + pr_debug("%s entered (inode %p info %p\n", __func__, inode, info); + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + ret = FFS_SUCCESS; + goto out; + } + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* get the directory entry of given file or directory */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, + ES_ALL_ENTRIES, &ep); + if (!es) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep + 1; + } else { + /* for other than exfat */ + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep; + } + + p_fs->fs_func->set_entry_attr(ep, info->Attr); + + /* set FILE_INFO structure using the acquired struct dentry_t */ + tm.sec = info->CreateTimestamp.Second; + tm.min = info->CreateTimestamp.Minute; + tm.hour = info->CreateTimestamp.Hour; + tm.day = info->CreateTimestamp.Day; + tm.mon = info->CreateTimestamp.Month; + tm.year = info->CreateTimestamp.Year; + p_fs->fs_func->set_entry_time(ep, &tm, TM_CREATE); + + tm.sec = info->ModifyTimestamp.Second; + tm.min = info->ModifyTimestamp.Minute; + tm.hour = info->ModifyTimestamp.Hour; + tm.day = info->ModifyTimestamp.Day; + tm.mon = info->ModifyTimestamp.Month; + tm.year = info->ModifyTimestamp.Year; + p_fs->fs_func->set_entry_time(ep, &tm, TM_MODIFY); + + p_fs->fs_func->set_entry_size(ep2, info->Size); + + if (p_fs->vol_type != EXFAT) { + buf_modify(sb, sector); + } else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + pr_debug("%s exited (%d)\n", __func__, ret); + + return ret; +} + +static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) +{ + s32 num_clusters, num_alloced; + bool modified = false; + u32 last_clu; + int ret = FFS_SUCCESS; + sector_t sector = 0; + struct chain_t new_clu; + struct dentry_t *ep; + struct entry_set_cache_t *es = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + + /* check the validity of pointer parameters */ + if (!clu) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + fid->rwoffset = (s64)(clu_offset) << p_fs->cluster_size_bits; + + if (EXFAT_I(inode)->mmu_private == 0) + num_clusters = 0; + else + num_clusters = (s32)((EXFAT_I(inode)->mmu_private - 1) >> + p_fs->cluster_size_bits) + 1; + + *clu = last_clu = fid->start_clu; + + if (fid->flags == 0x03) { + if ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + *clu = CLUSTER_32(~0); + else + *clu += clu_offset; + } + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + *clu = fid->hint_last_clu; + } + + while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) { + last_clu = *clu; + if (FAT_read(sb, *clu, clu) == -1) { + ret = FFS_MEDIAERR; + goto out; + } + clu_offset--; + } + } + + if (*clu == CLUSTER_32(~0)) { + fs_set_vol_flags(sb, VOL_DIRTY); + + new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) : + last_clu + 1; + new_clu.size = 0; + new_clu.flags = fid->flags; + + /* (1) allocate a cluster */ + num_alloced = p_fs->fs_func->alloc_cluster(sb, 1, &new_clu); + if (num_alloced < 0) { + ret = FFS_MEDIAERR; + goto out; + } else if (num_alloced == 0) { + ret = FFS_FULL; + goto out; + } + + /* (2) append to the FAT chain */ + if (last_clu == CLUSTER_32(~0)) { + if (new_clu.flags == 0x01) + fid->flags = 0x01; + fid->start_clu = new_clu.dir; + modified = true; + } else { + if (new_clu.flags != fid->flags) { + exfat_chain_cont_cluster(sb, fid->start_clu, + num_clusters); + fid->flags = 0x01; + modified = true; + } + if (new_clu.flags == 0x01) + FAT_write(sb, last_clu, new_clu.dir); + } + + num_clusters += num_alloced; + *clu = new_clu.dir; + + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, + ES_ALL_ENTRIES, &ep); + if (!es) { + ret = FFS_MEDIAERR; + goto out; + } + /* get stream entry */ + ep++; + } + + /* (3) update directory entry */ + if (modified) { + if (p_fs->vol_type != EXFAT) { + ep = get_entry_in_dir(sb, &(fid->dir), + fid->entry, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + } + + if (p_fs->fs_func->get_entry_flag(ep) != fid->flags) + p_fs->fs_func->set_entry_flag(ep, fid->flags); + + if (p_fs->fs_func->get_entry_clu0(ep) != fid->start_clu) + p_fs->fs_func->set_entry_clu0(ep, + fid->start_clu); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + } + + if (p_fs->vol_type == EXFAT) { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + /* add number of new blocks to inode */ + inode->i_blocks += num_alloced << (p_fs->cluster_size_bits - 9); + } + + /* hint information */ + fid->hint_last_off = (s32)(fid->rwoffset >> p_fs->cluster_size_bits); + fid->hint_last_clu = *clu; + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +/*----------------------------------------------------------------------*/ +/* Directory Operation Functions */ +/*----------------------------------------------------------------------*/ + +static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid) +{ + int ret = FFS_SUCCESS; + struct chain_t dir; + struct uni_name_t uni_name; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + pr_debug("%s entered\n", __func__); + + /* check the validity of pointer parameters */ + if (!fid || !path || (*path == '\0')) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check the validity of directory name in the given old pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + goto out; + + fs_set_vol_flags(sb, VOL_DIRTY); + + ret = create_dir(inode, &dir, &uni_name, fid); + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) +{ + int i, dentry, clu_offset; + int ret = FFS_SUCCESS; + s32 dentries_per_clu, dentries_per_clu_bits = 0; + u32 type; + sector_t sector; + struct chain_t dir, clu; + struct uni_name_t uni_name; + struct timestamp_t tm; + struct dentry_t *ep; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + + /* check the validity of pointer parameters */ + if (!dir_entry) + return FFS_ERROR; + + /* check if the given file ID is opened */ + if (fid->type != TYPE_DIR) + return FFS_PERMISSIONERR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + if (fid->entry == -1) { + dir.dir = p_fs->root_dir; + dir.flags = 0x01; + } else { + dir.dir = fid->start_clu; + dir.size = (s32)(fid->size >> p_fs->cluster_size_bits); + dir.flags = fid->flags; + } + + dentry = (s32)fid->rwoffset; + + if (dir.dir == CLUSTER_32(0)) { + /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + + if (dentry == dentries_per_clu) { + clu.dir = CLUSTER_32(~0); + } else { + clu.dir = dir.dir; + clu.size = dir.size; + clu.flags = dir.flags; + } + } else { + dentries_per_clu = p_fs->dentries_per_clu; + dentries_per_clu_bits = ilog2(dentries_per_clu); + + clu_offset = dentry >> dentries_per_clu_bits; + clu.dir = dir.dir; + clu.size = dir.size; + clu.flags = dir.flags; + + if (clu.flags == 0x03) { + clu.dir += clu_offset; + clu.size -= clu_offset; + } else { + /* hint_information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu.dir = fid->hint_last_clu; + } + + while (clu_offset > 0) { + /* clu.dir = FAT_read(sb, clu.dir); */ + if (FAT_read(sb, clu.dir, &clu.dir) == -1) { + ret = FFS_MEDIAERR; + goto out; + } + clu_offset--; + } + } + } + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + if (dir.dir == CLUSTER_32(0)) /* FAT16 root_dir */ + i = dentry % dentries_per_clu; + else + i = dentry & (dentries_per_clu - 1); + + for ( ; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + type = fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) + break; + + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + buf_lock(sb, sector); + dir_entry->Attr = fs_func->get_entry_attr(ep); + + fs_func->get_entry_time(ep, &tm, TM_CREATE); + dir_entry->CreateTimestamp.Year = tm.year; + dir_entry->CreateTimestamp.Month = tm.mon; + dir_entry->CreateTimestamp.Day = tm.day; + dir_entry->CreateTimestamp.Hour = tm.hour; + dir_entry->CreateTimestamp.Minute = tm.min; + dir_entry->CreateTimestamp.Second = tm.sec; + dir_entry->CreateTimestamp.MilliSecond = 0; + + fs_func->get_entry_time(ep, &tm, TM_MODIFY); + dir_entry->ModifyTimestamp.Year = tm.year; + dir_entry->ModifyTimestamp.Month = tm.mon; + dir_entry->ModifyTimestamp.Day = tm.day; + dir_entry->ModifyTimestamp.Hour = tm.hour; + dir_entry->ModifyTimestamp.Minute = tm.min; + dir_entry->ModifyTimestamp.Second = tm.sec; + dir_entry->ModifyTimestamp.MilliSecond = 0; + + memset((char *)&dir_entry->AccessTimestamp, 0, + sizeof(struct date_time_t)); + + *(uni_name.name) = 0x0; + fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry, + uni_name.name); + if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT) + get_uni_name_from_dos_entry(sb, + (struct dos_dentry_t *)ep, + &uni_name, 0x1); + nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name); + buf_unlock(sb, sector); + + if (p_fs->vol_type == EXFAT) { + ep = get_entry_in_dir(sb, &clu, i + 1, NULL); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + } else { + get_uni_name_from_dos_entry(sb, + (struct dos_dentry_t *)ep, + &uni_name, 0x0); + nls_uniname_to_cstring(sb, dir_entry->ShortName, + &uni_name); + } + + dir_entry->Size = fs_func->get_entry_size(ep); + + /* hint information */ + if (dir.dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + } else { + fid->hint_last_off = dentry >> + dentries_per_clu_bits; + fid->hint_last_clu = clu.dir; + } + + fid->rwoffset = (s64)(++dentry); + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + goto out; + } + + if (dir.dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + /* clu.dir = FAT_read(sb, clu.dir); */ + if (FAT_read(sb, clu.dir, &clu.dir) == -1) { + ret = FFS_MEDIAERR; + goto out; + } + } + } + + *(dir_entry->Name) = '\0'; + + fid->rwoffset = (s64)(++dentry); + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid) +{ + s32 dentry; + int ret = FFS_SUCCESS; + struct chain_t dir, clu_to_free; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (!fid) + return FFS_INVALIDFID; + + dir.dir = fid->dir.dir; + dir.size = fid->dir.size; + dir.flags = fid->dir.flags; + + dentry = fid->entry; + + /* check if the file is "." or ".." */ + if (p_fs->vol_type != EXFAT) { + if ((dir.dir != p_fs->root_dir) && (dentry < 2)) + return FFS_PERMISSIONERR; + } + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + clu_to_free.dir = fid->start_clu; + clu_to_free.size = (s32)((fid->size - 1) >> p_fs->cluster_size_bits) + 1; + clu_to_free.flags = fid->flags; + + if (!is_dir_empty(sb, &clu_to_free)) { + ret = FFS_FILEEXIST; + goto out; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* (1) update the directory entry */ + remove_file(inode, &dir, dentry); + + /* (2) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu_to_free, 1); + + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +/*======================================================================*/ +/* Directory Entry Operations */ +/*======================================================================*/ + +static int exfat_readdir(struct file *filp, struct dir_context *ctx) +{ + struct inode *inode = file_inode(filp); + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct dir_entry_t de; + unsigned long inum; + loff_t cpos; + int err = 0; + + __lock_super(sb); + + cpos = ctx->pos; + /* Fake . and .. for the root directory. */ + if ((p_fs->vol_type == EXFAT) || (inode->i_ino == EXFAT_ROOT_INO)) { + while (cpos < 2) { + if (inode->i_ino == EXFAT_ROOT_INO) + inum = EXFAT_ROOT_INO; + else if (cpos == 0) + inum = inode->i_ino; + else /* (cpos == 1) */ + inum = parent_ino(filp->f_path.dentry); + + if (!dir_emit_dots(filp, ctx)) + goto out; + cpos++; + ctx->pos++; + } + if (cpos == 2) + cpos = 0; + } + if (cpos & (DENTRY_SIZE - 1)) { + err = -ENOENT; + goto out; + } + +get_new: + EXFAT_I(inode)->fid.size = i_size_read(inode); + EXFAT_I(inode)->fid.rwoffset = cpos >> DENTRY_SIZE_BITS; + + err = ffsReadDir(inode, &de); + if (err) { + /* at least we tried to read a sector + * move cpos to next sector position (should be aligned) + */ + if (err == FFS_MEDIAERR) { + cpos += 1 << p_bd->sector_size_bits; + cpos &= ~((1 << p_bd->sector_size_bits) - 1); + } + + err = -EIO; + goto end_of_dir; + } + + cpos = EXFAT_I(inode)->fid.rwoffset << DENTRY_SIZE_BITS; + + if (!de.Name[0]) + goto end_of_dir; + + if (!memcmp(de.ShortName, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = inode->i_ino; + } else if (!memcmp(de.ShortName, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = parent_ino(filp->f_path.dentry); + } else { + loff_t i_pos = ((loff_t)EXFAT_I(inode)->fid.start_clu << 32) | + ((EXFAT_I(inode)->fid.rwoffset - 1) & 0xffffffff); + struct inode *tmp = exfat_iget(sb, i_pos); + + if (tmp) { + inum = tmp->i_ino; + iput(tmp); + } else { + inum = iunique(sb, EXFAT_ROOT_INO); + } + } + + if (!dir_emit(ctx, de.Name, strlen(de.Name), inum, + (de.Attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) + goto out; + + ctx->pos = cpos; + goto get_new; + +end_of_dir: + ctx->pos = cpos; +out: + __unlock_super(sb); + return err; +} + +static int exfat_ioctl_volume_id(struct inode *dir) +{ + struct super_block *sb = dir->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + + return p_fs->vol_id; +} + +static long exfat_generic_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ +struct inode *inode = filp->f_path.dentry->d_inode; +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + unsigned int flags; +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + + switch (cmd) { + case EXFAT_IOCTL_GET_VOLUME_ID: + return exfat_ioctl_volume_id(inode); +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + case EXFAT_IOC_GET_DEBUGFLAGS: { + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + flags = sbi->debug_flags; + return put_user(flags, (int __user *)arg); + } + case EXFAT_IOC_SET_DEBUGFLAGS: { + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (get_user(flags, (int __user *)arg)) + return -EFAULT; + + __lock_super(sb); + sbi->debug_flags = flags; + __unlock_super(sb); + + return 0; + } +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + default: + return -ENOTTY; /* Inappropriate ioctl for device */ + } +} + +static const struct file_operations exfat_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, + .iterate = exfat_readdir, + .unlocked_ioctl = exfat_generic_ioctl, + .fsync = generic_file_fsync, +}; + +static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, + bool excl) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct file_id_t fid; + loff_t i_pos; + int err; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_REGULAR, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else if (err == FFS_NAMETOOLONG) + err = -ENAMETOOLONG; + else + err = -EIO; + goto out; + } + INC_IVERSION(dir); + dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + (void)exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + INC_IVERSION(inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + /* + * timestamp is already written, so mark_inode_dirty() is unnecessary. + */ + + dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_find(struct inode *dir, struct qstr *qname, + struct file_id_t *fid) +{ + int err; + + if (qname->len == 0) + return -ENOENT; + + err = ffsLookupFile(dir, (u8 *)qname->name, fid); + if (err) + return -ENOENT; + + return 0; +} + +static int exfat_d_anon_disconn(struct dentry *dentry) +{ + return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); +} + +static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct dentry *alias; + int err; + struct file_id_t fid; + loff_t i_pos; + u64 ret; + mode_t i_mode; + + __lock_super(sb); + pr_debug("%s entered\n", __func__); + err = exfat_find(dir, &dentry->d_name, &fid); + if (err) { + if (err == -ENOENT) { + inode = NULL; + goto out; + } + goto error; + } + + i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff); + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto error; + } + + i_mode = inode->i_mode; + if (S_ISLNK(i_mode) && !EXFAT_I(inode)->target) { + EXFAT_I(inode)->target = kmalloc(i_size_read(inode) + 1, + GFP_KERNEL); + if (!EXFAT_I(inode)->target) { + err = -ENOMEM; + goto error; + } + ffsReadFile(dir, &fid, EXFAT_I(inode)->target, + i_size_read(inode), &ret); + *(EXFAT_I(inode)->target + i_size_read(inode)) = '\0'; + } + + alias = d_find_alias(inode); + if (alias && !exfat_d_anon_disconn(alias)) { + BUG_ON(d_unhashed(alias)); + if (!S_ISDIR(i_mode)) + d_move(alias, dentry); + iput(inode); + __unlock_super(sb); + pr_debug("%s exited 1\n", __func__); + return alias; + } + dput(alias); +out: + __unlock_super(sb); + dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); + dentry = d_splice_alias(inode, dentry); + if (dentry) + dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); + pr_debug("%s exited 2\n", __func__); + return dentry; + +error: + __unlock_super(sb); + pr_debug("%s exited 3\n", __func__); + return ERR_PTR(err); +} + +static inline unsigned long exfat_hash(loff_t i_pos) +{ + return hash_32(i_pos, EXFAT_HASH_BITS); +} + +static void exfat_attach(struct inode *inode, loff_t i_pos) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + + spin_lock(&sbi->inode_hash_lock); + EXFAT_I(inode)->i_pos = i_pos; + hlist_add_head(&EXFAT_I(inode)->i_hash_fat, head); + spin_unlock(&sbi->inode_hash_lock); +} + +static void exfat_detach(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + spin_lock(&sbi->inode_hash_lock); + hlist_del_init(&EXFAT_I(inode)->i_hash_fat); + EXFAT_I(inode)->i_pos = 0; + spin_unlock(&sbi->inode_hash_lock); +} + +static int exfat_unlink(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct super_block *sb = dir->i_sb; + int err; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = ffsRemoveFile(dir, &(EXFAT_I(inode)->fid)); + if (err) { + if (err == FFS_PERMISSIONERR) + err = -EPERM; + else + err = -EIO; + goto out; + } + INC_IVERSION(dir); + dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + (void)exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = current_time(inode); + exfat_detach(inode); + remove_inode_hash(inode); + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_symlink(struct inode *dir, struct dentry *dentry, + const char *target) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct file_id_t fid; + loff_t i_pos; + int err; + u64 len = (u64)strlen(target); + u64 ret; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_SYMLINK, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + + err = ffsWriteFile(dir, &fid, (char *)target, len, &ret); + + if (err) { + ffsRemoveFile(dir, &fid); + + if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + + INC_IVERSION(dir); + dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + (void)exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + INC_IVERSION(inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + EXFAT_I(inode)->target = kmemdup(target, len + 1, GFP_KERNEL); + if (!EXFAT_I(inode)->target) { + err = -ENOMEM; + goto out; + } + + dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct file_id_t fid; + loff_t i_pos; + int err; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + err = ffsCreateDir(dir, (u8 *)dentry->d_name.name, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else if (err == FFS_NAMETOOLONG) + err = -ENAMETOOLONG; + else + err = -EIO; + goto out; + } + INC_IVERSION(dir); + dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + (void)exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + inc_nlink(dir); + + i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + INC_IVERSION(inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct super_block *sb = dir->i_sb; + int err; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = ffsRemoveDir(dir, &(EXFAT_I(inode)->fid)); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -ENOTEMPTY; + else if (err == FFS_NOTFOUND) + err = -ENOENT; + else if (err == FFS_DIRBUSY) + err = -EBUSY; + else + err = -EIO; + goto out; + } + INC_IVERSION(dir); + dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + (void)exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + drop_nlink(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = current_time(inode); + exfat_detach(inode); + remove_inode_hash(inode); + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags) +{ + struct inode *old_inode, *new_inode; + struct super_block *sb = old_dir->i_sb; + loff_t i_pos; + int err; + + if (flags) + return -EINVAL; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + old_inode = old_dentry->d_inode; + new_inode = new_dentry->d_inode; + + EXFAT_I(old_inode)->fid.size = i_size_read(old_inode); + + err = ffsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir, + new_dentry); + if (err) { + if (err == FFS_PERMISSIONERR) + err = -EPERM; + else if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_NOTFOUND) + err = -ENOENT; + else if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + INC_IVERSION(new_dir); + new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = + current_time(new_dir); + if (IS_DIRSYNC(new_dir)) + (void)exfat_sync_inode(new_dir); + else + mark_inode_dirty(new_dir); + + i_pos = ((loff_t)EXFAT_I(old_inode)->fid.dir.dir << 32) | + (EXFAT_I(old_inode)->fid.entry & 0xffffffff); + + exfat_detach(old_inode); + exfat_attach(old_inode, i_pos); + if (IS_DIRSYNC(new_dir)) + (void)exfat_sync_inode(old_inode); + else + mark_inode_dirty(old_inode); + + if ((S_ISDIR(old_inode->i_mode)) && (old_dir != new_dir)) { + drop_nlink(old_dir); + if (!new_inode) + inc_nlink(new_dir); + } + INC_IVERSION(old_dir); + old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir); + if (IS_DIRSYNC(old_dir)) + (void)exfat_sync_inode(old_dir); + else + mark_inode_dirty(old_dir); + + if (new_inode) { + exfat_detach(new_inode); + drop_nlink(new_inode); + if (S_ISDIR(new_inode->i_mode)) + drop_nlink(new_inode); + new_inode->i_ctime = current_time(new_inode); + } + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_cont_expand(struct inode *inode, loff_t size) +{ + struct address_space *mapping = inode->i_mapping; + loff_t start = i_size_read(inode), count = size - i_size_read(inode); + int err, err2; + + err = generic_cont_expand_simple(inode, size); + if (err != 0) + return err; + + inode->i_ctime = inode->i_mtime = current_time(inode); + mark_inode_dirty(inode); + + if (IS_SYNC(inode)) { + err = filemap_fdatawrite_range(mapping, start, + start + count - 1); + err2 = sync_mapping_buffers(mapping); + err = (err) ? (err) : (err2); + err2 = write_inode_now(inode, 1); + err = (err) ? (err) : (err2); + if (!err) + err = filemap_fdatawait_range(mapping, start, + start + count - 1); + } + return err; +} + +static int exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) +{ + mode_t allow_utime = sbi->options.allow_utime; + + if (!uid_eq(current_fsuid(), inode->i_uid)) { + if (in_group_p(inode->i_gid)) + allow_utime >>= 3; + if (allow_utime & MAY_WRITE) + return 1; + } + + /* use a default check */ + return 0; +} + +static int exfat_sanitize_mode(const struct exfat_sb_info *sbi, + struct inode *inode, umode_t *mode_ptr) +{ + mode_t i_mode, mask, perm; + + i_mode = inode->i_mode; + + if (S_ISREG(i_mode) || S_ISLNK(i_mode)) + mask = sbi->options.fs_fmask; + else + mask = sbi->options.fs_dmask; + + perm = *mode_ptr & ~(S_IFMT | mask); + + /* Of the r and x bits, all (subject to umask) must be present.*/ + if ((perm & 0555) != (i_mode & 0555)) + return -EPERM; + + if (exfat_mode_can_hold_ro(inode)) { + /* + * Of the w bits, either all (subject to umask) or none must be + * present. + */ + if ((perm & 0222) && ((perm & 0222) != (0222 & ~mask))) + return -EPERM; + } else { + /* + * If exfat_mode_can_hold_ro(inode) is false, can't change w + * bits. + */ + if ((perm & 0222) != (0222 & ~mask)) + return -EPERM; + } + + *mode_ptr &= S_IFMT | perm; + + return 0; +} + +static void exfat_truncate(struct inode *inode, loff_t old_size) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + int err; + + __lock_super(sb); + + /* + * This protects against truncating a file bigger than it was then + * trying to write into the hole. + */ + if (EXFAT_I(inode)->mmu_private > i_size_read(inode)) + EXFAT_I(inode)->mmu_private = i_size_read(inode); + + if (EXFAT_I(inode)->fid.start_clu == 0) + goto out; + + err = ffsTruncateFile(inode, old_size, i_size_read(inode)); + if (err) + goto out; + + inode->i_ctime = inode->i_mtime = current_time(inode); + if (IS_DIRSYNC(inode)) + (void)exfat_sync_inode(inode); + else + mark_inode_dirty(inode); + + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) & + ~((loff_t)p_fs->cluster_size - 1)) >> 9; +out: + __unlock_super(sb); +} + +static int exfat_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb); + struct inode *inode = dentry->d_inode; + unsigned int ia_valid; + int error; + loff_t old_size; + + pr_debug("%s entered\n", __func__); + + if ((attr->ia_valid & ATTR_SIZE) + && (attr->ia_size > i_size_read(inode))) { + error = exfat_cont_expand(inode, attr->ia_size); + if (error || attr->ia_valid == ATTR_SIZE) + return error; + attr->ia_valid &= ~ATTR_SIZE; + } + + ia_valid = attr->ia_valid; + + if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) + && exfat_allow_set_time(sbi, inode)) { + attr->ia_valid &= ~(ATTR_MTIME_SET | + ATTR_ATIME_SET | + ATTR_TIMES_SET); + } + + error = setattr_prepare(dentry, attr); + attr->ia_valid = ia_valid; + if (error) + return error; + + if (((attr->ia_valid & ATTR_UID) && + (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) || + ((attr->ia_valid & ATTR_GID) && + (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) || + ((attr->ia_valid & ATTR_MODE) && + (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | 0777)))) { + return -EPERM; + } + + /* + * We don't return -EPERM here. Yes, strange, but this is too + * old behavior. + */ + if (attr->ia_valid & ATTR_MODE) { + if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0) + attr->ia_valid &= ~ATTR_MODE; + } + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + if (attr->ia_valid & ATTR_SIZE) { + old_size = i_size_read(inode); + down_write(&EXFAT_I(inode)->truncate_lock); + truncate_setsize(inode, attr->ia_size); + exfat_truncate(inode, old_size); + up_write(&EXFAT_I(inode)->truncate_lock); + } + setattr_copy(inode, attr); + mark_inode_dirty(inode); + + pr_debug("%s exited\n", __func__); + return error; +} + +static int exfat_getattr(const struct path *path, struct kstat *stat, + u32 request_mask, unsigned int flags) +{ + struct inode *inode = path->dentry->d_inode; + + pr_debug("%s entered\n", __func__); + + generic_fillattr(inode, stat); + stat->blksize = EXFAT_SB(inode->i_sb)->fs_info.cluster_size; + + pr_debug("%s exited\n", __func__); + return 0; +} + +static const struct inode_operations exfat_dir_inode_operations = { + .create = exfat_create, + .lookup = exfat_lookup, + .unlink = exfat_unlink, + .symlink = exfat_symlink, + .mkdir = exfat_mkdir, + .rmdir = exfat_rmdir, + .rename = exfat_rename, + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; + +/*======================================================================*/ +/* File Operations */ +/*======================================================================*/ +static const char *exfat_get_link(struct dentry *dentry, struct inode *inode, + struct delayed_call *done) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + + if (ei->target) { + char *cookie = ei->target; + + if (cookie) + return (char *)(ei->target); + } + return NULL; +} + +static const struct inode_operations exfat_symlink_inode_operations = { + .get_link = exfat_get_link, +}; + +static int exfat_file_release(struct inode *inode, struct file *filp) +{ + struct super_block *sb = inode->i_sb; + + EXFAT_I(inode)->fid.size = i_size_read(inode); + ffsSyncVol(sb, false); + return 0; +} + +static const struct file_operations exfat_file_operations = { + .llseek = generic_file_llseek, + .read_iter = generic_file_read_iter, + .write_iter = generic_file_write_iter, + .mmap = generic_file_mmap, + .release = exfat_file_release, + .unlocked_ioctl = exfat_generic_ioctl, + .fsync = generic_file_fsync, + .splice_read = generic_file_splice_read, +}; + +static const struct inode_operations exfat_file_inode_operations = { + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; + +/*======================================================================*/ +/* Address Space Operations */ +/*======================================================================*/ + +static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys, + unsigned long *mapped_blocks, int *create) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + struct bd_info_t *p_bd = &(sbi->bd_info); + const unsigned long blocksize = sb->s_blocksize; + const unsigned char blocksize_bits = sb->s_blocksize_bits; + sector_t last_block; + int err, clu_offset, sec_offset; + unsigned int cluster; + + *phys = 0; + *mapped_blocks = 0; + + if ((p_fs->vol_type == FAT12) || (p_fs->vol_type == FAT16)) { + if (inode->i_ino == EXFAT_ROOT_INO) { + if (sector < + (p_fs->dentries_in_root >> + (p_bd->sector_size_bits - DENTRY_SIZE_BITS))) { + *phys = sector + p_fs->root_start_sector; + *mapped_blocks = 1; + } + return 0; + } + } + + last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits; + if (sector >= last_block) { + if (*create == 0) + return 0; + } else { + *create = 0; + } + + /* cluster offset */ + clu_offset = sector >> p_fs->sectors_per_clu_bits; + + /* sector offset in cluster */ + sec_offset = sector & (p_fs->sectors_per_clu - 1); + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = ffsMapCluster(inode, clu_offset, &cluster); + + if (err) { + if (err == FFS_FULL) + return -ENOSPC; + else + return -EIO; + } else if (cluster != CLUSTER_32(~0)) { + *phys = START_SECTOR(cluster) + sec_offset; + *mapped_blocks = p_fs->sectors_per_clu - sec_offset; + } + + return 0; +} + +static int exfat_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + struct super_block *sb = inode->i_sb; + unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; + int err; + unsigned long mapped_blocks; + sector_t phys; + + __lock_super(sb); + + err = exfat_bmap(inode, iblock, &phys, &mapped_blocks, &create); + if (err) { + __unlock_super(sb); + return err; + } + + if (phys) { + max_blocks = min(mapped_blocks, max_blocks); + if (create) { + EXFAT_I(inode)->mmu_private += max_blocks << + sb->s_blocksize_bits; + set_buffer_new(bh_result); + } + map_bh(bh_result, sb, phys); + } + + bh_result->b_size = max_blocks << sb->s_blocksize_bits; + __unlock_super(sb); + + return 0; +} + +static int exfat_readpage(struct file *file, struct page *page) +{ + return mpage_readpage(page, exfat_get_block); +} + +static int exfat_readpages(struct file *file, struct address_space *mapping, + struct list_head *pages, unsigned int nr_pages) +{ + return mpage_readpages(mapping, pages, nr_pages, exfat_get_block); +} + +static int exfat_writepage(struct page *page, struct writeback_control *wbc) +{ + return block_write_full_page(page, exfat_get_block, wbc); +} + +static int exfat_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + return mpage_writepages(mapping, wbc, exfat_get_block); +} + +static void exfat_write_failed(struct address_space *mapping, loff_t to) +{ + struct inode *inode = mapping->host; + + if (to > i_size_read(inode)) { + truncate_pagecache(inode, i_size_read(inode)); + EXFAT_I(inode)->fid.size = i_size_read(inode); + exfat_truncate(inode, i_size_read(inode)); + } +} + +static int exfat_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int flags, + struct page **pagep, void **fsdata) +{ + int ret; + + *pagep = NULL; + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + exfat_get_block, + &EXFAT_I(mapping->host)->mmu_private); + + if (ret < 0) + exfat_write_failed(mapping, pos + len); + return ret; +} + +static int exfat_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int copied, + struct page *pagep, void *fsdata) +{ + struct inode *inode = mapping->host; + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + int err; + + err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); + + if (err < len) + exfat_write_failed(mapping, pos + len); + + if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) { + inode->i_mtime = inode->i_ctime = current_time(inode); + fid->attr |= ATTR_ARCHIVE; + mark_inode_dirty(inode); + } + return err; +} + +static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter) +{ + struct inode *inode = iocb->ki_filp->f_mapping->host; + struct address_space *mapping = iocb->ki_filp->f_mapping; + ssize_t ret; + int rw; + + rw = iov_iter_rw(iter); + + if (rw == WRITE) { + if (EXFAT_I(inode)->mmu_private < iov_iter_count(iter)) + return 0; + } + ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block); + + if ((ret < 0) && (rw & WRITE)) + exfat_write_failed(mapping, iov_iter_count(iter)); + return ret; +} + +static sector_t _exfat_bmap(struct address_space *mapping, sector_t block) +{ + sector_t blocknr; + + /* exfat_get_cluster() assumes the requested blocknr isn't truncated. */ + down_read(&EXFAT_I(mapping->host)->truncate_lock); + blocknr = generic_block_bmap(mapping, block, exfat_get_block); + up_read(&EXFAT_I(mapping->host)->truncate_lock); + + return blocknr; +} + +static const struct address_space_operations exfat_aops = { + .readpage = exfat_readpage, + .readpages = exfat_readpages, + .writepage = exfat_writepage, + .writepages = exfat_writepages, + .write_begin = exfat_write_begin, + .write_end = exfat_write_end, + .direct_IO = exfat_direct_IO, + .bmap = _exfat_bmap +}; + +/*======================================================================*/ +/* Super Operations */ +/*======================================================================*/ + +static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *info; + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + struct inode *inode = NULL; + + spin_lock(&sbi->inode_hash_lock); + hlist_for_each_entry(info, head, i_hash_fat) { + BUG_ON(info->vfs_inode.i_sb != sb); + + if (i_pos != info->i_pos) + continue; + inode = igrab(&info->vfs_inode); + if (inode) + break; + } + spin_unlock(&sbi->inode_hash_lock); + return inode; +} + +/* doesn't deal with root inode */ +static int exfat_fill_inode(struct inode *inode, struct file_id_t *fid) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + struct dir_entry_t info; + + memcpy(&(EXFAT_I(inode)->fid), fid, sizeof(struct file_id_t)); + + ffsReadStat(inode, &info); + + EXFAT_I(inode)->i_pos = 0; + EXFAT_I(inode)->target = NULL; + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + INC_IVERSION(inode); + inode->i_generation = get_seconds(); + + if (info.Attr & ATTR_SUBDIR) { /* directory */ + inode->i_generation &= ~1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, 0777); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); + set_nlink(inode, info.NumSubdirs); + } else if (info.Attr & ATTR_SYMLINK) { /* symbolic link */ + inode->i_generation |= 1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, 0777); + inode->i_op = &exfat_symlink_inode_operations; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); + } else { /* regular file */ + inode->i_generation |= 1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, 0777); + inode->i_op = &exfat_file_inode_operations; + inode->i_fop = &exfat_file_operations; + inode->i_mapping->a_ops = &exfat_aops; + inode->i_mapping->nrpages = 0; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); + } + exfat_save_attr(inode, info.Attr); + + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) + & ~((loff_t)p_fs->cluster_size - 1)) >> 9; + + exfat_time_fat2unix(&inode->i_mtime, &info.ModifyTimestamp); + exfat_time_fat2unix(&inode->i_ctime, &info.CreateTimestamp); + exfat_time_fat2unix(&inode->i_atime, &info.AccessTimestamp); + + return 0; +} + +static struct inode *exfat_build_inode(struct super_block *sb, + struct file_id_t *fid, loff_t i_pos) +{ + struct inode *inode; + int err; + + inode = exfat_iget(sb, i_pos); + if (inode) + goto out; + inode = new_inode(sb); + if (!inode) { + inode = ERR_PTR(-ENOMEM); + goto out; + } + inode->i_ino = iunique(sb, EXFAT_ROOT_INO); + SET_IVERSION(inode, 1); + err = exfat_fill_inode(inode, fid); + if (err) { + iput(inode); + inode = ERR_PTR(err); + goto out; + } + exfat_attach(inode, i_pos); + insert_inode_hash(inode); +out: + return inode; +} + +static int exfat_sync_inode(struct inode *inode) +{ + return exfat_write_inode(inode, NULL); +} + +static struct inode *exfat_alloc_inode(struct super_block *sb) +{ + struct exfat_inode_info *ei; + + ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS); + if (!ei) + return NULL; + + init_rwsem(&ei->truncate_lock); + + return &ei->vfs_inode; +} + +static void exfat_destroy_inode(struct inode *inode) +{ + kfree(EXFAT_I(inode)->target); + EXFAT_I(inode)->target = NULL; + + kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); +} + +static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + struct dir_entry_t info; + + if (inode->i_ino == EXFAT_ROOT_INO) + return 0; + + info.Attr = exfat_make_attr(inode); + info.Size = i_size_read(inode); + + exfat_time_unix2fat(&inode->i_mtime, &info.ModifyTimestamp); + exfat_time_unix2fat(&inode->i_ctime, &info.CreateTimestamp); + exfat_time_unix2fat(&inode->i_atime, &info.AccessTimestamp); + + ffsWriteStat(inode, &info); + + return 0; +} + +static void exfat_evict_inode(struct inode *inode) +{ + truncate_inode_pages(&inode->i_data, 0); + + if (!inode->i_nlink) + i_size_write(inode, 0); + invalidate_inode_buffers(inode); + clear_inode(inode); + exfat_detach(inode); + + remove_inode_hash(inode); +} + +static void exfat_free_super(struct exfat_sb_info *sbi) +{ + if (sbi->nls_disk) + unload_nls(sbi->nls_disk); + if (sbi->nls_io) + unload_nls(sbi->nls_io); + if (sbi->options.iocharset != exfat_default_iocharset) + kfree(sbi->options.iocharset); + /* mutex_init is in exfat_fill_super function. only for 3.7+ */ + mutex_destroy(&sbi->s_lock); + kfree(sbi); +} + +static void exfat_put_super(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + if (__is_sb_dirty(sb)) + exfat_write_super(sb); + + ffsUmountVol(sb); + + sb->s_fs_info = NULL; + exfat_free_super(sbi); +} + +static void exfat_write_super(struct super_block *sb) +{ + __lock_super(sb); + + __set_sb_clean(sb); + + if (!sb_rdonly(sb)) + ffsSyncVol(sb, true); + + __unlock_super(sb); +} + +static int exfat_sync_fs(struct super_block *sb, int wait) +{ + int err = 0; + + if (__is_sb_dirty(sb)) { + __lock_super(sb); + __set_sb_clean(sb); + err = ffsSyncVol(sb, true); + __unlock_super(sb); + } + + return err; +} + +static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb = dentry->d_sb; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct vol_info_t info; + + if (p_fs->used_clusters == UINT_MAX) { + if (ffsGetVolInfo(sb, &info) == FFS_MEDIAERR) + return -EIO; + + } else { + info.FatType = p_fs->vol_type; + info.ClusterSize = p_fs->cluster_size; + info.NumClusters = p_fs->num_clusters - 2; + info.UsedClusters = p_fs->used_clusters; + info.FreeClusters = info.NumClusters - info.UsedClusters; + + if (p_fs->dev_ejected) + pr_info("[EXFAT] statfs on device that is ejected\n"); + } + + buf->f_type = sb->s_magic; + buf->f_bsize = info.ClusterSize; + buf->f_blocks = info.NumClusters; + buf->f_bfree = info.FreeClusters; + buf->f_bavail = info.FreeClusters; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); + buf->f_namelen = 260; + + return 0; +} + +static int exfat_remount(struct super_block *sb, int *flags, char *data) +{ + *flags |= SB_NODIRATIME; + return 0; +} + +static int exfat_show_options(struct seq_file *m, struct dentry *root) +{ + struct exfat_sb_info *sbi = EXFAT_SB(root->d_sb); + struct exfat_mount_options *opts = &sbi->options; + + if (__kuid_val(opts->fs_uid)) + seq_printf(m, ",uid=%u", __kuid_val(opts->fs_uid)); + if (__kgid_val(opts->fs_gid)) + seq_printf(m, ",gid=%u", __kgid_val(opts->fs_gid)); + seq_printf(m, ",fmask=%04o", opts->fs_fmask); + seq_printf(m, ",dmask=%04o", opts->fs_dmask); + if (opts->allow_utime) + seq_printf(m, ",allow_utime=%04o", opts->allow_utime); + if (sbi->nls_disk) + seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); + if (sbi->nls_io) + seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); + seq_printf(m, ",namecase=%u", opts->casesensitive); + if (opts->errors == EXFAT_ERRORS_CONT) + seq_puts(m, ",errors=continue"); + else if (opts->errors == EXFAT_ERRORS_PANIC) + seq_puts(m, ",errors=panic"); + else + seq_puts(m, ",errors=remount-ro"); +#ifdef CONFIG_EXFAT_DISCARD + if (opts->discard) + seq_puts(m, ",discard"); +#endif + return 0; +} + +static const struct super_operations exfat_sops = { + .alloc_inode = exfat_alloc_inode, + .destroy_inode = exfat_destroy_inode, + .write_inode = exfat_write_inode, + .evict_inode = exfat_evict_inode, + .put_super = exfat_put_super, + .sync_fs = exfat_sync_fs, + .statfs = exfat_statfs, + .remount_fs = exfat_remount, + .show_options = exfat_show_options, +}; + +/*======================================================================*/ +/* Export Operations */ +/*======================================================================*/ + +static struct inode *exfat_nfs_get_inode(struct super_block *sb, u64 ino, + u32 generation) +{ + struct inode *inode = NULL; + + if (ino < EXFAT_ROOT_INO) + return inode; + inode = ilookup(sb, ino); + + if (inode && generation && (inode->i_generation != generation)) { + iput(inode); + inode = NULL; + } + + return inode; +} + +static struct dentry *exfat_fh_to_dentry(struct super_block *sb, + struct fid *fid, int fh_len, + int fh_type) +{ + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, + exfat_nfs_get_inode); +} + +static struct dentry *exfat_fh_to_parent(struct super_block *sb, + struct fid *fid, int fh_len, + int fh_type) +{ + return generic_fh_to_parent(sb, fid, fh_len, fh_type, + exfat_nfs_get_inode); +} + +static const struct export_operations exfat_export_ops = { + .fh_to_dentry = exfat_fh_to_dentry, + .fh_to_parent = exfat_fh_to_parent, +}; + +/*======================================================================*/ +/* Super Block Read Operations */ +/*======================================================================*/ + +enum { + Opt_uid, + Opt_gid, + Opt_umask, + Opt_dmask, + Opt_fmask, + Opt_allow_utime, + Opt_codepage, + Opt_charset, + Opt_namecase, + Opt_debug, + Opt_err_cont, + Opt_err_panic, + Opt_err_ro, + Opt_utf8_hack, + Opt_err, +#ifdef CONFIG_EXFAT_DISCARD + Opt_discard, +#endif /* EXFAT_CONFIG_DISCARD */ +}; + +static const match_table_t exfat_tokens = { + {Opt_uid, "uid=%u"}, + {Opt_gid, "gid=%u"}, + {Opt_umask, "umask=%o"}, + {Opt_dmask, "dmask=%o"}, + {Opt_fmask, "fmask=%o"}, + {Opt_allow_utime, "allow_utime=%o"}, + {Opt_codepage, "codepage=%u"}, + {Opt_charset, "iocharset=%s"}, + {Opt_namecase, "namecase=%u"}, + {Opt_debug, "debug"}, + {Opt_err_cont, "errors=continue"}, + {Opt_err_panic, "errors=panic"}, + {Opt_err_ro, "errors=remount-ro"}, + {Opt_utf8_hack, "utf8"}, +#ifdef CONFIG_EXFAT_DISCARD + {Opt_discard, "discard"}, +#endif /* CONFIG_EXFAT_DISCARD */ + {Opt_err, NULL} +}; + +static int parse_options(char *options, int silent, int *debug, + struct exfat_mount_options *opts) +{ + char *p; + substring_t args[MAX_OPT_ARGS]; + int option; + char *iocharset; + + opts->fs_uid = current_uid(); + opts->fs_gid = current_gid(); + opts->fs_fmask = opts->fs_dmask = current->fs->umask; + opts->allow_utime = U16_MAX; + opts->codepage = exfat_default_codepage; + opts->iocharset = exfat_default_iocharset; + opts->casesensitive = 0; + opts->errors = EXFAT_ERRORS_RO; +#ifdef CONFIG_EXFAT_DISCARD + opts->discard = 0; +#endif + *debug = 0; + + if (!options) + goto out; + + while ((p = strsep(&options, ","))) { + int token; + + if (!*p) + continue; + + token = match_token(p, exfat_tokens, args); + switch (token) { + case Opt_uid: + if (match_int(&args[0], &option)) + return 0; + opts->fs_uid = KUIDT_INIT(option); + break; + case Opt_gid: + if (match_int(&args[0], &option)) + return 0; + opts->fs_gid = KGIDT_INIT(option); + break; + case Opt_umask: + case Opt_dmask: + case Opt_fmask: + if (match_octal(&args[0], &option)) + return 0; + if (token != Opt_dmask) + opts->fs_fmask = option; + if (token != Opt_fmask) + opts->fs_dmask = option; + break; + case Opt_allow_utime: + if (match_octal(&args[0], &option)) + return 0; + opts->allow_utime = option & 0022; + break; + case Opt_codepage: + if (match_int(&args[0], &option)) + return 0; + opts->codepage = option; + break; + case Opt_charset: + if (opts->iocharset != exfat_default_iocharset) + kfree(opts->iocharset); + iocharset = match_strdup(&args[0]); + if (!iocharset) + return -ENOMEM; + opts->iocharset = iocharset; + break; + case Opt_namecase: + if (match_int(&args[0], &option)) + return 0; + opts->casesensitive = option; + break; + case Opt_err_cont: + opts->errors = EXFAT_ERRORS_CONT; + break; + case Opt_err_panic: + opts->errors = EXFAT_ERRORS_PANIC; + break; + case Opt_err_ro: + opts->errors = EXFAT_ERRORS_RO; + break; + case Opt_debug: + *debug = 1; + break; +#ifdef CONFIG_EXFAT_DISCARD + case Opt_discard: + opts->discard = 1; + break; +#endif /* CONFIG_EXFAT_DISCARD */ + case Opt_utf8_hack: + break; + default: + if (!silent) + pr_err("[EXFAT] Unrecognized mount option %s or missing value\n", + p); + return -EINVAL; + } + } + +out: + if (opts->allow_utime == U16_MAX) + opts->allow_utime = ~opts->fs_dmask & 0022; + + return 0; +} + +static void exfat_hash_init(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + int i; + + spin_lock_init(&sbi->inode_hash_lock); + for (i = 0; i < EXFAT_HASH_SIZE; i++) + INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); +} + +static int exfat_read_root(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + struct dir_entry_t info; + + EXFAT_I(inode)->fid.dir.dir = p_fs->root_dir; + EXFAT_I(inode)->fid.dir.flags = 0x01; + EXFAT_I(inode)->fid.entry = -1; + EXFAT_I(inode)->fid.start_clu = p_fs->root_dir; + EXFAT_I(inode)->fid.flags = 0x01; + EXFAT_I(inode)->fid.type = TYPE_DIR; + EXFAT_I(inode)->fid.rwoffset = 0; + EXFAT_I(inode)->fid.hint_last_off = -1; + + EXFAT_I(inode)->target = NULL; + + ffsReadStat(inode, &info); + + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + INC_IVERSION(inode); + inode->i_generation = 0; + inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, 0777); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + + i_size_write(inode, info.Size); + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) + & ~((loff_t)p_fs->cluster_size - 1)) >> 9; + EXFAT_I(inode)->i_pos = ((loff_t)p_fs->root_dir << 32) | 0xffffffff; + EXFAT_I(inode)->mmu_private = i_size_read(inode); + + exfat_save_attr(inode, ATTR_SUBDIR); + inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + set_nlink(inode, info.NumSubdirs + 2); + + return 0; +} + +static void setup_dops(struct super_block *sb) +{ + if (EXFAT_SB(sb)->options.casesensitive == 0) + sb->s_d_op = &exfat_ci_dentry_ops; + else + sb->s_d_op = &exfat_dentry_ops; +} + +static int exfat_fill_super(struct super_block *sb, void *data, int silent) +{ + struct inode *root_inode = NULL; + struct exfat_sb_info *sbi; + int debug, ret; + long error; + char buf[50]; + + /* + * GFP_KERNEL is ok here, because while we do hold the + * supeblock lock, memory pressure can't call back into + * the filesystem, since we're only just about to mount + * it and have no inodes etc active! + */ + sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; + mutex_init(&sbi->s_lock); + sb->s_fs_info = sbi; + sb->s_flags |= SB_NODIRATIME; + sb->s_magic = EXFAT_SUPER_MAGIC; + sb->s_op = &exfat_sops; + sb->s_export_op = &exfat_export_ops; + + error = parse_options(data, silent, &debug, &sbi->options); + if (error) + goto out_fail; + + setup_dops(sb); + + error = -EIO; + sb_min_blocksize(sb, 512); + sb->s_maxbytes = 0x7fffffffffffffffLL; /* maximum file size */ + + ret = ffsMountVol(sb); + if (ret) { + if (!silent) + pr_err("[EXFAT] ffsMountVol failed\n"); + + goto out_fail; + } + + /* set up enough so that it can read an inode */ + exfat_hash_init(sb); + + /* + * The low byte of FAT's first entry must have same value with + * media-field. But in real world, too many devices is + * writing wrong value. So, removed that validity check. + * + * if (FAT_FIRST_ENT(sb, media) != first) + */ + + /* codepage is not meaningful in exfat */ + if (sbi->fs_info.vol_type != EXFAT) { + error = -EINVAL; + sprintf(buf, "cp%d", sbi->options.codepage); + sbi->nls_disk = load_nls(buf); + if (!sbi->nls_disk) { + pr_err("[EXFAT] Codepage %s not found\n", buf); + goto out_fail2; + } + } + + sbi->nls_io = load_nls(sbi->options.iocharset); + + error = -ENOMEM; + root_inode = new_inode(sb); + if (!root_inode) + goto out_fail2; + root_inode->i_ino = EXFAT_ROOT_INO; + SET_IVERSION(root_inode, 1); + + error = exfat_read_root(root_inode); + if (error < 0) + goto out_fail2; + error = -ENOMEM; + exfat_attach(root_inode, EXFAT_I(root_inode)->i_pos); + insert_inode_hash(root_inode); + sb->s_root = d_make_root(root_inode); + if (!sb->s_root) { + pr_err("[EXFAT] Getting the root inode failed\n"); + goto out_fail2; + } + + return 0; + +out_fail2: + ffsUmountVol(sb); +out_fail: + if (root_inode) + iput(root_inode); + sb->s_fs_info = NULL; + exfat_free_super(sbi); + return error; +} + +static struct dentry *exfat_fs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data) +{ + return mount_bdev(fs_type, flags, dev_name, data, exfat_fill_super); +} + +static void init_once(void *foo) +{ + struct exfat_inode_info *ei = (struct exfat_inode_info *)foo; + + INIT_HLIST_NODE(&ei->i_hash_fat); + inode_init_once(&ei->vfs_inode); +} + +static int __init exfat_init_inodecache(void) +{ + exfat_inode_cachep = kmem_cache_create("exfat_inode_cache", + sizeof(struct exfat_inode_info), + 0, + (SLAB_RECLAIM_ACCOUNT | + SLAB_MEM_SPREAD), + init_once); + if (!exfat_inode_cachep) + return -ENOMEM; + return 0; +} + +static void __exit exfat_destroy_inodecache(void) +{ + /* + * Make sure all delayed rcu free inodes are flushed before we + * destroy cache. + */ + rcu_barrier(); + kmem_cache_destroy(exfat_inode_cachep); +} + +#ifdef CONFIG_EXFAT_KERNEL_DEBUG +static void exfat_debug_kill_sb(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct block_device *bdev = sb->s_bdev; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + long flags; + + if (sbi) { + flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_INVALID_UMOUNT) { + /* + * invalidate_bdev drops all device cache include + * dirty. We use this to simulate device removal. + */ + down(&p_fs->v_sem); + FAT_release_all(sb); + buf_release_all(sb); + up(&p_fs->v_sem); + + invalidate_bdev(bdev); + } + } + + kill_block_super(sb); +} +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + +static struct file_system_type exfat_fs_type = { + .owner = THIS_MODULE, + .name = "exfat", + .mount = exfat_fs_mount, +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + .kill_sb = exfat_debug_kill_sb, +#else + .kill_sb = kill_block_super, +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + .fs_flags = FS_REQUIRES_DEV, +}; + +static int __init init_exfat(void) +{ + int err; + + BUILD_BUG_ON(sizeof(struct dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct dos_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct ext_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct file_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct strm_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct name_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct bmap_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct case_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct volm_dentry_t) != DENTRY_SIZE); + + pr_info("exFAT: Version %s\n", EXFAT_VERSION); + + err = exfat_init_inodecache(); + if (err) + return err; + + err = register_filesystem(&exfat_fs_type); + if (err) + return err; + + return 0; +} + +static void __exit exit_exfat(void) +{ + exfat_destroy_inodecache(); + unregister_filesystem(&exfat_fs_type); +} + +module_init(init_exfat); +module_exit(exit_exfat); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("exFAT Filesystem Driver"); +MODULE_ALIAS_FS("exfat"); diff --git a/drivers/staging/exfat/exfat_upcase.c b/drivers/staging/exfat/exfat_upcase.c new file mode 100644 index 000000000000..366082fb3dab --- /dev/null +++ b/drivers/staging/exfat/exfat_upcase.c @@ -0,0 +1,740 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include <linux/types.h> +#include "exfat.h" + +const u8 uni_upcase[NUM_UPCASE << 1] = { + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, 0x00, + 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, + 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, + 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, + 0x18, 0x00, 0x19, 0x00, 0x1A, 0x00, 0x1B, 0x00, + 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x00, 0x1F, 0x00, + 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, + 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, + 0x28, 0x00, 0x29, 0x00, 0x2A, 0x00, 0x2B, 0x00, + 0x2C, 0x00, 0x2D, 0x00, 0x2E, 0x00, 0x2F, 0x00, + 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, + 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, + 0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x3B, 0x00, + 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, + 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, + 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, + 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, + 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, + 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, + 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x5B, 0x00, + 0x5C, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00, + 0x60, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, + 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, + 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, + 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, + 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, + 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x7B, 0x00, + 0x7C, 0x00, 0x7D, 0x00, 0x7E, 0x00, 0x7F, 0x00, + 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, + 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, + 0x88, 0x00, 0x89, 0x00, 0x8A, 0x00, 0x8B, 0x00, + 0x8C, 0x00, 0x8D, 0x00, 0x8E, 0x00, 0x8F, 0x00, + 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, + 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, + 0x98, 0x00, 0x99, 0x00, 0x9A, 0x00, 0x9B, 0x00, + 0x9C, 0x00, 0x9D, 0x00, 0x9E, 0x00, 0x9F, 0x00, + 0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, 0xA3, 0x00, + 0xA4, 0x00, 0xA5, 0x00, 0xA6, 0x00, 0xA7, 0x00, + 0xA8, 0x00, 0xA9, 0x00, 0xAA, 0x00, 0xAB, 0x00, + 0xAC, 0x00, 0xAD, 0x00, 0xAE, 0x00, 0xAF, 0x00, + 0xB0, 0x00, 0xB1, 0x00, 0xB2, 0x00, 0xB3, 0x00, + 0xB4, 0x00, 0xB5, 0x00, 0xB6, 0x00, 0xB7, 0x00, + 0xB8, 0x00, 0xB9, 0x00, 0xBA, 0x00, 0xBB, 0x00, + 0xBC, 0x00, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0x00, + 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, + 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, + 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, + 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, + 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, + 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xD7, 0x00, + 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, + 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0xDF, 0x00, + 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, + 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, + 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, + 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, + 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, + 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xF7, 0x00, + 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, + 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0x78, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x04, 0x01, 0x04, 0x01, 0x06, 0x01, 0x06, 0x01, + 0x08, 0x01, 0x08, 0x01, 0x0A, 0x01, 0x0A, 0x01, + 0x0C, 0x01, 0x0C, 0x01, 0x0E, 0x01, 0x0E, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x12, 0x01, 0x12, 0x01, + 0x14, 0x01, 0x14, 0x01, 0x16, 0x01, 0x16, 0x01, + 0x18, 0x01, 0x18, 0x01, 0x1A, 0x01, 0x1A, 0x01, + 0x1C, 0x01, 0x1C, 0x01, 0x1E, 0x01, 0x1E, 0x01, + 0x20, 0x01, 0x20, 0x01, 0x22, 0x01, 0x22, 0x01, + 0x24, 0x01, 0x24, 0x01, 0x26, 0x01, 0x26, 0x01, + 0x28, 0x01, 0x28, 0x01, 0x2A, 0x01, 0x2A, 0x01, + 0x2C, 0x01, 0x2C, 0x01, 0x2E, 0x01, 0x2E, 0x01, + 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x32, 0x01, + 0x34, 0x01, 0x34, 0x01, 0x36, 0x01, 0x36, 0x01, + 0x38, 0x01, 0x39, 0x01, 0x39, 0x01, 0x3B, 0x01, + 0x3B, 0x01, 0x3D, 0x01, 0x3D, 0x01, 0x3F, 0x01, + 0x3F, 0x01, 0x41, 0x01, 0x41, 0x01, 0x43, 0x01, + 0x43, 0x01, 0x45, 0x01, 0x45, 0x01, 0x47, 0x01, + 0x47, 0x01, 0x49, 0x01, 0x4A, 0x01, 0x4A, 0x01, + 0x4C, 0x01, 0x4C, 0x01, 0x4E, 0x01, 0x4E, 0x01, + 0x50, 0x01, 0x50, 0x01, 0x52, 0x01, 0x52, 0x01, + 0x54, 0x01, 0x54, 0x01, 0x56, 0x01, 0x56, 0x01, + 0x58, 0x01, 0x58, 0x01, 0x5A, 0x01, 0x5A, 0x01, + 0x5C, 0x01, 0x5C, 0x01, 0x5E, 0x01, 0x5E, 0x01, + 0x60, 0x01, 0x60, 0x01, 0x62, 0x01, 0x62, 0x01, + 0x64, 0x01, 0x64, 0x01, 0x66, 0x01, 0x66, 0x01, + 0x68, 0x01, 0x68, 0x01, 0x6A, 0x01, 0x6A, 0x01, + 0x6C, 0x01, 0x6C, 0x01, 0x6E, 0x01, 0x6E, 0x01, + 0x70, 0x01, 0x70, 0x01, 0x72, 0x01, 0x72, 0x01, + 0x74, 0x01, 0x74, 0x01, 0x76, 0x01, 0x76, 0x01, + 0x78, 0x01, 0x79, 0x01, 0x79, 0x01, 0x7B, 0x01, + 0x7B, 0x01, 0x7D, 0x01, 0x7D, 0x01, 0x7F, 0x01, + 0x43, 0x02, 0x81, 0x01, 0x82, 0x01, 0x82, 0x01, + 0x84, 0x01, 0x84, 0x01, 0x86, 0x01, 0x87, 0x01, + 0x87, 0x01, 0x89, 0x01, 0x8A, 0x01, 0x8B, 0x01, + 0x8B, 0x01, 0x8D, 0x01, 0x8E, 0x01, 0x8F, 0x01, + 0x90, 0x01, 0x91, 0x01, 0x91, 0x01, 0x93, 0x01, + 0x94, 0x01, 0xF6, 0x01, 0x96, 0x01, 0x97, 0x01, + 0x98, 0x01, 0x98, 0x01, 0x3D, 0x02, 0x9B, 0x01, + 0x9C, 0x01, 0x9D, 0x01, 0x20, 0x02, 0x9F, 0x01, + 0xA0, 0x01, 0xA0, 0x01, 0xA2, 0x01, 0xA2, 0x01, + 0xA4, 0x01, 0xA4, 0x01, 0xA6, 0x01, 0xA7, 0x01, + 0xA7, 0x01, 0xA9, 0x01, 0xAA, 0x01, 0xAB, 0x01, + 0xAC, 0x01, 0xAC, 0x01, 0xAE, 0x01, 0xAF, 0x01, + 0xAF, 0x01, 0xB1, 0x01, 0xB2, 0x01, 0xB3, 0x01, + 0xB3, 0x01, 0xB5, 0x01, 0xB5, 0x01, 0xB7, 0x01, + 0xB8, 0x01, 0xB8, 0x01, 0xBA, 0x01, 0xBB, 0x01, + 0xBC, 0x01, 0xBC, 0x01, 0xBE, 0x01, 0xF7, 0x01, + 0xC0, 0x01, 0xC1, 0x01, 0xC2, 0x01, 0xC3, 0x01, + 0xC4, 0x01, 0xC5, 0x01, 0xC4, 0x01, 0xC7, 0x01, + 0xC8, 0x01, 0xC7, 0x01, 0xCA, 0x01, 0xCB, 0x01, + 0xCA, 0x01, 0xCD, 0x01, 0xCD, 0x01, 0xCF, 0x01, + 0xCF, 0x01, 0xD1, 0x01, 0xD1, 0x01, 0xD3, 0x01, + 0xD3, 0x01, 0xD5, 0x01, 0xD5, 0x01, 0xD7, 0x01, + 0xD7, 0x01, 0xD9, 0x01, 0xD9, 0x01, 0xDB, 0x01, + 0xDB, 0x01, 0x8E, 0x01, 0xDE, 0x01, 0xDE, 0x01, + 0xE0, 0x01, 0xE0, 0x01, 0xE2, 0x01, 0xE2, 0x01, + 0xE4, 0x01, 0xE4, 0x01, 0xE6, 0x01, 0xE6, 0x01, + 0xE8, 0x01, 0xE8, 0x01, 0xEA, 0x01, 0xEA, 0x01, + 0xEC, 0x01, 0xEC, 0x01, 0xEE, 0x01, 0xEE, 0x01, + 0xF0, 0x01, 0xF1, 0x01, 0xF2, 0x01, 0xF1, 0x01, + 0xF4, 0x01, 0xF4, 0x01, 0xF6, 0x01, 0xF7, 0x01, + 0xF8, 0x01, 0xF8, 0x01, 0xFA, 0x01, 0xFA, 0x01, + 0xFC, 0x01, 0xFC, 0x01, 0xFE, 0x01, 0xFE, 0x01, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x04, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x02, + 0x08, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x0A, 0x02, + 0x0C, 0x02, 0x0C, 0x02, 0x0E, 0x02, 0x0E, 0x02, + 0x10, 0x02, 0x10, 0x02, 0x12, 0x02, 0x12, 0x02, + 0x14, 0x02, 0x14, 0x02, 0x16, 0x02, 0x16, 0x02, + 0x18, 0x02, 0x18, 0x02, 0x1A, 0x02, 0x1A, 0x02, + 0x1C, 0x02, 0x1C, 0x02, 0x1E, 0x02, 0x1E, 0x02, + 0x20, 0x02, 0x21, 0x02, 0x22, 0x02, 0x22, 0x02, + 0x24, 0x02, 0x24, 0x02, 0x26, 0x02, 0x26, 0x02, + 0x28, 0x02, 0x28, 0x02, 0x2A, 0x02, 0x2A, 0x02, + 0x2C, 0x02, 0x2C, 0x02, 0x2E, 0x02, 0x2E, 0x02, + 0x30, 0x02, 0x30, 0x02, 0x32, 0x02, 0x32, 0x02, + 0x34, 0x02, 0x35, 0x02, 0x36, 0x02, 0x37, 0x02, + 0x38, 0x02, 0x39, 0x02, 0x65, 0x2C, 0x3B, 0x02, + 0x3B, 0x02, 0x3D, 0x02, 0x66, 0x2C, 0x3F, 0x02, + 0x40, 0x02, 0x41, 0x02, 0x41, 0x02, 0x43, 0x02, + 0x44, 0x02, 0x45, 0x02, 0x46, 0x02, 0x46, 0x02, + 0x48, 0x02, 0x48, 0x02, 0x4A, 0x02, 0x4A, 0x02, + 0x4C, 0x02, 0x4C, 0x02, 0x4E, 0x02, 0x4E, 0x02, + 0x50, 0x02, 0x51, 0x02, 0x52, 0x02, 0x81, 0x01, + 0x86, 0x01, 0x55, 0x02, 0x89, 0x01, 0x8A, 0x01, + 0x58, 0x02, 0x8F, 0x01, 0x5A, 0x02, 0x90, 0x01, + 0x5C, 0x02, 0x5D, 0x02, 0x5E, 0x02, 0x5F, 0x02, + 0x93, 0x01, 0x61, 0x02, 0x62, 0x02, 0x94, 0x01, + 0x64, 0x02, 0x65, 0x02, 0x66, 0x02, 0x67, 0x02, + 0x97, 0x01, 0x96, 0x01, 0x6A, 0x02, 0x62, 0x2C, + 0x6C, 0x02, 0x6D, 0x02, 0x6E, 0x02, 0x9C, 0x01, + 0x70, 0x02, 0x71, 0x02, 0x9D, 0x01, 0x73, 0x02, + 0x74, 0x02, 0x9F, 0x01, 0x76, 0x02, 0x77, 0x02, + 0x78, 0x02, 0x79, 0x02, 0x7A, 0x02, 0x7B, 0x02, + 0x7C, 0x02, 0x64, 0x2C, 0x7E, 0x02, 0x7F, 0x02, + 0xA6, 0x01, 0x81, 0x02, 0x82, 0x02, 0xA9, 0x01, + 0x84, 0x02, 0x85, 0x02, 0x86, 0x02, 0x87, 0x02, + 0xAE, 0x01, 0x44, 0x02, 0xB1, 0x01, 0xB2, 0x01, + 0x45, 0x02, 0x8D, 0x02, 0x8E, 0x02, 0x8F, 0x02, + 0x90, 0x02, 0x91, 0x02, 0xB7, 0x01, 0x93, 0x02, + 0x94, 0x02, 0x95, 0x02, 0x96, 0x02, 0x97, 0x02, + 0x98, 0x02, 0x99, 0x02, 0x9A, 0x02, 0x9B, 0x02, + 0x9C, 0x02, 0x9D, 0x02, 0x9E, 0x02, 0x9F, 0x02, + 0xA0, 0x02, 0xA1, 0x02, 0xA2, 0x02, 0xA3, 0x02, + 0xA4, 0x02, 0xA5, 0x02, 0xA6, 0x02, 0xA7, 0x02, + 0xA8, 0x02, 0xA9, 0x02, 0xAA, 0x02, 0xAB, 0x02, + 0xAC, 0x02, 0xAD, 0x02, 0xAE, 0x02, 0xAF, 0x02, + 0xB0, 0x02, 0xB1, 0x02, 0xB2, 0x02, 0xB3, 0x02, + 0xB4, 0x02, 0xB5, 0x02, 0xB6, 0x02, 0xB7, 0x02, + 0xB8, 0x02, 0xB9, 0x02, 0xBA, 0x02, 0xBB, 0x02, + 0xBC, 0x02, 0xBD, 0x02, 0xBE, 0x02, 0xBF, 0x02, + 0xC0, 0x02, 0xC1, 0x02, 0xC2, 0x02, 0xC3, 0x02, + 0xC4, 0x02, 0xC5, 0x02, 0xC6, 0x02, 0xC7, 0x02, + 0xC8, 0x02, 0xC9, 0x02, 0xCA, 0x02, 0xCB, 0x02, + 0xCC, 0x02, 0xCD, 0x02, 0xCE, 0x02, 0xCF, 0x02, + 0xD0, 0x02, 0xD1, 0x02, 0xD2, 0x02, 0xD3, 0x02, + 0xD4, 0x02, 0xD5, 0x02, 0xD6, 0x02, 0xD7, 0x02, + 0xD8, 0x02, 0xD9, 0x02, 0xDA, 0x02, 0xDB, 0x02, + 0xDC, 0x02, 0xDD, 0x02, 0xDE, 0x02, 0xDF, 0x02, + 0xE0, 0x02, 0xE1, 0x02, 0xE2, 0x02, 0xE3, 0x02, + 0xE4, 0x02, 0xE5, 0x02, 0xE6, 0x02, 0xE7, 0x02, + 0xE8, 0x02, 0xE9, 0x02, 0xEA, 0x02, 0xEB, 0x02, + 0xEC, 0x02, 0xED, 0x02, 0xEE, 0x02, 0xEF, 0x02, + 0xF0, 0x02, 0xF1, 0x02, 0xF2, 0x02, 0xF3, 0x02, + 0xF4, 0x02, 0xF5, 0x02, 0xF6, 0x02, 0xF7, 0x02, + 0xF8, 0x02, 0xF9, 0x02, 0xFA, 0x02, 0xFB, 0x02, + 0xFC, 0x02, 0xFD, 0x02, 0xFE, 0x02, 0xFF, 0x02, + 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x03, + 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07, 0x03, + 0x08, 0x03, 0x09, 0x03, 0x0A, 0x03, 0x0B, 0x03, + 0x0C, 0x03, 0x0D, 0x03, 0x0E, 0x03, 0x0F, 0x03, + 0x10, 0x03, 0x11, 0x03, 0x12, 0x03, 0x13, 0x03, + 0x14, 0x03, 0x15, 0x03, 0x16, 0x03, 0x17, 0x03, + 0x18, 0x03, 0x19, 0x03, 0x1A, 0x03, 0x1B, 0x03, + 0x1C, 0x03, 0x1D, 0x03, 0x1E, 0x03, 0x1F, 0x03, + 0x20, 0x03, 0x21, 0x03, 0x22, 0x03, 0x23, 0x03, + 0x24, 0x03, 0x25, 0x03, 0x26, 0x03, 0x27, 0x03, + 0x28, 0x03, 0x29, 0x03, 0x2A, 0x03, 0x2B, 0x03, + 0x2C, 0x03, 0x2D, 0x03, 0x2E, 0x03, 0x2F, 0x03, + 0x30, 0x03, 0x31, 0x03, 0x32, 0x03, 0x33, 0x03, + 0x34, 0x03, 0x35, 0x03, 0x36, 0x03, 0x37, 0x03, + 0x38, 0x03, 0x39, 0x03, 0x3A, 0x03, 0x3B, 0x03, + 0x3C, 0x03, 0x3D, 0x03, 0x3E, 0x03, 0x3F, 0x03, + 0x40, 0x03, 0x41, 0x03, 0x42, 0x03, 0x43, 0x03, + 0x44, 0x03, 0x45, 0x03, 0x46, 0x03, 0x47, 0x03, + 0x48, 0x03, 0x49, 0x03, 0x4A, 0x03, 0x4B, 0x03, + 0x4C, 0x03, 0x4D, 0x03, 0x4E, 0x03, 0x4F, 0x03, + 0x50, 0x03, 0x51, 0x03, 0x52, 0x03, 0x53, 0x03, + 0x54, 0x03, 0x55, 0x03, 0x56, 0x03, 0x57, 0x03, + 0x58, 0x03, 0x59, 0x03, 0x5A, 0x03, 0x5B, 0x03, + 0x5C, 0x03, 0x5D, 0x03, 0x5E, 0x03, 0x5F, 0x03, + 0x60, 0x03, 0x61, 0x03, 0x62, 0x03, 0x63, 0x03, + 0x64, 0x03, 0x65, 0x03, 0x66, 0x03, 0x67, 0x03, + 0x68, 0x03, 0x69, 0x03, 0x6A, 0x03, 0x6B, 0x03, + 0x6C, 0x03, 0x6D, 0x03, 0x6E, 0x03, 0x6F, 0x03, + 0x70, 0x03, 0x71, 0x03, 0x72, 0x03, 0x73, 0x03, + 0x74, 0x03, 0x75, 0x03, 0x76, 0x03, 0x77, 0x03, + 0x78, 0x03, 0x79, 0x03, 0x7A, 0x03, 0xFD, 0x03, + 0xFE, 0x03, 0xFF, 0x03, 0x7E, 0x03, 0x7F, 0x03, + 0x80, 0x03, 0x81, 0x03, 0x82, 0x03, 0x83, 0x03, + 0x84, 0x03, 0x85, 0x03, 0x86, 0x03, 0x87, 0x03, + 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, 0x8B, 0x03, + 0x8C, 0x03, 0x8D, 0x03, 0x8E, 0x03, 0x8F, 0x03, + 0x90, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, + 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, + 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, + 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, + 0xA0, 0x03, 0xA1, 0x03, 0xA2, 0x03, 0xA3, 0x03, + 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, + 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, + 0x86, 0x03, 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, + 0xB0, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, + 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, + 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, + 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, + 0xA0, 0x03, 0xA1, 0x03, 0xA3, 0x03, 0xA3, 0x03, + 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, + 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, + 0x8C, 0x03, 0x8E, 0x03, 0x8F, 0x03, 0xCF, 0x03, + 0xD0, 0x03, 0xD1, 0x03, 0xD2, 0x03, 0xD3, 0x03, + 0xD4, 0x03, 0xD5, 0x03, 0xD6, 0x03, 0xD7, 0x03, + 0xD8, 0x03, 0xD8, 0x03, 0xDA, 0x03, 0xDA, 0x03, + 0xDC, 0x03, 0xDC, 0x03, 0xDE, 0x03, 0xDE, 0x03, + 0xE0, 0x03, 0xE0, 0x03, 0xE2, 0x03, 0xE2, 0x03, + 0xE4, 0x03, 0xE4, 0x03, 0xE6, 0x03, 0xE6, 0x03, + 0xE8, 0x03, 0xE8, 0x03, 0xEA, 0x03, 0xEA, 0x03, + 0xEC, 0x03, 0xEC, 0x03, 0xEE, 0x03, 0xEE, 0x03, + 0xF0, 0x03, 0xF1, 0x03, 0xF9, 0x03, 0xF3, 0x03, + 0xF4, 0x03, 0xF5, 0x03, 0xF6, 0x03, 0xF7, 0x03, + 0xF7, 0x03, 0xF9, 0x03, 0xFA, 0x03, 0xFA, 0x03, + 0xFC, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03, + 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, + 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, + 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, + 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, + 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, + 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, + 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, + 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, + 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, + 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, + 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, + 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, + 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, + 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, + 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, + 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, + 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, + 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, + 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, + 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, + 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, + 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, + 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, + 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, + 0x60, 0x04, 0x60, 0x04, 0x62, 0x04, 0x62, 0x04, + 0x64, 0x04, 0x64, 0x04, 0x66, 0x04, 0x66, 0x04, + 0x68, 0x04, 0x68, 0x04, 0x6A, 0x04, 0x6A, 0x04, + 0x6C, 0x04, 0x6C, 0x04, 0x6E, 0x04, 0x6E, 0x04, + 0x70, 0x04, 0x70, 0x04, 0x72, 0x04, 0x72, 0x04, + 0x74, 0x04, 0x74, 0x04, 0x76, 0x04, 0x76, 0x04, + 0x78, 0x04, 0x78, 0x04, 0x7A, 0x04, 0x7A, 0x04, + 0x7C, 0x04, 0x7C, 0x04, 0x7E, 0x04, 0x7E, 0x04, + 0x80, 0x04, 0x80, 0x04, 0x82, 0x04, 0x83, 0x04, + 0x84, 0x04, 0x85, 0x04, 0x86, 0x04, 0x87, 0x04, + 0x88, 0x04, 0x89, 0x04, 0x8A, 0x04, 0x8A, 0x04, + 0x8C, 0x04, 0x8C, 0x04, 0x8E, 0x04, 0x8E, 0x04, + 0x90, 0x04, 0x90, 0x04, 0x92, 0x04, 0x92, 0x04, + 0x94, 0x04, 0x94, 0x04, 0x96, 0x04, 0x96, 0x04, + 0x98, 0x04, 0x98, 0x04, 0x9A, 0x04, 0x9A, 0x04, + 0x9C, 0x04, 0x9C, 0x04, 0x9E, 0x04, 0x9E, 0x04, + 0xA0, 0x04, 0xA0, 0x04, 0xA2, 0x04, 0xA2, 0x04, + 0xA4, 0x04, 0xA4, 0x04, 0xA6, 0x04, 0xA6, 0x04, + 0xA8, 0x04, 0xA8, 0x04, 0xAA, 0x04, 0xAA, 0x04, + 0xAC, 0x04, 0xAC, 0x04, 0xAE, 0x04, 0xAE, 0x04, + 0xB0, 0x04, 0xB0, 0x04, 0xB2, 0x04, 0xB2, 0x04, + 0xB4, 0x04, 0xB4, 0x04, 0xB6, 0x04, 0xB6, 0x04, + 0xB8, 0x04, 0xB8, 0x04, 0xBA, 0x04, 0xBA, 0x04, + 0xBC, 0x04, 0xBC, 0x04, 0xBE, 0x04, 0xBE, 0x04, + 0xC0, 0x04, 0xC1, 0x04, 0xC1, 0x04, 0xC3, 0x04, + 0xC3, 0x04, 0xC5, 0x04, 0xC5, 0x04, 0xC7, 0x04, + 0xC7, 0x04, 0xC9, 0x04, 0xC9, 0x04, 0xCB, 0x04, + 0xCB, 0x04, 0xCD, 0x04, 0xCD, 0x04, 0xC0, 0x04, + 0xD0, 0x04, 0xD0, 0x04, 0xD2, 0x04, 0xD2, 0x04, + 0xD4, 0x04, 0xD4, 0x04, 0xD6, 0x04, 0xD6, 0x04, + 0xD8, 0x04, 0xD8, 0x04, 0xDA, 0x04, 0xDA, 0x04, + 0xDC, 0x04, 0xDC, 0x04, 0xDE, 0x04, 0xDE, 0x04, + 0xE0, 0x04, 0xE0, 0x04, 0xE2, 0x04, 0xE2, 0x04, + 0xE4, 0x04, 0xE4, 0x04, 0xE6, 0x04, 0xE6, 0x04, + 0xE8, 0x04, 0xE8, 0x04, 0xEA, 0x04, 0xEA, 0x04, + 0xEC, 0x04, 0xEC, 0x04, 0xEE, 0x04, 0xEE, 0x04, + 0xF0, 0x04, 0xF0, 0x04, 0xF2, 0x04, 0xF2, 0x04, + 0xF4, 0x04, 0xF4, 0x04, 0xF6, 0x04, 0xF6, 0x04, + 0xF8, 0x04, 0xF8, 0x04, 0xFA, 0x04, 0xFA, 0x04, + 0xFC, 0x04, 0xFC, 0x04, 0xFE, 0x04, 0xFE, 0x04, + 0x00, 0x05, 0x00, 0x05, 0x02, 0x05, 0x02, 0x05, + 0x04, 0x05, 0x04, 0x05, 0x06, 0x05, 0x06, 0x05, + 0x08, 0x05, 0x08, 0x05, 0x0A, 0x05, 0x0A, 0x05, + 0x0C, 0x05, 0x0C, 0x05, 0x0E, 0x05, 0x0E, 0x05, + 0x10, 0x05, 0x10, 0x05, 0x12, 0x05, 0x12, 0x05, + 0x14, 0x05, 0x15, 0x05, 0x16, 0x05, 0x17, 0x05, + 0x18, 0x05, 0x19, 0x05, 0x1A, 0x05, 0x1B, 0x05, + 0x1C, 0x05, 0x1D, 0x05, 0x1E, 0x05, 0x1F, 0x05, + 0x20, 0x05, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05, + 0x24, 0x05, 0x25, 0x05, 0x26, 0x05, 0x27, 0x05, + 0x28, 0x05, 0x29, 0x05, 0x2A, 0x05, 0x2B, 0x05, + 0x2C, 0x05, 0x2D, 0x05, 0x2E, 0x05, 0x2F, 0x05, + 0x30, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, + 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, + 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, + 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, + 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, + 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, + 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, + 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, + 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, + 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0x57, 0x05, + 0x58, 0x05, 0x59, 0x05, 0x5A, 0x05, 0x5B, 0x05, + 0x5C, 0x05, 0x5D, 0x05, 0x5E, 0x05, 0x5F, 0x05, + 0x60, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, + 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, + 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, + 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, + 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, + 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, + 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, + 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, + 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, + 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0xFF, 0xFF, + 0xF6, 0x17, 0x63, 0x2C, 0x7E, 0x1D, 0x7F, 0x1D, + 0x80, 0x1D, 0x81, 0x1D, 0x82, 0x1D, 0x83, 0x1D, + 0x84, 0x1D, 0x85, 0x1D, 0x86, 0x1D, 0x87, 0x1D, + 0x88, 0x1D, 0x89, 0x1D, 0x8A, 0x1D, 0x8B, 0x1D, + 0x8C, 0x1D, 0x8D, 0x1D, 0x8E, 0x1D, 0x8F, 0x1D, + 0x90, 0x1D, 0x91, 0x1D, 0x92, 0x1D, 0x93, 0x1D, + 0x94, 0x1D, 0x95, 0x1D, 0x96, 0x1D, 0x97, 0x1D, + 0x98, 0x1D, 0x99, 0x1D, 0x9A, 0x1D, 0x9B, 0x1D, + 0x9C, 0x1D, 0x9D, 0x1D, 0x9E, 0x1D, 0x9F, 0x1D, + 0xA0, 0x1D, 0xA1, 0x1D, 0xA2, 0x1D, 0xA3, 0x1D, + 0xA4, 0x1D, 0xA5, 0x1D, 0xA6, 0x1D, 0xA7, 0x1D, + 0xA8, 0x1D, 0xA9, 0x1D, 0xAA, 0x1D, 0xAB, 0x1D, + 0xAC, 0x1D, 0xAD, 0x1D, 0xAE, 0x1D, 0xAF, 0x1D, + 0xB0, 0x1D, 0xB1, 0x1D, 0xB2, 0x1D, 0xB3, 0x1D, + 0xB4, 0x1D, 0xB5, 0x1D, 0xB6, 0x1D, 0xB7, 0x1D, + 0xB8, 0x1D, 0xB9, 0x1D, 0xBA, 0x1D, 0xBB, 0x1D, + 0xBC, 0x1D, 0xBD, 0x1D, 0xBE, 0x1D, 0xBF, 0x1D, + 0xC0, 0x1D, 0xC1, 0x1D, 0xC2, 0x1D, 0xC3, 0x1D, + 0xC4, 0x1D, 0xC5, 0x1D, 0xC6, 0x1D, 0xC7, 0x1D, + 0xC8, 0x1D, 0xC9, 0x1D, 0xCA, 0x1D, 0xCB, 0x1D, + 0xCC, 0x1D, 0xCD, 0x1D, 0xCE, 0x1D, 0xCF, 0x1D, + 0xD0, 0x1D, 0xD1, 0x1D, 0xD2, 0x1D, 0xD3, 0x1D, + 0xD4, 0x1D, 0xD5, 0x1D, 0xD6, 0x1D, 0xD7, 0x1D, + 0xD8, 0x1D, 0xD9, 0x1D, 0xDA, 0x1D, 0xDB, 0x1D, + 0xDC, 0x1D, 0xDD, 0x1D, 0xDE, 0x1D, 0xDF, 0x1D, + 0xE0, 0x1D, 0xE1, 0x1D, 0xE2, 0x1D, 0xE3, 0x1D, + 0xE4, 0x1D, 0xE5, 0x1D, 0xE6, 0x1D, 0xE7, 0x1D, + 0xE8, 0x1D, 0xE9, 0x1D, 0xEA, 0x1D, 0xEB, 0x1D, + 0xEC, 0x1D, 0xED, 0x1D, 0xEE, 0x1D, 0xEF, 0x1D, + 0xF0, 0x1D, 0xF1, 0x1D, 0xF2, 0x1D, 0xF3, 0x1D, + 0xF4, 0x1D, 0xF5, 0x1D, 0xF6, 0x1D, 0xF7, 0x1D, + 0xF8, 0x1D, 0xF9, 0x1D, 0xFA, 0x1D, 0xFB, 0x1D, + 0xFC, 0x1D, 0xFD, 0x1D, 0xFE, 0x1D, 0xFF, 0x1D, + 0x00, 0x1E, 0x00, 0x1E, 0x02, 0x1E, 0x02, 0x1E, + 0x04, 0x1E, 0x04, 0x1E, 0x06, 0x1E, 0x06, 0x1E, + 0x08, 0x1E, 0x08, 0x1E, 0x0A, 0x1E, 0x0A, 0x1E, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0E, 0x1E, 0x0E, 0x1E, + 0x10, 0x1E, 0x10, 0x1E, 0x12, 0x1E, 0x12, 0x1E, + 0x14, 0x1E, 0x14, 0x1E, 0x16, 0x1E, 0x16, 0x1E, + 0x18, 0x1E, 0x18, 0x1E, 0x1A, 0x1E, 0x1A, 0x1E, + 0x1C, 0x1E, 0x1C, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x20, 0x1E, 0x20, 0x1E, 0x22, 0x1E, 0x22, 0x1E, + 0x24, 0x1E, 0x24, 0x1E, 0x26, 0x1E, 0x26, 0x1E, + 0x28, 0x1E, 0x28, 0x1E, 0x2A, 0x1E, 0x2A, 0x1E, + 0x2C, 0x1E, 0x2C, 0x1E, 0x2E, 0x1E, 0x2E, 0x1E, + 0x30, 0x1E, 0x30, 0x1E, 0x32, 0x1E, 0x32, 0x1E, + 0x34, 0x1E, 0x34, 0x1E, 0x36, 0x1E, 0x36, 0x1E, + 0x38, 0x1E, 0x38, 0x1E, 0x3A, 0x1E, 0x3A, 0x1E, + 0x3C, 0x1E, 0x3C, 0x1E, 0x3E, 0x1E, 0x3E, 0x1E, + 0x40, 0x1E, 0x40, 0x1E, 0x42, 0x1E, 0x42, 0x1E, + 0x44, 0x1E, 0x44, 0x1E, 0x46, 0x1E, 0x46, 0x1E, + 0x48, 0x1E, 0x48, 0x1E, 0x4A, 0x1E, 0x4A, 0x1E, + 0x4C, 0x1E, 0x4C, 0x1E, 0x4E, 0x1E, 0x4E, 0x1E, + 0x50, 0x1E, 0x50, 0x1E, 0x52, 0x1E, 0x52, 0x1E, + 0x54, 0x1E, 0x54, 0x1E, 0x56, 0x1E, 0x56, 0x1E, + 0x58, 0x1E, 0x58, 0x1E, 0x5A, 0x1E, 0x5A, 0x1E, + 0x5C, 0x1E, 0x5C, 0x1E, 0x5E, 0x1E, 0x5E, 0x1E, + 0x60, 0x1E, 0x60, 0x1E, 0x62, 0x1E, 0x62, 0x1E, + 0x64, 0x1E, 0x64, 0x1E, 0x66, 0x1E, 0x66, 0x1E, + 0x68, 0x1E, 0x68, 0x1E, 0x6A, 0x1E, 0x6A, 0x1E, + 0x6C, 0x1E, 0x6C, 0x1E, 0x6E, 0x1E, 0x6E, 0x1E, + 0x70, 0x1E, 0x70, 0x1E, 0x72, 0x1E, 0x72, 0x1E, + 0x74, 0x1E, 0x74, 0x1E, 0x76, 0x1E, 0x76, 0x1E, + 0x78, 0x1E, 0x78, 0x1E, 0x7A, 0x1E, 0x7A, 0x1E, + 0x7C, 0x1E, 0x7C, 0x1E, 0x7E, 0x1E, 0x7E, 0x1E, + 0x80, 0x1E, 0x80, 0x1E, 0x82, 0x1E, 0x82, 0x1E, + 0x84, 0x1E, 0x84, 0x1E, 0x86, 0x1E, 0x86, 0x1E, + 0x88, 0x1E, 0x88, 0x1E, 0x8A, 0x1E, 0x8A, 0x1E, + 0x8C, 0x1E, 0x8C, 0x1E, 0x8E, 0x1E, 0x8E, 0x1E, + 0x90, 0x1E, 0x90, 0x1E, 0x92, 0x1E, 0x92, 0x1E, + 0x94, 0x1E, 0x94, 0x1E, 0x96, 0x1E, 0x97, 0x1E, + 0x98, 0x1E, 0x99, 0x1E, 0x9A, 0x1E, 0x9B, 0x1E, + 0x9C, 0x1E, 0x9D, 0x1E, 0x9E, 0x1E, 0x9F, 0x1E, + 0xA0, 0x1E, 0xA0, 0x1E, 0xA2, 0x1E, 0xA2, 0x1E, + 0xA4, 0x1E, 0xA4, 0x1E, 0xA6, 0x1E, 0xA6, 0x1E, + 0xA8, 0x1E, 0xA8, 0x1E, 0xAA, 0x1E, 0xAA, 0x1E, + 0xAC, 0x1E, 0xAC, 0x1E, 0xAE, 0x1E, 0xAE, 0x1E, + 0xB0, 0x1E, 0xB0, 0x1E, 0xB2, 0x1E, 0xB2, 0x1E, + 0xB4, 0x1E, 0xB4, 0x1E, 0xB6, 0x1E, 0xB6, 0x1E, + 0xB8, 0x1E, 0xB8, 0x1E, 0xBA, 0x1E, 0xBA, 0x1E, + 0xBC, 0x1E, 0xBC, 0x1E, 0xBE, 0x1E, 0xBE, 0x1E, + 0xC0, 0x1E, 0xC0, 0x1E, 0xC2, 0x1E, 0xC2, 0x1E, + 0xC4, 0x1E, 0xC4, 0x1E, 0xC6, 0x1E, 0xC6, 0x1E, + 0xC8, 0x1E, 0xC8, 0x1E, 0xCA, 0x1E, 0xCA, 0x1E, + 0xCC, 0x1E, 0xCC, 0x1E, 0xCE, 0x1E, 0xCE, 0x1E, + 0xD0, 0x1E, 0xD0, 0x1E, 0xD2, 0x1E, 0xD2, 0x1E, + 0xD4, 0x1E, 0xD4, 0x1E, 0xD6, 0x1E, 0xD6, 0x1E, + 0xD8, 0x1E, 0xD8, 0x1E, 0xDA, 0x1E, 0xDA, 0x1E, + 0xDC, 0x1E, 0xDC, 0x1E, 0xDE, 0x1E, 0xDE, 0x1E, + 0xE0, 0x1E, 0xE0, 0x1E, 0xE2, 0x1E, 0xE2, 0x1E, + 0xE4, 0x1E, 0xE4, 0x1E, 0xE6, 0x1E, 0xE6, 0x1E, + 0xE8, 0x1E, 0xE8, 0x1E, 0xEA, 0x1E, 0xEA, 0x1E, + 0xEC, 0x1E, 0xEC, 0x1E, 0xEE, 0x1E, 0xEE, 0x1E, + 0xF0, 0x1E, 0xF0, 0x1E, 0xF2, 0x1E, 0xF2, 0x1E, + 0xF4, 0x1E, 0xF4, 0x1E, 0xF6, 0x1E, 0xF6, 0x1E, + 0xF8, 0x1E, 0xF8, 0x1E, 0xFA, 0x1E, 0xFB, 0x1E, + 0xFC, 0x1E, 0xFD, 0x1E, 0xFE, 0x1E, 0xFF, 0x1E, + 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, + 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, + 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, + 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, + 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, + 0x1C, 0x1F, 0x1D, 0x1F, 0x16, 0x1F, 0x17, 0x1F, + 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, + 0x1C, 0x1F, 0x1D, 0x1F, 0x1E, 0x1F, 0x1F, 0x1F, + 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, + 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, + 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, + 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, + 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, + 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, + 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, + 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, + 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, + 0x4C, 0x1F, 0x4D, 0x1F, 0x46, 0x1F, 0x47, 0x1F, + 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, + 0x4C, 0x1F, 0x4D, 0x1F, 0x4E, 0x1F, 0x4F, 0x1F, + 0x50, 0x1F, 0x59, 0x1F, 0x52, 0x1F, 0x5B, 0x1F, + 0x54, 0x1F, 0x5D, 0x1F, 0x56, 0x1F, 0x5F, 0x1F, + 0x58, 0x1F, 0x59, 0x1F, 0x5A, 0x1F, 0x5B, 0x1F, + 0x5C, 0x1F, 0x5D, 0x1F, 0x5E, 0x1F, 0x5F, 0x1F, + 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, + 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, + 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, + 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, + 0xBA, 0x1F, 0xBB, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F, + 0xCA, 0x1F, 0xCB, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, + 0xF8, 0x1F, 0xF9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, + 0xFA, 0x1F, 0xFB, 0x1F, 0x7E, 0x1F, 0x7F, 0x1F, + 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, + 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, + 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, + 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, + 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, + 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, + 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, + 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, + 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, + 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, + 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, + 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, + 0xB8, 0x1F, 0xB9, 0x1F, 0xB2, 0x1F, 0xBC, 0x1F, + 0xB4, 0x1F, 0xB5, 0x1F, 0xB6, 0x1F, 0xB7, 0x1F, + 0xB8, 0x1F, 0xB9, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F, + 0xBC, 0x1F, 0xBD, 0x1F, 0xBE, 0x1F, 0xBF, 0x1F, + 0xC0, 0x1F, 0xC1, 0x1F, 0xC2, 0x1F, 0xC3, 0x1F, + 0xC4, 0x1F, 0xC5, 0x1F, 0xC6, 0x1F, 0xC7, 0x1F, + 0xC8, 0x1F, 0xC9, 0x1F, 0xCA, 0x1F, 0xCB, 0x1F, + 0xC3, 0x1F, 0xCD, 0x1F, 0xCE, 0x1F, 0xCF, 0x1F, + 0xD8, 0x1F, 0xD9, 0x1F, 0xD2, 0x1F, 0xD3, 0x1F, + 0xD4, 0x1F, 0xD5, 0x1F, 0xD6, 0x1F, 0xD7, 0x1F, + 0xD8, 0x1F, 0xD9, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, + 0xDC, 0x1F, 0xDD, 0x1F, 0xDE, 0x1F, 0xDF, 0x1F, + 0xE8, 0x1F, 0xE9, 0x1F, 0xE2, 0x1F, 0xE3, 0x1F, + 0xE4, 0x1F, 0xEC, 0x1F, 0xE6, 0x1F, 0xE7, 0x1F, + 0xE8, 0x1F, 0xE9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, + 0xEC, 0x1F, 0xED, 0x1F, 0xEE, 0x1F, 0xEF, 0x1F, + 0xF0, 0x1F, 0xF1, 0x1F, 0xF2, 0x1F, 0xF3, 0x1F, + 0xF4, 0x1F, 0xF5, 0x1F, 0xF6, 0x1F, 0xF7, 0x1F, + 0xF8, 0x1F, 0xF9, 0x1F, 0xFA, 0x1F, 0xFB, 0x1F, + 0xF3, 0x1F, 0xFD, 0x1F, 0xFE, 0x1F, 0xFF, 0x1F, + 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x20, + 0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x20, + 0x08, 0x20, 0x09, 0x20, 0x0A, 0x20, 0x0B, 0x20, + 0x0C, 0x20, 0x0D, 0x20, 0x0E, 0x20, 0x0F, 0x20, + 0x10, 0x20, 0x11, 0x20, 0x12, 0x20, 0x13, 0x20, + 0x14, 0x20, 0x15, 0x20, 0x16, 0x20, 0x17, 0x20, + 0x18, 0x20, 0x19, 0x20, 0x1A, 0x20, 0x1B, 0x20, + 0x1C, 0x20, 0x1D, 0x20, 0x1E, 0x20, 0x1F, 0x20, + 0x20, 0x20, 0x21, 0x20, 0x22, 0x20, 0x23, 0x20, + 0x24, 0x20, 0x25, 0x20, 0x26, 0x20, 0x27, 0x20, + 0x28, 0x20, 0x29, 0x20, 0x2A, 0x20, 0x2B, 0x20, + 0x2C, 0x20, 0x2D, 0x20, 0x2E, 0x20, 0x2F, 0x20, + 0x30, 0x20, 0x31, 0x20, 0x32, 0x20, 0x33, 0x20, + 0x34, 0x20, 0x35, 0x20, 0x36, 0x20, 0x37, 0x20, + 0x38, 0x20, 0x39, 0x20, 0x3A, 0x20, 0x3B, 0x20, + 0x3C, 0x20, 0x3D, 0x20, 0x3E, 0x20, 0x3F, 0x20, + 0x40, 0x20, 0x41, 0x20, 0x42, 0x20, 0x43, 0x20, + 0x44, 0x20, 0x45, 0x20, 0x46, 0x20, 0x47, 0x20, + 0x48, 0x20, 0x49, 0x20, 0x4A, 0x20, 0x4B, 0x20, + 0x4C, 0x20, 0x4D, 0x20, 0x4E, 0x20, 0x4F, 0x20, + 0x50, 0x20, 0x51, 0x20, 0x52, 0x20, 0x53, 0x20, + 0x54, 0x20, 0x55, 0x20, 0x56, 0x20, 0x57, 0x20, + 0x58, 0x20, 0x59, 0x20, 0x5A, 0x20, 0x5B, 0x20, + 0x5C, 0x20, 0x5D, 0x20, 0x5E, 0x20, 0x5F, 0x20, + 0x60, 0x20, 0x61, 0x20, 0x62, 0x20, 0x63, 0x20, + 0x64, 0x20, 0x65, 0x20, 0x66, 0x20, 0x67, 0x20, + 0x68, 0x20, 0x69, 0x20, 0x6A, 0x20, 0x6B, 0x20, + 0x6C, 0x20, 0x6D, 0x20, 0x6E, 0x20, 0x6F, 0x20, + 0x70, 0x20, 0x71, 0x20, 0x72, 0x20, 0x73, 0x20, + 0x74, 0x20, 0x75, 0x20, 0x76, 0x20, 0x77, 0x20, + 0x78, 0x20, 0x79, 0x20, 0x7A, 0x20, 0x7B, 0x20, + 0x7C, 0x20, 0x7D, 0x20, 0x7E, 0x20, 0x7F, 0x20, + 0x80, 0x20, 0x81, 0x20, 0x82, 0x20, 0x83, 0x20, + 0x84, 0x20, 0x85, 0x20, 0x86, 0x20, 0x87, 0x20, + 0x88, 0x20, 0x89, 0x20, 0x8A, 0x20, 0x8B, 0x20, + 0x8C, 0x20, 0x8D, 0x20, 0x8E, 0x20, 0x8F, 0x20, + 0x90, 0x20, 0x91, 0x20, 0x92, 0x20, 0x93, 0x20, + 0x94, 0x20, 0x95, 0x20, 0x96, 0x20, 0x97, 0x20, + 0x98, 0x20, 0x99, 0x20, 0x9A, 0x20, 0x9B, 0x20, + 0x9C, 0x20, 0x9D, 0x20, 0x9E, 0x20, 0x9F, 0x20, + 0xA0, 0x20, 0xA1, 0x20, 0xA2, 0x20, 0xA3, 0x20, + 0xA4, 0x20, 0xA5, 0x20, 0xA6, 0x20, 0xA7, 0x20, + 0xA8, 0x20, 0xA9, 0x20, 0xAA, 0x20, 0xAB, 0x20, + 0xAC, 0x20, 0xAD, 0x20, 0xAE, 0x20, 0xAF, 0x20, + 0xB0, 0x20, 0xB1, 0x20, 0xB2, 0x20, 0xB3, 0x20, + 0xB4, 0x20, 0xB5, 0x20, 0xB6, 0x20, 0xB7, 0x20, + 0xB8, 0x20, 0xB9, 0x20, 0xBA, 0x20, 0xBB, 0x20, + 0xBC, 0x20, 0xBD, 0x20, 0xBE, 0x20, 0xBF, 0x20, + 0xC0, 0x20, 0xC1, 0x20, 0xC2, 0x20, 0xC3, 0x20, + 0xC4, 0x20, 0xC5, 0x20, 0xC6, 0x20, 0xC7, 0x20, + 0xC8, 0x20, 0xC9, 0x20, 0xCA, 0x20, 0xCB, 0x20, + 0xCC, 0x20, 0xCD, 0x20, 0xCE, 0x20, 0xCF, 0x20, + 0xD0, 0x20, 0xD1, 0x20, 0xD2, 0x20, 0xD3, 0x20, + 0xD4, 0x20, 0xD5, 0x20, 0xD6, 0x20, 0xD7, 0x20, + 0xD8, 0x20, 0xD9, 0x20, 0xDA, 0x20, 0xDB, 0x20, + 0xDC, 0x20, 0xDD, 0x20, 0xDE, 0x20, 0xDF, 0x20, + 0xE0, 0x20, 0xE1, 0x20, 0xE2, 0x20, 0xE3, 0x20, + 0xE4, 0x20, 0xE5, 0x20, 0xE6, 0x20, 0xE7, 0x20, + 0xE8, 0x20, 0xE9, 0x20, 0xEA, 0x20, 0xEB, 0x20, + 0xEC, 0x20, 0xED, 0x20, 0xEE, 0x20, 0xEF, 0x20, + 0xF0, 0x20, 0xF1, 0x20, 0xF2, 0x20, 0xF3, 0x20, + 0xF4, 0x20, 0xF5, 0x20, 0xF6, 0x20, 0xF7, 0x20, + 0xF8, 0x20, 0xF9, 0x20, 0xFA, 0x20, 0xFB, 0x20, + 0xFC, 0x20, 0xFD, 0x20, 0xFE, 0x20, 0xFF, 0x20, + 0x00, 0x21, 0x01, 0x21, 0x02, 0x21, 0x03, 0x21, + 0x04, 0x21, 0x05, 0x21, 0x06, 0x21, 0x07, 0x21, + 0x08, 0x21, 0x09, 0x21, 0x0A, 0x21, 0x0B, 0x21, + 0x0C, 0x21, 0x0D, 0x21, 0x0E, 0x21, 0x0F, 0x21, + 0x10, 0x21, 0x11, 0x21, 0x12, 0x21, 0x13, 0x21, + 0x14, 0x21, 0x15, 0x21, 0x16, 0x21, 0x17, 0x21, + 0x18, 0x21, 0x19, 0x21, 0x1A, 0x21, 0x1B, 0x21, + 0x1C, 0x21, 0x1D, 0x21, 0x1E, 0x21, 0x1F, 0x21, + 0x20, 0x21, 0x21, 0x21, 0x22, 0x21, 0x23, 0x21, + 0x24, 0x21, 0x25, 0x21, 0x26, 0x21, 0x27, 0x21, + 0x28, 0x21, 0x29, 0x21, 0x2A, 0x21, 0x2B, 0x21, + 0x2C, 0x21, 0x2D, 0x21, 0x2E, 0x21, 0x2F, 0x21, + 0x30, 0x21, 0x31, 0x21, 0x32, 0x21, 0x33, 0x21, + 0x34, 0x21, 0x35, 0x21, 0x36, 0x21, 0x37, 0x21, + 0x38, 0x21, 0x39, 0x21, 0x3A, 0x21, 0x3B, 0x21, + 0x3C, 0x21, 0x3D, 0x21, 0x3E, 0x21, 0x3F, 0x21, + 0x40, 0x21, 0x41, 0x21, 0x42, 0x21, 0x43, 0x21, + 0x44, 0x21, 0x45, 0x21, 0x46, 0x21, 0x47, 0x21, + 0x48, 0x21, 0x49, 0x21, 0x4A, 0x21, 0x4B, 0x21, + 0x4C, 0x21, 0x4D, 0x21, 0x32, 0x21, 0x4F, 0x21, + 0x50, 0x21, 0x51, 0x21, 0x52, 0x21, 0x53, 0x21, + 0x54, 0x21, 0x55, 0x21, 0x56, 0x21, 0x57, 0x21, + 0x58, 0x21, 0x59, 0x21, 0x5A, 0x21, 0x5B, 0x21, + 0x5C, 0x21, 0x5D, 0x21, 0x5E, 0x21, 0x5F, 0x21, + 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, + 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, + 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, + 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, + 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, + 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, + 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, + 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, + 0x80, 0x21, 0x81, 0x21, 0x82, 0x21, 0x83, 0x21, + 0x83, 0x21, 0xFF, 0xFF, 0x4B, 0x03, 0xB6, 0x24, + 0xB7, 0x24, 0xB8, 0x24, 0xB9, 0x24, 0xBA, 0x24, + 0xBB, 0x24, 0xBC, 0x24, 0xBD, 0x24, 0xBE, 0x24, + 0xBF, 0x24, 0xC0, 0x24, 0xC1, 0x24, 0xC2, 0x24, + 0xC3, 0x24, 0xC4, 0x24, 0xC5, 0x24, 0xC6, 0x24, + 0xC7, 0x24, 0xC8, 0x24, 0xC9, 0x24, 0xCA, 0x24, + 0xCB, 0x24, 0xCC, 0x24, 0xCD, 0x24, 0xCE, 0x24, + 0xCF, 0x24, 0xFF, 0xFF, 0x46, 0x07, 0x00, 0x2C, + 0x01, 0x2C, 0x02, 0x2C, 0x03, 0x2C, 0x04, 0x2C, + 0x05, 0x2C, 0x06, 0x2C, 0x07, 0x2C, 0x08, 0x2C, + 0x09, 0x2C, 0x0A, 0x2C, 0x0B, 0x2C, 0x0C, 0x2C, + 0x0D, 0x2C, 0x0E, 0x2C, 0x0F, 0x2C, 0x10, 0x2C, + 0x11, 0x2C, 0x12, 0x2C, 0x13, 0x2C, 0x14, 0x2C, + 0x15, 0x2C, 0x16, 0x2C, 0x17, 0x2C, 0x18, 0x2C, + 0x19, 0x2C, 0x1A, 0x2C, 0x1B, 0x2C, 0x1C, 0x2C, + 0x1D, 0x2C, 0x1E, 0x2C, 0x1F, 0x2C, 0x20, 0x2C, + 0x21, 0x2C, 0x22, 0x2C, 0x23, 0x2C, 0x24, 0x2C, + 0x25, 0x2C, 0x26, 0x2C, 0x27, 0x2C, 0x28, 0x2C, + 0x29, 0x2C, 0x2A, 0x2C, 0x2B, 0x2C, 0x2C, 0x2C, + 0x2D, 0x2C, 0x2E, 0x2C, 0x5F, 0x2C, 0x60, 0x2C, + 0x60, 0x2C, 0x62, 0x2C, 0x63, 0x2C, 0x64, 0x2C, + 0x65, 0x2C, 0x66, 0x2C, 0x67, 0x2C, 0x67, 0x2C, + 0x69, 0x2C, 0x69, 0x2C, 0x6B, 0x2C, 0x6B, 0x2C, + 0x6D, 0x2C, 0x6E, 0x2C, 0x6F, 0x2C, 0x70, 0x2C, + 0x71, 0x2C, 0x72, 0x2C, 0x73, 0x2C, 0x74, 0x2C, + 0x75, 0x2C, 0x75, 0x2C, 0x77, 0x2C, 0x78, 0x2C, + 0x79, 0x2C, 0x7A, 0x2C, 0x7B, 0x2C, 0x7C, 0x2C, + 0x7D, 0x2C, 0x7E, 0x2C, 0x7F, 0x2C, 0x80, 0x2C, + 0x80, 0x2C, 0x82, 0x2C, 0x82, 0x2C, 0x84, 0x2C, + 0x84, 0x2C, 0x86, 0x2C, 0x86, 0x2C, 0x88, 0x2C, + 0x88, 0x2C, 0x8A, 0x2C, 0x8A, 0x2C, 0x8C, 0x2C, + 0x8C, 0x2C, 0x8E, 0x2C, 0x8E, 0x2C, 0x90, 0x2C, + 0x90, 0x2C, 0x92, 0x2C, 0x92, 0x2C, 0x94, 0x2C, + 0x94, 0x2C, 0x96, 0x2C, 0x96, 0x2C, 0x98, 0x2C, + 0x98, 0x2C, 0x9A, 0x2C, 0x9A, 0x2C, 0x9C, 0x2C, + 0x9C, 0x2C, 0x9E, 0x2C, 0x9E, 0x2C, 0xA0, 0x2C, + 0xA0, 0x2C, 0xA2, 0x2C, 0xA2, 0x2C, 0xA4, 0x2C, + 0xA4, 0x2C, 0xA6, 0x2C, 0xA6, 0x2C, 0xA8, 0x2C, + 0xA8, 0x2C, 0xAA, 0x2C, 0xAA, 0x2C, 0xAC, 0x2C, + 0xAC, 0x2C, 0xAE, 0x2C, 0xAE, 0x2C, 0xB0, 0x2C, + 0xB0, 0x2C, 0xB2, 0x2C, 0xB2, 0x2C, 0xB4, 0x2C, + 0xB4, 0x2C, 0xB6, 0x2C, 0xB6, 0x2C, 0xB8, 0x2C, + 0xB8, 0x2C, 0xBA, 0x2C, 0xBA, 0x2C, 0xBC, 0x2C, + 0xBC, 0x2C, 0xBE, 0x2C, 0xBE, 0x2C, 0xC0, 0x2C, + 0xC0, 0x2C, 0xC2, 0x2C, 0xC2, 0x2C, 0xC4, 0x2C, + 0xC4, 0x2C, 0xC6, 0x2C, 0xC6, 0x2C, 0xC8, 0x2C, + 0xC8, 0x2C, 0xCA, 0x2C, 0xCA, 0x2C, 0xCC, 0x2C, + 0xCC, 0x2C, 0xCE, 0x2C, 0xCE, 0x2C, 0xD0, 0x2C, + 0xD0, 0x2C, 0xD2, 0x2C, 0xD2, 0x2C, 0xD4, 0x2C, + 0xD4, 0x2C, 0xD6, 0x2C, 0xD6, 0x2C, 0xD8, 0x2C, + 0xD8, 0x2C, 0xDA, 0x2C, 0xDA, 0x2C, 0xDC, 0x2C, + 0xDC, 0x2C, 0xDE, 0x2C, 0xDE, 0x2C, 0xE0, 0x2C, + 0xE0, 0x2C, 0xE2, 0x2C, 0xE2, 0x2C, 0xE4, 0x2C, + 0xE5, 0x2C, 0xE6, 0x2C, 0xE7, 0x2C, 0xE8, 0x2C, + 0xE9, 0x2C, 0xEA, 0x2C, 0xEB, 0x2C, 0xEC, 0x2C, + 0xED, 0x2C, 0xEE, 0x2C, 0xEF, 0x2C, 0xF0, 0x2C, + 0xF1, 0x2C, 0xF2, 0x2C, 0xF3, 0x2C, 0xF4, 0x2C, + 0xF5, 0x2C, 0xF6, 0x2C, 0xF7, 0x2C, 0xF8, 0x2C, + 0xF9, 0x2C, 0xFA, 0x2C, 0xFB, 0x2C, 0xFC, 0x2C, + 0xFD, 0x2C, 0xFE, 0x2C, 0xFF, 0x2C, 0xA0, 0x10, + 0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, + 0xA5, 0x10, 0xA6, 0x10, 0xA7, 0x10, 0xA8, 0x10, + 0xA9, 0x10, 0xAA, 0x10, 0xAB, 0x10, 0xAC, 0x10, + 0xAD, 0x10, 0xAE, 0x10, 0xAF, 0x10, 0xB0, 0x10, + 0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10, + 0xB5, 0x10, 0xB6, 0x10, 0xB7, 0x10, 0xB8, 0x10, + 0xB9, 0x10, 0xBA, 0x10, 0xBB, 0x10, 0xBC, 0x10, + 0xBD, 0x10, 0xBE, 0x10, 0xBF, 0x10, 0xC0, 0x10, + 0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, + 0xC5, 0x10, 0xFF, 0xFF, 0x1B, 0xD2, 0x21, 0xFF, + 0x22, 0xFF, 0x23, 0xFF, 0x24, 0xFF, 0x25, 0xFF, + 0x26, 0xFF, 0x27, 0xFF, 0x28, 0xFF, 0x29, 0xFF, + 0x2A, 0xFF, 0x2B, 0xFF, 0x2C, 0xFF, 0x2D, 0xFF, + 0x2E, 0xFF, 0x2F, 0xFF, 0x30, 0xFF, 0x31, 0xFF, + 0x32, 0xFF, 0x33, 0xFF, 0x34, 0xFF, 0x35, 0xFF, + 0x36, 0xFF, 0x37, 0xFF, 0x38, 0xFF, 0x39, 0xFF, + 0x3A, 0xFF, 0x5B, 0xFF, 0x5C, 0xFF, 0x5D, 0xFF, + 0x5E, 0xFF, 0x5F, 0xFF, 0x60, 0xFF, 0x61, 0xFF, + 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, + 0x66, 0xFF, 0x67, 0xFF, 0x68, 0xFF, 0x69, 0xFF, + 0x6A, 0xFF, 0x6B, 0xFF, 0x6C, 0xFF, 0x6D, 0xFF, + 0x6E, 0xFF, 0x6F, 0xFF, 0x70, 0xFF, 0x71, 0xFF, + 0x72, 0xFF, 0x73, 0xFF, 0x74, 0xFF, 0x75, 0xFF, + 0x76, 0xFF, 0x77, 0xFF, 0x78, 0xFF, 0x79, 0xFF, + 0x7A, 0xFF, 0x7B, 0xFF, 0x7C, 0xFF, 0x7D, 0xFF, + 0x7E, 0xFF, 0x7F, 0xFF, 0x80, 0xFF, 0x81, 0xFF, + 0x82, 0xFF, 0x83, 0xFF, 0x84, 0xFF, 0x85, 0xFF, + 0x86, 0xFF, 0x87, 0xFF, 0x88, 0xFF, 0x89, 0xFF, + 0x8A, 0xFF, 0x8B, 0xFF, 0x8C, 0xFF, 0x8D, 0xFF, + 0x8E, 0xFF, 0x8F, 0xFF, 0x90, 0xFF, 0x91, 0xFF, + 0x92, 0xFF, 0x93, 0xFF, 0x94, 0xFF, 0x95, 0xFF, + 0x96, 0xFF, 0x97, 0xFF, 0x98, 0xFF, 0x99, 0xFF, + 0x9A, 0xFF, 0x9B, 0xFF, 0x9C, 0xFF, 0x9D, 0xFF, + 0x9E, 0xFF, 0x9F, 0xFF, 0xA0, 0xFF, 0xA1, 0xFF, + 0xA2, 0xFF, 0xA3, 0xFF, 0xA4, 0xFF, 0xA5, 0xFF, + 0xA6, 0xFF, 0xA7, 0xFF, 0xA8, 0xFF, 0xA9, 0xFF, + 0xAA, 0xFF, 0xAB, 0xFF, 0xAC, 0xFF, 0xAD, 0xFF, + 0xAE, 0xFF, 0xAF, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, + 0xB2, 0xFF, 0xB3, 0xFF, 0xB4, 0xFF, 0xB5, 0xFF, + 0xB6, 0xFF, 0xB7, 0xFF, 0xB8, 0xFF, 0xB9, 0xFF, + 0xBA, 0xFF, 0xBB, 0xFF, 0xBC, 0xFF, 0xBD, 0xFF, + 0xBE, 0xFF, 0xBF, 0xFF, 0xC0, 0xFF, 0xC1, 0xFF, + 0xC2, 0xFF, 0xC3, 0xFF, 0xC4, 0xFF, 0xC5, 0xFF, + 0xC6, 0xFF, 0xC7, 0xFF, 0xC8, 0xFF, 0xC9, 0xFF, + 0xCA, 0xFF, 0xCB, 0xFF, 0xCC, 0xFF, 0xCD, 0xFF, + 0xCE, 0xFF, 0xCF, 0xFF, 0xD0, 0xFF, 0xD1, 0xFF, + 0xD2, 0xFF, 0xD3, 0xFF, 0xD4, 0xFF, 0xD5, 0xFF, + 0xD6, 0xFF, 0xD7, 0xFF, 0xD8, 0xFF, 0xD9, 0xFF, + 0xDA, 0xFF, 0xDB, 0xFF, 0xDC, 0xFF, 0xDD, 0xFF, + 0xDE, 0xFF, 0xDF, 0xFF, 0xE0, 0xFF, 0xE1, 0xFF, + 0xE2, 0xFF, 0xE3, 0xFF, 0xE4, 0xFF, 0xE5, 0xFF, + 0xE6, 0xFF, 0xE7, 0xFF, 0xE8, 0xFF, 0xE9, 0xFF, + 0xEA, 0xFF, 0xEB, 0xFF, 0xEC, 0xFF, 0xED, 0xFF, + 0xEE, 0xFF, 0xEF, 0xFF, 0xF0, 0xFF, 0xF1, 0xFF, + 0xF2, 0xFF, 0xF3, 0xFF, 0xF4, 0xFF, 0xF5, 0xFF, + 0xF6, 0xFF, 0xF7, 0xFF, 0xF8, 0xFF, 0xF9, 0xFF, + 0xFA, 0xFF, 0xFB, 0xFF, 0xFC, 0xFF, 0xFD, 0xFF, + 0xFE, 0xFF, 0xFF, 0xFF +}; diff --git a/drivers/staging/fbtft/fb_hx8340bn.c b/drivers/staging/fbtft/fb_hx8340bn.c index d47dcf31fffb..2fd7b87ea0ce 100644 --- a/drivers/staging/fbtft/fb_hx8340bn.c +++ b/drivers/staging/fbtft/fb_hx8340bn.c @@ -151,7 +151,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x0f, 0x0f, 0x1f, 0x0f, 0x0f, 0x0f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x0f, 0x0f, 0x1f, 0x0f, 0x0f, 0x0f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, diff --git a/drivers/staging/fbtft/fb_hx8347d.c b/drivers/staging/fbtft/fb_hx8347d.c index 3427a858d17c..37eaf0862c5b 100644 --- a/drivers/staging/fbtft/fb_hx8347d.c +++ b/drivers/staging/fbtft/fb_hx8347d.c @@ -95,7 +95,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x0f, }; diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c index fd32376700e2..05648c3ffe47 100644 --- a/drivers/staging/fbtft/fb_ili9163.c +++ b/drivers/staging/fbtft/fb_ili9163.c @@ -195,7 +195,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int gamma_adj(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1f, 0x3f, 0x0f, 0x0f, 0x7f, 0x1f, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F}; diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c index ea6e001288ce..f2e72d14431d 100644 --- a/drivers/staging/fbtft/fb_ili9320.c +++ b/drivers/staging/fbtft/fb_ili9320.c @@ -214,7 +214,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, }; diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c index 85e54a10ed72..c9aa4cb43123 100644 --- a/drivers/staging/fbtft/fb_ili9325.c +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -208,7 +208,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, }; diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c index ad49973ad594..08f8a4bb8772 100644 --- a/drivers/staging/fbtft/fb_pcd8544.c +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -157,10 +157,10 @@ static struct fbtft_display display = { .backlight = 1, }; -FBTFT_REGISTER_DRIVER(DRVNAME, "philips,pdc8544", &display); +FBTFT_REGISTER_DRIVER(DRVNAME, "philips,pcd8544", &display); MODULE_ALIAS("spi:" DRVNAME); -MODULE_ALIAS("spi:pdc8544"); +MODULE_ALIAS("spi:pcd8544"); MODULE_DESCRIPTION("FB driver for the PCD8544 LCD Controller"); MODULE_AUTHOR("Noralf Tronnes"); diff --git a/drivers/staging/fbtft/fb_s6d1121.c b/drivers/staging/fbtft/fb_s6d1121.c index 5a129b1352cc..8c7de3290343 100644 --- a/drivers/staging/fbtft/fb_s6d1121.c +++ b/drivers/staging/fbtft/fb_s6d1121.c @@ -123,7 +123,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f, diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c index 88a5b6925901..7a3fe022cc69 100644 --- a/drivers/staging/fbtft/fb_ssd1289.c +++ b/drivers/staging/fbtft/fb_ssd1289.c @@ -129,7 +129,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, }; diff --git a/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt b/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt index b1f9474f36d5..b1f9474f36d5 100644 --- a/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt +++ b/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt diff --git a/drivers/staging/fsl-dpaa2/ethsw/TODO b/drivers/staging/fsl-dpaa2/ethsw/TODO index 24b5e95a96f8..4d46857b0b2b 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/TODO +++ b/drivers/staging/fsl-dpaa2/ethsw/TODO @@ -1,7 +1,6 @@ * Add I/O capabilities on switch port netdevices. This will allow control traffic to reach the CPU. * Add ACL to redirect control traffic to CPU. -* Add support for displaying learned FDB entries * Add support for multiple FDBs and switch port partitioning * MC firmware uprev; the DPAA2 objects used by the Ethernet Switch driver need to be kept in sync with binary interface changes in MC diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h index 14b974defa3a..5e1339daa7c7 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h @@ -10,7 +10,7 @@ /* DPSW Version */ #define DPSW_VER_MAJOR 8 -#define DPSW_VER_MINOR 0 +#define DPSW_VER_MINOR 1 #define DPSW_CMD_BASE_VERSION 1 #define DPSW_CMD_ID_OFFSET 4 @@ -67,6 +67,7 @@ #define DPSW_CMDID_FDB_ADD_MULTICAST DPSW_CMD_ID(0x086) #define DPSW_CMDID_FDB_REMOVE_MULTICAST DPSW_CMD_ID(0x087) #define DPSW_CMDID_FDB_SET_LEARNING_MODE DPSW_CMD_ID(0x088) +#define DPSW_CMDID_FDB_DUMP DPSW_CMD_ID(0x08A) /* Macros for accessing command fields smaller than 1byte */ #define DPSW_MASK(field) \ @@ -351,6 +352,18 @@ struct dpsw_cmd_fdb_set_learning_mode { u8 mode; }; +struct dpsw_cmd_fdb_dump { + __le16 fdb_id; + __le16 pad0; + __le32 pad1; + __le64 iova_addr; + __le32 iova_size; +}; + +struct dpsw_rsp_fdb_dump { + __le16 num_entries; +}; + struct dpsw_rsp_get_api_version { __le16 version_major; __le16 version_minor; diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c index cabed77b445d..56b0fa789a67 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c @@ -981,6 +981,57 @@ int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io, } /** + * dpsw_fdb_dump() - Dump the content of FDB table into memory. + * @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 + * @fdb_id: Forwarding Database Identifier + * @iova_addr: Data will be stored here as an array of struct fdb_dump_entry + * @iova_size: Memory size allocated at iova_addr + * @num_entries:Number of entries written at iova_addr + * + * Return: Completion status. '0' on Success; Error code otherwise. + * + * The memory allocated at iova_addr must be initialized with zero before + * command execution. If the FDB table does not fit into memory MC will stop + * after the memory is filled up. + * The struct fdb_dump_entry array must be parsed until the end of memory + * area or until an entry with mac_addr set to zero is found. + */ +int dpsw_fdb_dump(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 fdb_id, + u64 iova_addr, + u32 iova_size, + u16 *num_entries) +{ + struct dpsw_cmd_fdb_dump *cmd_params; + struct dpsw_rsp_fdb_dump *rsp_params; + struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_DUMP, + cmd_flags, + token); + cmd_params = (struct dpsw_cmd_fdb_dump *)cmd.params; + cmd_params->fdb_id = cpu_to_le16(fdb_id); + cmd_params->iova_addr = cpu_to_le64(iova_addr); + cmd_params->iova_size = cpu_to_le32(iova_size); + + /* send command to mc */ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + rsp_params = (struct dpsw_rsp_fdb_dump *)cmd.params; + *num_entries = le16_to_cpu(rsp_params->num_entries); + + return 0; +} + +/** * dpsw_fdb_remove_unicast() - removes an entry from MAC lookup table * @mc_io: Pointer to MC portal's I/O object * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h index 25635259ce44..25b45850925c 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h @@ -75,37 +75,6 @@ enum dpsw_component_type { DPSW_COMPONENT_TYPE_S_VLAN }; -/** - * struct dpsw_cfg - DPSW configuration - * @num_ifs: Number of external and internal interfaces - * @adv: Advanced parameters; default is all zeros; - * use this structure to change default settings - * @adv.options: Enable/Disable DPSW features (bitmap) - * @adv.max_vlans: Maximum Number of VLAN's; 0 - indicates default 16 - * @adv.max_meters_per_if: Number of meters per interface - * @adv.max_fdbs: Maximum Number of FDB's; 0 - indicates default 16 - * @adv.max_fdb_entries: Number of FDB entries for default FDB table; - * 0 - indicates default 1024 entries. - * @adv.fdb_aging_time: Default FDB aging time for default FDB table; - * 0 - indicates default 300 seconds - * @adv.max_fdb_mc_groups: Number of multicast groups in each FDB table; - * 0 - indicates default 32 - * @adv.component_type: Indicates the component type of this bridge - */ -struct dpsw_cfg { - u16 num_ifs; - struct { - u64 options; - u16 max_vlans; - u8 max_meters_per_if; - u8 max_fdbs; - u16 max_fdb_entries; - u16 fdb_aging_time; - u16 max_fdb_mc_groups; - enum dpsw_component_type component_type; - } adv; -}; - int dpsw_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); @@ -496,6 +465,31 @@ int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io, u16 fdb_id, const struct dpsw_fdb_unicast_cfg *cfg); +#define DPSW_FDB_ENTRY_TYPE_DYNAMIC BIT(0) +#define DPSW_FDB_ENTRY_TYPE_UNICAST BIT(1) + +/** + * struct fdb_dump_entry - fdb snapshot entry + * @mac_addr: MAC address + * @type: bit0 - DINAMIC(1)/STATIC(0), bit1 - UNICAST(1)/MULTICAST(0) + * @if_info: unicast - egress interface, multicast - number of egress interfaces + * @if_mask: multicast - egress interface mask + */ +struct fdb_dump_entry { + u8 mac_addr[6]; + u8 type; + u8 if_info; + u8 if_mask[8]; +}; + +int dpsw_fdb_dump(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 fdb_id, + u64 iova_addr, + u32 iova_size, + u16 *num_entries); + /** * struct dpsw_fdb_multicast_cfg - Multi-cast entry configuration * @type: Select static or dynamic entry diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c index 926a0c053e18..4f0bff86e43e 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c @@ -65,7 +65,7 @@ ethsw_get_link_ksettings(struct net_device *netdev, port_priv->idx, &state); if (err) { - netdev_err(netdev, "ERROR %d getting link state", err); + netdev_err(netdev, "ERROR %d getting link state\n", err); goto out; } @@ -88,18 +88,21 @@ ethsw_set_link_ksettings(struct net_device *netdev, const struct ethtool_link_ksettings *link_ksettings) { struct ethsw_port_priv *port_priv = netdev_priv(netdev); + struct ethsw_core *ethsw = port_priv->ethsw_data; struct dpsw_link_cfg cfg = {0}; - int err = 0; - - netdev_dbg(netdev, "Setting link parameters..."); - - /* Due to a temporary MC limitation, the DPSW port must be down - * in order to be able to change link settings. Taking steps to let - * the user know that. - */ - if (netif_running(netdev)) { - netdev_info(netdev, "Sorry, interface must be brought down first.\n"); - return -EACCES; + bool if_running; + int err = 0, ret; + + /* Interface needs to be down to change link settings */ + if_running = netif_running(netdev); + if (if_running) { + err = dpsw_if_disable(ethsw->mc_io, 0, + ethsw->dpsw_handle, + port_priv->idx); + if (err) { + netdev_err(netdev, "dpsw_if_disable err %d\n", err); + return err; + } } cfg.rate = link_ksettings->base.speed; @@ -116,12 +119,16 @@ ethsw_set_link_ksettings(struct net_device *netdev, port_priv->ethsw_data->dpsw_handle, port_priv->idx, &cfg); - if (err) - /* ethtool will be loud enough if we return an error; no point - * in putting our own error message on the console by default - */ - netdev_dbg(netdev, "ERROR %d setting link cfg", err); + if (if_running) { + ret = dpsw_if_enable(ethsw->mc_io, 0, + ethsw->dpsw_handle, + port_priv->idx); + if (ret) { + netdev_err(netdev, "dpsw_if_enable err %d\n", ret); + return ret; + } + } return err; } @@ -156,9 +163,6 @@ static void ethsw_ethtool_get_stats(struct net_device *netdev, struct ethsw_port_priv *port_priv = netdev_priv(netdev); int i, err; - memset(data, 0, - sizeof(u64) * ETHSW_NUM_COUNTERS); - for (i = 0; i < ETHSW_NUM_COUNTERS; i++) { err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, port_priv->ethsw_data->dpsw_handle, diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index f73edaf6ce87..14a9eebf687e 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -22,7 +22,7 @@ static struct workqueue_struct *ethsw_owq; /* Minimal supported DPSW version */ #define DPSW_MIN_VER_MAJOR 8 -#define DPSW_MIN_VER_MINOR 0 +#define DPSW_MIN_VER_MINOR 1 #define DEFAULT_VLAN_ID 1 @@ -34,11 +34,6 @@ static int ethsw_add_vlan(struct ethsw_core *ethsw, u16 vid) .fdb_id = 0, }; - if (ethsw->vlans[vid]) { - dev_err(ethsw->dev, "VLAN already configured\n"); - return -EEXIST; - } - err = dpsw_vlan_add(ethsw->mc_io, 0, ethsw->dpsw_handle, vid, &vcfg); if (err) { @@ -149,12 +144,12 @@ static int ethsw_port_add_vlan(struct ethsw_port_priv *port_priv, return 0; } -static int ethsw_set_learning(struct ethsw_core *ethsw, u8 flag) +static int ethsw_set_learning(struct ethsw_core *ethsw, bool enable) { enum dpsw_fdb_learning_mode learn_mode; int err; - if (flag) + if (enable) learn_mode = DPSW_FDB_LEARNING_MODE_HW; else learn_mode = DPSW_FDB_LEARNING_MODE_DIS; @@ -165,24 +160,24 @@ static int ethsw_set_learning(struct ethsw_core *ethsw, u8 flag) dev_err(ethsw->dev, "dpsw_fdb_set_learning_mode err %d\n", err); return err; } - ethsw->learning = !!flag; + ethsw->learning = enable; return 0; } -static int ethsw_port_set_flood(struct ethsw_port_priv *port_priv, u8 flag) +static int ethsw_port_set_flood(struct ethsw_port_priv *port_priv, bool enable) { int err; err = dpsw_if_set_flooding(port_priv->ethsw_data->mc_io, 0, port_priv->ethsw_data->dpsw_handle, - port_priv->idx, flag); + port_priv->idx, enable); if (err) { netdev_err(port_priv->netdev, "dpsw_if_set_flooding err %d\n", err); return err; } - port_priv->flood = !!flag; + port_priv->flood = enable; return 0; } @@ -316,6 +311,31 @@ static int ethsw_port_fdb_del_mc(struct ethsw_port_priv *port_priv, return err; } +static int port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, const unsigned char *addr, + u16 vid, u16 flags, + struct netlink_ext_ack *extack) +{ + if (is_unicast_ether_addr(addr)) + return ethsw_port_fdb_add_uc(netdev_priv(dev), + addr); + else + return ethsw_port_fdb_add_mc(netdev_priv(dev), + addr); +} + +static int port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, + const unsigned char *addr, u16 vid) +{ + if (is_unicast_ether_addr(addr)) + return ethsw_port_fdb_del_uc(netdev_priv(dev), + addr); + else + return ethsw_port_fdb_del_mc(netdev_priv(dev), + addr); +} + static void port_get_stats(struct net_device *netdev, struct rtnl_link_stats64 *stats) { @@ -516,17 +536,165 @@ static int swdev_get_port_parent_id(struct net_device *dev, return 0; } +static int port_get_phys_name(struct net_device *netdev, char *name, + size_t len) +{ + struct ethsw_port_priv *port_priv = netdev_priv(netdev); + int err; + + err = snprintf(name, len, "p%d", port_priv->idx); + if (err >= len) + return -EINVAL; + + return 0; +} + +struct ethsw_dump_ctx { + struct net_device *dev; + struct sk_buff *skb; + struct netlink_callback *cb; + int idx; +}; + +static int ethsw_fdb_do_dump(struct fdb_dump_entry *entry, + struct ethsw_dump_ctx *dump) +{ + int is_dynamic = entry->type & DPSW_FDB_ENTRY_DINAMIC; + u32 portid = NETLINK_CB(dump->cb->skb).portid; + u32 seq = dump->cb->nlh->nlmsg_seq; + struct nlmsghdr *nlh; + struct ndmsg *ndm; + + if (dump->idx < dump->cb->args[2]) + goto skip; + + nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH, + sizeof(*ndm), NLM_F_MULTI); + if (!nlh) + return -EMSGSIZE; + + ndm = nlmsg_data(nlh); + ndm->ndm_family = AF_BRIDGE; + ndm->ndm_pad1 = 0; + ndm->ndm_pad2 = 0; + ndm->ndm_flags = NTF_SELF; + ndm->ndm_type = 0; + ndm->ndm_ifindex = dump->dev->ifindex; + ndm->ndm_state = is_dynamic ? NUD_REACHABLE : NUD_NOARP; + + if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, entry->mac_addr)) + goto nla_put_failure; + + nlmsg_end(dump->skb, nlh); + +skip: + dump->idx++; + return 0; + +nla_put_failure: + nlmsg_cancel(dump->skb, nlh); + return -EMSGSIZE; +} + +static int port_fdb_valid_entry(struct fdb_dump_entry *entry, + struct ethsw_port_priv *port_priv) +{ + int idx = port_priv->idx; + int valid; + + if (entry->type & DPSW_FDB_ENTRY_TYPE_UNICAST) + valid = entry->if_info == port_priv->idx; + else + valid = entry->if_mask[idx / 8] & BIT(idx % 8); + + return valid; +} + +static int port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, + struct net_device *net_dev, + struct net_device *filter_dev, int *idx) +{ + struct ethsw_port_priv *port_priv = netdev_priv(net_dev); + struct ethsw_core *ethsw = port_priv->ethsw_data; + struct device *dev = net_dev->dev.parent; + struct fdb_dump_entry *fdb_entries; + struct fdb_dump_entry fdb_entry; + struct ethsw_dump_ctx dump = { + .dev = net_dev, + .skb = skb, + .cb = cb, + .idx = *idx, + }; + dma_addr_t fdb_dump_iova; + u16 num_fdb_entries; + u32 fdb_dump_size; + int err = 0, i; + u8 *dma_mem; + + fdb_dump_size = ethsw->sw_attr.max_fdb_entries * sizeof(fdb_entry); + dma_mem = kzalloc(fdb_dump_size, GFP_KERNEL); + if (!dma_mem) + return -ENOMEM; + + fdb_dump_iova = dma_map_single(dev, dma_mem, fdb_dump_size, + DMA_FROM_DEVICE); + if (dma_mapping_error(dev, fdb_dump_iova)) { + netdev_err(net_dev, "dma_map_single() failed\n"); + err = -ENOMEM; + goto err_map; + } + + err = dpsw_fdb_dump(ethsw->mc_io, 0, ethsw->dpsw_handle, 0, + fdb_dump_iova, fdb_dump_size, &num_fdb_entries); + if (err) { + netdev_err(net_dev, "dpsw_fdb_dump() = %d\n", err); + goto err_dump; + } + + dma_unmap_single(dev, fdb_dump_iova, fdb_dump_size, DMA_FROM_DEVICE); + + fdb_entries = (struct fdb_dump_entry *)dma_mem; + for (i = 0; i < num_fdb_entries; i++) { + fdb_entry = fdb_entries[i]; + + if (!port_fdb_valid_entry(&fdb_entry, port_priv)) + continue; + + err = ethsw_fdb_do_dump(&fdb_entry, &dump); + if (err) + goto end; + } + +end: + *idx = dump.idx; + + kfree(dma_mem); + + return 0; + +err_dump: + dma_unmap_single(dev, fdb_dump_iova, fdb_dump_size, DMA_TO_DEVICE); +err_map: + kfree(dma_mem); + return err; +} + static const struct net_device_ops ethsw_port_ops = { .ndo_open = port_open, .ndo_stop = port_stop, .ndo_set_mac_address = eth_mac_addr, + .ndo_get_stats64 = port_get_stats, .ndo_change_mtu = port_change_mtu, .ndo_has_offload_stats = port_has_offload_stats, .ndo_get_offload_stats = port_get_offload_stats, + .ndo_fdb_add = port_fdb_add, + .ndo_fdb_del = port_fdb_del, + .ndo_fdb_dump = port_fdb_dump, .ndo_start_xmit = port_dropframe, .ndo_get_port_parent_id = swdev_get_port_parent_id, + .ndo_get_phys_port_name = port_get_phys_name, }; static void ethsw_links_state_update(struct ethsw_core *ethsw) @@ -549,12 +717,12 @@ static irqreturn_t ethsw_irq0_handler_thread(int irq_num, void *arg) err = dpsw_get_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle, DPSW_IRQ_INDEX_IF, &status); if (err) { - dev_err(dev, "Can't get irq status (err %d)", err); + dev_err(dev, "Can't get irq status (err %d)\n", err); err = dpsw_clear_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle, DPSW_IRQ_INDEX_IF, 0xFFFFFFFF); if (err) - dev_err(dev, "Can't clear irq status (err %d)", err); + dev_err(dev, "Can't clear irq status (err %d)\n", err); goto out; } @@ -599,21 +767,21 @@ static int ethsw_setup_irqs(struct fsl_mc_device *sw_dev) IRQF_NO_SUSPEND | IRQF_ONESHOT, dev_name(dev), dev); if (err) { - dev_err(dev, "devm_request_threaded_irq(): %d", err); + dev_err(dev, "devm_request_threaded_irq(): %d\n", err); goto free_irq; } err = dpsw_set_irq_mask(ethsw->mc_io, 0, ethsw->dpsw_handle, DPSW_IRQ_INDEX_IF, mask); if (err) { - dev_err(dev, "dpsw_set_irq_mask(): %d", err); + dev_err(dev, "dpsw_set_irq_mask(): %d\n", err); goto free_devm_irq; } err = dpsw_set_irq_enable(ethsw->mc_io, 0, ethsw->dpsw_handle, DPSW_IRQ_INDEX_IF, 1); if (err) { - dev_err(dev, "dpsw_set_irq_enable(): %d", err); + dev_err(dev, "dpsw_set_irq_enable(): %d\n", err); goto free_devm_irq; } @@ -673,11 +841,12 @@ static int port_attr_br_flags_set(struct net_device *netdev, return 0; /* Learning is enabled per switch */ - err = ethsw_set_learning(port_priv->ethsw_data, flags & BR_LEARNING); + err = ethsw_set_learning(port_priv->ethsw_data, + !!(flags & BR_LEARNING)); if (err) goto exit; - err = ethsw_port_set_flood(port_priv, flags & BR_FLOOD); + err = ethsw_port_set_flood(port_priv, !!(flags & BR_FLOOD)); exit: return err; @@ -950,8 +1119,7 @@ static int port_bridge_join(struct net_device *netdev, if (ethsw->ports[i]->bridge_dev && (ethsw->ports[i]->bridge_dev != upper_dev)) { netdev_err(netdev, - "Another switch port is connected to %s\n", - ethsw->ports[i]->bridge_dev->name); + "Only one bridge supported per DPSW object!\n"); return -EINVAL; } @@ -1023,18 +1191,30 @@ static void ethsw_switchdev_event_work(struct work_struct *work) container_of(work, struct ethsw_switchdev_event_work, work); struct net_device *dev = switchdev_work->dev; struct switchdev_notifier_fdb_info *fdb_info; + int err; rtnl_lock(); fdb_info = &switchdev_work->fdb_info; switch (switchdev_work->event) { case SWITCHDEV_FDB_ADD_TO_DEVICE: + if (!fdb_info->added_by_user) + break; if (is_unicast_ether_addr(fdb_info->addr)) - ethsw_port_fdb_add_uc(netdev_priv(dev), fdb_info->addr); + err = ethsw_port_fdb_add_uc(netdev_priv(dev), + fdb_info->addr); else - ethsw_port_fdb_add_mc(netdev_priv(dev), fdb_info->addr); + err = ethsw_port_fdb_add_mc(netdev_priv(dev), + fdb_info->addr); + if (err) + break; + fdb_info->offloaded = true; + call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, dev, + &fdb_info->info, NULL); break; case SWITCHDEV_FDB_DEL_TO_DEVICE: + if (!fdb_info->added_by_user) + break; if (is_unicast_ether_addr(fdb_info->addr)) ethsw_port_fdb_del_uc(netdev_priv(dev), fdb_info->addr); else @@ -1177,48 +1357,6 @@ err_switchdev_nb: return err; } -static int ethsw_open(struct ethsw_core *ethsw) -{ - struct ethsw_port_priv *port_priv = NULL; - int i, err; - - err = dpsw_enable(ethsw->mc_io, 0, ethsw->dpsw_handle); - if (err) { - dev_err(ethsw->dev, "dpsw_enable err %d\n", err); - return err; - } - - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { - port_priv = ethsw->ports[i]; - err = dev_open(port_priv->netdev, NULL); - if (err) { - netdev_err(port_priv->netdev, "dev_open err %d\n", err); - return err; - } - } - - return 0; -} - -static int ethsw_stop(struct ethsw_core *ethsw) -{ - struct ethsw_port_priv *port_priv = NULL; - int i, err; - - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { - port_priv = ethsw->ports[i]; - dev_close(port_priv->netdev); - } - - err = dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle); - if (err) { - dev_err(ethsw->dev, "dpsw_disable err %d\n", err); - return err; - } - - return 0; -} - static int ethsw_init(struct fsl_mc_device *sw_dev) { struct device *dev = &sw_dev->dev; @@ -1320,7 +1458,6 @@ err_close: static int ethsw_port_init(struct ethsw_port_priv *port_priv, u16 port) { - const char def_mcast[ETH_ALEN] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x01}; struct net_device *netdev = port_priv->netdev; struct ethsw_core *ethsw = port_priv->ethsw_data; struct dpsw_vlan_if_cfg vcfg; @@ -1346,12 +1483,10 @@ static int ethsw_port_init(struct ethsw_port_priv *port_priv, u16 port) err = dpsw_vlan_remove_if(ethsw->mc_io, 0, ethsw->dpsw_handle, DEFAULT_VLAN_ID, &vcfg); - if (err) { + if (err) netdev_err(netdev, "dpsw_vlan_remove_if err %d\n", err); - return err; - } - return ethsw_port_fdb_add_mc(port_priv, def_mcast); + return err; } static void ethsw_unregister_notifier(struct device *dev) @@ -1403,9 +1538,7 @@ static int ethsw_remove(struct fsl_mc_device *sw_dev) destroy_workqueue(ethsw_owq); - rtnl_lock(); - ethsw_stop(ethsw); - rtnl_unlock(); + dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle); for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { port_priv = ethsw->ports[i]; @@ -1455,16 +1588,24 @@ static int ethsw_probe_port(struct ethsw_core *ethsw, u16 port_idx) port_netdev->min_mtu = ETH_MIN_MTU; port_netdev->max_mtu = ETHSW_MAX_FRAME_LENGTH; + err = ethsw_port_init(port_priv, port_idx); + if (err) + goto err_port_probe; + err = register_netdev(port_netdev); if (err < 0) { dev_err(dev, "register_netdev error %d\n", err); - free_netdev(port_netdev); - return err; + goto err_port_probe; } ethsw->ports[port_idx] = port_priv; - return ethsw_port_init(port_priv, port_idx); + return 0; + +err_port_probe: + free_netdev(port_netdev); + + return err; } static int ethsw_probe(struct fsl_mc_device *sw_dev) @@ -1482,7 +1623,8 @@ static int ethsw_probe(struct fsl_mc_device *sw_dev) ethsw->dev = dev; dev_set_drvdata(dev, ethsw); - err = fsl_mc_portal_allocate(sw_dev, 0, ðsw->mc_io); + err = fsl_mc_portal_allocate(sw_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, + ðsw->mc_io); if (err) { if (err == -ENXIO) err = -EPROBE_DEFER; @@ -1514,12 +1656,11 @@ static int ethsw_probe(struct fsl_mc_device *sw_dev) goto err_free_ports; } - /* Switch starts up enabled */ - rtnl_lock(); - err = ethsw_open(ethsw); - rtnl_unlock(); - if (err) + err = dpsw_enable(ethsw->mc_io, 0, ethsw->dpsw_handle); + if (err) { + dev_err(ethsw->dev, "dpsw_enable err %d\n", err); goto err_free_ports; + } /* Setup IRQs */ err = ethsw_setup_irqs(sw_dev); @@ -1530,9 +1671,7 @@ static int ethsw_probe(struct fsl_mc_device *sw_dev) return 0; err_stop: - rtnl_lock(); - ethsw_stop(ethsw); - rtnl_unlock(); + dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle); err_free_ports: /* Cleanup registered ports only */ diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h index c48783680a05..3ea8a0ad8c10 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h @@ -23,9 +23,13 @@ /* Number of IRQs supported */ #define DPSW_IRQ_NUM 2 +/* Port is member of VLAN */ #define ETHSW_VLAN_MEMBER 1 +/* VLAN to be treated as untagged on egress */ #define ETHSW_VLAN_UNTAGGED 2 +/* Untagged frames will be assigned to this VLAN */ #define ETHSW_VLAN_PVID 4 +/* VLAN configured on the switch */ #define ETHSW_VLAN_GLOBAL 8 /* Maximum Frame Length supported by HW (currently 10k) */ diff --git a/drivers/staging/gasket/apex_driver.c b/drivers/staging/gasket/apex_driver.c index 464648ee2036..46199c8ca441 100644 --- a/drivers/staging/gasket/apex_driver.c +++ b/drivers/staging/gasket/apex_driver.c @@ -509,6 +509,8 @@ static ssize_t sysfs_show(struct device *device, struct device_attribute *attr, struct gasket_dev *gasket_dev; struct gasket_sysfs_attribute *gasket_attr; enum sysfs_attribute_type type; + struct gasket_page_table *gpt; + uint val; gasket_dev = gasket_sysfs_get_device_data(device); if (!gasket_dev) { @@ -524,29 +526,25 @@ static ssize_t sysfs_show(struct device *device, struct device_attribute *attr, } type = (enum sysfs_attribute_type)gasket_attr->data.attr_type; + gpt = gasket_dev->page_table[0]; switch (type) { case ATTR_KERNEL_HIB_PAGE_TABLE_SIZE: - ret = scnprintf(buf, PAGE_SIZE, "%u\n", - gasket_page_table_num_entries( - gasket_dev->page_table[0])); + val = gasket_page_table_num_entries(gpt); break; case ATTR_KERNEL_HIB_SIMPLE_PAGE_TABLE_SIZE: - ret = scnprintf(buf, PAGE_SIZE, "%u\n", - gasket_page_table_num_simple_entries( - gasket_dev->page_table[0])); + val = gasket_page_table_num_simple_entries(gpt); break; case ATTR_KERNEL_HIB_NUM_ACTIVE_PAGES: - ret = scnprintf(buf, PAGE_SIZE, "%u\n", - gasket_page_table_num_active_pages( - gasket_dev->page_table[0])); + val = gasket_page_table_num_active_pages(gpt); break; default: dev_dbg(gasket_dev->dev, "Unknown attribute: %s\n", attr->attr.name); ret = 0; - break; + goto exit; } - + ret = scnprintf(buf, PAGE_SIZE, "%u\n", val); +exit: gasket_sysfs_put_attr(device, gasket_attr); gasket_sysfs_put_device_data(device, gasket_dev); return ret; @@ -659,7 +657,7 @@ static void apex_pci_remove(struct pci_dev *pci_dev) pci_disable_device(pci_dev); } -static struct gasket_driver_desc apex_desc = { +static const struct gasket_driver_desc apex_desc = { .name = "apex", .driver_version = APEX_DRIVER_VERSION, .major = 120, diff --git a/drivers/staging/gasket/gasket_ioctl.c b/drivers/staging/gasket/gasket_ioctl.c index 7ecfba4f2b06..240f9bb10b71 100644 --- a/drivers/staging/gasket/gasket_ioctl.c +++ b/drivers/staging/gasket/gasket_ioctl.c @@ -39,8 +39,7 @@ static int gasket_set_event_fd(struct gasket_dev *gasket_dev, } /* Read the size of the page table. */ -static int gasket_read_page_table_size( - struct gasket_dev *gasket_dev, +static int gasket_read_page_table_size(struct gasket_dev *gasket_dev, struct gasket_page_table_ioctl __user *argp) { int ret = 0; @@ -66,8 +65,7 @@ static int gasket_read_page_table_size( } /* Read the size of the simple page table. */ -static int gasket_read_simple_page_table_size( - struct gasket_dev *gasket_dev, +static int gasket_read_simple_page_table_size(struct gasket_dev *gasket_dev, struct gasket_page_table_ioctl __user *argp) { int ret = 0; @@ -93,8 +91,7 @@ static int gasket_read_simple_page_table_size( } /* Set the boundary between the simple and extended page tables. */ -static int gasket_partition_page_table( - struct gasket_dev *gasket_dev, +static int gasket_partition_page_table(struct gasket_dev *gasket_dev, struct gasket_page_table_ioctl __user *argp) { int ret; @@ -185,8 +182,7 @@ static int gasket_unmap_buffers(struct gasket_dev *gasket_dev, * Reserve structures for coherent allocation, and allocate or free the * corresponding memory. */ -static int gasket_config_coherent_allocator( - struct gasket_dev *gasket_dev, +static int gasket_config_coherent_allocator(struct gasket_dev *gasket_dev, struct gasket_coherent_alloc_config_ioctl __user *argp) { int ret; diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c index 24a738238f9f..0c65a0121dde 100644 --- a/drivers/staging/goldfish/goldfish_audio.c +++ b/drivers/staging/goldfish/goldfish_audio.c @@ -302,10 +302,8 @@ static int goldfish_audio_probe(struct platform_device *pdev) return -ENOMEM; data->irq = platform_get_irq(pdev, 0); - if (data->irq < 0) { - dev_err(&pdev->dev, "platform_get_irq failed\n"); + if (data->irq < 0) return -ENODEV; - } data->buffer_virt = dmam_alloc_coherent(&pdev->dev, COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL); diff --git a/drivers/staging/greybus/Documentation/firmware/authenticate.c b/drivers/staging/greybus/Documentation/firmware/authenticate.c index 806e75b7f405..3d2c6f88a138 100644 --- a/drivers/staging/greybus/Documentation/firmware/authenticate.c +++ b/drivers/staging/greybus/Documentation/firmware/authenticate.c @@ -2,54 +2,8 @@ /* * Sample code to test CAP protocol * - * 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 Google Inc. All rights reserved. * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * 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 version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2016 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * 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 Google Inc. or Linaro Ltd. 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 GOOGLE INC. OR - * LINARO LTD. 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. */ #include <stdio.h> diff --git a/drivers/staging/greybus/Documentation/firmware/firmware.c b/drivers/staging/greybus/Documentation/firmware/firmware.c index 31d9c23e2eeb..765d69faa9cc 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware.c +++ b/drivers/staging/greybus/Documentation/firmware/firmware.c @@ -2,54 +2,8 @@ /* * Sample code to test firmware-management protocol * - * 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 Google Inc. All rights reserved. * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * 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 version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2016 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * 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 Google Inc. or Linaro Ltd. 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 GOOGLE INC. OR - * LINARO LTD. 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. */ #include <stdio.h> diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig index 4894c3514955..d4777f5a8b90 100644 --- a/drivers/staging/greybus/Kconfig +++ b/drivers/staging/greybus/Kconfig @@ -1,33 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -menuconfig GREYBUS - tristate "Greybus support" - depends on SYSFS - ---help--- - This option enables the Greybus driver core. Greybus is an - hardware protocol that was designed to provide Unipro with a - sane application layer. It was originally designed for the - ARA project, a module phone system, but has shown up in other - phones, and can be tunneled over other busses in order to - control hardware devices. - - Say Y here to enable support for these types of drivers. - - To compile this code as a module, chose M here: the module - will be called greybus.ko - if GREYBUS -config GREYBUS_ES2 - tristate "Greybus ES3 USB host controller" - depends on USB - ---help--- - Select this option if you have a Toshiba ES3 USB device that - acts as a Greybus "host controller". This device is a bridge - from a USB device to a Unipro network. - - To compile this code as a module, chose M here: the module - will be called gb-es2.ko - config GREYBUS_AUDIO tristate "Greybus Audio Class driver" depends on SOUND diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 2551ed16b742..627e44f2a983 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,29 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 -# Greybus core -greybus-y := core.o \ - debugfs.o \ - hd.o \ - manifest.o \ - module.o \ - interface.o \ - bundle.o \ - connection.o \ - control.o \ - svc.o \ - svc_watchdog.o \ - operation.o - -obj-$(CONFIG_GREYBUS) += greybus.o - # needed for trace events ccflags-y += -I$(src) - -# Greybus Host controller drivers -gb-es2-y := es2.o - -obj-$(CONFIG_GREYBUS_ES2) += gb-es2.o - # Greybus class drivers gb-bootrom-y := bootrom.o gb-camera-y := camera.o diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 6eb842040c22..eebf0deb39f5 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -19,8 +19,8 @@ #include <linux/irq.h> #include <linux/suspend.h> #include <linux/time.h> +#include <linux/greybus.h> #include "arche_platform.h" -#include "greybus.h" #if IS_ENABLED(CONFIG_USB_HSIC_USB3613) #include <linux/usb/usb3613.h> diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h deleted file mode 100644 index 3dab6375909c..000000000000 --- a/drivers/staging/greybus/arpc.h +++ /dev/null @@ -1,109 +0,0 @@ -/* 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 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * 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 version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2016 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * 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 Google Inc. or Linaro Ltd. 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 GOOGLE INC. OR - * LINARO LTD. 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 __ARPC_H -#define __ARPC_H - -/* APBridgeA RPC (ARPC) */ - -enum arpc_result { - ARPC_SUCCESS = 0x00, - ARPC_NO_MEMORY = 0x01, - ARPC_INVALID = 0x02, - ARPC_TIMEOUT = 0x03, - ARPC_UNKNOWN_ERROR = 0xff, -}; - -struct arpc_request_message { - __le16 id; /* RPC unique id */ - __le16 size; /* Size in bytes of header + payload */ - __u8 type; /* RPC type */ - __u8 data[0]; /* ARPC data */ -} __packed; - -struct arpc_response_message { - __le16 id; /* RPC unique id */ - __u8 result; /* Result of RPC */ -} __packed; - -/* ARPC requests */ -#define ARPC_TYPE_CPORT_CONNECTED 0x01 -#define ARPC_TYPE_CPORT_QUIESCE 0x02 -#define ARPC_TYPE_CPORT_CLEAR 0x03 -#define ARPC_TYPE_CPORT_FLUSH 0x04 -#define ARPC_TYPE_CPORT_SHUTDOWN 0x05 - -struct arpc_cport_connected_req { - __le16 cport_id; -} __packed; - -struct arpc_cport_quiesce_req { - __le16 cport_id; - __le16 peer_space; - __le16 timeout; -} __packed; - -struct arpc_cport_clear_req { - __le16 cport_id; -} __packed; - -struct arpc_cport_flush_req { - __le16 cport_id; -} __packed; - -struct arpc_cport_shutdown_req { - __le16 cport_id; - __le16 timeout; - __u8 phase; -} __packed; - -#endif /* __ARPC_H */ diff --git a/drivers/staging/greybus/audio_apbridgea.c b/drivers/staging/greybus/audio_apbridgea.c index 7ebb1bde5cb7..26117e390deb 100644 --- a/drivers/staging/greybus/audio_apbridgea.c +++ b/drivers/staging/greybus/audio_apbridgea.c @@ -5,8 +5,7 @@ * Copyright 2015-2016 Google Inc. */ -#include "greybus.h" -#include "greybus_protocols.h" +#include <linux/greybus.h> #include "audio_apbridgea.h" #include "audio_codec.h" diff --git a/drivers/staging/greybus/audio_apbridgea.h b/drivers/staging/greybus/audio_apbridgea.h index 330fc7a397eb..3f1f4dd2c61a 100644 --- a/drivers/staging/greybus/audio_apbridgea.h +++ b/drivers/staging/greybus/audio_apbridgea.h @@ -1,30 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/** +/* * Copyright (c) 2015-2016 Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the copyright holder 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 HOLDER 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. */ /* * This is a special protocol for configuring communication over the diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 9ba09ea9c2fc..cb5d271da1a5 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -8,12 +8,10 @@ #ifndef __LINUX_GBAUDIO_CODEC_H #define __LINUX_GBAUDIO_CODEC_H +#include <linux/greybus.h> #include <sound/soc.h> #include <sound/jack.h> -#include "greybus.h" -#include "greybus_protocols.h" - #define NAME_SIZE 32 #define MAX_DAIS 2 /* APB1, APB2 */ diff --git a/drivers/staging/greybus/audio_gb.c b/drivers/staging/greybus/audio_gb.c index 8894f1c87d48..9d8994fdb41a 100644 --- a/drivers/staging/greybus/audio_gb.c +++ b/drivers/staging/greybus/audio_gb.c @@ -5,9 +5,7 @@ * Copyright 2015-2016 Google Inc. */ -#include "greybus.h" -#include "greybus_protocols.h" -#include "operation.h" +#include <linux/greybus.h> #include "audio_codec.h" /* TODO: Split into separate calls */ diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c index c2a4af4c1d06..9b19ea9d3fa1 100644 --- a/drivers/staging/greybus/audio_manager.c +++ b/drivers/staging/greybus/audio_manager.c @@ -86,7 +86,7 @@ EXPORT_SYMBOL_GPL(gb_audio_manager_remove); void gb_audio_manager_remove_all(void) { struct gb_audio_manager_module *module, *next; - int is_empty = 1; + int is_empty; down_write(&modules_rwsem); diff --git a/drivers/staging/greybus/authentication.c b/drivers/staging/greybus/authentication.c index a5d7c53df987..297e69f011c7 100644 --- a/drivers/staging/greybus/authentication.c +++ b/drivers/staging/greybus/authentication.c @@ -6,8 +6,7 @@ * Copyright 2016 Linaro Ltd. */ -#include "greybus.h" - +#include <linux/greybus.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/ioctl.h> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index 402e6360834f..a8efb86de140 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -10,8 +10,8 @@ #include <linux/jiffies.h> #include <linux/mutex.h> #include <linux/workqueue.h> +#include <linux/greybus.h> -#include "greybus.h" #include "firmware.h" /* Timeout, in jiffies, within which the next request must be received */ diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 615c8e7fd51e..b570e13394ac 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -14,9 +14,9 @@ #include <linux/string.h> #include <linux/uaccess.h> #include <linux/vmalloc.h> +#include <linux/greybus.h> #include "gb-camera.h" -#include "greybus.h" #include "greybus_protocols.h" enum gb_camera_debugs_buffer_id { diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h index 946221307ef6..5d2564462ffc 100644 --- a/drivers/staging/greybus/firmware.h +++ b/drivers/staging/greybus/firmware.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Firmware Management Header * @@ -9,7 +9,7 @@ #ifndef __FIRMWARE_H #define __FIRMWARE_H -#include "greybus.h" +#include <linux/greybus.h> #define FW_NAME_PREFIX "gmp_" diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index 388866d92f5b..57bebf24636b 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -8,8 +8,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/firmware.h> +#include <linux/greybus.h> #include "firmware.h" -#include "greybus.h" #include "spilib.h" struct gb_fw_core { diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c index d3b7cccbc10d..543692c567f9 100644 --- a/drivers/staging/greybus/fw-download.c +++ b/drivers/staging/greybus/fw-download.c @@ -10,8 +10,8 @@ #include <linux/jiffies.h> #include <linux/mutex.h> #include <linux/workqueue.h> +#include <linux/greybus.h> #include "firmware.h" -#include "greybus.h" /* Estimated minimum buffer size, actual size can be smaller than this */ #define MIN_FETCH_SIZE 512 diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 71aec14f8181..687c6405c65b 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -13,10 +13,10 @@ #include <linux/idr.h> #include <linux/ioctl.h> #include <linux/uaccess.h> +#include <linux/greybus.h> #include "firmware.h" #include "greybus_firmware.h" -#include "greybus.h" #define FW_MGMT_TIMEOUT_MS 1000 diff --git a/drivers/staging/greybus/gb-camera.h b/drivers/staging/greybus/gb-camera.h index ee293e461fc3..5fc469101fc1 100644 --- a/drivers/staging/greybus/gb-camera.h +++ b/drivers/staging/greybus/gb-camera.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Camera protocol driver. * diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c index 6cb85c3d3572..9fc5c47be9bd 100644 --- a/drivers/staging/greybus/gbphy.c +++ b/drivers/staging/greybus/gbphy.c @@ -13,8 +13,8 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/device.h> +#include <linux/greybus.h> -#include "greybus.h" #include "gbphy.h" #define GB_GBPHY_AUTOSUSPEND_MS 3000 diff --git a/drivers/staging/greybus/gbphy.h b/drivers/staging/greybus/gbphy.h index 99463489d7d6..087928a586fb 100644 --- a/drivers/staging/greybus/gbphy.h +++ b/drivers/staging/greybus/gbphy.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Bridged-Phy Bus driver * diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 3151004d26fb..1ff34abd5692 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -13,8 +13,8 @@ #include <linux/irqdomain.h> #include <linux/gpio/driver.h> #include <linux/mutex.h> +#include <linux/greybus.h> -#include "greybus.h" #include "gbphy.h" struct gb_gpio_line { diff --git a/drivers/staging/greybus/greybus_authentication.h b/drivers/staging/greybus/greybus_authentication.h index 03ea9615b217..7edc7295b7ab 100644 --- a/drivers/staging/greybus/greybus_authentication.h +++ b/drivers/staging/greybus/greybus_authentication.h @@ -1,55 +1,9 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * Greybus Component Authentication User Header * - * 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 Google Inc. All rights reserved. * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * 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 version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2016 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * 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 Google Inc. or Linaro Ltd. 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 GOOGLE INC. OR - * LINARO LTD. 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 __GREYBUS_AUTHENTICATION_USER_H diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h index b58281a63ba4..f68fd5e25321 100644 --- a/drivers/staging/greybus/greybus_firmware.h +++ b/drivers/staging/greybus/greybus_firmware.h @@ -1,55 +1,9 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * Greybus Firmware Management User Header * - * 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 Google Inc. All rights reserved. * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * 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 version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2016 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * 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 Google Inc. or Linaro Ltd. 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 GOOGLE INC. OR - * LINARO LTD. 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 __GREYBUS_FIRMWARE_USER_H diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 8ab810bf5716..04bfd9110502 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -12,8 +12,7 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/slab.h> - -#include "greybus.h" +#include <linux/greybus.h> /* Greybus HID device's structure */ struct gb_hid { diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 7bb85a75d3b1..ab06fc3b9e7e 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -10,8 +10,8 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/i2c.h> +#include <linux/greybus.h> -#include "greybus.h" #include "gbphy.h" struct gb_i2c_device { @@ -31,7 +31,14 @@ static u32 gb_i2c_functionality_map(u32 gb_i2c_functionality) return gb_i2c_functionality; /* All bits the same for now */ } -static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) +/* + * Do initial setup of the i2c device. This includes verifying we + * can support it (based on the protocol version it advertises). + * If that's OK, we get and cached its functionality bits. + * + * Note: gb_i2c_dev->connection is assumed to have been valid. + */ +static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) { struct gb_i2c_functionality_response response; u32 functionality; @@ -235,19 +242,6 @@ static const struct i2c_algorithm gb_i2c_algorithm = { .functionality = gb_i2c_functionality, }; -/* - * Do initial setup of the i2c device. This includes verifying we - * can support it (based on the protocol version it advertises). - * If that's OK, we get and cached its functionality bits. - * - * Note: gb_i2c_dev->connection is assumed to have been valid. - */ -static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) -{ - /* Assume the functionality never changes, just get it once */ - return gb_i2c_functionality_operation(gb_i2c_dev); -} - static int gb_i2c_probe(struct gbphy_device *gbphy_dev, const struct gbphy_device_id *id) { diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 010ae1e9c7fb..d6ba25f21d80 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -11,11 +11,9 @@ #include <linux/led-class-flash.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/greybus.h> #include <media/v4l2-flash-led-class.h> -#include "greybus.h" -#include "greybus_protocols.h" - #define NAMES_MAX 32 struct gb_channel { @@ -1098,21 +1096,21 @@ static void gb_lights_channel_release(struct gb_channel *channel) static void gb_lights_light_release(struct gb_light *light) { int i; - int count; light->ready = false; - count = light->channels_count; - if (light->has_flash) gb_lights_light_v4l2_unregister(light); + light->has_flash = false; - for (i = 0; i < count; i++) { + for (i = 0; i < light->channels_count; i++) gb_lights_channel_release(&light->channels[i]); - light->channels_count--; - } + light->channels_count = 0; + kfree(light->channels); + light->channels = NULL; kfree(light->name); + light->name = NULL; } static void gb_lights_release(struct gb_lights *glights) diff --git a/drivers/staging/greybus/log.c b/drivers/staging/greybus/log.c index 15a88574dbb0..971f36dccac6 100644 --- a/drivers/staging/greybus/log.c +++ b/drivers/staging/greybus/log.c @@ -9,8 +9,7 @@ #include <linux/slab.h> #include <linux/sizes.h> #include <linux/uaccess.h> - -#include "greybus.h" +#include <linux/greybus.h> struct gb_log { struct gb_connection *connection; @@ -31,14 +30,14 @@ static int gb_log_request_handler(struct gb_operation *op) /* Verify size of payload */ if (op->request->payload_size < sizeof(*receive)) { dev_err(dev, "log request too small (%zu < %zu)\n", - op->request->payload_size, sizeof(*receive)); + op->request->payload_size, sizeof(*receive)); return -EINVAL; } receive = op->request->payload; len = le16_to_cpu(receive->len); if (len != (op->request->payload_size - sizeof(*receive))) { dev_err(dev, "log request wrong size %d vs %zu\n", len, - (op->request->payload_size - sizeof(*receive))); + (op->request->payload_size - sizeof(*receive))); return -EINVAL; } if (len == 0) { @@ -83,7 +82,7 @@ static int gb_log_probe(struct gb_bundle *bundle, return -ENOMEM; connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), - gb_log_request_handler); + gb_log_request_handler); if (IS_ERR(connection)) { retval = PTR_ERR(connection); goto error_free; diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 48d85ebe404a..583d9708a191 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -25,12 +25,9 @@ #include <linux/workqueue.h> #include <linux/atomic.h> #include <linux/pm_runtime.h> - +#include <linux/greybus.h> #include <asm/div64.h> -#include "greybus.h" -#include "connection.h" - #define NSEC_PER_DAY 86400000000000ULL struct gb_loopback_stats { @@ -882,7 +879,7 @@ static int gb_loopback_fn(void *data) gb->type = 0; gb->send_count = 0; sysfs_notify(&gb->dev->kobj, NULL, - "iteration_count"); + "iteration_count"); dev_dbg(&bundle->dev, "load test complete\n"); } else { dev_dbg(&bundle->dev, @@ -1054,7 +1051,7 @@ static int gb_loopback_probe(struct gb_bundle *bundle, /* Allocate kfifo */ if (kfifo_alloc(&gb->kfifo_lat, kfifo_depth * sizeof(u32), - GFP_KERNEL)) { + GFP_KERNEL)) { retval = -ENOMEM; goto out_conn; } diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 34b40a409ea3..ec96f28887f9 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -10,8 +10,7 @@ #include <linux/module.h> #include <linux/power_supply.h> #include <linux/slab.h> - -#include "greybus.h" +#include <linux/greybus.h> #define PROP_MAX 32 diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 4a6d394b6c44..891a6a672378 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -10,8 +10,8 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/pwm.h> +#include <linux/greybus.h> -#include "greybus.h" #include "gbphy.h" struct gb_pwm_chip { diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index 838acbe84ca0..64a17dfe3b6e 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -13,8 +13,7 @@ #include <linux/fs.h> #include <linux/idr.h> #include <linux/uaccess.h> - -#include "greybus.h" +#include <linux/greybus.h> struct gb_raw { struct gb_connection *connection; diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index a097a8916b3b..68c5718be827 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -12,8 +12,8 @@ #include <linux/mmc/mmc.h> #include <linux/scatterlist.h> #include <linux/workqueue.h> +#include <linux/greybus.h> -#include "greybus.h" #include "gbphy.h" struct gb_sdio_host { diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 47d896992b35..68e8d272db6d 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -7,8 +7,8 @@ */ #include <linux/module.h> +#include <linux/greybus.h> -#include "greybus.h" #include "gbphy.h" #include "spilib.h" diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index 2e07c6b41334..fc27c52de74a 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -10,9 +10,9 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/greybus.h> #include <linux/spi/spi.h> -#include "greybus.h" #include "spilib.h" struct gb_spilib { diff --git a/drivers/staging/greybus/spilib.h b/drivers/staging/greybus/spilib.h index 043d4d32c3ee..9d416839e3be 100644 --- a/drivers/staging/greybus/spilib.h +++ b/drivers/staging/greybus/spilib.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus SPI library header * diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index cebc1d90a180..ba6f905f26fa 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -4,8 +4,6 @@ * * Copyright 2015 Google Inc. * Copyright 2015 Linaro Ltd. - * - * Provided under the three clause BSD license found in the LICENSE file. */ #include <errno.h> #include <fcntl.h> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index b3bffe91ae99..55c51143bb09 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -28,8 +28,8 @@ #include <linux/kfifo.h> #include <linux/workqueue.h> #include <linux/completion.h> +#include <linux/greybus.h> -#include "greybus.h" #include "gbphy.h" #define GB_NUM_MINORS 16 /* 16 is more than enough */ diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 1c246c73a085..8e9d9d59a357 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -10,8 +10,8 @@ #include <linux/slab.h> #include <linux/usb.h> #include <linux/usb/hcd.h> +#include <linux/greybus.h> -#include "greybus.h" #include "gbphy.h" /* Greybus USB request types */ diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 3e5dedeacd5c..0e2b188e5ca3 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -13,8 +13,7 @@ #include <linux/kdev_t.h> #include <linux/idr.h> #include <linux/pm_runtime.h> - -#include "greybus.h" +#include <linux/greybus.h> struct gb_vibrator_device { struct gb_connection *connection; diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c index 62f4b3b1b457..82099db4bf0c 100644 --- a/drivers/staging/iio/accel/adis16240.c +++ b/drivers/staging/iio/accel/adis16240.c @@ -309,15 +309,12 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, long mask) { struct adis *st = iio_priv(indio_dev); - int bits = 10; - s16 val16; u8 addr; switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: - val16 = val & ((1 << bits) - 1); addr = adis16240_addresses[chan->scan_index][0]; - return adis_write_reg_16(st, addr, val16); + return adis_write_reg_16(st, addr, val & GENMASK(9, 0)); } return -EINVAL; } diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index b6d12fe7c12a..e6b660489165 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -25,8 +25,6 @@ #include <linux/iio/triggered_buffer.h> #include <linux/iio/adc/ad_sigma_delta.h> -#include "ad7192.h" - /* Registers */ #define AD7192_REG_COMM 0 /* Communications Register (WO, 8-bit) */ #define AD7192_REG_STAT 0 /* Status Register (RO, 8-bit) */ @@ -145,6 +143,10 @@ #define AD7192_EXT_FREQ_MHZ_MAX 5120000 #define AD7192_INT_FREQ_MHZ 4915200 +#define AD7192_NO_SYNC_FILTER 1 +#define AD7192_SYNC3_FILTER 3 +#define AD7192_SYNC4_FILTER 4 + /* NOTE: * The AD7190/2/5 features a dual use data out ready DOUT/RDY output. * In order to avoid contentions on the SPI bus, it's therefore necessary @@ -252,7 +254,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st) static int ad7192_setup(struct ad7192_state *st, struct device_node *np) { struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi); - bool rej60_en, sinc3_en, refin2_en, chop_en; + bool rej60_en, refin2_en; bool buf_en, bipolar, burnout_curr_en; unsigned long long scale_uv; int i, ret, id; @@ -284,24 +286,12 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np) if (rej60_en) st->mode |= AD7192_MODE_REJ60; - sinc3_en = of_property_read_bool(np, "adi,sinc3-filter-enable"); - if (sinc3_en) - st->mode |= AD7192_MODE_SINC3; - refin2_en = of_property_read_bool(np, "adi,refin2-pins-enable"); if (refin2_en && st->devid != ID_AD7195) st->conf |= AD7192_CONF_REFSEL; - chop_en = of_property_read_bool(np, "adi,chop-enable"); - if (chop_en) { - st->conf |= AD7192_CONF_CHOP; - if (sinc3_en) - st->f_order = 3; /* SINC 3rd order */ - else - st->f_order = 4; /* SINC 4th order */ - } else { - st->f_order = 1; - } + st->conf &= ~AD7192_CONF_CHOP; + st->f_order = AD7192_NO_SYNC_FILTER; buf_en = of_property_read_bool(np, "adi,buffer-enable"); if (buf_en) @@ -313,7 +303,7 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np) burnout_curr_en = of_property_read_bool(np, "adi,burnout-currents-enable"); - if (burnout_curr_en && buf_en && !chop_en) { + if (burnout_curr_en && buf_en) { st->conf |= AD7192_CONF_BURN; } else if (burnout_curr_en) { dev_warn(&st->sd.spi->dev, @@ -411,6 +401,49 @@ static ssize_t ad7192_set(struct device *dev, return ret ? ret : len; } +static void ad7192_get_available_filter_freq(struct ad7192_state *st, + int *freq) +{ + unsigned int fadc; + + /* Formulas for filter at page 25 of the datasheet */ + fadc = DIV_ROUND_CLOSEST(st->fclk, + AD7192_SYNC4_FILTER * AD7192_MODE_RATE(st->mode)); + freq[0] = DIV_ROUND_CLOSEST(fadc * 240, 1024); + + fadc = DIV_ROUND_CLOSEST(st->fclk, + AD7192_SYNC3_FILTER * AD7192_MODE_RATE(st->mode)); + freq[1] = DIV_ROUND_CLOSEST(fadc * 240, 1024); + + fadc = DIV_ROUND_CLOSEST(st->fclk, AD7192_MODE_RATE(st->mode)); + freq[2] = DIV_ROUND_CLOSEST(fadc * 230, 1024); + freq[3] = DIV_ROUND_CLOSEST(fadc * 272, 1024); +} + +static ssize_t ad7192_show_filter_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad7192_state *st = iio_priv(indio_dev); + unsigned int freq_avail[4], i; + size_t len = 0; + + ad7192_get_available_filter_freq(st, freq_avail); + + for (i = 0; i < ARRAY_SIZE(freq_avail); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, + "%d.%d ", freq_avail[i] / 1000, + freq_avail[i] % 1000); + + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEVICE_ATTR(filter_low_pass_3db_frequency_available, + 0444, ad7192_show_filter_avail, NULL, 0); + static IIO_DEVICE_ATTR(bridge_switch_en, 0644, ad7192_show_bridge_switch, ad7192_set, AD7192_REG_GPOCON); @@ -420,6 +453,7 @@ static IIO_DEVICE_ATTR(ac_excitation_en, 0644, AD7192_REG_MODE); static struct attribute *ad7192_attributes[] = { + &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_bridge_switch_en.dev_attr.attr, &iio_dev_attr_ac_excitation_en.dev_attr.attr, NULL @@ -430,6 +464,7 @@ static const struct attribute_group ad7192_attribute_group = { }; static struct attribute *ad7195_attributes[] = { + &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_bridge_switch_en.dev_attr.attr, NULL }; @@ -443,6 +478,75 @@ static unsigned int ad7192_get_temp_scale(bool unipolar) return unipolar ? 2815 * 2 : 2815; } +static int ad7192_set_3db_filter_freq(struct ad7192_state *st, + int val, int val2) +{ + int freq_avail[4], i, ret, freq; + unsigned int diff_new, diff_old; + int idx = 0; + + diff_old = U32_MAX; + freq = val * 1000 + val2; + + ad7192_get_available_filter_freq(st, freq_avail); + + for (i = 0; i < ARRAY_SIZE(freq_avail); i++) { + diff_new = abs(freq - freq_avail[i]); + if (diff_new < diff_old) { + diff_old = diff_new; + idx = i; + } + } + + switch (idx) { + case 0: + st->f_order = AD7192_SYNC4_FILTER; + st->mode &= ~AD7192_MODE_SINC3; + + st->conf |= AD7192_CONF_CHOP; + break; + case 1: + st->f_order = AD7192_SYNC3_FILTER; + st->mode |= AD7192_MODE_SINC3; + + st->conf |= AD7192_CONF_CHOP; + break; + case 2: + st->f_order = AD7192_NO_SYNC_FILTER; + st->mode &= ~AD7192_MODE_SINC3; + + st->conf &= ~AD7192_CONF_CHOP; + break; + case 3: + st->f_order = AD7192_NO_SYNC_FILTER; + st->mode |= AD7192_MODE_SINC3; + + st->conf &= ~AD7192_CONF_CHOP; + break; + } + + ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); + if (ret < 0) + return ret; + + return ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf); +} + +static int ad7192_get_3db_filter_freq(struct ad7192_state *st) +{ + unsigned int fadc; + + fadc = DIV_ROUND_CLOSEST(st->fclk, + st->f_order * AD7192_MODE_RATE(st->mode)); + + if (st->conf & AD7192_CONF_CHOP) + return DIV_ROUND_CLOSEST(fadc * 240, 1024); + if (st->mode & AD7192_MODE_SINC3) + return DIV_ROUND_CLOSEST(fadc * 272, 1024); + else + return DIV_ROUND_CLOSEST(fadc * 230, 1024); +} + static int ad7192_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -483,6 +587,10 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, *val = st->fclk / (st->f_order * 1024 * AD7192_MODE_RATE(st->mode)); return IIO_VAL_INT; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *val = ad7192_get_3db_filter_freq(st); + *val2 = 1000; + return IIO_VAL_FRACTIONAL; } return -EINVAL; @@ -537,6 +645,9 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, st->mode |= AD7192_MODE_RATE(div); ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); break; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + ret = ad7192_set_3db_filter_freq(st, val, val2 / 1000); + break; default: ret = -EINVAL; } @@ -555,6 +666,8 @@ static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_NANO; case IIO_CHAN_INFO_SAMP_FREQ: return IIO_VAL_INT; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } @@ -655,6 +768,8 @@ static int ad7192_channels_config(struct iio_dev *indio_dev) for (i = 0; i < indio_dev->num_channels; i++) { *chan = channels[i]; + chan->info_mask_shared_by_all |= + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY); if (chan->type != IIO_TEMP) chan->info_mask_shared_by_type_available |= BIT(IIO_CHAN_INFO_SCALE); @@ -666,16 +781,10 @@ static int ad7192_channels_config(struct iio_dev *indio_dev) static int ad7192_probe(struct spi_device *spi) { - const struct ad7192_platform_data *pdata = dev_get_platdata(&spi->dev); struct ad7192_state *st; struct iio_dev *indio_dev; int ret, voltage_uv = 0; - if (!pdata) { - dev_err(&spi->dev, "no platform data?\n"); - return -ENODEV; - } - if (!spi->irq) { dev_err(&spi->dev, "no IRQ?\n"); return -ENODEV; @@ -713,12 +822,10 @@ static int ad7192_probe(struct spi_device *spi) voltage_uv = regulator_get_voltage(st->avdd); - if (pdata->vref_mv) - st->int_vref_mv = pdata->vref_mv; - else if (voltage_uv) + if (voltage_uv) st->int_vref_mv = voltage_uv / 1000; else - dev_warn(&spi->dev, "reference voltage undefined\n"); + dev_err(&spi->dev, "Device tree error, reference voltage undefined\n"); spi_set_drvdata(spi, indio_dev); st->devid = spi_get_device_id(spi)->driver_data; @@ -809,11 +916,23 @@ static const struct spi_device_id ad7192_id[] = { {"ad7195", ID_AD7195}, {} }; + MODULE_DEVICE_TABLE(spi, ad7192_id); +static const struct of_device_id ad7192_of_match[] = { + { .compatible = "adi,ad7190" }, + { .compatible = "adi,ad7192" }, + { .compatible = "adi,ad7193" }, + { .compatible = "adi,ad7195" }, + {} +}; + +MODULE_DEVICE_TABLE(of, ad7192_of_match); + static struct spi_driver ad7192_driver = { .driver = { .name = "ad7192", + .of_match_table = ad7192_of_match, }, .probe = ad7192_probe, .remove = ad7192_remove, diff --git a/drivers/staging/iio/adc/ad7192.h b/drivers/staging/iio/adc/ad7192.h deleted file mode 100644 index f3669e1df084..000000000000 --- a/drivers/staging/iio/adc/ad7192.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * AD7190 AD7192 AD7195 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - */ -#ifndef IIO_ADC_AD7192_H_ -#define IIO_ADC_AD7192_H_ - -/* - * TODO: struct ad7192_platform_data needs to go into include/linux/iio - */ - -/** - * struct ad7192_platform_data - platform/board specific information - * @vref_mv: the external reference voltage in millivolt - * @clock_source_sel: [0..3] - * 0 External 4.92 MHz clock connected from MCLK1 to MCLK2 - * 1 External Clock applied to MCLK2 - * 2 Internal 4.92 MHz Clock not available at the MCLK2 pin - * 3 Internal 4.92 MHz Clock available at the MCLK2 pin - * @ext_clk_Hz: the external clock frequency in Hz, if not set - * the driver uses the internal clock (16.776 MHz) - * @refin2_en: REFIN1/REFIN2 Reference Select (AD7190/2 only) - * @rej60_en: 50/60Hz notch filter enable - * @sinc3_en: SINC3 filter enable (default SINC4) - * @chop_en: CHOP mode enable - * @buf_en: buffered input mode enable - * @unipolar_en: unipolar mode enable - * @burnout_curr_en: constant current generators on AIN(+|-) enable - */ - -struct ad7192_platform_data { - u16 vref_mv; -}; - -#endif /* IIO_ADC_AD7192_H_ */ diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index 0c1bd108c386..4b25a3a314ed 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -671,7 +671,7 @@ static int ad2s1210_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(ad2s1210_channels); indio_dev->name = spi_get_device_id(spi)->name; - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) return ret; @@ -683,15 +683,6 @@ static int ad2s1210_probe(struct spi_device *spi) return 0; } -static int ad2s1210_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - - return 0; -} - static const struct of_device_id ad2s1210_of_match[] = { { .compatible = "adi,ad2s1210", }, { } @@ -710,7 +701,6 @@ static struct spi_driver ad2s1210_driver = { .of_match_table = of_match_ptr(ad2s1210_of_match), }, .probe = ad2s1210_probe, - .remove = ad2s1210_remove, .id_table = ad2s1210_id, }; module_spi_driver(ad2s1210_driver); diff --git a/drivers/staging/isdn/hysdn/hysdn_net.c b/drivers/staging/isdn/hysdn/hysdn_net.c index bea37ae30ebb..dcb9ef7a2651 100644 --- a/drivers/staging/isdn/hysdn/hysdn_net.c +++ b/drivers/staging/isdn/hysdn/hysdn_net.c @@ -286,7 +286,7 @@ hysdn_net_create(hysdn_card *card) if (card->debug_flags & LOG_NET_INIT) hysdn_addlog(card, "network device created"); - return (0); /* and return success */ + return 0; /* and return success */ } /* hysdn_net_create */ /***************************************************************************/ diff --git a/drivers/staging/isdn/hysdn/hysdn_procconf.c b/drivers/staging/isdn/hysdn/hysdn_procconf.c index 73079213ec94..48afd9f5316e 100644 --- a/drivers/staging/isdn/hysdn/hysdn_procconf.c +++ b/drivers/staging/isdn/hysdn/hysdn_procconf.c @@ -382,7 +382,7 @@ hysdn_procconf_init(void) } printk(KERN_NOTICE "HYSDN: procfs initialised\n"); - return (0); + return 0; } /* hysdn_procconf_init */ /*************************************************************************************/ diff --git a/drivers/staging/kpc2000/kpc2000/cell_probe.c b/drivers/staging/kpc2000/kpc2000/cell_probe.c index c124a836db27..738122afc2ae 100644 --- a/drivers/staging/kpc2000/kpc2000/cell_probe.c +++ b/drivers/staging/kpc2000/kpc2000/cell_probe.c @@ -53,15 +53,15 @@ struct core_table_entry { static void parse_core_table_entry_v0(struct core_table_entry *cte, const u64 read_val) { - cte->type = ((read_val & 0xFFF0000000000000) >> 52); - cte->offset = ((read_val & 0x00000000FFFF0000) >> 16) * 4096; - cte->length = ((read_val & 0x0000FFFF00000000) >> 32) * 8; - cte->s2c_dma_present = ((read_val & 0x0008000000000000) >> 51); - cte->s2c_dma_channel_num = ((read_val & 0x0007000000000000) >> 48); - cte->c2s_dma_present = ((read_val & 0x0000000000008000) >> 15); - cte->c2s_dma_channel_num = ((read_val & 0x0000000000007000) >> 12); - cte->irq_count = ((read_val & 0x0000000000000C00) >> 10); - cte->irq_base_num = ((read_val & 0x00000000000003F8) >> 3); + cte->type = ((read_val & 0xFFF0000000000000UL) >> 52); + cte->offset = ((read_val & 0x00000000FFFF0000UL) >> 16) * 4096; + cte->length = ((read_val & 0x0000FFFF00000000UL) >> 32) * 8; + cte->s2c_dma_present = ((read_val & 0x0008000000000000UL) >> 51); + cte->s2c_dma_channel_num = ((read_val & 0x0007000000000000UL) >> 48); + cte->c2s_dma_present = ((read_val & 0x0000000000008000UL) >> 15); + cte->c2s_dma_channel_num = ((read_val & 0x0000000000007000UL) >> 12); + cte->irq_count = ((read_val & 0x0000000000000C00UL) >> 10); + cte->irq_base_num = ((read_val & 0x00000000000003F8UL) >> 3); } static diff --git a/drivers/staging/kpc2000/kpc2000/core.c b/drivers/staging/kpc2000/kpc2000/core.c index cb05cca687e1..0a23727d0dc3 100644 --- a/drivers/staging/kpc2000/kpc2000/core.c +++ b/drivers/staging/kpc2000/kpc2000/core.c @@ -205,7 +205,7 @@ static void wait_and_read_ssid(struct kp2000_device *pcard) u64 read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); unsigned long timeout; - if (read_val & 0x8000000000000000) { + if (read_val & 0x8000000000000000UL) { pcard->ssid = read_val; return; } @@ -213,7 +213,7 @@ static void wait_and_read_ssid(struct kp2000_device *pcard) timeout = jiffies + (HZ * 2); do { read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); - if (read_val & 0x8000000000000000) { + if (read_val & 0x8000000000000000UL) { pcard->ssid = read_val; return; } @@ -241,16 +241,16 @@ static int read_system_regs(struct kp2000_device *pcard) } read_val = readq(pcard->sysinfo_regs_base + REG_CARD_ID_AND_BUILD); - pcard->card_id = (read_val & 0xFFFFFFFF00000000) >> 32; - pcard->build_version = (read_val & 0x00000000FFFFFFFF) >> 0; + pcard->card_id = (read_val & 0xFFFFFFFF00000000UL) >> 32; + pcard->build_version = (read_val & 0x00000000FFFFFFFFUL) >> 0; read_val = readq(pcard->sysinfo_regs_base + REG_DATE_AND_TIME_STAMPS); - pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000) >> 32; - pcard->build_timestamp = (read_val & 0x00000000FFFFFFFF) >> 0; + pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000UL) >> 32; + pcard->build_timestamp = (read_val & 0x00000000FFFFFFFFUL) >> 0; read_val = readq(pcard->sysinfo_regs_base + REG_CORE_TABLE_OFFSET); - pcard->core_table_length = (read_val & 0xFFFFFFFF00000000) >> 32; - pcard->core_table_offset = (read_val & 0x00000000FFFFFFFF) >> 0; + pcard->core_table_length = (read_val & 0xFFFFFFFF00000000UL) >> 32; + pcard->core_table_offset = (read_val & 0x00000000FFFFFFFFUL) >> 0; wait_and_read_ssid(pcard); @@ -401,7 +401,7 @@ static int kp2000_pcie_probe(struct pci_dev *pdev, goto err_release_dma; // Disable all "user" interrupts because they're not used yet. - writeq(0xFFFFFFFFFFFFFFFF, + writeq(0xFFFFFFFFFFFFFFFFUL, pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); // let the card master PCIe diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index b108da4ac633..bc02534d8dc3 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -123,9 +123,9 @@ struct i2c_device { // FIXME! #undef inb_p -#define inb_p(a) readq((void *)a) +#define inb_p(a) readq((void __iomem *)a) #undef outb_p -#define outb_p(d, a) writeq(d, (void *)a) +#define outb_p(d, a) writeq(d, (void __iomem *)a) /* Make sure the SMBus host is ready to start transmitting. * Return 0 if it is, -EBUSY if it is not. diff --git a/drivers/staging/kpc2000/kpc2000_spi.c b/drivers/staging/kpc2000/kpc2000_spi.c index 35ac1d7070b3..3be33c450cab 100644 --- a/drivers/staging/kpc2000/kpc2000_spi.c +++ b/drivers/staging/kpc2000/kpc2000_spi.c @@ -412,8 +412,7 @@ kp_spi_cleanup(struct spi_device *spidev) { struct kp_spi_controller_state *cs = spidev->controller_state; - if (cs) - kfree(cs); + kfree(cs); } /****************** diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c index 48ca88bc6b0b..cb52bd9a6d2f 100644 --- a/drivers/staging/kpc2000/kpc_dma/fileops.c +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c @@ -146,15 +146,15 @@ static int kpc_dma_transfer(struct dev_private_data *priv, card_addr += desc->DescByteCount; dma_addr = sg_dma_address(sg) + (p * 0x80000); - desc->DescSystemAddrLS = (dma_addr & 0x00000000FFFFFFFF) >> 0; - desc->DescSystemAddrMS = (dma_addr & 0xFFFFFFFF00000000) >> 32; + desc->DescSystemAddrLS = (dma_addr & 0x00000000FFFFFFFFUL) >> 0; + desc->DescSystemAddrMS = (dma_addr & 0xFFFFFFFF00000000UL) >> 32; user_ctl = acd->priv->user_ctl; if (i == acd->mapped_entry_count-1 && p == pcnt-1) { user_ctl = acd->priv->user_ctl_last; } - desc->DescUserControlLS = (user_ctl & 0x00000000FFFFFFFF) >> 0; - desc->DescUserControlMS = (user_ctl & 0xFFFFFFFF00000000) >> 32; + desc->DescUserControlLS = (user_ctl & 0x00000000FFFFFFFFUL) >> 0; + desc->DescUserControlMS = (user_ctl & 0xFFFFFFFF00000000UL) >> 32; if (i == acd->mapped_entry_count-1 && p == pcnt-1) desc->acd = acd; diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index f050c7347fd5..6f0cd0784786 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -2947,10 +2947,8 @@ static int allegro_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq resource\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(&pdev->dev, irq, allegro_hardirq, allegro_irq_thread, diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index d8b6816b643b..6d9d41170832 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -797,10 +797,8 @@ static int hantro_probe(struct platform_device *pdev) continue; irq = platform_get_irq_byname(vpu->pdev, irq_name); - if (irq <= 0) { - dev_err(vpu->dev, "Could not get %s IRQ.\n", irq_name); + if (irq <= 0) return -ENXIO; - } ret = devm_request_irq(vpu->dev, irq, vpu->variant->irqs[i].handler, 0, diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c index 4ca79ff4c9b3..bfd6b5fbf484 100644 --- a/drivers/staging/media/imx/imx7-media-csi.c +++ b/drivers/staging/media/imx/imx7-media-csi.c @@ -1205,10 +1205,8 @@ static int imx7_csi_probe(struct platform_device *pdev) } csi->irq = platform_get_irq(pdev, 0); - if (csi->irq < 0) { - dev_err(dev, "Missing platform resources data\n"); + if (csi->irq < 0) return csi->irq; - } csi->regbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(csi->regbase)) diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c index d1cdf011c8f1..73d8354e618c 100644 --- a/drivers/staging/media/imx/imx7-mipi-csis.c +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -975,10 +975,8 @@ static int mipi_csis_probe(struct platform_device *pdev) return PTR_ERR(state->regs); state->irq = platform_get_irq(pdev, 0); - if (state->irq < 0) { - dev_err(dev, "Failed to get irq\n"); + if (state->irq < 0) return state->irq; - } ret = mipi_csis_clk_get(state); if (ret < 0) diff --git a/drivers/staging/media/meson/vdec/esparser.c b/drivers/staging/media/meson/vdec/esparser.c index 3a21a8cec799..95102a4bdc62 100644 --- a/drivers/staging/media/meson/vdec/esparser.c +++ b/drivers/staging/media/meson/vdec/esparser.c @@ -301,10 +301,8 @@ int esparser_init(struct platform_device *pdev, struct amvdec_core *core) int irq; irq = platform_get_irq_byname(pdev, "esparser"); - if (irq < 0) { - dev_err(dev, "Failed getting ESPARSER IRQ from dtb\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(dev, irq, esparser_isr, IRQF_SHARED, "esparserirq", core); diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index c8be1db532ab..1a966cb2f3a6 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -1276,7 +1276,6 @@ static int iss_probe(struct platform_device *pdev) /* Interrupt */ ret = platform_get_irq(pdev, 0); if (ret <= 0) { - dev_err(iss->dev, "No IRQ resource\n"); ret = -ENODEV; goto error_iss; } diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c index fc8579b90dab..a942cd9bed57 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c @@ -157,11 +157,8 @@ int cedrus_hw_probe(struct cedrus_dev *dev) dev->capabilities = variant->capabilities; irq_dec = platform_get_irq(dev->pdev, 0); - if (irq_dec <= 0) { - dev_err(dev->dev, "Failed to get IRQ\n"); - + if (irq_dec <= 0) return irq_dec; - } ret = devm_request_irq(dev->dev, irq_dec, cedrus_irq, 0, dev_name(dev->dev), dev); if (ret) { diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index d0cc0b746107..724d098aeef0 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -463,10 +463,8 @@ static int comp_probe(struct most_interface *iface, int channel_id, spin_lock_init(&c->unlink); INIT_KFIFO(c->fifo); retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL); - if (retval) { - pr_info("failed to alloc channel kfifo"); + if (retval) goto err_del_cdev_and_free_channel; - } init_waitqueue_head(&c->wq); mutex_init(&c->io_mutex); spin_lock_irqsave(&ch_list_lock, cl_flags); diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index b9841adb7181..8e9a0b67c6ed 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -303,7 +303,8 @@ static ssize_t set_datatype_show(struct device *dev, for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) - return snprintf(buf, PAGE_SIZE, "%s", ch_data_type[i].name); + return snprintf(buf, PAGE_SIZE, "%s", + ch_data_type[i].name); } return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } @@ -721,6 +722,7 @@ int most_add_link(char *mdev, char *mdev_ch, char *comp_name, char *link_name, return link_channel_to_component(c, comp, link_name, comp_param); } + /** * remove_link_store - store function for remove_link attribute * @drv: device driver diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 31fbc1a75b06..64c979155a49 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -129,25 +129,6 @@ bool dim2_sysfs_get_state_cb(void) } /** - * dimcb_io_read - callback from HAL to read an I/O register - * @ptr32: register address - */ -u32 dimcb_io_read(u32 __iomem *ptr32) -{ - return readl(ptr32); -} - -/** - * dimcb_io_write - callback from HAL to write value to an I/O register - * @ptr32: register address - * @value: value to write - */ -void dimcb_io_write(u32 __iomem *ptr32, u32 value) -{ - writel(value, ptr32); -} - -/** * dimcb_on_error - callback from HAL to report miscommunication between * HDM and HAL * @error_id: Error ID @@ -797,7 +778,6 @@ static int dim2_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, AHB0_INT_IDX); if (irq < 0) { - dev_err(&pdev->dev, "failed to get ahb0_int irq: %d\n", irq); ret = irq; goto err_shutdown_dim; } @@ -811,7 +791,6 @@ static int dim2_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, MLB_INT_IDX); if (irq < 0) { - dev_err(&pdev->dev, "failed to get mlb_int irq: %d\n", irq); ret = irq; goto err_shutdown_dim; } diff --git a/drivers/staging/most/dim2/hal.c b/drivers/staging/most/dim2/hal.c index 699e02f83bd4..39e17a7d2f24 100644 --- a/drivers/staging/most/dim2/hal.c +++ b/drivers/staging/most/dim2/hal.c @@ -13,6 +13,7 @@ #include "reg.h" #include <linux/stddef.h> #include <linux/kernel.h> +#include <linux/io.h> /* * Size factor for isochronous DBR buffer. @@ -143,13 +144,13 @@ static void free_dbr(int offs, int size) static void dim2_transfer_madr(u32 val) { - dimcb_io_write(&g.dim2->MADR, val); + writel(val, &g.dim2->MADR); /* wait for transfer completion */ - while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) + while ((readl(&g.dim2->MCTL) & 1) != 1) continue; - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + writel(0, &g.dim2->MCTL); /* clear transfer complete */ } static void dim2_clear_dbr(u16 addr, u16 size) @@ -159,8 +160,8 @@ static void dim2_clear_dbr(u16 addr, u16 size) u16 const end_addr = addr + size; u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT); - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ - dimcb_io_write(&g.dim2->MDAT0, 0); + writel(0, &g.dim2->MCTL); /* clear transfer complete */ + writel(0, &g.dim2->MDAT0); for (; addr < end_addr; addr++) dim2_transfer_madr(cmd | addr); @@ -170,28 +171,28 @@ static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) { dim2_transfer_madr(ctr_addr); - return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx); + return readl((&g.dim2->MDAT0) + mdat_idx); } static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) { enum { MADR_WNR_BIT = 31 }; - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + writel(0, &g.dim2->MCTL); /* clear transfer complete */ if (mask[0] != 0) - dimcb_io_write(&g.dim2->MDAT0, value[0]); + writel(value[0], &g.dim2->MDAT0); if (mask[1] != 0) - dimcb_io_write(&g.dim2->MDAT1, value[1]); + writel(value[1], &g.dim2->MDAT1); if (mask[2] != 0) - dimcb_io_write(&g.dim2->MDAT2, value[2]); + writel(value[2], &g.dim2->MDAT2); if (mask[3] != 0) - dimcb_io_write(&g.dim2->MDAT3, value[3]); + writel(value[3], &g.dim2->MDAT3); - dimcb_io_write(&g.dim2->MDWE0, mask[0]); - dimcb_io_write(&g.dim2->MDWE1, mask[1]); - dimcb_io_write(&g.dim2->MDWE2, mask[2]); - dimcb_io_write(&g.dim2->MDWE3, mask[3]); + writel(mask[0], &g.dim2->MDWE0); + writel(mask[1], &g.dim2->MDWE1); + writel(mask[2], &g.dim2->MDWE2); + writel(mask[3], &g.dim2->MDWE3); dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr); } @@ -356,15 +357,13 @@ static void dim2_configure_channel( dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1); /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */ - dimcb_io_write(&g.dim2->ACMR0, - dimcb_io_read(&g.dim2->ACMR0) | bit_mask(ch_addr)); + writel(readl(&g.dim2->ACMR0) | bit_mask(ch_addr), &g.dim2->ACMR0); } static void dim2_clear_channel(u8 ch_addr) { /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */ - dimcb_io_write(&g.dim2->ACMR0, - dimcb_io_read(&g.dim2->ACMR0) & ~bit_mask(ch_addr)); + writel(readl(&g.dim2->ACMR0) & ~bit_mask(ch_addr), &g.dim2->ACMR0); dim2_clear_cat(AHB_CAT, ch_addr); dim2_clear_adt(ch_addr); @@ -373,7 +372,7 @@ static void dim2_clear_channel(u8 ch_addr) dim2_clear_cdt(ch_addr); /* clear channel status bit */ - dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); + writel(bit_mask(ch_addr), &g.dim2->ACSR0); } /* -------------------------------------------------------------------------- */ @@ -471,7 +470,7 @@ static inline bool check_bytes_per_frame(u32 bytes_per_frame) return true; } -static inline u16 norm_ctrl_async_buffer_size(u16 buf_size) +u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) { u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u; @@ -517,20 +516,20 @@ static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) static void dim2_cleanup(void) { /* disable MediaLB */ - dimcb_io_write(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT); + writel(false << MLBC0_MLBEN_BIT, &g.dim2->MLBC0); dim2_clear_ctram(); /* disable mlb_int interrupt */ - dimcb_io_write(&g.dim2->MIEN, 0); + writel(0, &g.dim2->MIEN); /* clear status for all dma channels */ - dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF); - dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF); + writel(0xFFFFFFFF, &g.dim2->ACSR0); + writel(0xFFFFFFFF, &g.dim2->ACSR1); /* mask interrupts for all channels */ - dimcb_io_write(&g.dim2->ACMR0, 0); - dimcb_io_write(&g.dim2->ACMR1, 0); + writel(0, &g.dim2->ACMR0); + writel(0, &g.dim2->ACMR1); } static void dim2_initialize(bool enable_6pin, u8 mlb_clock) @@ -538,23 +537,22 @@ static void dim2_initialize(bool enable_6pin, u8 mlb_clock) dim2_cleanup(); /* configure and enable MediaLB */ - dimcb_io_write(&g.dim2->MLBC0, - enable_6pin << MLBC0_MLBPEN_BIT | - mlb_clock << MLBC0_MLBCLK_SHIFT | - g.fcnt << MLBC0_FCNT_SHIFT | - true << MLBC0_MLBEN_BIT); + writel(enable_6pin << MLBC0_MLBPEN_BIT | + mlb_clock << MLBC0_MLBCLK_SHIFT | + g.fcnt << MLBC0_FCNT_SHIFT | + true << MLBC0_MLBEN_BIT, + &g.dim2->MLBC0); /* activate all HBI channels */ - dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF); - dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF); + writel(0xFFFFFFFF, &g.dim2->HCMR0); + writel(0xFFFFFFFF, &g.dim2->HCMR1); /* enable HBI */ - dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT)); + writel(bit_mask(HCTL_EN_BIT), &g.dim2->HCTL); /* configure DMA */ - dimcb_io_write(&g.dim2->ACTL, - ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT | - true << ACTL_SCE_BIT); + writel(ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT | + true << ACTL_SCE_BIT, &g.dim2->ACTL); } static bool dim2_is_mlb_locked(void) @@ -562,12 +560,12 @@ static bool dim2_is_mlb_locked(void) u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT); u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) | bit_mask(MLBC1_LOCKERR_BIT); - u32 const c1 = dimcb_io_read(&g.dim2->MLBC1); + u32 const c1 = readl(&g.dim2->MLBC1); u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT; - dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask); - return (dimcb_io_read(&g.dim2->MLBC1) & mask1) == 0 && - (dimcb_io_read(&g.dim2->MLBC0) & mask0) != 0; + writel(c1 & nda_mask, &g.dim2->MLBC1); + return (readl(&g.dim2->MLBC1) & mask1) == 0 && + (readl(&g.dim2->MLBC0) & mask0) != 0; } /* -------------------------------------------------------------------------- */ @@ -590,7 +588,7 @@ static inline bool service_channel(u8 ch_addr, u8 idx) dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w); /* clear channel status bit */ - dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); + writel(bit_mask(ch_addr), &g.dim2->ACSR0); return true; } @@ -652,7 +650,7 @@ static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size) return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size"); if (ch->packet_length == 0 && ch->bytes_per_frame == 0 && - buf_size != norm_ctrl_async_buffer_size(buf_size)) + buf_size != dim_norm_ctrl_async_buffer_size(buf_size)) return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad control/async buffer size"); @@ -776,13 +774,8 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, void dim_service_mlb_int_irq(void) { - dimcb_io_write(&g.dim2->MS0, 0); - dimcb_io_write(&g.dim2->MS1, 0); -} - -u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) -{ - return norm_ctrl_async_buffer_size(buf_size); + writel(0, &g.dim2->MS0); + writel(0, &g.dim2->MS1); } /** @@ -829,7 +822,7 @@ u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address, if (is_tx && !g.atx_dbr.ch_addr) { g.atx_dbr.ch_addr = ch->addr; dbrcnt_init(ch->addr, ch->dbr_size); - dimcb_io_write(&g.dim2->MIEN, bit_mask(20)); + writel(bit_mask(20), &g.dim2->MIEN); } return ret; @@ -896,7 +889,7 @@ u8 dim_destroy_channel(struct dim_channel *ch) return DIM_ERR_DRIVER_NOT_INITIALIZED; if (ch->addr == g.atx_dbr.ch_addr) { - dimcb_io_write(&g.dim2->MIEN, 0); + writel(0, &g.dim2->MIEN); g.atx_dbr.ch_addr = 0; } diff --git a/drivers/staging/most/dim2/hal.h b/drivers/staging/most/dim2/hal.h index fca6c22de8a6..20531449acab 100644 --- a/drivers/staging/most/dim2/hal.h +++ b/drivers/staging/most/dim2/hal.h @@ -97,10 +97,6 @@ bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number); -u32 dimcb_io_read(u32 __iomem *ptr32); - -void dimcb_io_write(u32 __iomem *ptr32, u32 value); - void dimcb_on_error(u8 error_id, const char *error_message); #endif /* _DIM2_HAL_H */ diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index aababdf2be12..26a31854c636 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -69,7 +69,7 @@ struct net_dev_context { static struct list_head net_devices = LIST_HEAD_INIT(net_devices); static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */ -static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */ +static DEFINE_SPINLOCK(list_lock); /* list_head, ch->linked = false, dev_hold */ static struct core_component comp; static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) @@ -509,7 +509,6 @@ static int __init most_net_init(void) { int err; - spin_lock_init(&list_lock); mutex_init(&probe_disc_mt); err = most_register_component(&comp); if (err) diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 342f390d68b3..79817061fcfa 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -802,8 +802,11 @@ static int __init audio_init(void) if (ret) pr_err("Failed to register %s\n", comp.name); ret = most_register_configfs_subsys(&comp); - if (ret) + if (ret) { pr_err("Failed to register %s configfs subsys\n", comp.name); + most_deregister_component(&comp); + } + return ret; } diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 6f6e98ab0550..250af9fb704d 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -54,7 +54,7 @@ struct comp_fh { }; static struct list_head video_devices = LIST_HEAD_INIT(video_devices); -static struct spinlock list_lock; +static DEFINE_SPINLOCK(list_lock); static inline bool data_ready(struct most_video_dev *mdev) { @@ -538,7 +538,6 @@ static int __init comp_init(void) { int err; - spin_lock_init(&list_lock); err = most_register_component(&comp); if (err) return err; diff --git a/drivers/staging/mt7621-dma/mtk-hsdma.c b/drivers/staging/mt7621-dma/mtk-hsdma.c index 60db06768c8a..d964642d95a3 100644 --- a/drivers/staging/mt7621-dma/mtk-hsdma.c +++ b/drivers/staging/mt7621-dma/mtk-hsdma.c @@ -675,10 +675,8 @@ static int mtk_hsdma_probe(struct platform_device *pdev) tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (irq < 0) return -EINVAL; - } ret = devm_request_irq(&pdev->dev, irq, mtk_hsdma_irq, 0, dev_name(&pdev->dev), hsdma); if (ret) { diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c index 89fa813142ab..6b98827da57f 100644 --- a/drivers/staging/mt7621-pci/pci-mt7621.c +++ b/drivers/staging/mt7621-pci/pci-mt7621.c @@ -400,6 +400,7 @@ static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie) err = of_pci_get_devfn(child); if (err < 0) { + of_node_put(child); dev_err(dev, "failed to parse devfn: %d\n", err); return err; } @@ -407,8 +408,10 @@ static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie) slot = PCI_SLOT(err); err = mt7621_pcie_parse_port(pcie, child, slot); - if (err) + if (err) { + of_node_put(child); return err; + } } return 0; @@ -614,17 +617,12 @@ static int mt7621_pcie_request_resources(struct mt7621_pcie *pcie, struct list_head *res) { struct device *dev = pcie->dev; - int err; pci_add_resource_offset(res, &pcie->io, pcie->offset.io); pci_add_resource_offset(res, &pcie->mem, pcie->offset.mem); pci_add_resource(res, &pcie->busn); - err = devm_request_pci_bus_resources(dev, res); - if (err < 0) - return err; - - return 0; + return devm_request_pci_bus_resources(dev, res); } static int mt7621_pcie_register_host(struct pci_host_bridge *host, diff --git a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c index 9b52d44abef1..d0f06790d38f 100644 --- a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c +++ b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c @@ -358,12 +358,15 @@ static int rt2880_pinmux_probe(struct platform_device *pdev) gpiobase = of_get_property(np, "ralink,gpio-base", NULL); if (!ngpio || !gpiobase) { dev_err(&pdev->dev, "failed to load chip info\n"); + of_node_put(np); return -EINVAL; } range = devm_kzalloc(p->dev, sizeof(*range), GFP_KERNEL); - if (!range) + if (!range) { + of_node_put(np); return -ENOMEM; + } range->name = "pio"; range->npins = __be32_to_cpu(*ngpio); range->base = __be32_to_cpu(*gpiobase); diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 08027a36e0bc..360ec0407740 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -767,7 +767,6 @@ static int tegra_nvec_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct nvec_chip *nvec; struct nvec_msg *msg; - struct resource *res; void __iomem *base; char get_firmware_version[] = { NVEC_CNTL, GET_FIRMWARE_VERSION }, unmute_speakers[] = { NVEC_OEM0, 0x10, 0x59, 0x95 }, @@ -790,16 +789,13 @@ static int tegra_nvec_probe(struct platform_device *pdev) return -ENODEV; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); nvec->irq = platform_get_irq(pdev, 0); - if (nvec->irq < 0) { - dev_err(dev, "no irq resource?\n"); + if (nvec->irq < 0) return -ENODEV; - } i2c_clk = devm_clk_get(dev, "div-clk"); if (IS_ERR(i2c_clk)) { diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 8847a11c212f..33762f2e9a44 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -794,7 +794,7 @@ static int cvm_oct_probe(struct platform_device *pdev) priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED; priv->port = CVMX_PIP_NUM_INPUT_PORTS; priv->queue = -1; - strcpy(dev->name, "pow%d"); + strscpy(dev->name, "pow%d", sizeof(dev->name)); for (qos = 0; qos < 16; qos++) skb_queue_head_init(&priv->tx_free_list[qos]); dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead; @@ -866,39 +866,39 @@ static int cvm_oct_probe(struct platform_device *pdev) case CVMX_HELPER_INTERFACE_MODE_NPI: dev->netdev_ops = &cvm_oct_npi_netdev_ops; - strcpy(dev->name, "npi%d"); + strscpy(dev->name, "npi%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_XAUI: dev->netdev_ops = &cvm_oct_xaui_netdev_ops; - strcpy(dev->name, "xaui%d"); + strscpy(dev->name, "xaui%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_LOOP: dev->netdev_ops = &cvm_oct_npi_netdev_ops; - strcpy(dev->name, "loop%d"); + strscpy(dev->name, "loop%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_SGMII: priv->phy_mode = PHY_INTERFACE_MODE_SGMII; dev->netdev_ops = &cvm_oct_sgmii_netdev_ops; - strcpy(dev->name, "eth%d"); + strscpy(dev->name, "eth%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_SPI: dev->netdev_ops = &cvm_oct_spi_netdev_ops; - strcpy(dev->name, "spi%d"); + strscpy(dev->name, "spi%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_GMII: priv->phy_mode = PHY_INTERFACE_MODE_GMII; dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; - strcpy(dev->name, "eth%d"); + strscpy(dev->name, "eth%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_RGMII: dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; - strcpy(dev->name, "eth%d"); + strscpy(dev->name, "eth%d", sizeof(dev->name)); cvm_set_rgmii_delay(priv, interface, port_index); break; diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO index fe09efbc7f77..d8296f2ae872 100644 --- a/drivers/staging/olpc_dcon/TODO +++ b/drivers/staging/olpc_dcon/TODO @@ -8,10 +8,6 @@ TODO: internals, but isn't properly integrated, is not the correct solution. - see if vx855 gpio API can be made similar enough to cs5535 so we can share more code - - convert all uses of the old GPIO API from <linux/gpio.h> to the - GPIO descriptor API in <linux/gpio/consumer.h> and look up GPIO - lines from device tree, ACPI or board files, board files should - use <linux/gpio/machine.h> - allow simultaneous XO-1 and XO-1.5 support Please send patches to Greg Kroah-Hartman <greg@kroah.com> and diff --git a/drivers/staging/pi433/Documentation/pi433.txt b/drivers/staging/pi433/Documentation/pi433.txt index 21cffdb86ecf..4a0d34b4ad37 100644 --- a/drivers/staging/pi433/Documentation/pi433.txt +++ b/drivers/staging/pi433/Documentation/pi433.txt @@ -14,7 +14,7 @@ until something gets received terminates the read request. The driver supports on the fly reloading of the hardware fifo of the rf chip, thus enabling for much longer telegrams than the hardware fifo size. -Discription of driver operation +Description of driver operation =============================== a) transmission diff --git a/drivers/staging/ralink-gdma/ralink-gdma.c b/drivers/staging/ralink-gdma/ralink-gdma.c index 5854551d0a52..900424db9b97 100644 --- a/drivers/staging/ralink-gdma/ralink-gdma.c +++ b/drivers/staging/ralink-gdma/ralink-gdma.c @@ -826,10 +826,8 @@ static int gdma_dma_probe(struct platform_device *pdev) tasklet_init(&dma_dev->task, gdma_dma_tasklet, (unsigned long)dma_dev); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (irq < 0) return -EINVAL; - } ret = devm_request_irq(&pdev->dev, irq, gdma_dma_irq, 0, dev_name(&pdev->dev), dma_dev); if (ret) { diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index a24b40761af2..815dfee11968 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -1200,7 +1200,7 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) rtw_indicate_connect(padapter); } else { - pwlan = _rtw_alloc_network(pmlmepriv); + pwlan = rtw_alloc_network(pmlmepriv); spin_lock_bh(&pmlmepriv->scanned_queue.lock); if (!pwlan) { pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 51c3dd6d7ffb..02c476f45b33 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -108,7 +108,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* 1. Read the first byte to check if efuse is empty!!! */ /* */ /* */ - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if (rtemp8 != 0xFF) { efuse_utilized++; eFuse_Addr++; @@ -124,10 +124,10 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* Check PG header for section num. */ if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */ u1temp = (rtemp8 & 0xE0) >> 5; - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if ((rtemp8 & 0x0F) == 0x0F) { eFuse_Addr++; - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) eFuse_Addr++; @@ -147,13 +147,13 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { /* Check word enable condition in the section */ if (!(wren & 0x01)) { - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); eFuse_Addr++; efuse_utilized++; eFuseWord[offset][i] = (rtemp8 & 0xff); if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) break; - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); eFuse_Addr++; efuse_utilized++; eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00); @@ -165,7 +165,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) } } /* Read next PG header */ - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { efuse_utilized++; @@ -178,8 +178,8 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* */ for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) { for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { - efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff); - efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff); + efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff); + efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff); } } @@ -187,7 +187,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* 4. Copy from Efuse map to output pointer memory!!! */ /* */ for (i = 0; i < _size_byte; i++) - pbuf[i] = efuseTbl[_offset+i]; + pbuf[i] = efuseTbl[_offset + i]; /* */ /* 5. Calculate Efuse utilization. */ @@ -218,16 +218,16 @@ static void efuse_read_phymap_from_txpktbuf( u8 *pos = content; if (bcnhead < 0) /* if not valid */ - bcnhead = usb_read8(adapter, REG_TDECTRL+1); + bcnhead = usb_read8(adapter, REG_TDECTRL + 1); DBG_88E("%s bcnhead:%d\n", __func__, bcnhead); usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); - dbg_addr = bcnhead*128/8; /* 8-bytes addressing */ + dbg_addr = bcnhead * 128 / 8; /* 8-bytes addressing */ while (1) { - usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr+i); + usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr + i); usb_write8(adapter, REG_TXPKTBUF_DBG, 0); start = jiffies; @@ -246,34 +246,34 @@ static void efuse_read_phymap_from_txpktbuf( u16 aaa; lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L); - lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L+1); + lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L + 1); aaabak = le16_to_cpup((__le16 *)lenc); lenbak = le16_to_cpu(*((__le16 *)lenc)); aaa = le16_to_cpup((__le16 *)&lo32); len = le16_to_cpu(*((__le16 *)&lo32)); - limit = min_t(u16, len-2, limit); + limit = min_t(u16, len - 2, limit); DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak); - memcpy(pos, ((u8 *)&lo32)+2, (limit >= count+2) ? 2 : limit-count); - count += (limit >= count+2) ? 2 : limit-count; - pos = content+count; + memcpy(pos, ((u8 *)&lo32) + 2, (limit >= count + 2) ? 2 : limit - count); + count += (limit >= count + 2) ? 2 : limit - count; + pos = content + count; } else { - memcpy(pos, ((u8 *)&lo32), (limit >= count+4) ? 4 : limit-count); - count += (limit >= count+4) ? 4 : limit-count; - pos = content+count; + memcpy(pos, ((u8 *)&lo32), (limit >= count + 4) ? 4 : limit - count); + count += (limit >= count + 4) ? 4 : limit - count; + pos = content + count; } - if (limit > count && len-2 > count) { - memcpy(pos, (u8 *)&hi32, (limit >= count+4) ? 4 : limit-count); - count += (limit >= count+4) ? 4 : limit-count; - pos = content+count; + if (limit > count && len - 2 > count) { + memcpy(pos, (u8 *)&hi32, (limit >= count + 4) ? 4 : limit - count); + count += (limit >= count + 4) ? 4 : limit - count; + pos = content + count; } - if (limit <= count || len-2 <= count) + if (limit <= count || len - 2 <= count) break; i++; } @@ -288,7 +288,7 @@ static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset u8 physical_map[512]; u16 size = 512; - usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy); + usb_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy); memset(physical_map, 0xFF, 512); usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); status = iol_execute(padapter, CMD_READ_EFUSE_MAP); @@ -323,7 +323,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[1]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[1]); if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) badworden &= (~BIT(0)); } @@ -333,7 +333,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[3]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[3]); if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) badworden &= (~BIT(1)); } @@ -343,7 +343,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[5]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[5]); if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) badworden &= (~BIT(2)); } @@ -353,7 +353,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[7]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[7]); if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) badworden &= (~BIT(3)); } @@ -371,7 +371,7 @@ static u16 Efuse_GetCurrentSize(struct adapter *pAdapter) while (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && AVAILABLE_EFUSE_ADDR(efuse_addr)) { if (efuse_data != 0xFF) { - if ((efuse_data&0x1F) == 0x0F) { /* extended header */ + if ((efuse_data & 0x1F) == 0x0F) { /* extended header */ hoffset = efuse_data; efuse_addr++; efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data); @@ -383,12 +383,12 @@ static u16 Efuse_GetCurrentSize(struct adapter *pAdapter) hworden = efuse_data & 0x0F; } } else { - hoffset = (efuse_data>>4) & 0x0F; + hoffset = (efuse_data >> 4) & 0x0F; hworden = efuse_data & 0x0F; } word_cnts = Efuse_CalculateWordCnts(hworden); /* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; } else { break; } @@ -439,15 +439,15 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) continue; } } else { - hoffset = (efuse_data>>4) & 0x0F; + hoffset = (efuse_data >> 4) & 0x0F; hworden = efuse_data & 0x0F; } word_cnts = Efuse_CalculateWordCnts(hworden); bDataEmpty = true; if (hoffset == offset) { - for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) { - if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data)) { + for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) { + if (efuse_OneByteRead(pAdapter, efuse_addr + 1 + tmpidx, &efuse_data)) { tmpdata[tmpidx] = efuse_data; if (efuse_data != 0xff) bDataEmpty = false; @@ -456,11 +456,11 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) if (!bDataEmpty) { ReadState = PG_STATE_DATA; } else {/* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; ReadState = PG_STATE_HEADER; } } else {/* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; ReadState = PG_STATE_HEADER; } } else { @@ -469,7 +469,7 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) } else if (ReadState & PG_STATE_DATA) { /* Data section Read ------------- */ efuse_WordEnableDataRead(hworden, tmpdata, data); - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; ReadState = PG_STATE_HEADER; } } @@ -491,7 +491,7 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) { /* check if data exist */ - badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata); + badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pFixPkt->word_en, originaldata); if (badworden != 0xf) { /* write fail */ PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata); @@ -501,10 +501,10 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st else efuse_addr = Efuse_GetCurrentSize(pAdapter); } else { - efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; + efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1; } } else { - efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; + efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1; } *pAddr = efuse_addr; return true; @@ -601,7 +601,7 @@ static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuse } else { struct pgpkt fixPkt; - fixPkt.offset = (tmp_header>>4) & 0x0F; + fixPkt.offset = (tmp_header >> 4) & 0x0F; fixPkt.word_en = tmp_header & 0x0F; fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr)) @@ -619,7 +619,7 @@ static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u u32 PgWriteSuccess = 0; badworden = 0x0f; - badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data); + badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pTargetPkt->word_en, pTargetPkt->data); if (badworden == 0x0F) { /* write ok */ return true; @@ -681,8 +681,8 @@ static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, bool ret = false; u8 i, efuse_data; - for (i = 0; i < (word_cnts*2); i++) { - if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data) && (efuse_data != 0xFF)) + for (i = 0; i < (word_cnts * 2); i++) { + if (efuse_OneByteRead(pAdapter, (startAddr + i), &efuse_data) && (efuse_data != 0xFF)) ret = true; } return ret; @@ -721,7 +721,7 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u } } else { cur_header = efuse_data; - curPkt.offset = (cur_header>>4) & 0x0F; + curPkt.offset = (cur_header >> 4) & 0x0F; curPkt.word_en = cur_header & 0x0F; } @@ -729,10 +729,10 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u /* if same header is found but no data followed */ /* write some part of data followed by the header. */ if ((curPkt.offset == pTargetPkt->offset) && - (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1)) && + (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr + 1)) && wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) { /* Here to write partial data */ - badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data); + badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr + 1, matched_wden, pTargetPkt->data); if (badworden != 0x0F) { u32 PgWriteSuccess = 0; /* if write fail on some words, write these bad words again */ @@ -746,13 +746,13 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u } /* partial write ok, update the target packet for later use */ for (i = 0; i < 4; i++) { - if ((matched_wden & (0x1<<i)) == 0) /* this word has been written */ - pTargetPkt->word_en |= (0x1<<i); /* disable the word */ + if ((matched_wden & (0x1 << i)) == 0) /* this word has been written */ + pTargetPkt->word_en |= (0x1 << i); /* disable the word */ } pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); } /* read from next header */ - startAddr = startAddr + (curPkt.word_cnts*2) + 1; + startAddr = startAddr + (curPkt.word_cnts * 2) + 1; } else { /* not used header, 0xff */ *pAddr = startAddr; @@ -763,20 +763,9 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u return ret; } -static bool -hal_EfusePgCheckAvailableAddr( - struct adapter *pAdapter, - u8 efuseType - ) -{ - if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E) - return false; - return true; -} - static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt) { - memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8); + memset((void *)pTargetPkt->data, 0xFF, sizeof(u8) * 8); pTargetPkt->offset = offset; pTargetPkt->word_en = word_en; efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data); @@ -789,7 +778,7 @@ bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pD u16 startAddr = 0; u8 efuseType = EFUSE_WIFI; - if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType)) + if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E) return false; hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt); @@ -826,13 +815,13 @@ u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data) u8 tmpidx = 0; u8 result; - usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff)); - usb_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) | - (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC)); + usb_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); + usb_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) | + (usb_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC)); - usb_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */ + usb_write8(pAdapter, EFUSE_CTRL + 3, 0x72);/* read cmd */ - while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100)) + while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100)) tmpidx++; if (tmpidx < 100) { *data = usb_read8(pAdapter, EFUSE_CTRL); @@ -849,15 +838,15 @@ u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data) u8 tmpidx = 0; u8 result; - usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff)); - usb_write8(pAdapter, EFUSE_CTRL+2, - (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) | - (u8)((addr>>8) & 0x03)); + usb_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); + usb_write8(pAdapter, EFUSE_CTRL + 2, + (usb_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) | + (u8)((addr >> 8) & 0x03)); usb_write8(pAdapter, EFUSE_CTRL, data);/* data */ - usb_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */ + usb_write8(pAdapter, EFUSE_CTRL + 3, 0xF2);/* write cmd */ - while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100)) + while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100)) tmpidx++; if (tmpidx < 100) diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 28b3cdd10397..cc1b5438c04c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -59,7 +59,7 @@ static u8 WIFI_OFDMRATES[] = { int rtw_get_bit_value_from_ieee_value(u8 val) { - unsigned char dot11_rate_table[] = { + static const unsigned char dot11_rate_table[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0}; /* last element must be zero!! */ int i = 0; @@ -275,7 +275,7 @@ unsigned char *rtw_get_wpa_ie(unsigned char *pie, uint *wpa_ie_len, int limit) uint len; u16 val16; __le16 le_tmp; - unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01}; + static const unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01}; u8 *pbuf = pie; int limit_new = limit; diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index d2f7a88e992e..1ec3b237212e 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -104,7 +104,7 @@ void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv) } } -struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv) +struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv) /* _queue *free_queue) */ { struct wlan_network *pnetwork; @@ -119,7 +119,7 @@ struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv) list_del_init(&pnetwork->list); RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("_rtw_alloc_network: ptr=%p\n", &pnetwork->list)); + ("rtw_alloc_network: ptr=%p\n", &pnetwork->list)); pnetwork->network_type = 0; pnetwork->fixed = false; pnetwork->last_scanned = jiffies; @@ -272,11 +272,6 @@ u8 *rtw_get_beacon_interval_from_ie(u8 *ie) return ie + 8; } -static struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv) -{ - return _rtw_alloc_network(pmlmepriv); -} - int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork) { int ret = true; @@ -827,7 +822,7 @@ void rtw_indicate_disconnect(struct adapter *padapter) inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted) { - rtw_os_indicate_scan_done(padapter, aborted); + indicate_wx_scan_complete_event(padapter); } static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, struct wlan_network *pnetwork) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 6f3c03201f64..18dc9fc1c04a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -4854,7 +4854,7 @@ u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf) } rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type)); - /* Set_NETYPE0_MSR(padapter, type); */ + /* Set_MSR(padapter, type); */ return H2C_SUCCESS; } diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 9caf7041ad60..d4278361e002 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -145,8 +145,8 @@ int rtw_free_recvframe(struct recv_frame *precvframe, int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue) { - list_del_init(&(precvframe->list)); - list_add_tail(&(precvframe->list), get_list_head(queue)); + list_del_init(&precvframe->list); + list_add_tail(&precvframe->list, get_list_head(queue)); return _SUCCESS; } @@ -219,7 +219,7 @@ static int recvframe_chkmic(struct adapter *adapter, struct security_priv *psecuritypriv = &adapter->securitypriv; struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; stainfo = rtw_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]); @@ -1373,11 +1373,7 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter, /* append to first fragment frame's tail (if privacy frame, pull the ICV) */ skb_trim(prframe->pkt, prframe->pkt->len - prframe->attrib.icv_len); - /* memcpy */ - memcpy(skb_tail_pointer(prframe->pkt), pnfhdr->pkt->data, - pnfhdr->pkt->len); - - skb_put(prframe->pkt, pnfhdr->pkt->len); + skb_put_data(prframe->pkt, pnfhdr->pkt->data, pnfhdr->pkt->len); prframe->attrib.icv_len = pnfhdr->attrib.icv_len; plist = plist->next; @@ -1500,7 +1496,7 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe) struct rx_pkt_attrib *pattrib; struct sk_buff *sub_skb, *subframes[MAX_SUBFRAME_COUNT]; struct recv_priv *precvpriv = &padapter->recvpriv; - struct __queue *pfree_recv_queue = &(precvpriv->free_recv_queue); + struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue; nr_subframes = 0; pattrib = &prframe->attrib; diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index 2f90f60f1681..435c0fbec54a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -87,29 +87,28 @@ static u8 crc32_reverseBit(u8 data) static void crc32_init(void) { - if (bcrc32initialized == 1) { + int i, j; + u32 c; + u8 *p = (u8 *)&c, *p1; + u8 k; + + if (bcrc32initialized == 1) return; - } else { - int i, j; - u32 c; - u8 *p = (u8 *)&c, *p1; - u8 k; - - c = 0x12340000; - - for (i = 0; i < 256; ++i) { - k = crc32_reverseBit((u8)i); - for (c = ((u32)k) << 24, j = 8; j > 0; --j) - c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1); - p1 = (u8 *)&crc32_table[i]; - - p1[0] = crc32_reverseBit(p[3]); - p1[1] = crc32_reverseBit(p[2]); - p1[2] = crc32_reverseBit(p[1]); - p1[3] = crc32_reverseBit(p[0]); - } - bcrc32initialized = 1; + + c = 0x12340000; + + for (i = 0; i < 256; ++i) { + k = crc32_reverseBit((u8)i); + for (c = ((u32)k) << 24, j = 8; j > 0; --j) + c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1); + p1 = (u8 *)&crc32_table[i]; + + p1[0] = crc32_reverseBit(p[3]); + p1[1] = crc32_reverseBit(p[2]); + p1[2] = crc32_reverseBit(p[1]); + p1[3] = crc32_reverseBit(p[0]); } + bcrc32initialized = 1; } static __le32 getcrc32(u8 *buf, int len) diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 7bfc5b7c2757..c985b1468d41 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -270,14 +270,9 @@ void Switch_DM_Func(struct adapter *padapter, u32 mode, u8 enable) rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode)); } -static void Set_NETYPE0_MSR(struct adapter *padapter, u8 type) -{ - rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type)); -} - void Set_MSR(struct adapter *padapter, u8 type) { - Set_NETYPE0_MSR(padapter, type); + rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type)); } inline u8 rtw_get_oper_ch(struct adapter *adapter) @@ -1179,15 +1174,10 @@ void Update_RA_Entry(struct adapter *padapter, u32 mac_id) rtw_hal_update_ra_mask(padapter, mac_id, 0); } -static void enable_rate_adaptive(struct adapter *padapter, u32 mac_id) -{ - Update_RA_Entry(padapter, mac_id); -} - void set_sta_rate(struct adapter *padapter, struct sta_info *psta) { /* rate adaptive */ - enable_rate_adaptive(padapter, psta->mac_id); + Update_RA_Entry(padapter, psta->mac_id); } /* Update RRSR and Rate for USERATE */ @@ -1476,8 +1466,3 @@ void correct_TSF(struct adapter *padapter, struct mlme_ext_priv *pmlmeext) { rtw_hal_set_hwreg(padapter, HW_VAR_CORRECT_TSF, NULL); } - -void beacon_timing_control(struct adapter *padapter) -{ - rtw_hal_bcn_related_reg_setting(padapter); -} diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c index 11e0bb9c67d7..51882858fcf0 100644 --- a/drivers/staging/rtl8188eu/hal/bb_cfg.c +++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c @@ -653,7 +653,7 @@ static bool config_parafile(struct adapter *adapt) bool rtl88eu_phy_bb_config(struct adapter *adapt) { - int rtstatus = true; + bool rtstatus; u32 regval; u8 crystal_cap; diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index 02aeb12c9870..47b1bf5a6143 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -218,11 +218,11 @@ static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt) return true; } -static bool rf6052_conf_para(struct adapter *adapt) +bool rtl88eu_phy_rf_config(struct adapter *adapt) { struct hal_data_8188e *hal_data = adapt->HalData; u32 u4val = 0; - bool rtstatus = true; + bool rtstatus; struct bb_reg_def *pphyreg; pphyreg = &hal_data->PHYRegDef[RF90_PATH_A]; @@ -246,13 +246,3 @@ static bool rf6052_conf_para(struct adapter *adapt) return rtstatus; } - -static bool rtl88e_phy_rf6052_config(struct adapter *adapt) -{ - return rf6052_conf_para(adapt); -} - -bool rtl88eu_phy_rf_config(struct adapter *adapt) -{ - return rtl88e_phy_rf6052_config(adapt); -} diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index ac5552050752..16a57b31a439 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -183,14 +183,14 @@ static void _InitTxBufferBoundary(struct adapter *Adapter, u8 txpktbuf_bndy) usb_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); usb_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy); usb_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy); - usb_write8(Adapter, REG_TDECTRL+1, txpktbuf_bndy); + usb_write8(Adapter, REG_TDECTRL + 1, txpktbuf_bndy); } static void _InitPageBoundary(struct adapter *Adapter) { /* RX Page Boundary */ /* */ - u16 rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E-1; + u16 rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E - 1; usb_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy); } @@ -504,7 +504,7 @@ static void usb_AggSettingRxUpdate(struct adapter *Adapter) switch (haldata->UsbRxAggMode) { case USB_RX_AGG_DMA: usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount); - usb_write8(Adapter, REG_RXDMA_AGG_PG_TH+1, haldata->UsbRxAggPageTimeout); + usb_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, haldata->UsbRxAggPageTimeout); break; case USB_RX_AGG_USB: usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount); @@ -512,7 +512,7 @@ static void usb_AggSettingRxUpdate(struct adapter *Adapter) break; case USB_RX_AGG_MIX: usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount); - usb_write8(Adapter, REG_RXDMA_AGG_PG_TH+1, (haldata->UsbRxAggPageTimeout & 0x1F));/* 0x280[12:8] */ + usb_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, (haldata->UsbRxAggPageTimeout & 0x1F));/* 0x280[12:8] */ usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount); usb_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout); break; @@ -569,9 +569,9 @@ static void _InitBeaconParameters(struct adapter *Adapter) haldata->RegBcnCtrlVal = usb_read8(Adapter, REG_BCN_CTRL); haldata->RegTxPause = usb_read8(Adapter, REG_TXPAUSE); - haldata->RegFwHwTxQCtrl = usb_read8(Adapter, REG_FWHW_TXQ_CTRL+2); - haldata->RegReg542 = usb_read8(Adapter, REG_TBTT_PROHIBIT+2); - haldata->RegCR_1 = usb_read8(Adapter, REG_CR+1); + haldata->RegFwHwTxQCtrl = usb_read8(Adapter, REG_FWHW_TXQ_CTRL + 2); + haldata->RegReg542 = usb_read8(Adapter, REG_TBTT_PROHIBIT + 2); + haldata->RegCR_1 = usb_read8(Adapter, REG_CR + 1); } static void _BeaconFunctionEnable(struct adapter *Adapter, @@ -579,7 +579,7 @@ static void _BeaconFunctionEnable(struct adapter *Adapter, { usb_write8(Adapter, REG_BCN_CTRL, (BIT(4) | BIT(3) | BIT(1))); - usb_write8(Adapter, REG_RD_CTRL+1, 0x6F); + usb_write8(Adapter, REG_RD_CTRL + 1, 0x6F); } /* Set CCK and OFDM Block "ON" */ @@ -633,7 +633,7 @@ enum rt_rf_power_state RfOnOffDetect(struct adapter *adapt) DBG_88E("pwrdown, 0x5c(BIT(7))=%02x\n", val8); rfpowerstate = (val8 & BIT(7)) ? rf_off : rf_on; } else { /* rf on/off */ - usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG)&~(BIT(3))); + usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG) & ~(BIT(3))); val8 = usb_read8(adapt, REG_GPIO_IO_SEL); DBG_88E("GPIO_IN=%02x\n", val8); rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off; @@ -770,7 +770,7 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) value8 = usb_read8(Adapter, REG_TX_RPT_CTRL); usb_write8(Adapter, REG_TX_RPT_CTRL, (value8 | BIT(1) | BIT(0))); /* Set MAX RPT MACID */ - usb_write8(Adapter, REG_TX_RPT_CTRL+1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */ + usb_write8(Adapter, REG_TX_RPT_CTRL + 1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */ /* Tx RPT Timer. Unit: 32us */ usb_write16(Adapter, REG_TX_RPT_TIME, 0xCdf0); @@ -827,10 +827,10 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) pwrctrlpriv->rf_pwrstate = rf_on; /* enable Tx report. */ - usb_write8(Adapter, REG_FWHW_TXQ_CTRL+1, 0x0F); + usb_write8(Adapter, REG_FWHW_TXQ_CTRL + 1, 0x0F); /* Suggested by SD1 pisa. Added by tynli. 2011.10.21. */ - usb_write8(Adapter, REG_EARLY_MODE_CONTROL+3, 0x01);/* Pretx_en, for WEP/TKIP SEC */ + usb_write8(Adapter, REG_EARLY_MODE_CONTROL + 3, 0x01);/* Pretx_en, for WEP/TKIP SEC */ /* tynli_test_tx_report. */ usb_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0); @@ -880,7 +880,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) /* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */ val8 = usb_read8(Adapter, REG_TX_RPT_CTRL); - usb_write8(Adapter, REG_TX_RPT_CTRL, val8&(~BIT(1))); + usb_write8(Adapter, REG_TX_RPT_CTRL, val8 & (~BIT(1))); /* stop rx */ usb_write8(Adapter, REG_CR, 0x0); @@ -894,9 +894,9 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) val8 = usb_read8(Adapter, REG_MCUFWDL); if ((val8 & RAM_DL_SEL) && Adapter->bFWReady) { /* 8051 RAM code */ /* Reset MCU 0x2[10]=0. */ - val8 = usb_read8(Adapter, REG_SYS_FUNC_EN+1); + val8 = usb_read8(Adapter, REG_SYS_FUNC_EN + 1); val8 &= ~BIT(2); /* 0x2[10], FEN_CPUEN */ - usb_write8(Adapter, REG_SYS_FUNC_EN+1, val8); + usb_write8(Adapter, REG_SYS_FUNC_EN + 1, val8); } /* reset MCU ready status */ @@ -905,17 +905,17 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) /* YJ,add,111212 */ /* Disable 32k */ val8 = usb_read8(Adapter, REG_32K_CTRL); - usb_write8(Adapter, REG_32K_CTRL, val8&(~BIT(0))); + usb_write8(Adapter, REG_32K_CTRL, val8 & (~BIT(0))); /* Card disable power action flow */ rtl88eu_pwrseqcmdparsing(Adapter, PWR_CUT_ALL_MSK, Rtl8188E_NIC_DISABLE_FLOW); /* Reset MCU IO Wrapper */ - val8 = usb_read8(Adapter, REG_RSV_CTRL+1); - usb_write8(Adapter, REG_RSV_CTRL+1, (val8&(~BIT(3)))); - val8 = usb_read8(Adapter, REG_RSV_CTRL+1); - usb_write8(Adapter, REG_RSV_CTRL+1, val8 | BIT(3)); + val8 = usb_read8(Adapter, REG_RSV_CTRL + 1); + usb_write8(Adapter, REG_RSV_CTRL + 1, (val8 & (~BIT(3)))); + val8 = usb_read8(Adapter, REG_RSV_CTRL + 1); + usb_write8(Adapter, REG_RSV_CTRL + 1, val8 | BIT(3)); /* YJ,test add, 111207. For Power Consumption. */ val8 = usb_read8(Adapter, GPIO_IN); @@ -923,9 +923,9 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) usb_write8(Adapter, GPIO_IO_SEL, 0xFF);/* Reg0x46 */ val8 = usb_read8(Adapter, REG_GPIO_IO_SEL); - usb_write8(Adapter, REG_GPIO_IO_SEL, (val8<<4)); - val8 = usb_read8(Adapter, REG_GPIO_IO_SEL+1); - usb_write8(Adapter, REG_GPIO_IO_SEL+1, val8|0x0F);/* Reg0x43 */ + usb_write8(Adapter, REG_GPIO_IO_SEL, (val8 << 4)); + val8 = usb_read8(Adapter, REG_GPIO_IO_SEL + 1); + usb_write8(Adapter, REG_GPIO_IO_SEL + 1, val8 | 0x0F);/* Reg0x43 */ usb_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */ Adapter->HalData->bMacPwrCtrlOn = false; Adapter->bFWReady = false; @@ -1103,11 +1103,11 @@ static void ResumeTxBeacon(struct adapter *adapt) /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ /* which should be read from register to a global variable. */ - usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) | BIT(6)); + usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) | BIT(6)); haldata->RegFwHwTxQCtrl |= BIT(6); - usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0xff); + usb_write8(adapt, REG_TBTT_PROHIBIT + 1, 0xff); haldata->RegReg542 |= BIT(0); - usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542); + usb_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542); } static void StopTxBeacon(struct adapter *adapt) @@ -1117,11 +1117,11 @@ static void StopTxBeacon(struct adapter *adapt) /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ /* which should be read from register to a global variable. */ - usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) & (~BIT(6))); + usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) & (~BIT(6))); haldata->RegFwHwTxQCtrl &= (~BIT(6)); - usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0x64); + usb_write8(adapt, REG_TBTT_PROHIBIT + 1, 0x64); haldata->RegReg542 &= ~(BIT(0)); - usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542); + usb_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542); /* todo: CheckFwRsvdPageContent(Adapter); 2010.06.23. Added by tynli. */ } @@ -1135,7 +1135,7 @@ static void hw_var_set_opmode(struct adapter *Adapter, u8 variable, u8 *val) usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4)); /* set net_type */ - val8 = usb_read8(Adapter, MSR)&0x0c; + val8 = usb_read8(Adapter, MSR) & 0x0c; val8 |= mode; usb_write8(Adapter, MSR, val8); @@ -1176,7 +1176,7 @@ static void hw_var_set_opmode(struct adapter *Adapter, u8 variable, u8 *val) /* enable BCN0 Function for if1 */ /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */ - usb_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP|EN_BCN_FUNCTION | BIT(1))); + usb_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | BIT(1))); /* dis BCN1 ATIM WND if if2 is station */ usb_write8(Adapter, REG_BCN_CTRL_1, usb_read8(Adapter, REG_BCN_CTRL_1) | BIT(0)); @@ -1191,7 +1191,7 @@ static void hw_var_set_macaddr(struct adapter *Adapter, u8 variable, u8 *val) reg_macid = REG_MACID; for (idx = 0; idx < 6; idx++) - usb_write8(Adapter, (reg_macid+idx), val[idx]); + usb_write8(Adapter, (reg_macid + idx), val[idx]); } static void hw_var_set_bssid(struct adapter *Adapter, u8 variable, u8 *val) @@ -1202,7 +1202,7 @@ static void hw_var_set_bssid(struct adapter *Adapter, u8 variable, u8 *val) reg_bssid = REG_BSSID; for (idx = 0; idx < 6; idx++) - usb_write8(Adapter, (reg_bssid+idx), val[idx]); + usb_write8(Adapter, (reg_bssid + idx), val[idx]); } static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val) @@ -1214,7 +1214,7 @@ static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val) if (*((u8 *)val)) usb_write8(Adapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT)); else - usb_write8(Adapter, bcn_ctrl_reg, usb_read8(Adapter, bcn_ctrl_reg)&(~(EN_BCN_FUNCTION | EN_TXBCN_RPT))); + usb_write8(Adapter, bcn_ctrl_reg, usb_read8(Adapter, bcn_ctrl_reg) & (~(EN_BCN_FUNCTION | EN_TXBCN_RPT))); } void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) @@ -1228,7 +1228,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { u8 val8; - val8 = usb_read8(Adapter, MSR)&0x0c; + val8 = usb_read8(Adapter, MSR) & 0x0c; val8 |= *((u8 *)val); usb_write8(Adapter, MSR, val8); } @@ -1274,8 +1274,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) BrateCfg |= 0x01; /* default enable 1M ACK rate */ /* Set RRSR rate table. */ usb_write8(Adapter, REG_RRSR, BrateCfg & 0xff); - usb_write8(Adapter, REG_RRSR+1, (BrateCfg >> 8) & 0xff); - usb_write8(Adapter, REG_RRSR+2, usb_read8(Adapter, REG_RRSR+2)&0xf0); + usb_write8(Adapter, REG_RRSR + 1, (BrateCfg >> 8) & 0xff); + usb_write8(Adapter, REG_RRSR + 2, usb_read8(Adapter, REG_RRSR + 2) & 0xf0); /* Set RTS initial rate */ while (BrateCfg > 0x1) { @@ -1298,27 +1298,27 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - tsf = pmlmeext->TSFValue - rtw_modular64(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024)) - 1024; /* us */ + tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval * 1024)) - 1024; /* us */ - if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) + if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) StopTxBeacon(Adapter); /* disable related TSF function */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(3))); + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(3))); usb_write32(Adapter, REG_TSFTR, tsf); - usb_write32(Adapter, REG_TSFTR+4, tsf>>32); + usb_write32(Adapter, REG_TSFTR + 4, tsf >> 32); /* enable related TSF function */ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(3)); - if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) + if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) ResumeTxBeacon(Adapter); } break; case HW_VAR_CHECK_BSSID: if (*((u8 *)val)) { - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); + usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN); } else { u32 val32; @@ -1357,19 +1357,19 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; if ((is_client_associated_to_ap(Adapter)) || - ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)) { + ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) { /* enable to rx data frame */ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); /* enable update TSF */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); - } else if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); + } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); /* enable update TSF */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); } - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); + usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN); } break; case HW_VAR_MLME_JOIN: @@ -1382,7 +1382,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* enable to rx data frame.Accept all data frame */ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); + usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN); if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) RetryLimit = (haldata->CustomerID == RT_CID_CCX) ? 7 : 48; @@ -1394,9 +1394,9 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) } else if (type == 2) { /* sta add event call back */ /* enable update TSF */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) + if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) RetryLimit = 0x7; } usb_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT); @@ -1432,21 +1432,21 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) case HW_VAR_RESP_SIFS: /* RESP_SIFS for CCK */ usb_write8(Adapter, REG_R2T_SIFS, val[0]); /* SIFS_T2T_CCK (0x08) */ - usb_write8(Adapter, REG_R2T_SIFS+1, val[1]); /* SIFS_R2T_CCK(0x08) */ + usb_write8(Adapter, REG_R2T_SIFS + 1, val[1]); /* SIFS_R2T_CCK(0x08) */ /* RESP_SIFS for OFDM */ usb_write8(Adapter, REG_T2T_SIFS, val[2]); /* SIFS_T2T_OFDM (0x0a) */ - usb_write8(Adapter, REG_T2T_SIFS+1, val[3]); /* SIFS_R2T_OFDM(0x0a) */ + usb_write8(Adapter, REG_T2T_SIFS + 1, val[3]); /* SIFS_R2T_OFDM(0x0a) */ break; case HW_VAR_ACK_PREAMBLE: { u8 regTmp; u8 bShortPreamble = *((bool *)val); /* Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */ - regTmp = (haldata->nCur40MhzPrimeSC)<<5; + regTmp = (haldata->nCur40MhzPrimeSC) << 5; if (bShortPreamble) regTmp |= 0x80; - usb_write8(Adapter, REG_RRSR+2, regTmp); + usb_write8(Adapter, REG_RRSR + 2, regTmp); } break; case HW_VAR_SEC_CFG: @@ -1480,12 +1480,13 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) for (i = 0; i < CAM_CONTENT_COUNT; i++) { /* filled id in CAM config 2 byte */ if (i == 0) - ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo)<<2); + ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo) << 2); else ulContent = 0; /* polling bit, and No Write enable, and address */ - ulCommand = CAM_CONTENT_COUNT*ucIndex+i; - ulCommand = ulCommand | CAM_POLLINIG|CAM_WRITE; + ulCommand = CAM_CONTENT_COUNT * ucIndex + i; + ulCommand = ulCommand | CAM_POLLINIG | + CAM_WRITE; /* write content 0 is equall to mark invalid */ usb_write32(Adapter, WCAMI, ulContent); /* delay_ms(40); */ usb_write32(Adapter, RWCAM, ulCommand); /* delay_ms(40); */ @@ -1589,13 +1590,13 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) FactorToSet = 0xf; for (index = 0; index < 4; index++) { - if ((pRegToSet[index] & 0xf0) > (FactorToSet<<4)) - pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet<<4); + if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4)) + pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet << 4); if ((pRegToSet[index] & 0x0f) > FactorToSet) pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet); - usb_write8(Adapter, (REG_AGGLEN_LMT+index), pRegToSet[index]); + usb_write8(Adapter, (REG_AGGLEN_LMT + index), pRegToSet[index]); } } } @@ -1681,9 +1682,9 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) if (!pwrpriv->bkeepfwalive) { /* RX DMA stop */ - usb_write32(Adapter, REG_RXPKT_NUM, (usb_read32(Adapter, REG_RXPKT_NUM)|RW_RELEASE_EN)); + usb_write32(Adapter, REG_RXPKT_NUM, (usb_read32(Adapter, REG_RXPKT_NUM) | RW_RELEASE_EN)); do { - if (!(usb_read32(Adapter, REG_RXPKT_NUM)&RXDMA_IDLE)) + if (!(usb_read32(Adapter, REG_RXPKT_NUM) & RXDMA_IDLE)) break; } while (trycnt--); if (trycnt == 0) @@ -1706,8 +1707,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { u8 maxMacid = *val; - DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid+1); - usb_write8(Adapter, REG_TX_RPT_CTRL+1, maxMacid+1); + DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid + 1); + usb_write8(Adapter, REG_TX_RPT_CTRL + 1, maxMacid + 1); } break; case HW_VAR_H2C_MEDIA_STATUS_RPT: @@ -1715,7 +1716,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) break; case HW_VAR_BCN_VALID: /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */ - usb_write8(Adapter, REG_TDECTRL+2, usb_read8(Adapter, REG_TDECTRL+2) | BIT(0)); + usb_write8(Adapter, REG_TDECTRL + 2, usb_read8(Adapter, REG_TDECTRL + 2) | BIT(0)); break; default: break; @@ -1733,7 +1734,7 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) break; case HW_VAR_BCN_VALID: /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */ - val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false; + val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL + 2)) ? true : false; break; case HW_VAR_FWLPS_RF_ON: { @@ -1764,7 +1765,7 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) *val = Adapter->HalData->bMacPwrCtrlOn; break; case HW_VAR_CHK_HI_QUEUE_EMPTY: - *val = ((usb_read32(Adapter, REG_HGQ_INFORMATION)&0x0000ff00) == 0) ? true : false; + *val = ((usb_read32(Adapter, REG_HGQ_INFORMATION) & 0x0000ff00) == 0) ? true : false; break; default: break; @@ -1888,7 +1889,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) if (mac_id >= NUM_STA) /* CAM_SIZE */ return; psta = pmlmeinfo->FW_sta_info[mac_id].psta; - if (psta == NULL) + if (!psta) return; switch (mac_id) { case 0:/* for infra mode */ @@ -1925,7 +1926,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) mask &= rate_bitmap; - init_rate = get_highest_rate_idx(mask)&0x3f; + init_rate = get_highest_rate_idx(mask) & 0x3f; ODM_RA_UpdateRateInfo_8188E(odmpriv, mac_id, raid, mask, shortGIrate); @@ -1934,7 +1935,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) psta->init_rate = init_rate; } -void rtw_hal_bcn_related_reg_setting(struct adapter *adapt) +void beacon_timing_control(struct adapter *adapt) { u32 value32; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; diff --git a/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h b/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h index 53afcea21c96..bd915a1f2511 100644 --- a/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h +++ b/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h @@ -16,55 +16,10 @@ /* 5. Other definition for BB/RF R/W */ /* */ - -/* */ -/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */ -/* 1. Page1(0x100) */ -/* */ -#define rPMAC_Reset 0x100 -#define rPMAC_TxStart 0x104 -#define rPMAC_TxLegacySIG 0x108 -#define rPMAC_TxHTSIG1 0x10c -#define rPMAC_TxHTSIG2 0x110 -#define rPMAC_PHYDebug 0x114 -#define rPMAC_TxPacketNum 0x118 -#define rPMAC_TxIdle 0x11c -#define rPMAC_TxMACHeader0 0x120 -#define rPMAC_TxMACHeader1 0x124 -#define rPMAC_TxMACHeader2 0x128 -#define rPMAC_TxMACHeader3 0x12c -#define rPMAC_TxMACHeader4 0x130 -#define rPMAC_TxMACHeader5 0x134 -#define rPMAC_TxDataType 0x138 -#define rPMAC_TxRandomSeed 0x13c -#define rPMAC_CCKPLCPPreamble 0x140 -#define rPMAC_CCKPLCPHeader 0x144 -#define rPMAC_CCKCRC16 0x148 -#define rPMAC_OFDMRxCRC32OK 0x170 -#define rPMAC_OFDMRxCRC32Er 0x174 -#define rPMAC_OFDMRxParityEr 0x178 -#define rPMAC_OFDMRxCRC8Er 0x17c -#define rPMAC_CCKCRxRC16Er 0x180 -#define rPMAC_CCKCRxRC32Er 0x184 -#define rPMAC_CCKCRxRC32OK 0x188 -#define rPMAC_TxStatus 0x18c - -/* 2. Page2(0x200) */ -/* The following two definition are only used for USB interface. */ -#define RF_BB_CMD_ADDR 0x02c0 /* RF/BB r/w cmd address. */ -#define RF_BB_CMD_DATA 0x02c4 /* RF/BB r/w cmd data. */ - /* 3. Page8(0x800) */ #define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC RF BW Setting */ - -#define rFPGA0_TxInfo 0x804 /* Status report?? */ -#define rFPGA0_PSDFunction 0x808 - #define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */ -#define rFPGA0_RFTiming1 0x810 /* Useless now */ -#define rFPGA0_RFTiming2 0x814 - #define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */ #define rFPGA0_XA_HSSIParameter2 0x824 #define rFPGA0_XB_HSSIParameter1 0x828 @@ -73,9 +28,6 @@ #define rFPGA0_XA_LSSIParameter 0x840 #define rFPGA0_XB_LSSIParameter 0x844 -#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */ -#define rFPGA0_RFSleepUpParameter 0x854 - #define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */ #define rFPGA0_XCD_SwitchControl 0x85c @@ -86,181 +38,63 @@ #define rFPGA0_XCD_RFInterfaceSW 0x874 #define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */ -#define rFPGA0_XCD_RFParameter 0x87c - -/* Crystal cap setting RF-R/W protection for parameter4?? */ -#define rFPGA0_AnalogParameter1 0x880 -#define rFPGA0_AnalogParameter2 0x884 -#define rFPGA0_AnalogParameter3 0x888 -/* enable ad/da clock1 for dual-phy */ -#define rFPGA0_AdDaClockEn 0x888 -#define rFPGA0_AnalogParameter4 0x88c #define rFPGA0_XA_LSSIReadBack 0x8a0 /* Tranceiver LSSI Readback */ #define rFPGA0_XB_LSSIReadBack 0x8a4 -#define rFPGA0_XC_LSSIReadBack 0x8a8 -#define rFPGA0_XD_LSSIReadBack 0x8ac -#define rFPGA0_PSDReport 0x8b4 /* Useless now */ -/* Transceiver A HSPI Readback */ #define TransceiverA_HSPI_Readback 0x8b8 -/* Transceiver B HSPI Readback */ #define TransceiverB_HSPI_Readback 0x8bc -/* Useless now RF Interface Readback Value */ #define rFPGA0_XAB_RFInterfaceRB 0x8e0 -#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */ /* 4. Page9(0x900) */ /* RF mode & OFDM TxSC RF BW Setting?? */ #define rFPGA1_RFMOD 0x900 -#define rFPGA1_TxBlock 0x904 /* Useless now */ -#define rFPGA1_DebugSelect 0x908 /* Useless now */ -#define rFPGA1_TxInfo 0x90c /* Useless now Status report */ - /* 5. PageA(0xA00) */ /* Set Control channel to upper or lower - required only for 40MHz */ #define rCCK0_System 0xa00 -/* Disable init gain now Select RX path by RSSI */ -#define rCCK0_AFESetting 0xa04 -/* Disable init gain now Init gain */ -#define rCCK0_CCA 0xa08 - -/* AGC default value, saturation level Antenna Diversity, RX AGC, LNA Threshold, - * RX LNA Threshold useless now. Not the same as 90 series - */ -#define rCCK0_RxAGC1 0xa0c -#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */ - -#define rCCK0_RxHP 0xa14 - -/* Timing recovery & Channel estimation threshold */ -#define rCCK0_DSPParameter1 0xa18 -#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */ - -#define rCCK0_TxFilter1 0xa20 -#define rCCK0_TxFilter2 0xa24 -#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */ -#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now */ -#define rCCK0_TRSSIReport 0xa50 -#define rCCK0_RxReport 0xa54 /* 0xa57 */ -#define rCCK0_FACounterLower 0xa5c /* 0xa5b */ -#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */ - /* */ /* PageB(0xB00) */ /* */ -#define rPdp_AntA 0xb00 -#define rPdp_AntA_4 0xb04 -#define rConfig_Pmpd_AntA 0xb28 #define rConfig_AntA 0xb68 #define rConfig_AntB 0xb6c -#define rPdp_AntB 0xb70 -#define rPdp_AntB_4 0xb74 -#define rConfig_Pmpd_AntB 0xb98 -#define rAPK 0xbd8 /* */ /* 6. PageC(0xC00) */ /* */ -#define rOFDM0_LSTF 0xc00 - #define rOFDM0_TRxPathEnable 0xc04 #define rOFDM0_TRMuxPar 0xc08 -#define rOFDM0_TRSWIsolation 0xc0c /* RxIQ DC offset, Rx digital filter, DC notch filter */ #define rOFDM0_XARxAFE 0xc10 #define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */ #define rOFDM0_XBRxAFE 0xc18 #define rOFDM0_XBRxIQImbalance 0xc1c -#define rOFDM0_XCRxAFE 0xc20 -#define rOFDM0_XCRxIQImbalance 0xc24 -#define rOFDM0_XDRxAFE 0xc28 -#define rOFDM0_XDRxIQImbalance 0xc2c - -#define rOFDM0_RxDetector1 0xc30 /*PD,BW & SBD DM tune init gain*/ -#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */ -#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */ -#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync & Short-GI */ #define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */ -#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */ -#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */ #define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */ #define rOFDM0_XAAGCCore1 0xc50 /* DIG */ #define rOFDM0_XAAGCCore2 0xc54 #define rOFDM0_XBAGCCore1 0xc58 #define rOFDM0_XBAGCCore2 0xc5c -#define rOFDM0_XCAGCCore1 0xc60 -#define rOFDM0_XCAGCCore2 0xc64 -#define rOFDM0_XDAGCCore1 0xc68 -#define rOFDM0_XDAGCCore2 0xc6c -#define rOFDM0_AGCParameter1 0xc70 -#define rOFDM0_AGCParameter2 0xc74 #define rOFDM0_AGCRSSITable 0xc78 -#define rOFDM0_HTSTFAGC 0xc7c #define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */ #define rOFDM0_XATxAFE 0xc84 #define rOFDM0_XBTxIQImbalance 0xc88 #define rOFDM0_XBTxAFE 0xc8c -#define rOFDM0_XCTxIQImbalance 0xc90 #define rOFDM0_XCTxAFE 0xc94 -#define rOFDM0_XDTxIQImbalance 0xc98 #define rOFDM0_XDTxAFE 0xc9c #define rOFDM0_RxIQExtAnta 0xca0 -#define rOFDM0_TxCoeff1 0xca4 -#define rOFDM0_TxCoeff2 0xca8 -#define rOFDM0_TxCoeff3 0xcac -#define rOFDM0_TxCoeff4 0xcb0 -#define rOFDM0_TxCoeff5 0xcb4 -#define rOFDM0_TxCoeff6 0xcb8 -#define rOFDM0_RxHPParameter 0xce0 -#define rOFDM0_TxPseudoNoiseWgt 0xce4 -#define rOFDM0_FrameSync 0xcf0 -#define rOFDM0_DFSReport 0xcf4 - /* */ /* 7. PageD(0xD00) */ /* */ #define rOFDM1_LSTF 0xd00 -#define rOFDM1_TRxPathEnable 0xd04 - -#define rOFDM1_CFO 0xd08 /* No setting now */ -#define rOFDM1_CSI1 0xd10 -#define rOFDM1_SBD 0xd14 -#define rOFDM1_CSI2 0xd18 -#define rOFDM1_CFOTracking 0xd2c -#define rOFDM1_TRxMesaure1 0xd34 -#define rOFDM1_IntfDet 0xd3c -#define rOFDM1_PseudoNoiseStateAB 0xd50 -#define rOFDM1_PseudoNoiseStateCD 0xd54 -#define rOFDM1_RxPseudoNoiseWgt 0xd58 - -#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */ -#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */ -#define rOFDM_PHYCounter3 0xda8 /* MCS not support */ - -#define rOFDM_ShortCFOAB 0xdac /* No setting now */ -#define rOFDM_ShortCFOCD 0xdb0 -#define rOFDM_LongCFOAB 0xdb4 -#define rOFDM_LongCFOCD 0xdb8 -#define rOFDM_TailCFOAB 0xdbc -#define rOFDM_TailCFOCD 0xdc0 -#define rOFDM_PWMeasure1 0xdc4 -#define rOFDM_PWMeasure2 0xdc8 -#define rOFDM_BWReport 0xdcc -#define rOFDM_AGCReport 0xdd0 -#define rOFDM_RxSNR 0xdd4 -#define rOFDM_RxEVMCSI 0xdd8 -#define rOFDM_SIGReport 0xddc - /* */ /* 8. PageE(0xE00) */ @@ -292,10 +126,6 @@ #define rRx_IQK 0xe44 #define rIQK_AGC_Pts 0xe48 #define rIQK_AGC_Rsp 0xe4c -#define rTx_IQK_Tone_B 0xe50 -#define rRx_IQK_Tone_B 0xe54 -#define rTx_IQK_PI_B 0xe58 -#define rRx_IQK_PI_B 0xe5c #define rIQK_AGC_Cont 0xe60 #define rBlue_Tooth 0xe6c @@ -311,17 +141,13 @@ #define rTx_Power_Before_IQK_A 0xe94 #define rTx_Power_After_IQK_A 0xe9c -#define rRx_Power_Before_IQK_A 0xea0 #define rRx_Power_Before_IQK_A_2 0xea4 -#define rRx_Power_After_IQK_A 0xea8 #define rRx_Power_After_IQK_A_2 0xeac #define rTx_Power_Before_IQK_B 0xeb4 #define rTx_Power_After_IQK_B 0xebc -#define rRx_Power_Before_IQK_B 0xec0 #define rRx_Power_Before_IQK_B_2 0xec4 -#define rRx_Power_After_IQK_B 0xec8 #define rRx_Power_After_IQK_B_2 0xecc #define rRx_OFDM 0xed0 @@ -332,751 +158,44 @@ #define rPMPD_ANAEN 0xeec /* */ -/* 7. RF Register 0x00-0x2E (RF 8256) */ -/* RF-0222D 0x00-3F */ -/* */ -/* Zebra1 */ -#define rZebra1_HSSIEnable 0x0 /* Useless now */ -#define rZebra1_TRxEnable1 0x1 -#define rZebra1_TRxEnable2 0x2 -#define rZebra1_AGC 0x4 -#define rZebra1_ChargePump 0x5 -#define rZebra1_Channel 0x7 /* RF channel switch */ - -/* endif */ -#define rZebra1_TxGain 0x8 /* Useless now */ -#define rZebra1_TxLPF 0x9 -#define rZebra1_RxLPF 0xb -#define rZebra1_RxHPFCorner 0xc - -/* Zebra4 */ -#define rGlobalCtrl 0 /* Useless now */ -#define rRTL8256_TxLPF 19 -#define rRTL8256_RxLPF 11 - -/* RTL8258 */ -#define rRTL8258_TxLPF 0x11 /* Useless now */ -#define rRTL8258_RxLPF 0x13 -#define rRTL8258_RSSILPF 0xa - -/* */ /* RL6052 Register definition */ /* */ #define RF_AC 0x00 /* */ - -#define RF_IQADJ_G1 0x01 /* */ -#define RF_IQADJ_G2 0x02 /* */ - -#define RF_POW_TRSW 0x05 /* */ - -#define RF_GAIN_RX 0x06 /* */ -#define RF_GAIN_TX 0x07 /* */ - -#define RF_TXM_IDAC 0x08 /* */ -#define RF_IPA_G 0x09 /* */ -#define RF_TXBIAS_G 0x0A -#define RF_TXPA_AG 0x0B -#define RF_IPA_A 0x0C /* */ -#define RF_TXBIAS_A 0x0D -#define RF_BS_PA_APSET_G9_G11 0x0E -#define RF_BS_IQGEN 0x0F /* */ - -#define RF_MODE1 0x10 /* */ -#define RF_MODE2 0x11 /* */ - -#define RF_RX_AGC_HP 0x12 /* */ -#define RF_TX_AGC 0x13 /* */ -#define RF_BIAS 0x14 /* */ -#define RF_IPA 0x15 /* */ -#define RF_TXBIAS 0x16 -#define RF_POW_ABILITY 0x17 /* */ #define RF_CHNLBW 0x18 /* RF channel and BW switch */ -#define RF_TOP 0x19 /* */ - -#define RF_RX_G1 0x1A /* */ -#define RF_RX_G2 0x1B /* */ - -#define RF_RX_BB2 0x1C /* */ -#define RF_RX_BB1 0x1D /* */ - -#define RF_RCK1 0x1E /* */ -#define RF_RCK2 0x1F /* */ - -#define RF_TX_G1 0x20 /* */ -#define RF_TX_G2 0x21 /* */ -#define RF_TX_G3 0x22 /* */ - -#define RF_TX_BB1 0x23 /* */ - -#define RF_T_METER_92D 0x42 /* */ #define RF_T_METER_88E 0x42 /* */ -#define RF_T_METER 0x24 /* */ - -#define RF_SYN_G1 0x25 /* RF TX Power control */ -#define RF_SYN_G2 0x26 /* RF TX Power control */ -#define RF_SYN_G3 0x27 /* RF TX Power control */ -#define RF_SYN_G4 0x28 /* RF TX Power control */ -#define RF_SYN_G5 0x29 /* RF TX Power control */ -#define RF_SYN_G6 0x2A /* RF TX Power control */ -#define RF_SYN_G7 0x2B /* RF TX Power control */ -#define RF_SYN_G8 0x2C /* RF TX Power control */ - #define RF_RCK_OS 0x30 /* RF TX PA control */ #define RF_TXPA_G1 0x31 /* RF TX PA control */ #define RF_TXPA_G2 0x32 /* RF TX PA control */ -#define RF_TXPA_G3 0x33 /* RF TX PA control */ -#define RF_TX_BIAS_A 0x35 -#define RF_TX_BIAS_D 0x36 -#define RF_LOBF_9 0x38 -#define RF_RXRF_A3 0x3C /* */ -#define RF_TRSW 0x3F - -#define RF_TXRF_A2 0x41 -#define RF_TXPA_G4 0x46 -#define RF_TXPA_A4 0x4B -#define RF_0x52 0x52 #define RF_WE_LUT 0xEF - /* */ /* Bit Mask */ /* */ -/* 1. Page1(0x100) */ -#define bBBResetB 0x100 /* Useless now? */ -#define bGlobalResetB 0x200 -#define bOFDMTxStart 0x4 -#define bCCKTxStart 0x8 -#define bCRC32Debug 0x100 -#define bPMACLoopback 0x10 -#define bTxLSIG 0xffffff -#define bOFDMTxRate 0xf -#define bOFDMTxReserved 0x10 -#define bOFDMTxLength 0x1ffe0 -#define bOFDMTxParity 0x20000 -#define bTxHTSIG1 0xffffff -#define bTxHTMCSRate 0x7f -#define bTxHTBW 0x80 -#define bTxHTLength 0xffff00 -#define bTxHTSIG2 0xffffff -#define bTxHTSmoothing 0x1 -#define bTxHTSounding 0x2 -#define bTxHTReserved 0x4 -#define bTxHTAggreation 0x8 -#define bTxHTSTBC 0x30 -#define bTxHTAdvanceCoding 0x40 -#define bTxHTShortGI 0x80 -#define bTxHTNumberHT_LTF 0x300 -#define bTxHTCRC8 0x3fc00 -#define bCounterReset 0x10000 -#define bNumOfOFDMTx 0xffff -#define bNumOfCCKTx 0xffff0000 -#define bTxIdleInterval 0xffff -#define bOFDMService 0xffff0000 -#define bTxMACHeader 0xffffffff -#define bTxDataInit 0xff -#define bTxHTMode 0x100 -#define bTxDataType 0x30000 -#define bTxRandomSeed 0xffffffff -#define bCCKTxPreamble 0x1 -#define bCCKTxSFD 0xffff0000 -#define bCCKTxSIG 0xff -#define bCCKTxService 0xff00 -#define bCCKLengthExt 0x8000 -#define bCCKTxLength 0xffff0000 -#define bCCKTxCRC16 0xffff -#define bCCKTxStatus 0x1 -#define bOFDMTxStatus 0x2 - -#define IS_BB_REG_OFFSET_92S(_Offset) \ - ((_Offset >= 0x800) && (_Offset <= 0xfff)) /* 2. Page8(0x800) */ #define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */ -#define bJapanMode 0x2 -#define bCCKTxSC 0x30 #define bCCKEn 0x1000000 #define bOFDMEn 0x2000000 -#define bOFDMRxADCPhase 0x10000 /* Useless now */ -#define bOFDMTxDACPhase 0x40000 -#define bXATxAGC 0x3f - -#define bAntennaSelect 0x0300 - -#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */ -#define bXCTxAGC 0xf000 -#define bXDTxAGC 0xf0000 - -#define bPAStart 0xf0000000 /* Useless now */ -#define bTRStart 0x00f00000 -#define bRFStart 0x0000f000 -#define bBBStart 0x000000f0 -#define bBBCCKStart 0x0000000f -#define bPAEnd 0xf /* Reg0x814 */ -#define bTREnd 0x0f000000 -#define bRFEnd 0x000f0000 -#define bCCAMask 0x000000f0 /* T2R */ -#define bR2RCCAMask 0x00000f00 -#define bHSSI_R2TDelay 0xf8000000 -#define bHSSI_T2RDelay 0xf80000 -#define bContTxHSSI 0x400 /* change gain at continue Tx */ -#define bIGFromCCK 0x200 -#define bAGCAddress 0x3f -#define bRxHPTx 0x7000 -#define bRxHPT2R 0x38000 -#define bRxHPCCKIni 0xc0000 -#define bAGCTxCode 0xc00000 -#define bAGCRxCode 0x300000 - -/* Reg 0x820~84f rFPGA0_XA_HSSIParameter1 */ -#define b3WireDataLength 0x800 -#define b3WireAddressLength 0x400 - -#define b3WireRFPowerDown 0x1 /* Useless now */ -#define b5GPAPEPolarity 0x40000000 -#define b2GPAPEPolarity 0x80000000 -#define bRFSW_TxDefaultAnt 0x3 -#define bRFSW_TxOptionAnt 0x30 -#define bRFSW_RxDefaultAnt 0x300 -#define bRFSW_RxOptionAnt 0x3000 -#define bRFSI_3WireData 0x1 -#define bRFSI_3WireClock 0x2 -#define bRFSI_3WireLoad 0x4 -#define bRFSI_3WireRW 0x8 -#define bRFSI_3Wire 0xf - -#define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */ - -#define bRFSI_TRSW 0x20 /* Useless now */ -#define bRFSI_TRSWB 0x40 -#define bRFSI_ANTSW 0x100 -#define bRFSI_ANTSWB 0x200 -#define bRFSI_PAPE 0x400 -#define bRFSI_PAPE5G 0x800 -#define bBandSelect 0x1 -#define bHTSIG2_GI 0x80 -#define bHTSIG2_Smoothing 0x01 -#define bHTSIG2_Sounding 0x02 -#define bHTSIG2_Aggreaton 0x08 -#define bHTSIG2_STBC 0x30 -#define bHTSIG2_AdvCoding 0x40 -#define bHTSIG2_NumOfHTLTF 0x300 -#define bHTSIG2_CRC8 0x3fc -#define bHTSIG1_MCS 0x7f -#define bHTSIG1_BandWidth 0x80 -#define bHTSIG1_HTLength 0xffff -#define bLSIG_Rate 0xf -#define bLSIG_Reserved 0x10 -#define bLSIG_Length 0x1fffe -#define bLSIG_Parity 0x20 -#define bCCKRxPhase 0x4 - #define bLSSIReadAddress 0x7f800000 /* T65 RF */ - #define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */ - #define bLSSIReadBackData 0xfffff /* T65 RF */ -#define bLSSIReadOKFlag 0x1000 /* Useless now */ -#define bCCKSampleRate 0x8 /* 0: 44MHz, 1:88MHz */ -#define bRegulator0Standby 0x1 -#define bRegulatorPLLStandby 0x2 -#define bRegulator1Standby 0x4 -#define bPLLPowerUp 0x8 -#define bDPLLPowerUp 0x10 -#define bDA10PowerUp 0x20 -#define bAD7PowerUp 0x200 -#define bDA6PowerUp 0x2000 -#define bXtalPowerUp 0x4000 -#define b40MDClkPowerUP 0x8000 -#define bDA6DebugMode 0x20000 -#define bDA6Swing 0x380000 - -/* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */ -#define bADClkPhase 0x4000000 - -#define b80MClkDelay 0x18000000 /* Useless */ -#define bAFEWatchDogEnable 0x20000000 - -/* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */ -#define bXtalCap01 0xc0000000 -#define bXtalCap23 0x3 -#define bXtalCap92x 0x0f000000 -#define bXtalCap 0x0f000000 - -#define bIntDifClkEnable 0x400 /* Useless */ -#define bExtSigClkEnable 0x800 -#define bBandgapMbiasPowerUp 0x10000 -#define bAD11SHGain 0xc0000 -#define bAD11InputRange 0x700000 -#define bAD11OPCurrent 0x3800000 -#define bIPathLoopback 0x4000000 -#define bQPathLoopback 0x8000000 -#define bAFELoopback 0x10000000 -#define bDA10Swing 0x7e0 -#define bDA10Reverse 0x800 -#define bDAClkSource 0x1000 -#define bAD7InputRange 0x6000 -#define bAD7Gain 0x38000 -#define bAD7OutputCMMode 0x40000 -#define bAD7InputCMMode 0x380000 -#define bAD7Current 0xc00000 -#define bRegulatorAdjust 0x7000000 -#define bAD11PowerUpAtTx 0x1 -#define bDA10PSAtTx 0x10 -#define bAD11PowerUpAtRx 0x100 -#define bDA10PSAtRx 0x1000 -#define bCCKRxAGCFormat 0x200 -#define bPSDFFTSamplepPoint 0xc000 -#define bPSDAverageNum 0x3000 -#define bIQPathControl 0xc00 -#define bPSDFreq 0x3ff -#define bPSDAntennaPath 0x30 -#define bPSDIQSwitch 0x40 -#define bPSDRxTrigger 0x400000 -#define bPSDTxTrigger 0x80000000 -#define bPSDSineToneScale 0x7f000000 -#define bPSDReport 0xffff - -/* 3. Page9(0x900) */ -#define bOFDMTxSC 0x30000000 /* Useless */ -#define bCCKTxOn 0x1 -#define bOFDMTxOn 0x2 -#define bDebugPage 0xfff /* reset debug page and HWord, LWord */ -#define bDebugItem 0xff /* reset debug page and LWord */ -#define bAntL 0x10 -#define bAntNonHT 0x100 -#define bAntHT1 0x1000 -#define bAntHT2 0x10000 -#define bAntHT1S1 0x100000 -#define bAntNonHTS1 0x1000000 - -/* 4. PageA(0xA00) */ -#define bCCKBBMode 0x3 /* Useless */ -#define bCCKTxPowerSaving 0x80 -#define bCCKRxPowerSaving 0x40 - #define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 */ -#define bCCKScramble 0x8 /* Useless */ -#define bCCKAntDiversity 0x8000 -#define bCCKCarrierRecovery 0x4000 -#define bCCKTxRate 0x3000 -#define bCCKDCCancel 0x0800 -#define bCCKISICancel 0x0400 -#define bCCKMatchFilter 0x0200 -#define bCCKEqualizer 0x0100 -#define bCCKPreambleDetect 0x800000 -#define bCCKFastFalseCCA 0x400000 -#define bCCKChEstStart 0x300000 -#define bCCKCCACount 0x080000 -#define bCCKcs_lim 0x070000 -#define bCCKBistMode 0x80000000 -#define bCCKCCAMask 0x40000000 -#define bCCKTxDACPhase 0x4 -#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */ -#define bCCKr_cp_mode0 0x0100 -#define bCCKTxDCOffset 0xf0 -#define bCCKRxDCOffset 0xf -#define bCCKCCAMode 0xc000 -#define bCCKFalseCS_lim 0x3f00 -#define bCCKCS_ratio 0xc00000 -#define bCCKCorgBit_sel 0x300000 -#define bCCKPD_lim 0x0f0000 -#define bCCKNewCCA 0x80000000 -#define bCCKRxHPofIG 0x8000 -#define bCCKRxIG 0x7f00 -#define bCCKLNAPolarity 0x800000 -#define bCCKRx1stGain 0x7f0000 -#define bCCKRFExtend 0x20000000 /* CCK Rx Iinital gain polarity */ -#define bCCKRxAGCSatLevel 0x1f000000 -#define bCCKRxAGCSatCount 0xe0 -#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */ -#define bCCKFixedRxAGC 0x8000 -#define bCCKAntennaPolarity 0x2000 -#define bCCKTxFilterType 0x0c00 -#define bCCKRxAGCReportType 0x0300 -#define bCCKRxDAGCEn 0x80000000 -#define bCCKRxDAGCPeriod 0x20000000 -#define bCCKRxDAGCSatLevel 0x1f000000 -#define bCCKTimingRecovery 0x800000 -#define bCCKTxC0 0x3f0000 -#define bCCKTxC1 0x3f000000 -#define bCCKTxC2 0x3f -#define bCCKTxC3 0x3f00 -#define bCCKTxC4 0x3f0000 -#define bCCKTxC5 0x3f000000 -#define bCCKTxC6 0x3f -#define bCCKTxC7 0x3f00 -#define bCCKDebugPort 0xff0000 -#define bCCKDACDebug 0x0f000000 -#define bCCKFalseAlarmEnable 0x8000 -#define bCCKFalseAlarmRead 0x4000 -#define bCCKTRSSI 0x7f -#define bCCKRxAGCReport 0xfe -#define bCCKRxReport_AntSel 0x80000000 -#define bCCKRxReport_MFOff 0x40000000 -#define bCCKRxRxReport_SQLoss 0x20000000 -#define bCCKRxReport_Pktloss 0x10000000 -#define bCCKRxReport_Lockedbit 0x08000000 -#define bCCKRxReport_RateError 0x04000000 -#define bCCKRxReport_RxRate 0x03000000 -#define bCCKRxFACounterLower 0xff -#define bCCKRxFACounterUpper 0xff000000 -#define bCCKRxHPAGCStart 0xe000 -#define bCCKRxHPAGCFinal 0x1c00 -#define bCCKRxFalseAlarmEnable 0x8000 -#define bCCKFACounterFreeze 0x4000 -#define bCCKTxPathSel 0x10000000 -#define bCCKDefaultRxPath 0xc000000 -#define bCCKOptionRxPath 0x3000000 - -/* 5. PageC(0xC00) */ -#define bNumOfSTF 0x3 /* Useless */ -#define bShift_L 0xc0 -#define bGI_TH 0xc -#define bRxPathA 0x1 -#define bRxPathB 0x2 -#define bRxPathC 0x4 -#define bRxPathD 0x8 -#define bTxPathA 0x1 -#define bTxPathB 0x2 -#define bTxPathC 0x4 -#define bTxPathD 0x8 -#define bTRSSIFreq 0x200 -#define bADCBackoff 0x3000 -#define bDFIRBackoff 0xc000 -#define bTRSSILatchPhase 0x10000 -#define bRxIDCOffset 0xff -#define bRxQDCOffset 0xff00 -#define bRxDFIRMode 0x1800000 -#define bRxDCNFType 0xe000000 -#define bRXIQImb_A 0x3ff -#define bRXIQImb_B 0xfc00 -#define bRXIQImb_C 0x3f0000 -#define bRXIQImb_D 0xffc00000 -#define bDC_dc_Notch 0x60000 -#define bRxNBINotch 0x1f000000 -#define bPD_TH 0xf -#define bPD_TH_Opt2 0xc000 -#define bPWED_TH 0x700 -#define bIfMF_Win_L 0x800 -#define bPD_Option 0x1000 -#define bMF_Win_L 0xe000 -#define bBW_Search_L 0x30000 -#define bwin_enh_L 0xc0000 -#define bBW_TH 0x700000 -#define bED_TH2 0x3800000 -#define bBW_option 0x4000000 -#define bRatio_TH 0x18000000 -#define bWindow_L 0xe0000000 -#define bSBD_Option 0x1 -#define bFrame_TH 0x1c -#define bFS_Option 0x60 -#define bDC_Slope_check 0x80 -#define bFGuard_Counter_DC_L 0xe00 -#define bFrame_Weight_Short 0x7000 -#define bSub_Tune 0xe00000 -#define bFrame_DC_Length 0xe000000 -#define bSBD_start_offset 0x30000000 -#define bFrame_TH_2 0x7 -#define bFrame_GI2_TH 0x38 -#define bGI2_Sync_en 0x40 -#define bSarch_Short_Early 0x300 -#define bSarch_Short_Late 0xc00 -#define bSarch_GI2_Late 0x70000 -#define bCFOAntSum 0x1 -#define bCFOAcc 0x2 -#define bCFOStartOffset 0xc -#define bCFOLookBack 0x70 -#define bCFOSumWeight 0x80 -#define bDAGCEnable 0x10000 -#define bTXIQImb_A 0x3ff -#define bTXIQImb_B 0xfc00 -#define bTXIQImb_C 0x3f0000 -#define bTXIQImb_D 0xffc00000 -#define bTxIDCOffset 0xff -#define bTxQDCOffset 0xff00 -#define bTxDFIRMode 0x10000 -#define bTxPesudoNoiseOn 0x4000000 -#define bTxPesudoNoise_A 0xff -#define bTxPesudoNoise_B 0xff00 -#define bTxPesudoNoise_C 0xff0000 -#define bTxPesudoNoise_D 0xff000000 -#define bCCADropOption 0x20000 -#define bCCADropThres 0xfff00000 -#define bEDCCA_H 0xf -#define bEDCCA_L 0xf0 -#define bLambda_ED 0x300 -#define bRxInitialGain 0x7f -#define bRxAntDivEn 0x80 -#define bRxAGCAddressForLNA 0x7f00 -#define bRxHighPowerFlow 0x8000 -#define bRxAGCFreezeThres 0xc0000 -#define bRxFreezeStep_AGC1 0x300000 -#define bRxFreezeStep_AGC2 0xc00000 -#define bRxFreezeStep_AGC3 0x3000000 -#define bRxFreezeStep_AGC0 0xc000000 -#define bRxRssi_Cmp_En 0x10000000 -#define bRxQuickAGCEn 0x20000000 -#define bRxAGCFreezeThresMode 0x40000000 -#define bRxOverFlowCheckType 0x80000000 -#define bRxAGCShift 0x7f -#define bTRSW_Tri_Only 0x80 -#define bPowerThres 0x300 -#define bRxAGCEn 0x1 -#define bRxAGCTogetherEn 0x2 -#define bRxAGCMin 0x4 -#define bRxHP_Ini 0x7 -#define bRxHP_TRLNA 0x70 -#define bRxHP_RSSI 0x700 -#define bRxHP_BBP1 0x7000 -#define bRxHP_BBP2 0x70000 -#define bRxHP_BBP3 0x700000 -#define bRSSI_H 0x7f0000 /* threshold for high power */ -#define bRSSI_Gen 0x7f000000 /* threshold for ant diversity */ -#define bRxSettle_TRSW 0x7 -#define bRxSettle_LNA 0x38 -#define bRxSettle_RSSI 0x1c0 -#define bRxSettle_BBP 0xe00 -#define bRxSettle_RxHP 0x7000 -#define bRxSettle_AntSW_RSSI 0x38000 -#define bRxSettle_AntSW 0xc0000 -#define bRxProcessTime_DAGC 0x300000 -#define bRxSettle_HSSI 0x400000 -#define bRxProcessTime_BBPPW 0x800000 -#define bRxAntennaPowerShift 0x3000000 -#define bRSSITableSelect 0xc000000 -#define bRxHP_Final 0x7000000 -#define bRxHTSettle_BBP 0x7 -#define bRxHTSettle_HSSI 0x8 -#define bRxHTSettle_RxHP 0x70 -#define bRxHTSettle_BBPPW 0x80 -#define bRxHTSettle_Idle 0x300 -#define bRxHTSettle_Reserved 0x1c00 -#define bRxHTRxHPEn 0x8000 -#define bRxHTAGCFreezeThres 0x30000 -#define bRxHTAGCTogetherEn 0x40000 -#define bRxHTAGCMin 0x80000 -#define bRxHTAGCEn 0x100000 -#define bRxHTDAGCEn 0x200000 -#define bRxHTRxHP_BBP 0x1c00000 -#define bRxHTRxHP_Final 0xe0000000 -#define bRxPWRatioTH 0x3 -#define bRxPWRatioEn 0x4 -#define bRxMFHold 0x3800 -#define bRxPD_Delay_TH1 0x38 -#define bRxPD_Delay_TH2 0x1c0 -#define bRxPD_DC_COUNT_MAX 0x600 -#define bRxPD_Delay_TH 0x8000 -#define bRxProcess_Delay 0xf0000 -#define bRxSearchrange_GI2_Early 0x700000 -#define bRxFrame_Guard_Counter_L 0x3800000 -#define bRxSGI_Guard_L 0xc000000 -#define bRxSGI_Search_L 0x30000000 -#define bRxSGI_TH 0xc0000000 -#define bDFSCnt0 0xff -#define bDFSCnt1 0xff00 -#define bDFSFlag 0xf0000 -#define bMFWeightSum 0x300000 -#define bMinIdxTH 0x7f000000 -#define bDAFormat 0x40000 -#define bTxChEmuEnable 0x01000000 -#define bTRSWIsolation_A 0x7f -#define bTRSWIsolation_B 0x7f00 -#define bTRSWIsolation_C 0x7f0000 -#define bTRSWIsolation_D 0x7f000000 -#define bExtLNAGain 0x7c00 - -/* 6. PageE(0xE00) */ -#define bSTBCEn 0x4 /* Useless */ -#define bAntennaMapping 0x10 -#define bNss 0x20 -#define bCFOAntSumD 0x200 -#define bPHYCounterReset 0x8000000 -#define bCFOReportGet 0x4000000 -#define bOFDMContinueTx 0x10000000 -#define bOFDMSingleCarrier 0x20000000 -#define bOFDMSingleTone 0x40000000 -#define bHTDetect 0x100 -#define bCFOEn 0x10000 -#define bCFOValue 0xfff00000 -#define bSigTone_Re 0x3f -#define bSigTone_Im 0x7f00 -#define bCounter_CCA 0xffff -#define bCounter_ParityFail 0xffff0000 -#define bCounter_RateIllegal 0xffff -#define bCounter_CRC8Fail 0xffff0000 -#define bCounter_MCSNoSupport 0xffff -#define bCounter_FastSync 0xffff -#define bShortCFO 0xfff -#define bShortCFOTLength 12 /* total */ -#define bShortCFOFLength 11 /* fraction */ -#define bLongCFO 0x7ff -#define bLongCFOTLength 11 -#define bLongCFOFLength 11 -#define bTailCFO 0x1fff -#define bTailCFOTLength 13 -#define bTailCFOFLength 12 -#define bmax_en_pwdB 0xffff -#define bCC_power_dB 0xffff0000 -#define bnoise_pwdB 0xffff -#define bPowerMeasTLength 10 -#define bPowerMeasFLength 3 -#define bRx_HT_BW 0x1 -#define bRxSC 0x6 -#define bRx_HT 0x8 -#define bNB_intf_det_on 0x1 -#define bIntf_win_len_cfg 0x30 -#define bNB_Intf_TH_cfg 0x1c0 -#define bRFGain 0x3f -#define bTableSel 0x40 -#define bTRSW 0x80 -#define bRxSNR_A 0xff -#define bRxSNR_B 0xff00 -#define bRxSNR_C 0xff0000 -#define bRxSNR_D 0xff000000 -#define bSNREVMTLength 8 -#define bSNREVMFLength 1 -#define bCSI1st 0xff -#define bCSI2nd 0xff00 -#define bRxEVM1st 0xff0000 -#define bRxEVM2nd 0xff000000 -#define bSIGEVM 0xff -#define bPWDB 0xff00 -#define bSGIEN 0x10000 - -#define bSFactorQAM1 0xf /* Useless */ -#define bSFactorQAM2 0xf0 -#define bSFactorQAM3 0xf00 -#define bSFactorQAM4 0xf000 -#define bSFactorQAM5 0xf0000 -#define bSFactorQAM6 0xf0000 -#define bSFactorQAM7 0xf00000 -#define bSFactorQAM8 0xf000000 -#define bSFactorQAM9 0xf0000000 -#define bCSIScheme 0x100000 - -#define bNoiseLvlTopSet 0x3 /* Useless */ -#define bChSmooth 0x4 -#define bChSmoothCfg1 0x38 -#define bChSmoothCfg2 0x1c0 -#define bChSmoothCfg3 0xe00 -#define bChSmoothCfg4 0x7000 -#define bMRCMode 0x800000 -#define bTHEVMCfg 0x7000000 - -#define bLoopFitType 0x1 /* Useless */ -#define bUpdCFO 0x40 -#define bUpdCFOOffData 0x80 -#define bAdvUpdCFO 0x100 -#define bAdvTimeCtrl 0x800 -#define bUpdClko 0x1000 -#define bFC 0x6000 -#define bTrackingMode 0x8000 -#define bPhCmpEnable 0x10000 -#define bUpdClkoLTF 0x20000 -#define bComChCFO 0x40000 -#define bCSIEstiMode 0x80000 -#define bAdvUpdEqz 0x100000 -#define bUChCfg 0x7000000 -#define bUpdEqz 0x8000000 - -/* Rx Pseduo noise */ -#define bRxPesudoNoiseOn 0x20000000 /* Useless */ -#define bRxPesudoNoise_A 0xff -#define bRxPesudoNoise_B 0xff00 -#define bRxPesudoNoise_C 0xff0000 -#define bRxPesudoNoise_D 0xff000000 -#define bPesudoNoiseState_A 0xffff -#define bPesudoNoiseState_B 0xffff0000 -#define bPesudoNoiseState_C 0xffff -#define bPesudoNoiseState_D 0xffff0000 - -/* 7. RF Register */ -/* Zebra1 */ -#define bZebra1_HSSIEnable 0x8 /* Useless */ -#define bZebra1_TRxControl 0xc00 -#define bZebra1_TRxGainSetting 0x07f -#define bZebra1_RxCorner 0xc00 -#define bZebra1_TxChargePump 0x38 -#define bZebra1_RxChargePump 0x7 -#define bZebra1_ChannelNum 0xf80 -#define bZebra1_TxLPFBW 0x400 -#define bZebra1_RxLPFBW 0x600 - -/* Zebra4 */ -#define bRTL8256RegModeCtrl1 0x100 /* Useless */ -#define bRTL8256RegModeCtrl0 0x40 -#define bRTL8256_TxLPFBW 0x18 -#define bRTL8256_RxLPFBW 0x600 - -/* RTL8258 */ -#define bRTL8258_TxLPFBW 0xc /* Useless */ -#define bRTL8258_RxLPFBW 0xc00 -#define bRTL8258_RSSILPFBW 0xc0 - - /* */ /* Other Definition */ /* */ -/* byte endable for sb_write */ -#define bByte0 0x1 /* Useless */ -#define bByte1 0x2 -#define bByte2 0x4 -#define bByte3 0x8 -#define bWord0 0x3 -#define bWord1 0xc -#define bDWord 0xf - /* for PutRegsetting & GetRegSetting BitMask */ #define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */ #define bMaskByte1 0xff00 -#define bMaskByte2 0xff0000 #define bMaskByte3 0xff000000 -#define bMaskHWord 0xffff0000 -#define bMaskLWord 0x0000ffff #define bMaskDWord 0xffffffff #define bMask12Bits 0xfff -#define bMaskH4Bits 0xf0000000 #define bMaskOFDM_D 0xffc00000 -#define bMaskCCK 0x3f3f3f3f /* for PutRFRegsetting & GetRFRegSetting BitMask */ #define bRFRegOffsetMask 0xfffff -#define bEnable 0x1 /* Useless */ -#define bDisable 0x0 - -#define LeftAntenna 0x0 /* Useless */ -#define RightAntenna 0x1 - -#define tCheckTxStatus 500 /* 500ms Useless */ -#define tUpdateRxCounter 100 /* 100ms */ - -#define rateCCK 0 /* Useless */ -#define rateOFDM 1 -#define rateHT 2 - -/* define Register-End */ -#define bPMAC_End 0x1ff /* Useless */ -#define bFPGAPHY0_End 0x8ff -#define bFPGAPHY1_End 0x9ff -#define bCCKPHY0_End 0xaff -#define bOFDMPHY0_End 0xcff -#define bOFDMPHY1_End 0xdff - -#define bPMACControl 0x0 /* Useless */ -#define bWMACControl 0x1 -#define bWNICControl 0x2 - -#define PathA 0x0 /* Useless */ -#define PathB 0x1 -#define PathC 0x2 -#define PathD 0x3 - -/*--------------------------Define Parameters-------------------------------*/ - - #endif diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 8b65fcba1967..516a89647003 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -199,7 +199,7 @@ void rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg, u8 level); void rtw_hal_clone_data(struct adapter *dst_adapt, struct adapter *src_adapt); -void rtw_hal_bcn_related_reg_setting(struct adapter *padapter); +void beacon_timing_control(struct adapter *padapter); u32 rtw_hal_read_rfreg(struct adapter *padapter, enum rf_radio_path eRFPath, u32 RegAddr, u32 BitMask); diff --git a/drivers/staging/rtl8188eu/include/mlme_osdep.h b/drivers/staging/rtl8188eu/include/mlme_osdep.h index eda16c06336a..8e919441c2aa 100644 --- a/drivers/staging/rtl8188eu/include/mlme_osdep.h +++ b/drivers/staging/rtl8188eu/include/mlme_osdep.h @@ -13,7 +13,6 @@ void rtw_init_mlme_timer(struct adapter *padapter); void rtw_os_indicate_disconnect(struct adapter *adapter); void rtw_os_indicate_connect(struct adapter *adapter); -void rtw_os_indicate_scan_done(struct adapter *padapter, bool aborted); void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie); void rtw_reset_securitypriv(struct adapter *adapter); diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index cfe5698fbbb1..c0114ad79788 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -80,8 +80,6 @@ void rtw_free_netdev(struct net_device *netdev); #define FUNC_ADPT_FMT "%s(%s)" #define FUNC_ADPT_ARG(adapter) __func__, adapter->pnetdev->name -u64 rtw_modular64(u64 x, u64 y); - /* Macros for handling unaligned memory accesses */ #define RTW_GET_BE24(a) ((((u32)(a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 9abb7c320192..010f0c42368a 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -333,7 +333,7 @@ void rtw_dynamic_check_timer_handlder(struct timer_list *t); void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv); -struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv); +struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv); int rtw_if_up(struct adapter *padapter); diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 327f7d1bc20c..d70780c8fd62 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -535,7 +535,6 @@ void report_del_sta_event(struct adapter *padapter, void report_add_sta_event(struct adapter *padapter, unsigned char *addr, int cam_idx); -void beacon_timing_control(struct adapter *padapter); u8 set_tx_beacon_cmd(struct adapter *padapter); unsigned int setup_beacon_frame(struct adapter *padapter, unsigned char *beacon_frame); diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c index e660bd4d91ef..321b2c46479c 100644 --- a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c @@ -27,11 +27,6 @@ void rtw_os_indicate_connect(struct adapter *adapter) netif_carrier_on(adapter->pnetdev); } -void rtw_os_indicate_scan_done(struct adapter *padapter, bool aborted) -{ - indicate_wx_scan_complete_event(padapter); -} - static struct rt_pmkid_list backup_pmkid[NUM_PMKID_CACHE]; void rtw_reset_securitypriv(struct adapter *adapter) diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 105f3f21bdea..69d4b1d66b6f 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -59,11 +59,6 @@ RETURN: return; } -u64 rtw_modular64(u64 x, u64 y) -{ - return do_div(x, y); -} - void rtw_buf_free(u8 **buf, u32 *buf_len) { *buf_len = 0; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index eedf2cd831d1..aaab0d577453 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -122,8 +122,7 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) precvframe->pkt = pkt_copy; skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */ skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */ - memcpy(pkt_copy->data, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len); - skb_put(precvframe->pkt, skb_len); + skb_put_data(pkt_copy, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len); } else { DBG_88E("%s: alloc_skb fail , drop frag frame\n", __func__); diff --git a/drivers/staging/rtl8192e/Kconfig b/drivers/staging/rtl8192e/Kconfig index 11528d17bb3c..1007eea6c8fc 100644 --- a/drivers/staging/rtl8192e/Kconfig +++ b/drivers/staging/rtl8192e/Kconfig @@ -15,6 +15,7 @@ config RTLLIB_CRYPTO_CCMP tristate "Support for rtllib CCMP crypto" depends on RTLLIB select CRYPTO_AES + select CRYPTO_CCM default y help CCMP crypto driver for rtllib. diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index 1b7e3fda7905..20e494186c9e 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -618,7 +618,7 @@ static void _rtl92e_dm_tx_update_tssi_strong_signal(struct net_device *dev, static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); - bool bHighpowerstate, viviflag = false; + bool viviflag = false; struct dcmd_txcmd tx_cmd; u8 powerlevelOFDM24G; int i = 0, j = 0, k = 0; @@ -632,7 +632,6 @@ static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev) rtl92e_writeb(dev, Pw_Track_Flag, 0); rtl92e_writeb(dev, FW_Busy_Flag, 0); priv->rtllib->bdynamic_txpower_enable = false; - bHighpowerstate = priv->bDynamicTxHighPower; powerlevelOFDM24G = (u8)(priv->Pwr_Track>>24); RF_Type = priv->rf_type; @@ -1901,7 +1900,7 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) u8 cck_default_Rx = 0x2; u8 cck_optional_Rx = 0x3; long tmp_cck_max_pwdb = 0, tmp_cck_min_pwdb = 0, tmp_cck_sec_pwdb = 0; - u8 cck_rx_ver2_max_index = 0, cck_rx_ver2_min_index = 0; + u8 cck_rx_ver2_max_index = 0; u8 cck_rx_ver2_sec_index = 0; u8 cur_rf_rssi; long cur_cck_pwdb; @@ -1984,7 +1983,6 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) if (rf_num == 1) { cck_rx_ver2_max_index = i; - cck_rx_ver2_min_index = i; cck_rx_ver2_sec_index = i; tmp_cck_max_pwdb = cur_cck_pwdb; tmp_cck_min_pwdb = cur_cck_pwdb; @@ -1997,7 +1995,6 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) tmp_cck_sec_pwdb = cur_cck_pwdb; tmp_cck_min_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; - cck_rx_ver2_min_index = i; } } else { if (cur_cck_pwdb > tmp_cck_max_pwdb) { @@ -2027,13 +2024,10 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) (cur_cck_pwdb > tmp_cck_min_pwdb)) { ; } else if (cur_cck_pwdb == tmp_cck_min_pwdb) { - if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { + if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) tmp_cck_min_pwdb = cur_cck_pwdb; - cck_rx_ver2_min_index = i; - } } else if (cur_cck_pwdb < tmp_cck_min_pwdb) { tmp_cck_min_pwdb = cur_cck_pwdb; - cck_rx_ver2_min_index = i; } } diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 2dd57e88276e..328f410daa03 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -479,7 +479,6 @@ enum wireless_mode { #define P80211_OUI_LEN 3 struct rtllib_snap_hdr { - u8 dsap; /* always 0xAA */ u8 ssap; /* always 0xAA */ u8 ctrl; /* always 0x03 */ @@ -1940,7 +1939,7 @@ int rtllib_encrypt_fragment( int hdr_len); int rtllib_xmit(struct sk_buff *skb, struct net_device *dev); -void rtllib_txb_free(struct rtllib_txb *); +void rtllib_txb_free(struct rtllib_txb *txb); /* rtllib_rx.c */ int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb, @@ -2132,7 +2131,7 @@ static inline const char *escape_essid(const char *essid, u8 essid_len) return escaped; } - snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid); + snprintf(escaped, sizeof(escaped), "%*pE", essid_len, essid); return escaped; } diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c index 2581ed6d14fa..0cbf4a1a326b 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c @@ -17,6 +17,7 @@ #include "rtllib.h" #include <linux/crypto.h> +#include <crypto/aead.h> #include <linux/scatterlist.h> @@ -39,20 +40,13 @@ struct rtllib_ccmp_data { int key_idx; - struct crypto_tfm *tfm; + struct crypto_aead *tfm; /* scratch buffers for virt_to_page() (crypto API) */ - u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], - tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; - u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; + u8 tx_aad[2 * AES_BLOCK_LEN]; + u8 rx_aad[2 * AES_BLOCK_LEN]; }; -static void rtllib_ccmp_aes_encrypt(struct crypto_tfm *tfm, - const u8 pt[16], u8 ct[16]) -{ - crypto_cipher_encrypt_one((void *)tfm, ct, pt); -} - static void *rtllib_ccmp_init(int key_idx) { struct rtllib_ccmp_data *priv; @@ -62,7 +56,7 @@ static void *rtllib_ccmp_init(int key_idx) goto fail; priv->key_idx = key_idx; - priv->tfm = (void *)crypto_alloc_cipher("aes", 0, 0); + priv->tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tfm)) { pr_debug("Could not allocate crypto API aes\n"); priv->tfm = NULL; @@ -73,7 +67,7 @@ static void *rtllib_ccmp_init(int key_idx) fail: if (priv) { if (priv->tfm) - crypto_free_cipher((void *)priv->tfm); + crypto_free_aead(priv->tfm); kfree(priv); } @@ -86,31 +80,18 @@ static void rtllib_ccmp_deinit(void *priv) struct rtllib_ccmp_data *_priv = priv; if (_priv && _priv->tfm) - crypto_free_cipher((void *)_priv->tfm); + crypto_free_aead(_priv->tfm); kfree(priv); } -static inline void xor_block(u8 *b, u8 *a, size_t len) -{ - int i; - - for (i = 0; i < len; i++) - b[i] ^= a[i]; -} - - - -static void ccmp_init_blocks(struct crypto_tfm *tfm, - struct rtllib_hdr_4addr *hdr, - u8 *pn, size_t dlen, u8 *b0, u8 *auth, - u8 *s0) +static int ccmp_init_iv_and_aad(struct rtllib_hdr_4addr *hdr, + u8 *pn, u8 *iv, u8 *aad) { u8 *pos, qc = 0; size_t aad_len; u16 fc; int a4_included, qc_included; - u8 aad[2 * AES_BLOCK_LEN]; fc = le16_to_cpu(hdr->frame_ctl); a4_included = ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) == @@ -128,18 +109,19 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, qc = *pos & 0x0f; aad_len += 2; } - /* CCM Initial Block: - * Flag (Include authentication header, M=3 (8-octet MIC), - * L=1 (2-octet Dlen)) - * Nonce: 0x00 | A2 | PN - * Dlen + /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC + * mode authentication are not allowed to collide, yet both are derived + * from the same vector. We only set L := 1 here to indicate that the + * data size can be represented in (L+1) bytes. The CCM layer will take + * care of storing the data length in the top (L+1) bytes and setting + * and clearing the other bits as is required to derive the two IVs. */ - b0[0] = 0x59; - b0[1] = qc; - memcpy(b0 + 2, hdr->addr2, ETH_ALEN); - memcpy(b0 + 8, pn, CCMP_PN_LEN); - b0[14] = (dlen >> 8) & 0xff; - b0[15] = dlen & 0xff; + iv[0] = 0x1; + + /* Nonce: QC | A2 | PN */ + iv[1] = qc; + memcpy(iv + 2, hdr->addr2, ETH_ALEN); + memcpy(iv + 8, pn, CCMP_PN_LEN); /* AAD: * FC with bits 4..6 and 11..13 masked to zero; 14 is always one @@ -149,31 +131,21 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, * QC (if present) */ pos = (u8 *) hdr; - aad[0] = 0; /* aad_len >> 8 */ - aad[1] = aad_len & 0xff; - aad[2] = pos[0] & 0x8f; - aad[3] = pos[1] & 0xc7; - memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); + aad[0] = pos[0] & 0x8f; + aad[1] = pos[1] & 0xc7; + memcpy(aad + 2, hdr->addr1, 3 * ETH_ALEN); pos = (u8 *) &hdr->seq_ctl; - aad[22] = pos[0] & 0x0f; - aad[23] = 0; /* all bits masked */ - memset(aad + 24, 0, 8); + aad[20] = pos[0] & 0x0f; + aad[21] = 0; /* all bits masked */ + memset(aad + 22, 0, 8); if (a4_included) - memcpy(aad + 24, hdr->addr4, ETH_ALEN); + memcpy(aad + 22, hdr->addr4, ETH_ALEN); if (qc_included) { - aad[a4_included ? 30 : 24] = qc; + aad[a4_included ? 28 : 22] = qc; /* rest of QC masked */ } - /* Start with the first block and AAD */ - rtllib_ccmp_aes_encrypt(tfm, b0, auth); - xor_block(auth, aad, AES_BLOCK_LEN); - rtllib_ccmp_aes_encrypt(tfm, auth, auth); - xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); - rtllib_ccmp_aes_encrypt(tfm, auth, auth); - b0[0] &= 0x07; - b0[14] = b0[15] = 0; - rtllib_ccmp_aes_encrypt(tfm, b0, s0); + return aad_len; } @@ -181,7 +153,7 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct rtllib_ccmp_data *key = priv; - int data_len, i; + int i; u8 *pos; struct rtllib_hdr_4addr *hdr; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + @@ -191,7 +163,6 @@ static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) skb->len < hdr_len) return -1; - data_len = skb->len - hdr_len; pos = skb_push(skb, CCMP_HDR_LEN); memmove(pos, pos + CCMP_HDR_LEN, hdr_len); pos += hdr_len; @@ -213,40 +184,37 @@ static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) *pos++ = key->tx_pn[1]; *pos++ = key->tx_pn[0]; - hdr = (struct rtllib_hdr_4addr *) skb->data; if (!tcb_desc->bHwSec) { - int blocks, last, len; - u8 *mic; - u8 *b0 = key->tx_b0; - u8 *b = key->tx_b; - u8 *e = key->tx_e; - u8 *s0 = key->tx_s0; - - mic = skb_put(skb, CCMP_MIC_LEN); - - ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, - b0, b, s0); - - blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Authentication */ - xor_block(b, pos, len); - rtllib_ccmp_aes_encrypt(key->tfm, b, b); - /* Encryption, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - rtllib_ccmp_aes_encrypt(key->tfm, b0, e); - xor_block(pos, e, len); - pos += len; - } + struct aead_request *req; + struct scatterlist sg[2]; + u8 *aad = key->tx_aad; + u8 iv[AES_BLOCK_LEN]; + int aad_len, ret; + int data_len = skb->len - hdr_len - CCMP_HDR_LEN; + + req = aead_request_alloc(key->tfm, GFP_ATOMIC); + if (!req) + return -ENOMEM; + + aad_len = ccmp_init_iv_and_aad(hdr, key->tx_pn, iv, aad); + + skb_put(skb, CCMP_MIC_LEN); + sg_init_table(sg, 2); + sg_set_buf(&sg[0], aad, aad_len); + sg_set_buf(&sg[1], skb->data + hdr_len + CCMP_HDR_LEN, + data_len + CCMP_MIC_LEN); - for (i = 0; i < CCMP_MIC_LEN; i++) - mic[i] = b[i] ^ s0[i]; + aead_request_set_callback(req, 0, NULL, NULL); + aead_request_set_ad(req, aad_len); + aead_request_set_crypt(req, sg, sg, data_len, iv); + + ret = crypto_aead_encrypt(req); + aead_request_free(req); + + return ret; } + return 0; } @@ -302,35 +270,31 @@ static int rtllib_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return -4; } if (!tcb_desc->bHwSec) { - size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - - CCMP_MIC_LEN; - u8 *mic = skb->data + skb->len - CCMP_MIC_LEN; - u8 *b0 = key->rx_b0; - u8 *b = key->rx_b; - u8 *a = key->rx_a; - int i, blocks, last, len; - - - ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b); - xor_block(mic, b, CCMP_MIC_LEN); - - blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Decrypt, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - rtllib_ccmp_aes_encrypt(key->tfm, b0, b); - xor_block(pos, b, len); - /* Authentication */ - xor_block(a, pos, len); - rtllib_ccmp_aes_encrypt(key->tfm, a, a); - pos += len; - } + size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN; + struct aead_request *req; + struct scatterlist sg[2]; + u8 *aad = key->rx_aad; + u8 iv[AES_BLOCK_LEN]; + int aad_len, ret; + + req = aead_request_alloc(key->tfm, GFP_ATOMIC); + if(!req) + return -ENOMEM; + + aad_len = ccmp_init_iv_and_aad(hdr, pn, iv, aad); + + sg_init_table(sg, 2); + sg_set_buf(&sg[0], aad, aad_len); + sg_set_buf(&sg[1], pos, data_len); + + aead_request_set_callback(req, 0, NULL, NULL); + aead_request_set_ad(req, aad_len); + aead_request_set_crypt(req, sg, sg, data_len, iv); + + ret = crypto_aead_decrypt(req); + aead_request_free(req); - if (memcmp(mic, a, CCMP_MIC_LEN) != 0) { + if (ret) { if (net_ratelimit()) { pr_debug("CCMP: decrypt failed: STA= %pM\n", hdr->addr2); @@ -354,7 +318,7 @@ static int rtllib_ccmp_set_key(void *key, int len, u8 *seq, void *priv) { struct rtllib_ccmp_data *data = priv; int keyidx; - struct crypto_tfm *tfm = data->tfm; + struct crypto_aead *tfm = data->tfm; keyidx = data->key_idx; memset(data, 0, sizeof(*data)); @@ -371,7 +335,9 @@ static int rtllib_ccmp_set_key(void *key, int len, u8 *seq, void *priv) data->rx_pn[4] = seq[1]; data->rx_pn[5] = seq[0]; } - crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN); + if (crypto_aead_setauthsize(data->tfm, CCMP_MIC_LEN) || + crypto_aead_setkey(data->tfm, data->key, CCMP_TK_LEN)) + return -1; } else if (len == 0) { data->key_set = 0; } else { diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index 0c19ac2bc3bf..0bae0a0a4cbe 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -1300,7 +1300,6 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, struct rx_ts_record *pTS = NULL; u16 fc, sc, SeqNum = 0; u8 type, stype, multicast = 0, unicast = 0, nr_subframes = 0, TID = 0; - u8 *payload; u8 dst[ETH_ALEN]; u8 src[ETH_ALEN]; u8 bssid[ETH_ALEN] = {0}; @@ -1412,7 +1411,6 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, /* Parse rx data frame (For AMSDU) */ /* skb: hdr + (possible reassembled) full plaintext payload */ - payload = skb->data + hdrlen; rxb = kmalloc(sizeof(struct rtllib_rxb), GFP_ATOMIC); if (!rxb) goto rx_dropped; diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index e29e8d6f4611..f2f7529e7c80 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -1382,15 +1382,10 @@ rtllib_association_req(struct rtllib_network *beacon, ieee->assocreq_ies = NULL; ies = &(hdr->info_element[0].id); ieee->assocreq_ies_len = (skb->data + skb->len) - ies; - ieee->assocreq_ies = kmalloc(ieee->assocreq_ies_len, GFP_ATOMIC); - if (ieee->assocreq_ies) - memcpy(ieee->assocreq_ies, ies, ieee->assocreq_ies_len); - else { - netdev_info(ieee->dev, - "%s()Warning: can't alloc memory for assocreq_ies\n", - __func__); + ieee->assocreq_ies = kmemdup(ies, ieee->assocreq_ies_len, GFP_ATOMIC); + if (!ieee->assocreq_ies) ieee->assocreq_ies_len = 0; - } + return skb; } @@ -2259,17 +2254,12 @@ rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb, ieee->assocresp_ies = NULL; ies = &(assoc_resp->info_element[0].id); ieee->assocresp_ies_len = (skb->data + skb->len) - ies; - ieee->assocresp_ies = kmalloc(ieee->assocresp_ies_len, + ieee->assocresp_ies = kmemdup(ies, + ieee->assocresp_ies_len, GFP_ATOMIC); - if (ieee->assocresp_ies) - memcpy(ieee->assocresp_ies, ies, - ieee->assocresp_ies_len); - else { - netdev_info(ieee->dev, - "%s()Warning: can't alloc memory for assocresp_ies\n", - __func__); + if (!ieee->assocresp_ies) ieee->assocresp_ies_len = 0; - } + rtllib_associate_complete(ieee); } else { /* aid could not been allocated */ diff --git a/drivers/staging/rtl8192u/Kconfig b/drivers/staging/rtl8192u/Kconfig index 22c2165e8b1c..1edca5c304fb 100644 --- a/drivers/staging/rtl8192u/Kconfig +++ b/drivers/staging/rtl8192u/Kconfig @@ -6,3 +6,5 @@ config RTL8192U select WIRELESS_EXT select WEXT_PRIV select CRYPTO + select CRYPTO_AES + select CRYPTO_CCM diff --git a/drivers/staging/rtl8192u/ieee80211/dot11d.c b/drivers/staging/rtl8192u/ieee80211/dot11d.c index 130ddfe9868f..bc642076b96f 100644 --- a/drivers/staging/rtl8192u/ieee80211/dot11d.c +++ b/drivers/staging/rtl8192u/ieee80211/dot11d.c @@ -12,7 +12,7 @@ void rtl8192u_dot11d_init(struct ieee80211_device *ieee) dot11d_info->state = DOT11D_STATE_NONE; dot11d_info->country_ie_len = 0; memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); - memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1); RESET_CIE_WATCHDOG(ieee); netdev_info(ieee->dev, "rtl8192u_dot11d_init()\n"); @@ -25,8 +25,8 @@ void dot11d_reset(struct ieee80211_device *ieee) u32 i; struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee); /* Clear old channel map */ - memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); + memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1); /* Set new channel map */ for (i = 1; i <= 11; i++) (dot11d_info->channel_map)[i] = 1; @@ -56,8 +56,8 @@ void dot11d_update_country_ie(struct ieee80211_device *dev, u8 *pTaddr, u8 i, j, NumTriples, MaxChnlNum; struct chnl_txpower_triple *pTriple; - memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); + memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1); MaxChnlNum = 0; NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */ pTriple = (struct chnl_txpower_triple *)(pCoutryIe + 3); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index d36963469015..9576b647f6b1 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -169,9 +169,9 @@ struct cb_desc { #define MGN_MCS14 0x8e #define MGN_MCS15 0x8f -#define aSifsTime ((priv->ieee80211->current_network.mode == IEEE_A || \ +#define aSifsTime ((priv->ieee80211->current_network.mode == IEEE_A || \ priv->ieee80211->current_network.mode == IEEE_N_24G || \ - priv->ieee80211->current_network.mode == IEEE_N_5G) ? \ + priv->ieee80211->current_network.mode == IEEE_N_5G) ? \ 16 : 10) #define MGMT_QUEUE_NUM 5 @@ -387,7 +387,7 @@ struct ieee_param { #define IEEE80211_STYPE_ACK 0x00D0 #define IEEE80211_STYPE_CFEND 0x00E0 #define IEEE80211_STYPE_CFENDACK 0x00F0 -#define IEEE80211_STYPE_BLOCKACK 0x0094 +#define IEEE80211_STYPE_BLOCKACK 0x0094 /* data */ #define IEEE80211_STYPE_DATA 0x0000 @@ -452,23 +452,23 @@ do { if (ieee80211_debug_level & (level)) \ printk(KERN_DEBUG "ieee80211: " fmt, ## args); } while (0) //wb added to debug out data buf //if you want print DATA buffer related BA, please set ieee80211_debug_level to DATA|BA -#define IEEE80211_DEBUG_DATA(level, data, datalen) \ - do { if ((ieee80211_debug_level & (level)) == (level)) \ - { \ - int i; \ - u8 *pdata = (u8 *) data; \ - printk(KERN_DEBUG "ieee80211: %s()\n", __func__); \ - for (i = 0; i < (int)(datalen); i++) \ - { \ - printk("%2x ", pdata[i]); \ - if ((i + 1) % 16 == 0) printk("\n"); \ - } \ - printk("\n"); \ - } \ +#define IEEE80211_DEBUG_DATA(level, data, datalen) \ + do { if ((ieee80211_debug_level & (level)) == (level)) \ + { \ + int i; \ + u8 *pdata = (u8 *)data; \ + printk(KERN_DEBUG "ieee80211: %s()\n", __func__); \ + for (i = 0; i < (int)(datalen); i++) { \ + printk("%2x ", pdata[i]); \ + if ((i + 1) % 16 == 0) \ + printk("\n"); \ + } \ + printk("\n"); \ + } \ } while (0) #else #define IEEE80211_DEBUG (level, fmt, args...) do {} while (0) -#define IEEE80211_DEBUG_DATA (level, data, datalen) do {} while(0) +#define IEEE80211_DEBUG_DATA (level, data, datalen) do {} while (0) #endif /* CONFIG_IEEE80211_DEBUG */ /* debug macros not dependent on CONFIG_IEEE80211_DEBUG */ @@ -1649,10 +1649,8 @@ struct ieee80211_device { struct list_head Rx_TS_Pending_List; struct list_head Rx_TS_Unused_List; struct rx_ts_record RxTsRecord[TOTAL_TS_NUM]; -//#ifdef TO_DO_LIST struct rx_reorder_entry RxReorderEntry[128]; struct list_head RxReorder_Unused_List; -//#endif // Qos related. Added by Annie, 2005-11-01. // PSTA_QOS pStaQos; u8 ForcedPriority; // Force per-packet priority 1~7. (default: 0, not to force it.) @@ -2015,8 +2013,8 @@ struct ieee80211_device { #define IEEE_A (1<<0) #define IEEE_B (1<<1) #define IEEE_G (1<<2) -#define IEEE_N_24G (1<<4) -#define IEEE_N_5G (1<<5) +#define IEEE_N_24G (1<<4) +#define IEEE_N_5G (1<<5) #define IEEE_MODE_MASK (IEEE_A | IEEE_B | IEEE_G) /* Generate a 802.11 header */ @@ -2426,7 +2424,7 @@ static inline const char *escape_essid(const char *essid, u8 essid_len) return escaped; } - snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid); + snprintf(escaped, sizeof(escaped), "%*pE", essid_len, essid); return escaped; } diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c index 36987fccac5d..01012dddcd73 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c @@ -176,7 +176,7 @@ struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name) } -static void *ieee80211_crypt_null_init(int keyidx) { return (void *) 1; } +static void *ieee80211_crypt_null_init(int keyidx) { return (void *)1; } static void ieee80211_crypt_null_deinit(void *priv) {} static struct ieee80211_crypto_ops ieee80211_crypt_null = { diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c index d7188b3f3190..c241cf484023 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c @@ -19,6 +19,7 @@ #include "ieee80211.h" #include <linux/crypto.h> +#include <crypto/aead.h> #include <linux/scatterlist.h> MODULE_AUTHOR("Jouni Malinen"); @@ -44,20 +45,13 @@ struct ieee80211_ccmp_data { int key_idx; - struct crypto_tfm *tfm; + struct crypto_aead *tfm; /* scratch buffers for virt_to_page() (crypto API) */ - u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], - tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; - u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; + u8 tx_aad[2 * AES_BLOCK_LEN]; + u8 rx_aad[2 * AES_BLOCK_LEN]; }; -static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm, - const u8 pt[16], u8 ct[16]) -{ - crypto_cipher_encrypt_one((void *)tfm, ct, pt); -} - static void *ieee80211_ccmp_init(int key_idx) { struct ieee80211_ccmp_data *priv; @@ -67,7 +61,7 @@ static void *ieee80211_ccmp_init(int key_idx) goto fail; priv->key_idx = key_idx; - priv->tfm = (void *)crypto_alloc_cipher("aes", 0, 0); + priv->tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tfm)) { pr_debug("ieee80211_crypt_ccmp: could not allocate crypto API aes\n"); priv->tfm = NULL; @@ -79,7 +73,7 @@ static void *ieee80211_ccmp_init(int key_idx) fail: if (priv) { if (priv->tfm) - crypto_free_cipher((void *)priv->tfm); + crypto_free_aead(priv->tfm); kfree(priv); } @@ -91,28 +85,17 @@ static void ieee80211_ccmp_deinit(void *priv) struct ieee80211_ccmp_data *_priv = priv; if (_priv && _priv->tfm) - crypto_free_cipher((void *)_priv->tfm); + crypto_free_aead(_priv->tfm); kfree(priv); } -static inline void xor_block(u8 *b, u8 *a, size_t len) -{ - int i; - - for (i = 0; i < len; i++) - b[i] ^= a[i]; -} - -static void ccmp_init_blocks(struct crypto_tfm *tfm, - struct rtl_80211_hdr_4addr *hdr, - u8 *pn, size_t dlen, u8 *b0, u8 *auth, - u8 *s0) +static int ccmp_init_iv_and_aad(struct rtl_80211_hdr_4addr *hdr, + u8 *pn, u8 *iv, u8 *aad) { u8 *pos, qc = 0; size_t aad_len; u16 fc; int a4_included, qc_included; - u8 aad[2 * AES_BLOCK_LEN]; fc = le16_to_cpu(hdr->frame_ctl); a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == @@ -133,18 +116,20 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, qc = *pos & 0x0f; aad_len += 2; } - /* CCM Initial Block: - * Flag (Include authentication header, M=3 (8-octet MIC), - * L=1 (2-octet Dlen)) - * Nonce: 0x00 | A2 | PN - * Dlen + + /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC + * mode authentication are not allowed to collide, yet both are derived + * from the same vector. We only set L := 1 here to indicate that the + * data size can be represented in (L+1) bytes. The CCM layer will take + * care of storing the data length in the top (L+1) bytes and setting + * and clearing the other bits as is required to derive the two IVs. */ - b0[0] = 0x59; - b0[1] = qc; - memcpy(b0 + 2, hdr->addr2, ETH_ALEN); - memcpy(b0 + 8, pn, CCMP_PN_LEN); - b0[14] = (dlen >> 8) & 0xff; - b0[15] = dlen & 0xff; + iv[0] = 0x1; + + /* Nonce: QC | A2 | PN */ + iv[1] = qc; + memcpy(iv + 2, hdr->addr2, ETH_ALEN); + memcpy(iv + 8, pn, CCMP_PN_LEN); /* AAD: * FC with bits 4..6 and 11..13 masked to zero; 14 is always one @@ -154,38 +139,27 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, * QC (if present) */ pos = (u8 *)hdr; - aad[0] = 0; /* aad_len >> 8 */ - aad[1] = aad_len & 0xff; - aad[2] = pos[0] & 0x8f; - aad[3] = pos[1] & 0xc7; - memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); + aad[0] = pos[0] & 0x8f; + aad[1] = pos[1] & 0xc7; + memcpy(aad + 2, hdr->addr1, 3 * ETH_ALEN); pos = (u8 *)&hdr->seq_ctl; - aad[22] = pos[0] & 0x0f; - aad[23] = 0; /* all bits masked */ - memset(aad + 24, 0, 8); + aad[20] = pos[0] & 0x0f; + aad[21] = 0; /* all bits masked */ + memset(aad + 22, 0, 8); if (a4_included) - memcpy(aad + 24, hdr->addr4, ETH_ALEN); + memcpy(aad + 22, hdr->addr4, ETH_ALEN); if (qc_included) { - aad[a4_included ? 30 : 24] = qc; + aad[a4_included ? 28 : 22] = qc; /* rest of QC masked */ } - /* Start with the first block and AAD */ - ieee80211_ccmp_aes_encrypt(tfm, b0, auth); - xor_block(auth, aad, AES_BLOCK_LEN); - ieee80211_ccmp_aes_encrypt(tfm, auth, auth); - xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); - ieee80211_ccmp_aes_encrypt(tfm, auth, auth); - b0[0] &= 0x07; - b0[14] = 0; - b0[15] = 0; - ieee80211_ccmp_aes_encrypt(tfm, b0, s0); + return aad_len; } static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct ieee80211_ccmp_data *key = priv; - int data_len, i; + int i; u8 *pos; struct rtl_80211_hdr_4addr *hdr; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); @@ -195,7 +169,6 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) skb->len < hdr_len) return -1; - data_len = skb->len - hdr_len; pos = skb_push(skb, CCMP_HDR_LEN); memmove(pos, pos + CCMP_HDR_LEN, hdr_len); pos += hdr_len; @@ -220,36 +193,34 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (!tcb_desc->bHwSec) { - int blocks, last, len; - u8 *mic; - u8 *b0 = key->tx_b0; - u8 *b = key->tx_b; - u8 *e = key->tx_e; - u8 *s0 = key->tx_s0; - - /* mic is moved to here by john */ - mic = skb_put(skb, CCMP_MIC_LEN); - - ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); - - blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Authentication */ - xor_block(b, pos, len); - ieee80211_ccmp_aes_encrypt(key->tfm, b, b); - /* Encryption, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - ieee80211_ccmp_aes_encrypt(key->tfm, b0, e); - xor_block(pos, e, len); - pos += len; - } + struct aead_request *req; + struct scatterlist sg[2]; + u8 *aad = key->tx_aad; + u8 iv[AES_BLOCK_LEN]; + int aad_len, ret; + size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN; - for (i = 0; i < CCMP_MIC_LEN; i++) - mic[i] = b[i] ^ s0[i]; + req = aead_request_alloc(key->tfm, GFP_ATOMIC); + if (!req) + return -ENOMEM; + + aad_len = ccmp_init_iv_and_aad(hdr, key->tx_pn, iv, aad); + + skb_put(skb, CCMP_MIC_LEN); + + sg_init_table(sg, 2); + sg_set_buf(&sg[0], aad, aad_len); + sg_set_buf(&sg[1], skb->data + hdr_len + CCMP_HDR_LEN, + data_len + CCMP_MIC_LEN); + + aead_request_set_callback(req, 0, NULL, NULL); + aead_request_set_ad(req, aad_len); + aead_request_set_crypt(req, sg, sg, data_len, iv); + + ret = crypto_aead_encrypt(req); + aead_request_free(req); + + return ret; } return 0; } @@ -309,33 +280,31 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return -4; } if (!tcb_desc->bHwSec) { - size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN; - u8 *mic = skb->data + skb->len - CCMP_MIC_LEN; - u8 *b0 = key->rx_b0; - u8 *b = key->rx_b; - u8 *a = key->rx_a; - int i, blocks, last, len; - - ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b); - xor_block(mic, b, CCMP_MIC_LEN); - - blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Decrypt, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - ieee80211_ccmp_aes_encrypt(key->tfm, b0, b); - xor_block(pos, b, len); - /* Authentication */ - xor_block(a, pos, len); - ieee80211_ccmp_aes_encrypt(key->tfm, a, a); - pos += len; - } + struct aead_request *req; + struct scatterlist sg[2]; + u8 *aad = key->rx_aad; + u8 iv[AES_BLOCK_LEN]; + int aad_len, ret; + size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN; + + req = aead_request_alloc(key->tfm, GFP_ATOMIC); + if (!req) + return -ENOMEM; + + aad_len = ccmp_init_iv_and_aad(hdr, pn, iv, aad); + + sg_init_table(sg, 2); + sg_set_buf(&sg[0], aad, aad_len); + sg_set_buf(&sg[1], pos, data_len); + + aead_request_set_callback(req, 0, NULL, NULL); + aead_request_set_ad(req, aad_len); + aead_request_set_crypt(req, sg, sg, data_len, iv); + + ret = crypto_aead_decrypt(req); + aead_request_free(req); - if (memcmp(mic, a, CCMP_MIC_LEN) != 0) { + if (ret) { if (net_ratelimit()) { netdev_dbg(skb->dev, "CCMP: decrypt failed: STA=%pM\n", hdr->addr2); @@ -358,12 +327,11 @@ static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv) { struct ieee80211_ccmp_data *data = priv; int keyidx; - struct crypto_tfm *tfm = data->tfm; + struct crypto_aead *tfm = data->tfm; keyidx = data->key_idx; memset(data, 0, sizeof(*data)); data->key_idx = keyidx; - data->tfm = tfm; if (len == CCMP_TK_LEN) { memcpy(data->key, key, CCMP_TK_LEN); data->key_set = 1; @@ -375,7 +343,9 @@ static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv) data->rx_pn[4] = seq[1]; data->rx_pn[5] = seq[0]; } - crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN); + if (crypto_aead_setauthsize(tfm, CCMP_MIC_LEN) || + crypto_aead_setkey(tfm, data->key, CCMP_TK_LEN)) + return -1; } else if (len == 0) { data->key_set = 0; } else { diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c index 0927b2b15151..6f4710171151 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c @@ -160,7 +160,7 @@ static inline u16 Hi16(u32 val) static inline u16 Mk16(u8 hi, u8 lo) { - return lo | (((u16) hi) << 8); + return lo | (((u16)hi) << 8); } static const u16 Sbox[256] = { @@ -238,7 +238,7 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, * Make temporary area overlap WEP seed so that the final copy can be * avoided on little endian hosts. */ - u16 *PPK = (u16 *) &WEPSeed[4]; + u16 *PPK = (u16 *)&WEPSeed[4]; /* Step 1 - make copy of TTAK and bring in TSC */ PPK[0] = TTAK[0]; @@ -299,7 +299,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) skb->len < hdr_len) return -1; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (!tcb_desc->bHwSec) { if (!tkey->tx_phase1_done) { @@ -343,7 +343,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[2] = crc >> 16; icv[3] = crc >> 24; crypto_sync_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); - sg_init_one(&sg, pos, len+4); + sg_init_one(&sg, pos, len + 4); skcipher_request_set_sync_tfm(req, tkey->tx_tfm_arc4); skcipher_request_set_callback(req, 0, NULL, NULL); skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); @@ -383,7 +383,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) if (skb->len < hdr_len + 8 + 4) return -1; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; pos = skb->data + hdr_len; keyidx = pos[3]; if (!(keyidx & BIT(5))) { @@ -435,7 +435,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 12; crypto_sync_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); - sg_init_one(&sg, pos, plen+4); + sg_init_one(&sg, pos, plen + 4); skcipher_request_set_sync_tfm(req, tkey->rx_tfm_arc4); skcipher_request_set_callback(req, 0, NULL, NULL); @@ -523,7 +523,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) { struct rtl_80211_hdr_4addr *hdr11; - hdr11 = (struct rtl_80211_hdr_4addr *) skb->data; + hdr11 = (struct rtl_80211_hdr_4addr *)skb->data; switch (le16_to_cpu(hdr11->frame_ctl) & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { case IEEE80211_FCTL_TODS: @@ -556,7 +556,7 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *pri u8 *pos; struct rtl_80211_hdr_4addr *hdr; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { printk(KERN_DEBUG "Invalid packet for Michael MIC add " @@ -599,7 +599,7 @@ static void ieee80211_michael_mic_failure(struct net_device *dev, memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = sizeof(ev); - wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev); + wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); } static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, @@ -609,7 +609,7 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, u8 mic[8]; struct rtl_80211_hdr_4addr *hdr; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (!tkey->key_set) return -1; @@ -626,7 +626,7 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, return -1; if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { struct rtl_80211_hdr_4addr *hdr; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; printk(KERN_DEBUG "%s: Michael MIC verification failed for " "MSDU from %pM keyidx=%d\n", diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c index 805493a0870d..26482c3dcd1c 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c @@ -135,7 +135,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[3] = crc >> 24; crypto_sync_skcipher_setkey(wep->tx_tfm, key, klen); - sg_init_one(&sg, pos, len+4); + sg_init_one(&sg, pos, len + 4); skcipher_request_set_sync_tfm(req, wep->tx_tfm); skcipher_request_set_callback(req, 0, NULL, NULL); @@ -192,7 +192,7 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) SYNC_SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm); crypto_sync_skcipher_setkey(wep->rx_tfm, key, klen); - sg_init_one(&sg, pos, plen+4); + sg_init_one(&sg, pos, plen + 4); skcipher_request_set_sync_tfm(req, wep->rx_tfm); skcipher_request_set_callback(req, 0, NULL, NULL); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 0a3e478fccd6..5c33bcb0db2e 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -103,17 +103,17 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee, u8 tid; if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; + hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; } else if (IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)hdr; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; + hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)hdr; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; } else { - tid = 0; + tid = 0; } if (frag == 0) { @@ -124,7 +124,7 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee, 2 /* alignment */ + 8 /* WEP */ + ETH_ALEN /* WDS */ + - (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */); + (IEEE80211_QOS_HAS_SEQ(fc) ? 2 : 0) /* QOS Control */); if (!skb) return NULL; @@ -145,7 +145,7 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee, } else { /* received a fragment of a frame for which the head fragment * should have already been received */ - entry = ieee80211_frag_cache_find(ieee, seq, frag, tid,hdr->addr2, + entry = ieee80211_frag_cache_find(ieee, seq, frag, tid, hdr->addr2, hdr->addr1); if (entry) { entry->last_frag = frag; @@ -169,18 +169,18 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, struct rtl_80211_hdr_4addrqos *hdr_4addrqos; u8 tid; - if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; + if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { + hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; } else if (IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)hdr; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; + hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)hdr; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; } else { - tid = 0; + tid = 0; } entry = ieee80211_frag_cache_find(ieee, seq, -1, tid, hdr->addr2, @@ -216,10 +216,10 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, struct rtl_80211_hdr_3addr *hdr = (struct rtl_80211_hdr_3addr *)skb->data; rx_stats->len = skb->len; - ieee80211_rx_mgt(ieee,(struct rtl_80211_hdr_4addr *)skb->data,rx_stats); + ieee80211_rx_mgt(ieee, (struct rtl_80211_hdr_4addr *)skb->data, rx_stats); /* if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) */ - if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))/* use ADDR1 to perform address matching for Management frames */ - { + if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN))) { + /* use ADDR1 to perform address matching for Management frames */ dev_kfree_skb_any(skb); return 0; } @@ -281,11 +281,11 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ /* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -static unsigned char rfc1042_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; +static unsigned char rfc1042_header[] = { + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static unsigned char bridge_tunnel_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; +static unsigned char bridge_tunnel_header[] = { + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; /* No encapsulation header if EtherType < 0x600 (=length) */ /* Called by ieee80211_rx_frame_decrypt */ @@ -300,7 +300,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, if (skb->len < 24) return 0; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; fc = le16_to_cpu(hdr->frame_ctl); /* check that the frame is unicast frame to us */ @@ -339,12 +339,11 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, if (!crypt || !crypt->ops->decrypt_mpdu) return 0; - if (ieee->hwsec_active) - { - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE); + if (ieee->hwsec_active) { + struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bHwSec = 1; } - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); if (ieee->tkip_countermeasures && @@ -386,13 +385,12 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s if (!crypt || !crypt->ops->decrypt_msdu) return 0; - if (ieee->hwsec_active) - { - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE); + if (ieee->hwsec_active) { + struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bHwSec = 1; } - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); atomic_inc(&crypt->refcnt); @@ -410,7 +408,7 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s /* this function is stolen from ipw2200 driver*/ -#define IEEE_PACKET_RETRY_TIME (5*HZ) +#define IEEE_PACKET_RETRY_TIME (5 * HZ) static int is_duplicate_packet(struct ieee80211_device *ieee, struct rtl_80211_hdr_4addr *header) { @@ -426,18 +424,18 @@ static int is_duplicate_packet(struct ieee80211_device *ieee, //TO2DS and QoS - if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)header; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; - } else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS - hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)header; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; + if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { + hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)header; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; + } else if (IEEE80211_QOS_HAS_SEQ(fc)) { //QoS + hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)header; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; } else { // no QoS - tid = 0; + tid = 0; } switch (ieee->iw_mode) { @@ -507,8 +505,7 @@ drop: static bool AddReorderEntry(struct rx_ts_record *pTS, struct rx_reorder_entry *pReorderEntry) { struct list_head *pList = &pTS->rx_pending_pkt_list; - while(pList->next != &pTS->rx_pending_pkt_list) - { + while (pList->next != &pTS->rx_pending_pkt_list) { if (SN_LESS(pReorderEntry->SeqNum, list_entry(pList->next, struct rx_reorder_entry, List)->SeqNum)) pList = pList->next; else if (SN_EQUAL(pReorderEntry->SeqNum, list_entry(pList->next, struct rx_reorder_entry, List)->SeqNum)) @@ -524,17 +521,16 @@ static bool AddReorderEntry(struct rx_ts_record *pTS, struct rx_reorder_entry *p return true; } -void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb **prxbIndicateArray,u8 index) +void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb **prxbIndicateArray, u8 index) { - u8 i = 0 , j=0; + u8 i = 0, j = 0; u16 ethertype; // if(index > 1) // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): hahahahhhh, We indicate packet from reorder list, index is %u\n",__func__,index); - for(j = 0; j<index; j++) - { + for (j = 0; j < index; j++) { //added by amy for reorder struct ieee80211_rxb *prxb = prxbIndicateArray[j]; - for(i = 0; i<prxb->nr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { struct sk_buff *sub_skb = prxb->subframes[i]; /* convert hdr + possible LLC headers into Ethernet header */ @@ -585,7 +581,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, u16 WinEnd = (pTS->rx_indicate_seq + WinSize - 1) % 4096; u8 index = 0; bool bMatchWinStart = false, bPktInBuf = false; - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->rx_indicate_seq is %d, WinSize is %d\n",__func__,SeqNum,pTS->rx_indicate_seq,WinSize); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): Seq is %d,pTS->rx_indicate_seq is %d, WinSize is %d\n", __func__, SeqNum, pTS->rx_indicate_seq, WinSize); prxbIndicateArray = kmalloc_array(REORDER_WIN_SIZE, sizeof(struct ieee80211_rxb *), @@ -599,12 +595,12 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, /* Drop out the packet which SeqNum is smaller than WinStart */ if (SN_LESS(SeqNum, pTS->rx_indicate_seq)) { - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packet Drop! IndicateSeq: %d, NewSeq: %d\n", + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packet Drop! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); pHTInfo->RxReorderDropCounter++; { int i; - for(i =0; i < prxb->nr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { dev_kfree_skb(prxb->subframes[i]); } kfree(prxb); @@ -620,16 +616,16 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, * 1. Incoming SeqNum is equal to WinStart =>Window shift 1 * 2. Incoming SeqNum is larger than the WinEnd => Window shift N */ - if(SN_EQUAL(SeqNum, pTS->rx_indicate_seq)) { + if (SN_EQUAL(SeqNum, pTS->rx_indicate_seq)) { pTS->rx_indicate_seq = (pTS->rx_indicate_seq + 1) % 4096; bMatchWinStart = true; - } else if(SN_LESS(WinEnd, SeqNum)) { - if(SeqNum >= (WinSize - 1)) { - pTS->rx_indicate_seq = SeqNum + 1 -WinSize; + } else if (SN_LESS(WinEnd, SeqNum)) { + if (SeqNum >= (WinSize - 1)) { + pTS->rx_indicate_seq = SeqNum + 1 - WinSize; } else { pTS->rx_indicate_seq = 4095 - (WinSize - (SeqNum + 1)) + 1; } - IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n",pTS->rx_indicate_seq, SeqNum); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); } /* @@ -641,7 +637,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, * 1. All packets with SeqNum smaller than WinStart => Indicate * 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. */ - if(bMatchWinStart) { + if (bMatchWinStart) { /* Current packet is going to be indicated.*/ IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",\ pTS->rx_indicate_seq, SeqNum); @@ -651,7 +647,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } else { /* Current packet is going to be inserted into pending list.*/ //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): We RX no ordered packed, insert to ordered list\n",__func__); - if(!list_empty(&ieee->RxReorder_Unused_List)) { + if (!list_empty(&ieee->RxReorder_Unused_List)) { pReorderEntry = list_entry(ieee->RxReorder_Unused_List.next, struct rx_reorder_entry, List); list_del_init(&pReorderEntry->List); @@ -660,13 +656,13 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, pReorderEntry->prxb = prxb; // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pREorderEntry->SeqNum is %d\n",__func__,pReorderEntry->SeqNum); - if(!AddReorderEntry(pTS, pReorderEntry)) { + if (!AddReorderEntry(pTS, pReorderEntry)) { IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", __func__, pTS->rx_indicate_seq, SeqNum); - list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List); + list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List); { int i; - for(i =0; i < prxb->nr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { dev_kfree_skb(prxb->subframes[i]); } kfree(prxb); @@ -674,10 +670,9 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } } else { IEEE80211_DEBUG(IEEE80211_DL_REORDER, - "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n",pTS->rx_indicate_seq, SeqNum); + "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); } - } - else { + } else { /* * Packets are dropped if there is not enough reorder entries. * This part shall be modified!! We can just indicate all the @@ -686,7 +681,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n"); { int i; - for(i =0; i < prxb->nr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { dev_kfree_skb(prxb->subframes[i]); } kfree(prxb); @@ -696,12 +691,11 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } /* Check if there is any packet need indicate.*/ - while(!list_empty(&pTS->rx_pending_pkt_list)) { - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): start RREORDER indicate\n",__func__); + while (!list_empty(&pTS->rx_pending_pkt_list)) { + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): start RREORDER indicate\n", __func__); pReorderEntry = list_entry(pTS->rx_pending_pkt_list.prev, struct rx_reorder_entry, List); if (SN_LESS(pReorderEntry->SeqNum, pTS->rx_indicate_seq) || - SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) - { + SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) { /* This protect buffer from overflow. */ if (index >= REORDER_WIN_SIZE) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!! \n"); @@ -711,15 +705,15 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, list_del_init(&pReorderEntry->List); - if(SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) + if (SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) pTS->rx_indicate_seq = (pTS->rx_indicate_seq + 1) % 4096; - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packets indication!! IndicateSeq: %d, NewSeq: %d\n",pTS->rx_indicate_seq, SeqNum); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); prxbIndicateArray[index] = pReorderEntry->prxb; // printk("========================>%s(): pReorderEntry->SeqNum is %d\n",__func__,pReorderEntry->SeqNum); index++; - list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List); + list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List); } else { bPktInBuf = true; break; @@ -727,13 +721,13 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } /* Handling pending timer. Set this timer to prevent from long time Rx buffering.*/ - if (index>0) { + if (index > 0) { // Cancel previous pending timer. // del_timer_sync(&pTS->rx_pkt_pending_timer); pTS->rx_timeout_indicate_seq = 0xffff; // Indicate packets - if(index>REORDER_WIN_SIZE){ + if (index > REORDER_WIN_SIZE) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder buffer full!! \n"); kfree(prxbIndicateArray); return; @@ -743,9 +737,9 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, if (bPktInBuf && pTS->rx_timeout_indicate_seq == 0xffff) { // Set new pending timer. - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): SET rx timeout timer\n", __func__); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): SET rx timeout timer\n", __func__); pTS->rx_timeout_indicate_seq = pTS->rx_indicate_seq; - if(timer_pending(&pTS->rx_pkt_pending_timer)) + if (timer_pending(&pTS->rx_pkt_pending_timer)) del_timer_sync(&pTS->rx_pkt_pending_timer); pTS->rx_pkt_pending_timer.expires = jiffies + msecs_to_jiffies(pHTInfo->RxReorderPendingTime); @@ -762,12 +756,12 @@ static u8 parse_subframe(struct sk_buff *skb, struct rtl_80211_hdr_3addr *hdr = (struct rtl_80211_hdr_3addr *)skb->data; u16 fc = le16_to_cpu(hdr->frame_ctl); - u16 LLCOffset= sizeof(struct rtl_80211_hdr_3addr); + u16 LLCOffset = sizeof(struct rtl_80211_hdr_3addr); u16 ChkLength; bool bIsAggregateFrame = false; u16 nSubframe_Length; u8 nPadding_Length = 0; - u16 SeqNum=0; + u16 SeqNum = 0; struct sk_buff *sub_skb; /* just for debug purpose */ @@ -793,7 +787,7 @@ static u8 parse_subframe(struct sk_buff *skb, skb_pull(skb, LLCOffset); - if(!bIsAggregateFrame) { + if (!bIsAggregateFrame) { rxb->nr_subframes = 1; #ifdef JOHN_NOCPY rxb->subframes[0] = skb; @@ -801,26 +795,26 @@ static u8 parse_subframe(struct sk_buff *skb, rxb->subframes[0] = skb_copy(skb, GFP_ATOMIC); #endif - memcpy(rxb->src,src,ETH_ALEN); - memcpy(rxb->dst,dst,ETH_ALEN); + memcpy(rxb->src, src, ETH_ALEN); + memcpy(rxb->dst, dst, ETH_ALEN); //IEEE80211_DEBUG_DATA(IEEE80211_DL_RX,skb->data,skb->len); return 1; } else { rxb->nr_subframes = 0; - memcpy(rxb->src,src,ETH_ALEN); - memcpy(rxb->dst,dst,ETH_ALEN); - while(skb->len > ETHERNET_HEADER_SIZE) { + memcpy(rxb->src, src, ETH_ALEN); + memcpy(rxb->dst, dst, ETH_ALEN); + while (skb->len > ETHERNET_HEADER_SIZE) { /* Offset 12 denote 2 mac address */ nSubframe_Length = *((u16 *)(skb->data + 12)); //==m==>change the length order - nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8); + nSubframe_Length = (nSubframe_Length >> 8) + (nSubframe_Length << 8); - if (skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) { + if (skb->len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) { printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\ __func__, rxb->nr_subframes); - printk("%s: A-MSDU parse error!! Subframe Length: %d\n",__func__, nSubframe_Length); - printk("nRemain_Length is %d and nSubframe_Length is : %d\n",skb->len,nSubframe_Length); - printk("The Packet SeqNum is %d\n",SeqNum); + printk("%s: A-MSDU parse error!! Subframe Length: %d\n", __func__, nSubframe_Length); + printk("nRemain_Length is %d and nSubframe_Length is : %d\n", skb->len, nSubframe_Length); + printk("The Packet SeqNum is %d\n", SeqNum); return 0; } @@ -923,9 +917,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, frag = WLAN_GET_SEQ_FRAG(sc); hdrlen = ieee80211_get_hdrlen(fc); - if (HTCCheck(ieee, skb->data)) - { - if(net_ratelimit()) + if (HTCCheck(ieee, skb->data)) { + if (net_ratelimit()) printk("find HTCControl\n"); hdrlen += 4; rx_stats->bContainHTC = true; @@ -972,7 +965,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, * stations that do not support WEP key mapping). */ if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) - (void) hostap_handle_sta_crypto(local, hdr, &crypt, + (void)hostap_handle_sta_crypto(local, hdr, &crypt, &sta); #endif @@ -998,39 +991,32 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_dropped; // if QoS enabled, should check the sequence for each of the AC - if ((!ieee->pHTInfo->bCurRxReorderEnable) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)) { + if ((!ieee->pHTInfo->bCurRxReorderEnable) || !ieee->current_network.qos_data.active || !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)) { if (is_duplicate_packet(ieee, hdr)) - goto rx_dropped; + goto rx_dropped; - } - else - { + } else { struct rx_ts_record *pRxTS = NULL; //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): QOS ENABLE AND RECEIVE QOS DATA , we will get Ts, tid:%d\n",__func__, tid); - if(GetTs( + if (GetTs( ieee, - (struct ts_common_info **) &pRxTS, + (struct ts_common_info **)&pRxTS, hdr->addr2, Frame_QoSTID((u8 *)(skb->data)), RX_DIR, - true)) - { + true)) { // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pRxTS->rx_last_frag_num is %d,frag is %d,pRxTS->rx_last_seq_num is %d,seq is %d\n",__func__,pRxTS->rx_last_frag_num,frag,pRxTS->rx_last_seq_num,WLAN_GET_SEQ_SEQ(sc)); - if ((fc & (1<<11)) && + if ((fc & (1 << 11)) && (frag == pRxTS->rx_last_frag_num) && (WLAN_GET_SEQ_SEQ(sc) == pRxTS->rx_last_seq_num)) { goto rx_dropped; - } - else - { + } else { pRxTS->rx_last_frag_num = frag; pRxTS->rx_last_seq_num = WLAN_GET_SEQ_SEQ(sc); } - } - else - { - IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s(): No TS!! Skip the check!!\n",__func__); + } else { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s(): No TS!! Skip the check!!\n", __func__); goto rx_dropped; } } @@ -1126,14 +1112,13 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) - { + (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) { printk("decrypt frame error\n"); goto rx_dropped; } - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; /* skb: hdr + (possibly fragmented) plaintext payload */ // PR: FIXME: hostap has additional conditions in the "if" below: @@ -1185,15 +1170,14 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* this was the last fragment and the frame will be * delivered, so remove skb from fragment cache */ skb = frag_skb; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; ieee80211_frag_cache_invalidate(ieee, hdr); } /* skb: hdr + (possible reassembled) full MSDU payload; possibly still * encrypted/authenticated */ if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) - { + ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) { printk("==>decrypt msdu error\n"); goto rx_dropped; } @@ -1202,7 +1186,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ieee->LinkDetectInfo.NumRecvDataInPeriod++; ieee->LinkDetectInfo.NumRxOkInPeriod++; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) { if (/*ieee->ieee802_1x &&*/ ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { @@ -1227,10 +1211,10 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, #ifdef CONFIG_IEEE80211_DEBUG if (crypt && !(fc & IEEE80211_FCTL_WEP) && ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { - struct eapol *eap = (struct eapol *)(skb->data + - 24); - IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", - eap_get_type(eap->type)); + struct eapol *eap = (struct eapol *)(skb->data + + 24); + IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", + eap_get_type(eap->type)); } #endif @@ -1250,13 +1234,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, */ //added by amy for reorder if (ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data) - && !is_multicast_ether_addr(hdr->addr1)) - { + && !is_multicast_ether_addr(hdr->addr1)) { TID = Frame_QoSTID(skb->data); SeqNum = WLAN_GET_SEQ_SEQ(sc); - GetTs(ieee,(struct ts_common_info **) &pTS,hdr->addr2,TID,RX_DIR,true); - if (TID !=0 && TID !=3) - { + GetTs(ieee, (struct ts_common_info **)&pTS, hdr->addr2, TID, RX_DIR, true); + if (TID != 0 && TID != 3) { ieee->bis_any_nonbepkts = true; } } @@ -1270,7 +1252,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* qos data packets & reserved bit is 1 */ if (parse_subframe(skb, rx_stats, rxb, src, dst) == 0) { /* only to free rxb, and not submit the packets to upper layer */ - for(i =0; i < rxb->nr_subframes; i++) { + for (i = 0; i < rxb->nr_subframes; i++) { dev_kfree_skb(rxb->subframes[i]); } kfree(rxb); @@ -1281,7 +1263,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, //added by amy for reorder if (!ieee->pHTInfo->bCurRxReorderEnable || !pTS) { //added by amy for reorder - for(i = 0; i<rxb->nr_subframes; i++) { + for (i = 0; i < rxb->nr_subframes; i++) { struct sk_buff *sub_skb = rxb->subframes[i]; if (sub_skb) { @@ -1324,10 +1306,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, kfree(rxb); rxb = NULL; - } - else - { - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n",__func__); + } else { + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n", __func__); RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum); } #ifndef JOHN_NOCPY @@ -1407,10 +1387,9 @@ static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info /* * Parse a QoS information element */ -static int ieee80211_read_qos_info_element(struct - ieee80211_qos_information_element - *element_info, struct ieee80211_info_element - *info_element) +static int ieee80211_read_qos_info_element( + struct ieee80211_qos_information_element *element_info, + struct ieee80211_info_element *info_element) { int ret = 0; u16 size = sizeof(struct ieee80211_qos_information_element) - 2; @@ -1438,11 +1417,9 @@ static int ieee80211_read_qos_info_element(struct /* * Write QoS parameters from the ac parameters. */ -static int ieee80211_qos_convert_ac_to_parameters(struct - ieee80211_qos_parameter_info - *param_elm, struct - ieee80211_qos_parameters - *qos_param) +static int ieee80211_qos_convert_ac_to_parameters( + struct ieee80211_qos_parameter_info *param_elm, + struct ieee80211_qos_parameters *qos_param) { int i; struct ieee80211_qos_ac_parameter *ac_params; @@ -1455,12 +1432,12 @@ static int ieee80211_qos_convert_ac_to_parameters(struct aci = (ac_params->aci_aifsn & 0x60) >> 5; - if(aci >= QOS_QUEUE_NUM) + if (aci >= QOS_QUEUE_NUM) continue; qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f; /* WMM spec P.11: The minimum value for AIFSN shall be 2 */ - qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2:qos_param->aifs[aci]; + qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2 : qos_param->aifs[aci]; qos_param->cw_min[aci] = cpu_to_le16(ac_params->ecw_min_max & 0x0F); @@ -1561,15 +1538,12 @@ static inline void ieee80211_extract_country_ie( u8 *addr2 ) { - if (IS_DOT11D_ENABLE(ieee)) - { - if (info_element->len!= 0) - { + if (IS_DOT11D_ENABLE(ieee)) { + if (info_element->len != 0) { memcpy(network->CountryIeBuf, info_element->data, info_element->len); network->CountryIeLen = info_element->len; - if (!IS_COUNTRY_IE_VALID(ieee)) - { + if (!IS_COUNTRY_IE_VALID(ieee)) { dot11d_update_country_ie(ieee, addr2, info_element->len, info_element->data); } } @@ -1579,8 +1553,7 @@ static inline void ieee80211_extract_country_ie( // some AP (e.g. Cisco 1242) don't include country IE in their // probe response frame. // - if (IS_EQUAL_CIE_SRC(ieee, addr2) ) - { + if (IS_EQUAL_CIE_SRC(ieee, addr2)) { UPDATE_CIE_WATCHDOG(ieee); } } @@ -1595,9 +1568,9 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, { u8 i; short offset; - u16 tmp_htcap_len=0; - u16 tmp_htinfo_len=0; - u16 ht_realtek_agg_len=0; + u16 tmp_htcap_len = 0; + u16 tmp_htinfo_len = 0; + u16 ht_realtek_agg_len = 0; u8 ht_realtek_agg_buf[MAX_IE_LEN]; // u16 broadcom_len = 0; #ifdef CONFIG_IEEE80211_DEBUG @@ -1628,7 +1601,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, } network->ssid_len = min(info_element->len, - (u8) IW_ESSID_MAX_SIZE); + (u8)IW_ESSID_MAX_SIZE); memcpy(network->ssid, info_element->data, network->ssid_len); if (network->ssid_len < IW_ESSID_MAX_SIZE) memset(network->ssid + network->ssid_len, 0, @@ -1707,14 +1680,14 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, break; case MFIE_TYPE_TIM: - if(info_element->len < 4) + if (info_element->len < 4) break; network->tim.tim_count = info_element->data[0]; network->tim.tim_period = info_element->data[1]; network->dtim_period = info_element->data[1]; - if(ieee->state != IEEE80211_LINKED) + if (ieee->state != IEEE80211_LINKED) break; network->last_dtim_sta_time[0] = stats->mac_time[0]; @@ -1722,22 +1695,22 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, network->dtim_data = IEEE80211_DTIM_VALID; - if(info_element->data[0] != 0) + if (info_element->data[0] != 0) break; - if(info_element->data[2] & 1) + if (info_element->data[2] & 1) network->dtim_data |= IEEE80211_DTIM_MBCAST; - offset = (info_element->data[2] >> 1)*2; + offset = (info_element->data[2] >> 1) * 2; - if(ieee->assoc_id < 8*offset || - ieee->assoc_id > 8*(offset + info_element->len -3)) + if (ieee->assoc_id < 8 * offset || + ieee->assoc_id > 8 * (offset + info_element->len - 3)) break; offset = (ieee->assoc_id / 8) - offset;// + ((aid % 8)? 0 : 1) ; - if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) + if (info_element->data[3 + offset] & (1 << (ieee->assoc_id % 8))) network->dtim_data |= IEEE80211_DTIM_UCAST; //IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n"); @@ -1790,66 +1763,66 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, #endif //for HTcap and HTinfo parameters - if(tmp_htcap_len == 0){ - if(info_element->len >= 4 && + if (tmp_htcap_len == 0) { + if (info_element->len >= 4 && info_element->data[0] == 0x00 && info_element->data[1] == 0x90 && info_element->data[2] == 0x4c && info_element->data[3] == 0x033){ - tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htcap_len != 0){ - network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; - network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\ - sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len; - memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen); - } + tmp_htcap_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htcap_len != 0) { + network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; + network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ? \ + sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len; + memcpy(network->bssht.bdHTCapBuf, info_element->data, network->bssht.bdHTCapLen); + } } - if(tmp_htcap_len != 0) + if (tmp_htcap_len != 0) network->bssht.bdSupportHT = true; else network->bssht.bdSupportHT = false; } - if(tmp_htinfo_len == 0){ - if(info_element->len >= 4 && + if (tmp_htinfo_len == 0) { + if (info_element->len >= 4 && info_element->data[0] == 0x00 && info_element->data[1] == 0x90 && info_element->data[2] == 0x4c && info_element->data[3] == 0x034){ - tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htinfo_len != 0){ - network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; - if(tmp_htinfo_len){ - network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\ - sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len; - memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen); - } - + tmp_htinfo_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htinfo_len != 0) { + network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; + if (tmp_htinfo_len) { + network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf) ? \ + sizeof(network->bssht.bdHTInfoBuf) : tmp_htinfo_len; + memcpy(network->bssht.bdHTInfoBuf, info_element->data, network->bssht.bdHTInfoLen); } + } + } } - if(ieee->aggregation){ - if(network->bssht.bdSupportHT){ - if(info_element->len >= 4 && + if (ieee->aggregation) { + if (network->bssht.bdSupportHT) { + if (info_element->len >= 4 && info_element->data[0] == 0x00 && info_element->data[1] == 0xe0 && info_element->data[2] == 0x4c && info_element->data[3] == 0x02){ - ht_realtek_agg_len = min(info_element->len,(u8)MAX_IE_LEN); - memcpy(ht_realtek_agg_buf,info_element->data,info_element->len); + ht_realtek_agg_len = min(info_element->len, (u8)MAX_IE_LEN); + memcpy(ht_realtek_agg_buf, info_element->data, info_element->len); } - if(ht_realtek_agg_len >= 5){ + if (ht_realtek_agg_len >= 5) { network->bssht.bdRT2RTAggregation = true; - if((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02)) - network->bssht.bdRT2RTLongSlotTime = true; + if ((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02)) + network->bssht.bdRT2RTLongSlotTime = true; } } @@ -1870,78 +1843,63 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[1] == 0x10 && info_element->data[2] == 0x18)){ - network->broadcom_cap_exist = true; + network->broadcom_cap_exist = true; } } - if(info_element->len >= 3 && + if (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x0c && - info_element->data[2] == 0x43) - { + info_element->data[2] == 0x43) { network->ralink_cap_exist = true; - } - else + } else network->ralink_cap_exist = false; //added by amy for atheros AP - if((info_element->len >= 3 && + if ((info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x03 && info_element->data[2] == 0x7f) || (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x13 && - info_element->data[2] == 0x74)) - { - printk("========>%s(): athros AP is exist\n",__func__); + info_element->data[2] == 0x74)) { + printk("========>%s(): athros AP is exist\n", __func__); network->atheros_cap_exist = true; - } - else + } else network->atheros_cap_exist = false; - if(info_element->len >= 3 && + if (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x40 && - info_element->data[2] == 0x96) - { + info_element->data[2] == 0x96) { network->cisco_cap_exist = true; - } - else + } else network->cisco_cap_exist = false; //added by amy for LEAP of cisco if (info_element->len > 4 && info_element->data[0] == 0x00 && info_element->data[1] == 0x40 && info_element->data[2] == 0x96 && - info_element->data[3] == 0x01) - { - if(info_element->len == 6) - { + info_element->data[3] == 0x01) { + if (info_element->len == 6) { memcpy(network->CcxRmState, &info_element[4], 2); - if(network->CcxRmState[0] != 0) - { + if (network->CcxRmState[0] != 0) network->bCcxRmEnable = true; - } else network->bCcxRmEnable = false; // // CCXv4 Table 59-1 MBSSID Masks. // network->MBssidMask = network->CcxRmState[1] & 0x07; - if(network->MBssidMask != 0) - { + if (network->MBssidMask != 0) { network->bMBssidValid = true; network->MBssidMask = 0xff << (network->MBssidMask); ether_addr_copy(network->MBssid, network->bssid); network->MBssid[5] &= network->MBssidMask; - } - else - { + } else { network->bMBssidValid = false; } - } - else - { + } else { network->bCcxRmEnable = false; } } @@ -1949,15 +1907,11 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[0] == 0x00 && info_element->data[1] == 0x40 && info_element->data[2] == 0x96 && - info_element->data[3] == 0x03) - { - if(info_element->len == 5) - { + info_element->data[3] == 0x03) { + if (info_element->len == 5) { network->bWithCcxVerNum = true; network->BssCcxVerNumber = info_element->data[4]; - } - else - { + } else { network->bWithCcxVerNum = false; network->BssCcxVerNumber = 0; } @@ -1977,19 +1931,18 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, case MFIE_TYPE_HT_CAP: IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n", info_element->len); - tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htcap_len != 0){ + tmp_htcap_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htcap_len != 0) { network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; - network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\ - sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len; - memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen); + network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ? \ + sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len; + memcpy(network->bssht.bdHTCapBuf, info_element->data, network->bssht.bdHTCapLen); //If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT() // windows driver will update WMM parameters each beacon received once connected // Linux driver is a bit different. network->bssht.bdSupportHT = true; - } - else + } else network->bssht.bdSupportHT = false; break; @@ -1997,37 +1950,31 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, case MFIE_TYPE_HT_INFO: IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n", info_element->len); - tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htinfo_len){ + tmp_htinfo_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htinfo_len) { network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE; - network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\ - sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len; - memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen); + network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf) ? \ + sizeof(network->bssht.bdHTInfoBuf) : tmp_htinfo_len; + memcpy(network->bssht.bdHTInfoBuf, info_element->data, network->bssht.bdHTInfoLen); } break; case MFIE_TYPE_AIRONET: IEEE80211_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n", info_element->len); - if(info_element->len >IE_CISCO_FLAG_POSITION) - { + if (info_element->len > IE_CISCO_FLAG_POSITION) { network->bWithAironetIE = true; // CCX 1 spec v1.13, A01.1 CKIP Negotiation (page23): // "A Cisco access point advertises support for CKIP in beacon and probe response packets, // by adding an Aironet element and setting one or both of the CKIP negotiation bits." - if( (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_MIC) || - (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_PK) ) - { + if ((info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_MIC) || + (info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_PK)) { network->bCkipSupported = true; - } - else - { + } else { network->bCkipSupported = false; } - } - else - { + } else { network->bWithAironetIE = false; network->bCkipSupported = false; } @@ -2057,13 +2004,10 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, data[info_element->len]; } - if(!network->atheros_cap_exist && !network->broadcom_cap_exist && - !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation) - { + if (!network->atheros_cap_exist && !network->broadcom_cap_exist && + !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation) { network->unknown_cap_exist = true; - } - else - { + } else { network->unknown_cap_exist = false; } return 0; @@ -2076,44 +2020,25 @@ static inline u8 ieee80211_SignalStrengthTranslate( u8 RetSS; // Step 1. Scale mapping. - if(CurrSS >= 71 && CurrSS <= 100) - { + if (CurrSS >= 71 && CurrSS <= 100) { RetSS = 90 + ((CurrSS - 70) / 3); - } - else if(CurrSS >= 41 && CurrSS <= 70) - { + } else if (CurrSS >= 41 && CurrSS <= 70) { RetSS = 78 + ((CurrSS - 40) / 3); - } - else if(CurrSS >= 31 && CurrSS <= 40) - { + } else if (CurrSS >= 31 && CurrSS <= 40) { RetSS = 66 + (CurrSS - 30); - } - else if(CurrSS >= 21 && CurrSS <= 30) - { + } else if (CurrSS >= 21 && CurrSS <= 30) { RetSS = 54 + (CurrSS - 20); - } - else if(CurrSS >= 5 && CurrSS <= 20) - { + } else if (CurrSS >= 5 && CurrSS <= 20) { RetSS = 42 + (((CurrSS - 5) * 2) / 3); - } - else if(CurrSS == 4) - { + } else if (CurrSS == 4) { RetSS = 36; - } - else if(CurrSS == 3) - { + } else if (CurrSS == 3) { RetSS = 27; - } - else if(CurrSS == 2) - { + } else if (CurrSS == 2) { RetSS = 18; - } - else if(CurrSS == 1) - { + } else if (CurrSS == 1) { RetSS = 9; - } - else - { + } else { RetSS = CurrSS; } //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); @@ -2193,7 +2118,7 @@ static inline int ieee80211_network_init( network->rsn_ie_len = 0; if (ieee80211_parse_info_param - (ieee,beacon->info_element, stats->len - sizeof(*beacon), network, stats)) + (ieee, beacon->info_element, stats->len - sizeof(*beacon), network, stats)) return 1; network->mode = 0; @@ -2215,10 +2140,10 @@ static inline int ieee80211_network_init( return 1; } - if(network->bssht.bdSupportHT){ - if(network->mode == IEEE_A) + if (network->bssht.bdSupportHT) { + if (network->mode == IEEE_A) network->mode = IEEE_N_5G; - else if(network->mode & (IEEE_G | IEEE_B)) + else if (network->mode & (IEEE_G | IEEE_B)) network->mode = IEEE_N_24G; } if (ieee80211_is_empty_essid(network->ssid, network->ssid_len)) @@ -2226,7 +2151,7 @@ static inline int ieee80211_network_init( stats->signal = 30 + (stats->SignalStrength * 70) / 100; //stats->signal = ieee80211_SignalStrengthTranslate(stats->signal); - stats->noise = ieee80211_translate_todbm((u8)(100-stats->signal)) -25; + stats->noise = ieee80211_translate_todbm((u8)(100 - stats->signal)) - 25; memcpy(&network->stats, stats, sizeof(network->stats)); @@ -2264,8 +2189,7 @@ static inline void update_network(struct ieee80211_network *dst, dst->rates_len = src->rates_len; memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); dst->rates_ex_len = src->rates_ex_len; - if (src->ssid_len > 0) - { + if (src->ssid_len > 0) { memset(dst->ssid, 0, dst->ssid_len); dst->ssid_len = src->ssid_len; memcpy(dst->ssid, src->ssid, src->ssid_len); @@ -2274,8 +2198,7 @@ static inline void update_network(struct ieee80211_network *dst, dst->flags = src->flags; dst->time_stamp[0] = src->time_stamp[0]; dst->time_stamp[1] = src->time_stamp[1]; - if (src->flags & NETWORK_HAS_ERP_VALUE) - { + if (src->flags & NETWORK_HAS_ERP_VALUE) { dst->erp_value = src->erp_value; dst->berp_info_valid = src->berp_info_valid = true; } @@ -2290,10 +2213,10 @@ static inline void update_network(struct ieee80211_network *dst, dst->bssht.bdSupportHT = src->bssht.bdSupportHT; dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation; - dst->bssht.bdHTCapLen= src->bssht.bdHTCapLen; - memcpy(dst->bssht.bdHTCapBuf,src->bssht.bdHTCapBuf,src->bssht.bdHTCapLen); - dst->bssht.bdHTInfoLen= src->bssht.bdHTInfoLen; - memcpy(dst->bssht.bdHTInfoBuf,src->bssht.bdHTInfoBuf,src->bssht.bdHTInfoLen); + dst->bssht.bdHTCapLen = src->bssht.bdHTCapLen; + memcpy(dst->bssht.bdHTCapBuf, src->bssht.bdHTCapBuf, src->bssht.bdHTCapLen); + dst->bssht.bdHTInfoLen = src->bssht.bdHTInfoLen; + memcpy(dst->bssht.bdHTInfoBuf, src->bssht.bdHTInfoBuf, src->bssht.bdHTInfoLen); dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer; dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime; dst->broadcom_cap_exist = src->broadcom_cap_exist; @@ -2312,7 +2235,7 @@ static inline void update_network(struct ieee80211_network *dst, qos_active = dst->qos_data.active; //old_param = dst->qos_data.old_param_count; old_param = dst->qos_data.param_count; - if(dst->flags & NETWORK_HAS_QOS_MASK) + if (dst->flags & NETWORK_HAS_QOS_MASK) memcpy(&dst->qos_data, &src->qos_data, sizeof(struct ieee80211_qos_data)); else { @@ -2322,7 +2245,7 @@ static inline void update_network(struct ieee80211_network *dst, if (dst->qos_data.supported == 1) { dst->QoS_Enable = 1; - if(dst->ssid_len) + if (dst->ssid_len) IEEE80211_DEBUG_QOS ("QoS the network %s is QoS supported\n", dst->ssid); @@ -2335,11 +2258,11 @@ static inline void update_network(struct ieee80211_network *dst, /* dst->last_associate is not overwritten */ dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame. - if (src->wmm_param[0].aci_aifsn|| \ - src->wmm_param[1].aci_aifsn|| \ - src->wmm_param[2].aci_aifsn|| \ + if (src->wmm_param[0].aci_aifsn || \ + src->wmm_param[1].aci_aifsn || \ + src->wmm_param[2].aci_aifsn || \ src->wmm_param[3].aci_aifsn) { - memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); + memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); } //dst->QoS_Enable = src->QoS_Enable; #ifdef THOMAS_TURBO @@ -2429,46 +2352,34 @@ static inline void ieee80211_process_probe_response( if (!is_legal_channel(ieee, network->channel)) goto out; - if (ieee->bGlobalDomain) - { - if (fc == IEEE80211_STYPE_PROBE_RESP) - { - // Case 1: Country code - if(IS_COUNTRY_IE_VALID(ieee) ) - { + if (ieee->bGlobalDomain) { + if (fc == IEEE80211_STYPE_PROBE_RESP) { + if (IS_COUNTRY_IE_VALID(ieee)) { + // Case 1: Country code if (!is_legal_channel(ieee, network->channel)) { printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network->channel); goto out; } - } - // Case 2: No any country code. - else - { + } else { + // Case 2: No any country code. // Filter over channel ch12~14 - if (network->channel > 11) - { + if (network->channel > 11) { printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network->channel); goto out; } } - } - else - { - // Case 1: Country code - if(IS_COUNTRY_IE_VALID(ieee) ) - { + } else { + if (IS_COUNTRY_IE_VALID(ieee)) { + // Case 1: Country code if (!is_legal_channel(ieee, network->channel)) { - printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network->channel); + printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network->channel); goto out; } - } - // Case 2: No any country code. - else - { + } else { + // Case 2: No any country code. // Filter over channel ch12~14 - if (network->channel > 14) - { - printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network->channel); + if (network->channel > 14) { + printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network->channel); goto out; } } @@ -2490,19 +2401,17 @@ static inline void ieee80211_process_probe_response( if (is_same_network(&ieee->current_network, network, ieee)) { update_network(&ieee->current_network, network); if ((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G) - && ieee->current_network.berp_info_valid){ - if(ieee->current_network.erp_value& ERP_UseProtection) - ieee->current_network.buseprotection = true; - else - ieee->current_network.buseprotection = false; + && ieee->current_network.berp_info_valid){ + if (ieee->current_network.erp_value & ERP_UseProtection) + ieee->current_network.buseprotection = true; + else + ieee->current_network.buseprotection = false; } - if(is_beacon(beacon->header.frame_ctl)) - { - if(ieee->state == IEEE80211_LINKED) + if (is_beacon(beacon->header.frame_ctl)) { + if (ieee->state == IEEE80211_LINKED) ieee->LinkDetectInfo.NumRecvBcnInPeriod++; - } - else //hidden AP - network->flags = (~NETWORK_EMPTY_ESSID & network->flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags); + } else //hidden AP + network->flags = (~NETWORK_EMPTY_ESSID & network->flags) | (NETWORK_EMPTY_ESSID & ieee->current_network.flags); } list_for_each_entry(target, &ieee->network_list, list) { @@ -2543,8 +2452,8 @@ static inline void ieee80211_process_probe_response( #endif memcpy(target, network, sizeof(*target)); list_add_tail(&target->list, &ieee->network_list); - if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) - ieee80211_softmac_new_net(ieee,network); + if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) + ieee80211_softmac_new_net(ieee, network); } else { IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n", escape_essid(target->ssid, @@ -2559,26 +2468,26 @@ static inline void ieee80211_process_probe_response( */ renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); //YJ,add,080819,for hidden ap - if(is_beacon(beacon->header.frame_ctl) == 0) - network->flags = (~NETWORK_EMPTY_ESSID & network->flags)|(NETWORK_EMPTY_ESSID & target->flags); + if (is_beacon(beacon->header.frame_ctl) == 0) + network->flags = (~NETWORK_EMPTY_ESSID & network->flags) | (NETWORK_EMPTY_ESSID & target->flags); //if(strncmp(network->ssid, "linksys-c",9) == 0) // printk("====>2 network->ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network->ssid, network->flags, target->ssid, target->flags); - if(((network->flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ + if (((network->flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ && (((network->ssid_len > 0) && (strncmp(target->ssid, network->ssid, network->ssid_len)))\ - ||((ieee->current_network.ssid_len == network->ssid_len) && (strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK)))) + || ((ieee->current_network.ssid_len == network->ssid_len) && (strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK)))) renew = 1; //YJ,add,080819,for hidden ap,end update_network(target, network); - if(renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) - ieee80211_softmac_new_net(ieee,network); + if (renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) + ieee80211_softmac_new_net(ieee, network); } spin_unlock_irqrestore(&ieee->lock, flags); if (is_beacon(beacon->header.frame_ctl) && is_same_network(&ieee->current_network, network, ieee) && \ (ieee->state == IEEE80211_LINKED)) { if (ieee->handle_beacon) - ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network); + ieee->handle_beacon(ieee->dev, beacon, &ieee->current_network); } out: diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index e0da0900a4f7..33a6af7aad22 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -743,7 +743,6 @@ static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d if (ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT)) beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); - crypt = ieee->crypt[ieee->tx_keyidx]; if (encrypt) beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c index 4a8d16a45fc5..b1baaa18b129 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c @@ -42,8 +42,8 @@ int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info /* if setting by freq convert to channel */ if (fwrq->e == 1) { - if ((fwrq->m >= (int) 2.412e8 && - fwrq->m <= (int) 2.487e8)) { + if ((fwrq->m >= (int)2.412e8 && + fwrq->m <= (int)2.487e8)) { int f = fwrq->m / 100000; int c = 0; @@ -92,7 +92,7 @@ int ieee80211_wx_get_freq(struct ieee80211_device *ieee, if (ieee->current_network.channel == 0) return -1; /* NM 0.7.0 will not accept channel any more. */ - fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel-1] * 100000; + fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel - 1] * 100000; fwrq->e = 1; /* fwrq->m = ieee->current_network.channel; */ /* fwrq->e = 0; */ @@ -220,7 +220,7 @@ int ieee80211_wx_set_rate(struct ieee80211_device *ieee, u32 target_rate = wrqu->bitrate.value; - ieee->rate = target_rate/100000; + ieee->rate = target_rate / 100000; /* FIXME: we might want to limit rate also in management protocols. */ return 0; } @@ -415,9 +415,9 @@ int ieee80211_wx_set_essid(struct ieee80211_device *ieee, if (wrqu->essid.flags && wrqu->essid.length) { /* first flush current network.ssid */ - len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE; - strncpy(ieee->current_network.ssid, extra, len+1); - ieee->current_network.ssid_len = len+1; + len = ((wrqu->essid.length - 1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length - 1) : IW_ESSID_MAX_SIZE; + strncpy(ieee->current_network.ssid, extra, len + 1); + ieee->current_network.ssid_len = len + 1; ieee->ssid_set = 1; } else { ieee->ssid_set = 0; diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c index fc6eb97801e1..f0b6b8372f91 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -214,7 +214,8 @@ int ieee80211_encrypt_fragment( } -void ieee80211_txb_free(struct ieee80211_txb *txb) { +void ieee80211_txb_free(struct ieee80211_txb *txb) +{ //int i; if (unlikely(!txb)) return; @@ -293,7 +294,7 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, struct tx_ts_record *pTxTs = NULL; struct rtl_80211_hdr_1addr *hdr = (struct rtl_80211_hdr_1addr *)skb->data; - if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) return; if (!IsQoSDataFrame(skb->data)) return; @@ -301,13 +302,6 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, if (is_multicast_ether_addr(hdr->addr1)) return; //check packet and mode later -#ifdef TO_DO_LIST - if (pTcb->PacketLength >= 4096) - return; - // For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation. - if (!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter)) - return; -#endif if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) { return; } @@ -333,8 +327,7 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, } } FORCED_AGG_SETTING: - switch (pHTInfo->ForcedAMPDUMode ) - { + switch (pHTInfo->ForcedAMPDUMode) { case HT_AGG_AUTO: break; @@ -372,7 +365,7 @@ ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, struct cb_desc *tcb_ tcb_desc->bUseShortGI = false; - if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) return; if (pHTInfo->bForcedShortGI) { @@ -380,9 +373,9 @@ ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, struct cb_desc *tcb_ return; } - if ((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz) + if ((pHTInfo->bCurBW40MHz == true) && pHTInfo->bCurShortGI40MHz) tcb_desc->bUseShortGI = true; - else if ((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz) + else if ((pHTInfo->bCurBW40MHz == false) && pHTInfo->bCurShortGI20MHz) tcb_desc->bUseShortGI = true; } @@ -393,16 +386,16 @@ static void ieee80211_query_BandwidthMode(struct ieee80211_device *ieee, tcb_desc->bPacketBW = false; - if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) return; if (tcb_desc->bMulticast || tcb_desc->bBroadcast) return; - if ((tcb_desc->data_rate & 0x80)==0) // If using legacy rate, it shall use 20MHz channel. + if ((tcb_desc->data_rate & 0x80) == 0) // If using legacy rate, it shall use 20MHz channel. return; //BandWidthAutoSwitch is for auto switch to 20 or 40 in long distance - if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz) + if (pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz) tcb_desc->bPacketBW = true; return; } @@ -418,25 +411,21 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, tcb_desc->RTSSC = 0; // 20MHz: Don't care; 40MHz: Duplicate. tcb_desc->bRTSBW = false; // RTS frame bandwidth is always 20MHz - if(tcb_desc->bBroadcast || tcb_desc->bMulticast)//only unicast frame will use rts/cts + if (tcb_desc->bBroadcast || tcb_desc->bMulticast) //only unicast frame will use rts/cts return; - if (is_broadcast_ether_addr(skb->data+16)) //check addr3 as infrastructure add3 is DA. + if (is_broadcast_ether_addr(skb->data + 16)) //check addr3 as infrastructure add3 is DA. return; - if (ieee->mode < IEEE_N_24G) //b, g mode - { + if (ieee->mode < IEEE_N_24G) /* b, g mode */ { // (1) RTS_Threshold is compared to the MPDU, not MSDU. // (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. // Other fragments are protected by previous fragment. // So we only need to check the length of first fragment. - if (skb->len > ieee->rts) - { + if (skb->len > ieee->rts) { tcb_desc->bRTSEnable = true; tcb_desc->rts_rate = MGN_24M; - } - else if (ieee->current_network.buseprotection) - { + } else if (ieee->current_network.buseprotection) { // Use CTS-to-SELF in protection mode. tcb_desc->bRTSEnable = true; tcb_desc->bCTSEnable = true; @@ -444,43 +433,35 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, } //otherwise return; return; - } - else - {// 11n High throughput case. + } else { // 11n High throughput case. PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; - while (true) - { + while (true) { //check ERP protection - if (ieee->current_network.buseprotection) - {// CTS-to-SELF + if (ieee->current_network.buseprotection) {// CTS-to-SELF tcb_desc->bRTSEnable = true; tcb_desc->bCTSEnable = true; tcb_desc->rts_rate = MGN_24M; break; } //check HT op mode - if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) - { + if (pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) { u8 HTOpMode = pHTInfo->CurrentOpMode; - if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) || - (!pHTInfo->bCurBW40MHz && HTOpMode == 3) ) - { + if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) || + (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. tcb_desc->bRTSEnable = true; break; } } //check rts - if (skb->len > ieee->rts) - { + if (skb->len > ieee->rts) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. tcb_desc->bRTSEnable = true; break; } //to do list: check MIMO power save condition. //check AMPDU aggregation for TXOP - if(tcb_desc->bAMPDUEnable) - { + if (tcb_desc->bAMPDUEnable) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. // According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads // throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily @@ -488,8 +469,7 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, break; } //check IOT action - if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) - { + if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) { tcb_desc->bCTSEnable = true; tcb_desc->rts_rate = MGN_24M; tcb_desc->bRTSEnable = true; @@ -508,7 +488,7 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) tcb_desc->bUseShortPreamble = true; if (ieee->mode == IW_MODE_MASTER) - goto NO_PROTECTION; + goto NO_PROTECTION; return; NO_PROTECTION: tcb_desc->bRTSEnable = false; @@ -522,27 +502,12 @@ NO_PROTECTION: static void ieee80211_txrate_selectmode(struct ieee80211_device *ieee, struct cb_desc *tcb_desc) { -#ifdef TO_DO_LIST - if (!IsDataFrame(pFrame)) { - pTcb->bTxDisableRateFallBack = true; - pTcb->bTxUseDriverAssingedRate = true; - pTcb->RATRIndex = 7; - return; - } - - if (pMgntInfo->ForcedDataRate!= 0) { - pTcb->bTxDisableRateFallBack = true; - pTcb->bTxUseDriverAssingedRate = true; - return; - } -#endif if (ieee->bTxDisableRateFallBack) tcb_desc->bTxDisableRateFallBack = true; if (ieee->bTxUseDriverAssingedRate) tcb_desc->bTxUseDriverAssingedRate = true; - if (!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate) - { + if (!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate) { if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) tcb_desc->RATRIndex = 0; } @@ -553,11 +518,9 @@ static void ieee80211_query_seqnum(struct ieee80211_device *ieee, { if (is_multicast_ether_addr(dst)) return; - if (IsQoSDataFrame(skb->data)) //we deal qos data only - { + if (IsQoSDataFrame(skb->data)) /* we deal qos data only */ { struct tx_ts_record *pTS = NULL; - if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, skb->priority, TX_DIR, true)) - { + if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, skb->priority, TX_DIR, true)) { return; } pTS->tx_cur_seq = (pTS->tx_cur_seq + 1) % 4096; @@ -592,7 +555,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) /* If there is no driver handler to take the TXB, dont' bother * creating it... */ - if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| + if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)) || ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); @@ -631,7 +594,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) /* Save source and destination addresses */ memcpy(&dest, skb->data, ETH_ALEN); - memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); + memcpy(&src, skb->data + ETH_ALEN, ETH_ALEN); /* Advance the SKB to the start of the payload */ skb_pull(skb, sizeof(struct ethhdr)); @@ -646,7 +609,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) fc = IEEE80211_FTYPE_DATA; //if(ieee->current_network.QoS_Enable) - if(qos_actived) + if (qos_actived) fc |= IEEE80211_STYPE_QOS_DATA; else fc |= IEEE80211_STYPE_DATA; @@ -740,7 +703,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) for (i = 0; i < nr_frags; i++) { skb_frag = txb->fragments[i]; tcb_desc = (struct cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); - if(qos_actived){ + if (qos_actived) { skb_frag->priority = skb->priority;//UP2AC(skb->priority); tcb_desc->queue_index = UP2AC(skb->priority); } else { @@ -749,15 +712,13 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) } skb_reserve(skb_frag, ieee->tx_headroom); - if (encrypt){ + if (encrypt) { if (ieee->hwsec_active) tcb_desc->bHwSec = 1; else tcb_desc->bHwSec = 0; skb_reserve(skb_frag, crypt->ops->extra_prefix_len); - } - else - { + } else { tcb_desc->bHwSec = 0; } frag_hdr = skb_put_data(skb_frag, &header, hdr_len); @@ -775,12 +736,11 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) bytes = bytes_last_frag; } //if(ieee->current_network.QoS_Enable) - if(qos_actived) - { + if (qos_actived) { // add 1 only indicate to corresponding seq number control 2006/7/12 - frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); + frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority) + 1] << 4 | i); } else { - frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); + frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4 | i); } /* Put a SNAP header on the first fragment */ @@ -806,17 +766,16 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) skb_put(skb_frag, 4); } - if(qos_actived) - { - if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) - ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; - else - ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; + if (qos_actived) { + if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) + ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; + else + ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; } else { - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; } } else { if (unlikely(skb->len < sizeof(struct rtl_80211_hdr_3addr))) { @@ -826,7 +785,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) } txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); - if(!txb){ + if (!txb) { printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; @@ -839,8 +798,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) success: //WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place. - if (txb) - { + if (txb) { struct cb_desc *tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bTxEnableFwCalcDur = 1; if (is_multicast_ether_addr(header.addr1)) @@ -862,9 +820,9 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&ieee->lock, flags); dev_kfree_skb_any(skb); if (txb) { - if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ + if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) { ieee80211_softmac_xmit(txb, ieee); - }else{ + } else { if ((*ieee->hard_start_xmit)(txb, dev) == 0) { stats->tx_packets++; stats->tx_bytes += __le16_to_cpu(txb->payload_size); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c index be08cd1d37a7..9dd5c04181ea 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c @@ -70,10 +70,10 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, } /* Add the protocol name */ iwe.cmd = SIOCGIWNAME; - for(i=0; i<ARRAY_SIZE(ieee80211_modes); i++) { + for (i = 0; i < ARRAY_SIZE(ieee80211_modes); i++) { if (network->mode & BIT(i)) { - sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size); - pname +=ieee80211_modes[i].mode_size; + sprintf(pname, ieee80211_modes[i].mode_string, ieee80211_modes[i].mode_size); + pname += ieee80211_modes[i].mode_size; } } *pname = '\0'; @@ -130,8 +130,7 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, max_rate = rate; } - if (network->mode >= IEEE_N_24G)//add N rate here; - { + if (network->mode >= IEEE_N_24G) /* add N rate here */ { struct ht_capability_ele *ht_cap = NULL; bool is40M = false, isShortGI = false; u8 max_mcs = 0; @@ -139,13 +138,13 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, ht_cap = (struct ht_capability_ele *)&network->bssht.bdHTCapBuf[4]; else ht_cap = (struct ht_capability_ele *)&network->bssht.bdHTCapBuf[0]; - is40M = (ht_cap->ChlWidth)?1:0; - isShortGI = (ht_cap->ChlWidth)? - ((ht_cap->ShortGI40Mhz)?1:0): - ((ht_cap->ShortGI20Mhz)?1:0); + is40M = (ht_cap->ChlWidth) ? 1 : 0; + isShortGI = (ht_cap->ChlWidth) ? + ((ht_cap->ShortGI40Mhz) ? 1 : 0) : + ((ht_cap->ShortGI20Mhz) ? 1 : 0); max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL); - rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f]; + rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f]; if (rate > max_rate) max_rate = rate; } @@ -178,7 +177,7 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, iwe.u.data.length = p - custom; if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); + start = iwe_stream_add_point(info, start, stop, &iwe, custom); if (ieee->wpa_enabled && network->wpa_ie_len) { char buf[MAX_WPA_IE_LEN * 2 + 30]; @@ -219,7 +218,7 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100)); iwe.u.data.length = p - custom; if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); + start = iwe_stream_add_point(info, start, stop, &iwe, custom); return start; } @@ -243,7 +242,7 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee, list_for_each_entry(network, &ieee->network_list, list) { i++; - if((stop-ev)<200) { + if ((stop - ev) < 200) { err = -E2BIG; break; } @@ -454,7 +453,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee, IEEE80211_DEBUG_WX("GET_ENCODE\n"); - if(ieee->iw_mode == IW_MODE_MONITOR) + if (ieee->iw_mode == IW_MODE_MONITOR) return -1; key = erq->flags & IW_ENCODE_INDEX; @@ -571,7 +570,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, ret = -EINVAL; goto done; } - printk("alg name:%s\n",alg); + printk("alg name:%s\n", alg); ops = try_then_request_module(ieee80211_get_crypto_ops(alg), module); if (!ops) { @@ -688,7 +687,7 @@ int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee, ext->key_len = 0; encoding->flags |= IW_ENCODE_DISABLED; } else { - if (strcmp(crypt->ops->name, "WEP") == 0 ) + if (strcmp(crypt->ops->name, "WEP") == 0) ext->alg = IW_ENCODE_ALG_WEP; else if (strcmp(crypt->ops->name, "TKIP")) ext->alg = IW_ENCODE_ALG_TKIP; @@ -712,7 +711,7 @@ int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - struct iw_mlme *mlme = (struct iw_mlme *) extra; + struct iw_mlme *mlme = (struct iw_mlme *)extra; switch (mlme->cmd) { case IW_MLME_DEAUTH: case IW_MLME_DISASSOC: @@ -765,7 +764,7 @@ int ieee80211_wx_set_auth(struct ieee80211_device *ieee, break; case IW_AUTH_WPA_ENABLED: - ieee->wpa_enabled = (data->value)?1:0; + ieee->wpa_enabled = (data->value) ? 1 : 0; break; case IW_AUTH_RX_UNENCRYPTED_EAPOL: @@ -785,14 +784,14 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) { u8 *buf; - if (len>MAX_WPA_IE_LEN || (len && !ie)) { - // printk("return error out, len:%d\n", len); - return -EINVAL; + if (len > MAX_WPA_IE_LEN || (len && !ie)) { + //printk("return error out, len:%d\n", len); + return -EINVAL; } if (len) { - if (len != ie[1]+2) { + if (len != ie[1] + 2) { printk("len:%zu, ie:%d\n", len, ie[1]); return -EINVAL; } diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index 53869b3c985c..379a2ccf4d9f 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -162,7 +162,7 @@ static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, s tag += 2; } - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); return skb; //return NULL; } @@ -229,7 +229,7 @@ static struct sk_buff *ieee80211_DELBA( put_unaligned_le16(ReasonCode, tag); tag += 2; - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); if (net_ratelimit()) IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __func__); @@ -331,9 +331,9 @@ int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb) return -1; } - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); - req = (struct rtl_80211_hdr_3addr *) skb->data; + req = (struct rtl_80211_hdr_3addr *)skb->data; tag = (u8 *)req; dst = &req->addr2[0]; tag += sizeof(struct rtl_80211_hdr_3addr); @@ -556,7 +556,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb) return -1; } - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); delba = (struct rtl_80211_hdr_3addr *)skb->data; dst = &delba->addr2[0]; pDelBaParamSet = (union delba_param_set *)&delba->payload[2]; @@ -643,7 +643,7 @@ TsInitDelBA(struct ieee80211_device *ieee, struct ts_common_info *pTsCommonInfo, ieee80211_send_DELBA( ieee, pTsCommonInfo->addr, - (pTxTs->tx_admitted_ba_record.valid)?(&pTxTs->tx_admitted_ba_record):(&pTxTs->tx_pending_ba_record), + (pTxTs->tx_admitted_ba_record.valid) ? (&pTxTs->tx_admitted_ba_record) : (&pTxTs->tx_pending_ba_record), TxRxSelect, DELBA_REASON_END_BA); } else if (TxRxSelect == RX_DIR) { diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h index b7769bca9740..79346a00af09 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h @@ -253,10 +253,10 @@ extern u8 MCS_FILTER_1SS[16]; /* 2007/07/12 MH We only define legacy and HT wireless mode now. */ #define LEGACY_WIRELESS_MODE IEEE_MODE_MASK -#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \ - ((WirelessMode & (LEGACY_WIRELESS_MODE)) != 0) ?\ - (LegacyRate) :\ - (PICK_RATE(LegacyRate, HTRate)) +#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \ + ((WirelessMode & (LEGACY_WIRELESS_MODE)) != 0) ? \ + (LegacyRate) : \ + (PICK_RATE(LegacyRate, HTRate)) // MCS Bw 40 {1~7, 12~15,32} #define RATE_ADPT_1SS_MASK 0xFF @@ -270,11 +270,10 @@ typedef enum _HT_AGGRE_SIZE { HT_AGG_SIZE_16K = 1, HT_AGG_SIZE_32K = 2, HT_AGG_SIZE_64K = 3, -}HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E; +} HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E; /* Indicate different AP vendor for IOT issue */ -typedef enum _HT_IOT_PEER -{ +typedef enum _HT_IOT_PEER { HT_IOT_PEER_UNKNOWN = 0, HT_IOT_PEER_REALTEK = 1, HT_IOT_PEER_BROADCOM = 2, @@ -282,7 +281,7 @@ typedef enum _HT_IOT_PEER HT_IOT_PEER_ATHEROS = 4, HT_IOT_PEER_CISCO = 5, HT_IOT_PEER_MAX = 6 -}HT_IOT_PEER_E, *PHTIOT_PEER_E; +} HT_IOT_PEER_E, *PHTIOT_PEER_E; /* * IOT Action for different AP @@ -298,6 +297,6 @@ typedef enum _HT_IOT_ACTION { HT_IOT_ACT_CDD_FSYNC = 0x00000080, HT_IOT_ACT_PURE_N_MODE = 0x00000100, HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200, -}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E; +} HT_IOT_ACTION_E, *PHT_IOT_ACTION_E; #endif //_RTL819XU_HTTYPE_H_ diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c index c73a8058cf87..dba3f2db9f48 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c @@ -93,10 +93,6 @@ void HTUpdateDefaultSetting(struct ieee80211_device *ieee) ieee->bTxDisableRateFallBack = 0; ieee->bTxUseDriverAssingedRate = 0; -#ifdef TO_DO_LIST - // 8190 only. Assign duration operation mode to firmware - pMgntInfo->bTxEnableFwCalcDur = (BOOLEAN)pNdisCommon->bRegTxEnableFwCalcDur; -#endif /* * 8190 only, Realtek proprietary aggregation mode * Set MPDUDensity=2, 1: Set MPDUDensity=2(32k) for Realtek AP and set MPDUDensity=0(8k) for others diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index 59d179ae7ad2..5cee1031a27c 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -105,7 +105,7 @@ static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo) { eth_zero_addr(pTsCommonInfo->addr); memset(&pTsCommonInfo->t_spec, 0, sizeof(struct tspec_body)); - memset(&pTsCommonInfo->t_class, 0, sizeof(union qos_tclas)*TCLAS_NUM); + memset(&pTsCommonInfo->t_class, 0, sizeof(union qos_tclas) * TCLAS_NUM); pTsCommonInfo->t_clas_proc = 0; pTsCommonInfo->t_clas_num = 0; } @@ -180,14 +180,12 @@ void TSInitialize(struct ieee80211_device *ieee) } // Initialize unused Rx Reorder List. INIT_LIST_HEAD(&ieee->RxReorder_Unused_List); -//#ifdef TO_DO_LIST for (count = 0; count < REORDER_ENTRY_NUM; count++) { list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List); - if (count == (REORDER_ENTRY_NUM-1)) + if (count == (REORDER_ENTRY_NUM - 1)) break; - pRxReorderEntry = &ieee->RxReorderEntry[count+1]; + pRxReorderEntry = &ieee->RxReorderEntry[count + 1]; } -//#endif } static void AdmitTS(struct ieee80211_device *ieee, @@ -259,7 +257,7 @@ static struct ts_common_info *SearchAdmitTRStream(struct ieee80211_device *ieee, } if (&pRet->list != psearch_list) - return pRet ; + return pRet; else return NULL; } @@ -367,8 +365,8 @@ bool GetTs( (&ieee->Rx_TS_Admit_List); enum direction_value Dir = (ieee->iw_mode == IW_MODE_MASTER) ? - ((TxRxSelect == TX_DIR)?DIR_DOWN:DIR_UP) : - ((TxRxSelect == TX_DIR)?DIR_UP:DIR_DOWN); + ((TxRxSelect == TX_DIR) ? DIR_DOWN : DIR_UP) : + ((TxRxSelect == TX_DIR) ? DIR_UP : DIR_DOWN); IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n"); if (!list_empty(pUnusedList)) { (*ppTS) = list_entry(pUnusedList->next, struct ts_common_info, list); @@ -417,7 +415,6 @@ static void RemoveTsEntry(struct ieee80211_device *ieee, struct ts_common_info * TsInitDelBA(ieee, pTs, TxRxSelect); if (TxRxSelect == RX_DIR) { -//#ifdef TO_DO_LIST struct rx_reorder_entry *pRxReorderEntry; struct rx_ts_record *pRxTS = (struct rx_ts_record *)pTs; if (timer_pending(&pRxTS->rx_pkt_pending_timer)) @@ -445,7 +442,6 @@ static void RemoveTsEntry(struct ieee80211_device *ieee, struct ts_common_info * spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); } -//#endif } else { struct tx_ts_record *pTxTS = (struct tx_ts_record *)pTs; del_timer_sync(&pTxTS->ts_add_ba_timer); @@ -530,7 +526,7 @@ void TsStartAddBaProcess(struct ieee80211_device *ieee, struct tx_ts_record *pTx jiffies + msecs_to_jiffies(TS_ADDBA_DELAY)); } else { IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: Immediately Start ADDBA now!!\n", __func__); - mod_timer(&pTxTS->ts_add_ba_timer, jiffies+10); //set 10 ticks + mod_timer(&pTxTS->ts_add_ba_timer, jiffies + 10); //set 10 ticks } } else { IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __func__); diff --git a/drivers/staging/rtl8192u/r8180_93cx6.c b/drivers/staging/rtl8192u/r8180_93cx6.c index de83daa0c9ed..2527cea60e3e 100644 --- a/drivers/staging/rtl8192u/r8180_93cx6.c +++ b/drivers/staging/rtl8192u/r8180_93cx6.c @@ -39,7 +39,6 @@ static void eprom_cs(struct net_device *dev, short bit) udelay(EPROM_DELAY); } - static void eprom_ck_cycle(struct net_device *dev) { u8 cmdreg; @@ -58,7 +57,6 @@ static void eprom_ck_cycle(struct net_device *dev) udelay(EPROM_DELAY); } - static void eprom_w(struct net_device *dev, short bit) { u8 cmdreg; @@ -76,7 +74,6 @@ static void eprom_w(struct net_device *dev, short bit) udelay(EPROM_DELAY); } - static short eprom_r(struct net_device *dev) { u8 bit; @@ -94,7 +91,6 @@ static short eprom_r(struct net_device *dev) return 0; } - static void eprom_send_bits_string(struct net_device *dev, short b[], int len) { int i; @@ -105,7 +101,6 @@ static void eprom_send_bits_string(struct net_device *dev, short b[], int len) } } - int eprom_read(struct net_device *dev, u32 addr) { struct r8192_priv *priv = ieee80211_priv(dev); @@ -119,7 +114,7 @@ int eprom_read(struct net_device *dev, u32 addr) ret = 0; /* enable EPROM programming */ write_nic_byte_E(dev, EPROM_CMD, - (EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT)); + (EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT)); force_pci_posting(dev); udelay(EPROM_DELAY); @@ -162,7 +157,7 @@ int eprom_read(struct net_device *dev, u32 addr) if (err < 0) return err; - ret |= err<<(15-i); + ret |= err << (15 - i); } eprom_cs(dev, 0); @@ -170,6 +165,6 @@ int eprom_read(struct net_device *dev, u32 addr) /* disable EPROM programming */ write_nic_byte_E(dev, EPROM_CMD, - (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT)); + (EPROM_CMD_NORMAL << EPROM_CMD_OPERATING_MODE_SHIFT)); return ret; } diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.c b/drivers/staging/rtl8192u/r8190_rtl8256.c index 92de92a3325a..b169460b9f26 100644 --- a/drivers/staging/rtl8192u/r8190_rtl8256.c +++ b/drivers/staging/rtl8192u/r8190_rtl8256.c @@ -42,9 +42,9 @@ void phy_set_rf8256_bandwidth(struct net_device *dev, enum ht_channel_width Band switch (Bandwidth) { case HT_CHANNEL_WIDTH_20: - if (priv->card_8192_version == VERSION_819XU_A - || priv->card_8192_version - == VERSION_819XU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */ + if (priv->card_8192_version == VERSION_819XU_A || + priv->card_8192_version == + VERSION_819XU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */ rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0b, bMask12Bits, 0x100); /* phy para:1ba */ @@ -79,10 +79,10 @@ void phy_set_rf8256_bandwidth(struct net_device *dev, enum ht_channel_width Band default: RT_TRACE(COMP_ERR, "phy_set_rf8256_bandwidth(): unknown Bandwidth: %#X\n", Bandwidth); break; - } } } + /*-------------------------------------------------------------------------- * Overview: Interface to config 8256 * Input: struct net_device* dev @@ -101,6 +101,7 @@ void phy_rf8256_config(struct net_device *dev) /* Config BB and RF */ phy_rf8256_config_para_file(dev); } + /*-------------------------------------------------------------------------- * Overview: Interface to config 8256 * Input: struct net_device* dev @@ -137,12 +138,12 @@ static void phy_rf8256_config_para_file(struct net_device *dev) break; case RF90_PATH_B: case RF90_PATH_D: - u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16); + u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV << 16); break; } /*----Set RF_ENV enable----*/ - rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1); + rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1); /*----Set RF_ENV output high----*/ rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); @@ -151,7 +152,7 @@ static void phy_rf8256_config_para_file(struct net_device *dev) rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258 */ rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for Z-serial and 8258, and set 1 to 14 bits for ??? */ - rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e) eRFPath, 0x0, bMask12Bits, 0xbf); + rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0, bMask12Bits, 0xbf); /* Check RF block (for FPGA platform only)---- * TODO: this function should be removed on ASIC , Emily 2007.2.2 @@ -207,7 +208,7 @@ static void phy_rf8256_config_para_file(struct net_device *dev) break; case RF90_PATH_B: case RF90_PATH_D: - rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue); + rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV << 16, u4RegValue); break; } @@ -215,7 +216,6 @@ static void phy_rf8256_config_para_file(struct net_device *dev) RT_TRACE(COMP_ERR, "phy_rf8256_config_para_file():Radio[%d] Fail!!", eRFPath); goto phy_RF8256_Config_ParaFile_Fail; } - } RT_TRACE(COMP_PHY, "PHY Initialization Success\n"); @@ -225,11 +225,11 @@ phy_RF8256_Config_ParaFile_Fail: RT_TRACE(COMP_ERR, "PHY Initialization failed\n"); } - void phy_set_rf8256_cck_tx_power(struct net_device *dev, u8 powerlevel) { u32 TxAGC = 0; struct r8192_priv *priv = ieee80211_priv(dev); + TxAGC = powerlevel; if (priv->bDynamicTxLowPower) { @@ -244,7 +244,6 @@ void phy_set_rf8256_cck_tx_power(struct net_device *dev, u8 powerlevel) rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); } - void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel) { struct r8192_priv *priv = ieee80211_priv(dev); @@ -255,16 +254,16 @@ void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel) u8 byte0, byte1, byte2, byte3; powerBase0 = powerlevel + priv->TxPowerDiff; /* OFDM rates */ - powerBase0 = (powerBase0<<24) | (powerBase0<<16) | (powerBase0<<8) | powerBase0; + powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | (powerBase0 << 8) | powerBase0; powerBase1 = powerlevel; /* MCS rates */ - powerBase1 = (powerBase1<<24) | (powerBase1<<16) | (powerBase1<<8) | powerBase1; + powerBase1 = (powerBase1 << 24) | (powerBase1 << 16) | (powerBase1 << 8) | powerBase1; for (index = 0; index < 6; index++) { - writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index < 2)?powerBase0:powerBase1); + writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index < 2) ? powerBase0 : powerBase1); byte0 = (u8)(writeVal & 0x7f); - byte1 = (u8)((writeVal & 0x7f00)>>8); - byte2 = (u8)((writeVal & 0x7f0000)>>16); - byte3 = (u8)((writeVal & 0x7f000000)>>24); + byte1 = (u8)((writeVal & 0x7f00) >> 8); + byte2 = (u8)((writeVal & 0x7f0000) >> 16); + byte3 = (u8)((writeVal & 0x7f000000) >> 24); if (byte0 > 0x24) /* Max power index = 0x24 */ @@ -278,7 +277,7 @@ void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel) /* for tx power track */ if (index == 3) { - writeVal_tmp = (byte3<<24) | (byte2<<16) | (byte1<<8) | byte0; + writeVal_tmp = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0; priv->Pwr_Track = writeVal_tmp; } @@ -288,10 +287,9 @@ void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel) */ writeVal = 0x03030303; } else { - writeVal = (byte3<<24) | (byte2<<16) | (byte1<<8) | byte0; - } - rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); + writeVal = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0; + } + rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); } return; - } diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index fe1f279ca368..2821411878ce 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -2076,14 +2076,6 @@ static void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode) wireless_mode = WIRELESS_MODE_B; } } -#ifdef TO_DO_LIST - /* TODO: this function doesn't work well at this time, - * we should wait for FPGA - */ - ActUpdateChannelAccessSetting( - pAdapter, pHalData->CurrentWirelessMode, - &pAdapter->MgntInfo.Info8185.ChannelAccessSetting); -#endif priv->ieee80211->mode = wireless_mode; if (wireless_mode == WIRELESS_MODE_N_24G || @@ -2096,7 +2088,7 @@ static void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode) } /* init priv variables here. only non_zero value should be initialized here. */ -static void rtl8192_init_priv_variable(struct net_device *dev) +static int rtl8192_init_priv_variable(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); u8 i; @@ -2159,12 +2151,6 @@ static void rtl8192_init_priv_variable(struct net_device *dev) priv->ieee80211->InitialGainHandler = InitialGain819xUsb; priv->card_type = USB; -#ifdef TO_DO_LIST - if (Adapter->bInHctTest) { - pHalData->ShortRetryLimit = 7; - pHalData->LongRetryLimit = 7; - } -#endif priv->ShortRetryLimit = 0x30; priv->LongRetryLimit = 0x30; priv->EarlyRxThreshold = 7; @@ -2180,34 +2166,6 @@ static void rtl8192_init_priv_variable(struct net_device *dev) * TRUE: SW provides them */ (false ? TCR_SAT : 0); -#ifdef TO_DO_LIST - if (Adapter->bInHctTest) - pHalData->ReceiveConfig = - pHalData->CSMethod | - /* accept management/data */ - RCR_AMF | RCR_ADF | - /* accept control frame for SW - * AP needs PS-poll - */ - RCR_ACF | - /* accept BC/MC/UC */ - RCR_AB | RCR_AM | RCR_APM | - /* accept ICV/CRC error - * packet - */ - RCR_AICV | RCR_ACRC32 | - /* Max DMA Burst Size per Tx - * DMA Burst, 7: unlimited. - */ - ((u32)7 << RCR_MXDMA_OFFSET) | - /* Rx FIFO Threshold, - * 7: No Rx threshold. - */ - (pHalData->EarlyRxThreshold << RCR_FIFO_OFFSET) | - (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt : 0); - else - -#endif priv->ReceiveConfig = /* accept management/data */ RCR_AMF | RCR_ADF | @@ -2223,6 +2181,8 @@ static void rtl8192_init_priv_variable(struct net_device *dev) priv->AcmControl = 0; priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL); + if (!priv->pFirmware) + return -ENOMEM; /* rx related queue */ skb_queue_head_init(&priv->rx_queue); @@ -2236,6 +2196,8 @@ static void rtl8192_init_priv_variable(struct net_device *dev) for (i = 0; i < MAX_QUEUE_SIZE; i++) skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ[i]); priv->rf_set_chan = rtl8192_phy_SwChnl; + + return 0; } /* init lock here */ @@ -2605,7 +2567,10 @@ static short rtl8192_init(struct net_device *dev) memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9); } #endif - rtl8192_init_priv_variable(dev); + err = rtl8192_init_priv_variable(dev); + if (err) + return err; + rtl8192_init_priv_lock(priv); rtl8192_init_priv_task(dev); rtl8192_get_eeprom_size(dev); @@ -2658,19 +2623,10 @@ static void rtl8192_hwconfig(struct net_device *dev) regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; break; case WIRELESS_MODE_AUTO: -#ifdef TO_DO_LIST - if (Adapter->bInHctTest) { - regBwOpMode = BW_OPMODE_20MHZ; - regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - } else -#endif - { - regBwOpMode = BW_OPMODE_20MHZ; - regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | - RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; - regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - } + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | + RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; break; case WIRELESS_MODE_N_24G: /* It support CCK rate by default. CCK rate will be filtered @@ -2841,48 +2797,6 @@ static bool rtl8192_adapter_start(struct net_device *dev) } RT_TRACE(COMP_INIT, "%s():after firmware download\n", __func__); -#ifdef TO_DO_LIST - if (Adapter->ResetProgress == RESET_TYPE_NORESET) { - if (pMgntInfo->RegRfOff) { /* User disable RF via registry. */ - RT_TRACE((COMP_INIT | COMP_RF), DBG_LOUD, - ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n")); - MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW); - /* Those actions will be discard in MgntActSet_RF_State - * because of the same state - */ - for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) - PHY_SetRFReg(Adapter, - (enum rf90_radio_path_e)eRFPath, - 0x4, 0xC00, 0x0); - } else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { - /* H/W or S/W RF OFF before sleep. */ - RT_TRACE((COMP_INIT | COMP_RF), DBG_LOUD, - ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", - pMgntInfo->RfOffReason)); - MgntActSet_RF_State(Adapter, - eRfOff, - pMgntInfo->RfOffReason); - } else { - pHalData->eRFPowerState = eRfOn; - pMgntInfo->RfOffReason = 0; - RT_TRACE((COMP_INIT | COMP_RF), DBG_LOUD, - ("InitializeAdapter819xUsb(): RF is on ----------\n")); - } - } else { - if (pHalData->eRFPowerState == eRfOff) { - MgntActSet_RF_State(Adapter, - eRfOff, - pMgntInfo->RfOffReason); - /* Those actions will be discard in MgntActSet_RF_State - * because of the same state - */ - for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) - PHY_SetRFReg(Adapter, - (enum rf90_radio_path_e)eRFPath, - 0x4, 0xC00, 0x0); - } - } -#endif /* config RF. */ if (priv->ResetProgress == RESET_TYPE_NORESET) { rtl8192_phy_RFConfig(dev); diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index ade14ef05730..c23e43b095d9 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -1334,7 +1334,7 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) return; } /*DbgPrint("Schedule TxPowerTrackingWorkItem\n");*/ - queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); + queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); TM_Trigger = 0; } diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c index 153d4ee0ec07..dd81d210bd49 100644 --- a/drivers/staging/rtl8192u/r819xU_firmware.c +++ b/drivers/staging/rtl8192u/r819xU_firmware.c @@ -231,7 +231,7 @@ bool init_firmware(struct net_device *dev) rst_opt = OPT_FIRMWARE_RESET; starting_state = FW_INIT_STEP2_DATA; } else { - RT_TRACE(COMP_FIRMWARE, "PlatformInitFirmware: undefined firmware state\n"); + RT_TRACE(COMP_FIRMWARE, "PlatformInitFirmware: undefined firmware state\n"); } /* diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c index 5f04afe53d69..c04d8eca0cfb 100644 --- a/drivers/staging/rtl8192u/r819xU_phy.c +++ b/drivers/staging/rtl8192u/r819xU_phy.c @@ -516,16 +516,6 @@ static void rtl8192_phyConfigBB(struct net_device *dev, { u32 i; -#ifdef TO_DO_LIST - u32 *rtl8192PhyRegArrayTable = NULL, *rtl8192AgcTabArrayTable = NULL; - - if (Adapter->bInHctTest) { - PHY_REGArrayLen = PHY_REGArrayLengthDTM; - AGCTAB_ArrayLen = AGCTAB_ArrayLengthDTM; - Rtl8190PHY_REGArray_Table = Rtl819XPHY_REGArrayDTM; - Rtl8190AGCTAB_Array_Table = Rtl819XAGCTAB_ArrayDTM; - } -#endif if (ConfigType == BASEBAND_CONFIG_PHY_REG) { for (i = 0; i < PHY_REG_1T2RArrayLength; i += 2) { rtl8192_setBBreg(dev, Rtl8192UsbPHY_REG_1T2RArray[i], @@ -1059,10 +1049,6 @@ static void rtl8192_SetTxPowerLevel(struct net_device *dev, u8 channel) switch (priv->rf_chip) { case RF_8225: -#ifdef TO_DO_LIST - PHY_SetRF8225CckTxPower(Adapter, powerlevel); - PHY_SetRF8225OfdmTxPower(Adapter, powerlevelOFDM24G); -#endif break; case RF_8256: @@ -1160,48 +1146,6 @@ bool rtl8192_SetRFPowerState(struct net_device *dev, RT_TRACE(COMP_ERR, "Not support rf_chip(%x)\n", priv->rf_chip); break; } -#ifdef TO_DO_LIST - if (bResult) { - /* Update current RF state variable. */ - pHalData->eRFPowerState = eRFPowerState; - switch (pHalData->RFChipID) { - case RF_8256: - switch (pHalData->eRFPowerState) { - case eRfOff: - /* If Rf off reason is from IPS, - * LED should blink with no link - */ - if (pMgntInfo->RfOffReason == RF_CHANGE_BY_IPS) - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_NO_LINK); - else - /* Turn off LED if RF is not ON. */ - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_POWER_OFF); - break; - - case eRfOn: - /* Turn on RF we are still linked, which might - * happen when we quickly turn off and on HW RF. - */ - if (pMgntInfo->bMediaConnect) - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_LINK); - else - /* Turn off LED if RF is not ON. */ - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_NO_LINK); - break; - - default: - break; - } - break; - - default: - RT_TRACE(COMP_RF, DBG_LOUD, "%s(): Unknown RF type\n", - __func__); - break; - } - - } -#endif priv->SetRFPowerStateInProgress = false; return bResult; @@ -1628,9 +1572,6 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev) /* <3> Set RF related register */ switch (priv->rf_chip) { case RF_8225: -#ifdef TO_DO_LIST - PHY_SetRF8225Bandwidth(Adapter, pHalData->CurrentChannelBW); -#endif break; case RF_8256: diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index b554cf8bd679..0c3ae8495afb 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -258,7 +258,7 @@ void r8712_stop_drv_timers(struct _adapter *padapter) del_timer_sync(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer); } -static u8 init_default_value(struct _adapter *padapter) +static void init_default_value(struct _adapter *padapter) { struct registry_priv *pregistrypriv = &padapter->registrypriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; @@ -292,37 +292,41 @@ static u8 init_default_value(struct _adapter *padapter) r8712_init_registrypriv_dev_network(padapter); r8712_update_registrypriv_dev_network(padapter); /*misc.*/ - return _SUCCESS; } -u8 r8712_init_drv_sw(struct _adapter *padapter) +int r8712_init_drv_sw(struct _adapter *padapter) { - if (r8712_init_cmd_priv(&padapter->cmdpriv)) - return _FAIL; + int ret; + + ret = r8712_init_cmd_priv(&padapter->cmdpriv); + if (ret) + return ret; padapter->cmdpriv.padapter = padapter; - if (r8712_init_evt_priv(&padapter->evtpriv)) - return _FAIL; - if (r8712_init_mlme_priv(padapter) == _FAIL) - return _FAIL; + ret = r8712_init_evt_priv(&padapter->evtpriv); + if (ret) + return ret; + ret = r8712_init_mlme_priv(padapter); + if (ret) + return ret; _r8712_init_xmit_priv(&padapter->xmitpriv, padapter); _r8712_init_recv_priv(&padapter->recvpriv, padapter); memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv)); timer_setup(&padapter->securitypriv.tkip_timer, r8712_use_tkipkey_handler, 0); - if (_r8712_init_sta_priv(&padapter->stapriv)) - return _FAIL; + ret = _r8712_init_sta_priv(&padapter->stapriv); + if (ret) + return ret; padapter->stapriv.padapter = padapter; r8712_init_bcmc_stainfo(padapter); r8712_init_pwrctrl_priv(padapter); mp871xinit(padapter); - if (init_default_value(padapter) != _SUCCESS) - return _FAIL; + init_default_value(padapter); r8712_InitSwLeds(padapter); - return _SUCCESS; + return ret; } -u8 r8712_free_drv_sw(struct _adapter *padapter) +void r8712_free_drv_sw(struct _adapter *padapter) { struct net_device *pnetdev = padapter->pnetdev; @@ -337,7 +341,6 @@ u8 r8712_free_drv_sw(struct _adapter *padapter) mp871xdeinit(padapter); if (pnetdev) free_netdev(pnetdev); - return _SUCCESS; } static void enable_video_mode(struct _adapter *padapter, int cbw40_value) diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 84c4c8580f9a..215fca4abb3a 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -29,24 +29,23 @@ /*init os related resource in struct recv_priv*/ /*alloc os related resource in union recv_frame*/ -int r8712_os_recv_resource_alloc(struct _adapter *padapter, - union recv_frame *precvframe) +void r8712_os_recv_resource_alloc(struct _adapter *padapter, + union recv_frame *precvframe) { precvframe->u.hdr.pkt_newalloc = NULL; precvframe->u.hdr.pkt = NULL; - return _SUCCESS; } /*alloc os related resource in struct recv_buf*/ int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, struct recv_buf *precvbuf) { - int res = _SUCCESS; + int res = 0; precvbuf->irp_pending = false; precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); if (!precvbuf->purb) - res = _FAIL; + res = -ENOMEM; precvbuf->pskb = NULL; precvbuf->pallocated_buf = NULL; precvbuf->pbuf = NULL; @@ -60,8 +59,8 @@ int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, } /*free os related resource in struct recv_buf*/ -int r8712_os_recvbuf_resource_free(struct _adapter *padapter, - struct recv_buf *precvbuf) +void r8712_os_recvbuf_resource_free(struct _adapter *padapter, + struct recv_buf *precvbuf) { if (precvbuf->pskb) dev_kfree_skb_any(precvbuf->pskb); @@ -69,7 +68,6 @@ int r8712_os_recvbuf_resource_free(struct _adapter *padapter, usb_kill_urb(precvbuf->purb); usb_free_urb(precvbuf->purb); } - return _SUCCESS; } void r8712_handle_tkip_mic_err(struct _adapter *adapter, u8 bgroup) @@ -115,8 +113,8 @@ void r8712_recv_indicatepkt(struct _adapter *adapter, skb->protocol = eth_type_trans(skb, adapter->pnetdev); netif_rx(skb); recvframe->u.hdr.pkt = NULL; /* pointers to NULL before - * r8712_free_recvframe() - */ + * r8712_free_recvframe() + */ r8712_free_recvframe(recvframe, free_recv_queue); return; _recv_indicatepkt_drop: diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index dcd3b484c793..d8c1fa74f544 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -18,22 +18,22 @@ #include "drv_types.h" #include <linux/skbuff.h> -sint _r8712_init_recv_priv(struct recv_priv *precvpriv, +void _r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter); void _r8712_free_recv_priv(struct recv_priv *precvpriv); -s32 r8712_recv_entry(union recv_frame *precv_frame); +void r8712_recv_entry(union recv_frame *precv_frame); void r8712_recv_indicatepkt(struct _adapter *adapter, union recv_frame *precv_frame); void r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup); -int r8712_init_recv_priv(struct recv_priv *precvpriv, - struct _adapter *padapter); +void r8712_init_recv_priv(struct recv_priv *precvpriv, + struct _adapter *padapter); void r8712_free_recv_priv(struct recv_priv *precvpriv); -int r8712_os_recv_resource_alloc(struct _adapter *padapter, - union recv_frame *precvframe); +void r8712_os_recv_resource_alloc(struct _adapter *padapter, + union recv_frame *precvframe); int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, struct recv_buf *precvbuf); -int r8712_os_recvbuf_resource_free(struct _adapter *padapter, - struct recv_buf *precvbuf); +void r8712_os_recvbuf_resource_free(struct _adapter *padapter, + struct recv_buf *precvbuf); void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl); #endif diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index 6a72a4ad176a..ff3cb09c57a6 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -263,11 +263,6 @@ static struct cmd_obj *cmd_hdl_filter(struct _adapter *padapter, return pcmd_r; /* if returning pcmd_r == NULL, pcmd must be free. */ } -static u8 check_cmd_fifo(struct _adapter *padapter, uint sz) -{ - return _SUCCESS; -} - u8 r8712_fw_cmd(struct _adapter *pAdapter, u32 cmd) { int pollingcnts = 50; @@ -311,7 +306,7 @@ int r8712_cmd_thread(void *context) break; if (padapter->driver_stopped || padapter->surprise_removed) break; - if (r8712_register_cmd_alive(padapter) != _SUCCESS) + if (r8712_register_cmd_alive(padapter)) continue; _next: pcmd = r8712_dequeue_cmd(&pcmdpriv->cmd_queue); @@ -359,13 +354,6 @@ _next: (pcmdpriv->cmd_seq << 24)); pcmdbuf += 2; /* 8 bytes alignment */ memcpy((u8 *)pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); - while (check_cmd_fifo(padapter, wr_sz) == _FAIL) { - if (padapter->driver_stopped || - padapter->surprise_removed) - break; - msleep(100); - continue; - } if (blnPending) wr_sz += 8; /* Append 8 bytes */ r8712_write_mem(padapter, RTL8712_DMA_H2CCMD, wr_sz, diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 82ddc0c3ecd4..9901815604f4 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -35,11 +35,11 @@ static u8 rfc1042_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; static void recv_tasklet(void *priv); -int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) +void r8712_init_recv_priv(struct recv_priv *precvpriv, + struct _adapter *padapter) { int i; struct recv_buf *precvbuf; - int res = _SUCCESS; addr_t tmpaddr = 0; int alignment = 0; struct sk_buff *pskb = NULL; @@ -49,15 +49,14 @@ int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) precvpriv->pallocated_recv_buf = kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_ATOMIC); if (!precvpriv->pallocated_recv_buf) - return _FAIL; + return; precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 - ((addr_t)(precvpriv->pallocated_recv_buf) & 3); precvbuf = (struct recv_buf *)precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { INIT_LIST_HEAD(&precvbuf->list); spin_lock_init(&precvbuf->recvbuf_lock); - res = r8712_os_recvbuf_resource_alloc(padapter, precvbuf); - if (res == _FAIL) + if (r8712_os_recvbuf_resource_alloc(padapter, precvbuf)) break; precvbuf->ref_cnt = 0; precvbuf->adapter = padapter; @@ -83,7 +82,6 @@ int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) } pskb = NULL; } - return res; } void r8712_free_recv_priv(struct recv_priv *precvpriv) @@ -107,7 +105,7 @@ void r8712_free_recv_priv(struct recv_priv *precvpriv) skb_queue_len(&precvpriv->free_recv_skb_queue)); } -int r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) +void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) { precvbuf->transfer_len = 0; precvbuf->len = 0; @@ -118,10 +116,9 @@ int r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) precvbuf->ptail = precvbuf->pbuf; precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ; } - return _SUCCESS; } -int r8712_free_recvframe(union recv_frame *precvframe, +void r8712_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue) { unsigned long irqL; @@ -140,7 +137,6 @@ int r8712_free_recvframe(union recv_frame *precvframe, precvpriv->free_recvframe_cnt++; } spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL); - return _SUCCESS; } static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib, @@ -323,7 +319,7 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, return prtnframe; } -static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) +static void amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) { int a_len, padding_len; u16 eth_type, nSubframe_Length; @@ -421,7 +417,6 @@ static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) exit: prframe->u.hdr.len = 0; r8712_free_recvframe(prframe, pfree_recv_queue); - return _SUCCESS; } void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf) @@ -511,7 +506,6 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter, union recv_frame *prframe; struct rx_pkt_attrib *pattrib; int bPktInBuf = false; - struct recv_priv *precvpriv = &padapter->recvpriv; struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; @@ -548,10 +542,7 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter, prframe); } } else if (pattrib->amsdu == 1) { - if (amsdu_to_msdu(padapter, prframe) != - _SUCCESS) - r8712_free_recvframe(prframe, - &precvpriv->free_recv_queue); + amsdu_to_msdu(padapter, prframe); } /* Update local variables. */ bPktInBuf = false; @@ -579,9 +570,9 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter, if (!padapter->driver_stopped && !padapter->surprise_removed) { r8712_recv_indicatepkt(padapter, prframe); - return _SUCCESS; + return 0; } else { - return _FAIL; + return -EINVAL; } } } @@ -603,8 +594,7 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter, * 2. All packets with SeqNum larger than or equal to * WinStart => Buffer it. */ - if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false) == - true) { + if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false)) { mod_timer(&preorder_ctrl->reordering_ctrl_timer, jiffies + msecs_to_jiffies(REORDER_WAIT_TIME)); spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); @@ -612,10 +602,10 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter, spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); del_timer(&preorder_ctrl->reordering_ctrl_timer); } - return _SUCCESS; + return 0; _err_exit: spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); - return _FAIL; + return -ENOMEM; } void r8712_reordering_ctrl_timeout_handler(void *pcontext) @@ -641,7 +631,7 @@ static int r8712_process_recv_indicatepkts(struct _adapter *padapter, struct ht_priv *phtpriv = &pmlmepriv->htpriv; if (phtpriv->ht_option == 1) { /*B/G/N Mode*/ - if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) { + if (recv_indicatepkt_reorder(padapter, prframe)) { /* including perform A-MPDU Rx Ordering Buffer Control*/ if (!padapter->driver_stopped && !padapter->surprise_removed) @@ -649,8 +639,8 @@ static int r8712_process_recv_indicatepkts(struct _adapter *padapter, } } else { /*B/G mode*/ retval = r8712_wlanhdr_to_ethhdr(prframe); - if (retval != _SUCCESS) - return retval; + if (retval) + return _FAIL; if (!padapter->driver_stopped && !padapter->surprise_removed) { /* indicate this recv_frame */ r8712_recv_indicatepkt(padapter, prframe); @@ -991,7 +981,7 @@ _exit_recv_func: return retval; } -static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) +static void recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) { u8 *pbuf, shift_sz = 0; u8 frag, mf; @@ -1018,7 +1008,7 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) /* In this case, it means the MAX_RECVBUF_SZ is too small to * get the data from 8712u. */ - return _FAIL; + return; } do { prxstat = (struct recv_stat *)pbuf; @@ -1031,13 +1021,13 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16; drvinfo_sz <<= 3; if (pkt_len <= 0) - goto _exit_recvbuf2recvframe; + return; /* Qos data, wireless lan header length is 26 */ if ((le32_to_cpu(prxstat->rxdw0) >> 23) & 0x01) shift_sz = 2; precvframe = r8712_alloc_recvframe(pfree_recv_queue); if (!precvframe) - goto _exit_recvbuf2recvframe; + return; INIT_LIST_HEAD(&precvframe->u.hdr.list); precvframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf*/ precvframe->u.hdr.len = 0; @@ -1068,7 +1058,7 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) } else { precvframe->u.hdr.pkt = skb_clone(pskb, GFP_ATOMIC); if (!precvframe->u.hdr.pkt) - return _FAIL; + return; precvframe->u.hdr.rx_head = pbuf; precvframe->u.hdr.rx_data = pbuf; precvframe->u.hdr.rx_tail = pbuf; @@ -1088,8 +1078,6 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) precvframe = NULL; pkt_copy = NULL; } while ((transfer_len > 0) && pkt_cnt > 0); -_exit_recvbuf2recvframe: - return _SUCCESS; } static void recv_tasklet(void *priv) diff --git a/drivers/staging/rtl8712/rtl8712_recv.h b/drivers/staging/rtl8712/rtl8712_recv.h index 6954c5bfbcaf..3e385b2242d8 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.h +++ b/drivers/staging/rtl8712/rtl8712_recv.h @@ -136,7 +136,7 @@ union recv_frame { } u; }; -int r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf); +void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf); void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf); s32 r8712_signal_scale_mapping(s32 cur_sig); void r8712_reordering_ctrl_timeout_handler(void *pcontext); diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 307b0e292976..c247f92207f5 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -246,7 +246,7 @@ void r8712_do_queue_select(struct _adapter *padapter, } #ifdef CONFIG_R8712_TX_AGGR -u8 r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) +void r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) { struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; @@ -260,11 +260,9 @@ u8 r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) /* dw1 */ ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00); - - return _SUCCESS; } -u8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) +void r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) { struct xmit_frame *pxmitframe = (struct xmit_frame *) pxmitbuf->priv_data; @@ -278,12 +276,10 @@ u8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) | (pcmdpriv->cmd_seq << 24)); pcmdpriv->cmd_seq++; - - return _SUCCESS; } -u8 r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe) +void r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, + struct xmit_frame *pxmitframe) { struct _adapter *padapter = pxmitframe->padapter; struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; @@ -319,13 +315,11 @@ u8 r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, ((ptx_desc->txdw0 & 0x0000ffff) + ((TXDESC_SIZE + last_txcmdsz + padding_sz) & 0x0000ffff))); - - return _SUCCESS; } -u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe) +void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, + struct xmit_frame *pxmitframe) { /* linux complete context doesn't need to protect */ pxmitframe->pxmitbuf = pxmitbuf; @@ -336,10 +330,8 @@ u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, /*RTL8712_DMA_H2CCMD */ r8712_construct_txaggr_cmd_desc(pxmitbuf); r8712_construct_txaggr_cmd_hdr(pxmitbuf); - if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS) - pxmitbuf->aggr_nr = 1; - - return _SUCCESS; + r8712_append_mpdu_unit(pxmitbuf, pxmitframe); + pxmitbuf->aggr_nr = 1; } u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, @@ -351,18 +343,17 @@ u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, /* buffer addr assoc */ pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); - if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS) { - r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv, - pxmitframe); - pxmitbuf->aggr_nr++; - } + r8712_append_mpdu_unit(pxmitbuf, pxmitframe); + r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv, + pxmitframe); + pxmitbuf->aggr_nr++; return TXDESC_SIZE + (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); } -u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe) +void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, + struct xmit_frame *pxmitframe) { struct _adapter *padapter = pxmitframe->padapter; struct dvobj_priv *pdvobj = &padapter->dvobjpriv; @@ -399,8 +390,6 @@ u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, } r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD, total_length + TXDESC_SIZE, (u8 *)pxmitframe); - - return _SUCCESS; } #endif @@ -737,20 +726,19 @@ static void dump_xframe(struct _adapter *padapter, } } -int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) +void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) { - int res = _SUCCESS; + int res; res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); pxmitframe->pkt = NULL; if (res == _SUCCESS) dump_xframe(padapter, pxmitframe); - return res; } int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe) { - if (r8712_xmit_classifier(padapter, pxmitframe) == _FAIL) { + if (r8712_xmit_classifier(padapter, pxmitframe)) { pxmitframe->pkt = NULL; return _FAIL; } diff --git a/drivers/staging/rtl8712/rtl8712_xmit.h b/drivers/staging/rtl8712/rtl8712_xmit.h index 9be8fb70c92e..0b56bd3ac4d0 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.h +++ b/drivers/staging/rtl8712/rtl8712_xmit.h @@ -102,10 +102,10 @@ void r8712_do_queue_select(struct _adapter *padapter, struct pkt_attrib *pattrib); #ifdef CONFIG_R8712_TX_AGGR -u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe); -u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe); +void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, + struct xmit_frame *pxmitframe); +void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, + struct xmit_frame *pxmitframe); #endif #endif diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h index 28941423b7ed..c20dd5a6bbd1 100644 --- a/drivers/staging/rtl8712/rtl871x_io.h +++ b/drivers/staging/rtl8712/rtl871x_io.h @@ -11,8 +11,8 @@ * Larry Finger <Larry.Finger@lwfinger.net> * ******************************************************************************/ -#ifndef _IO_H_ -#define _IO_H_ +#ifndef _RTL871X_IO_H_ +#define _RTL871X_IO_H_ #include "osdep_service.h" #include "osdep_intf.h" @@ -234,5 +234,4 @@ void r8712_write_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem); uint r8712_alloc_io_queue(struct _adapter *adapter); void r8712_free_io_queue(struct _adapter *adapter); -#endif /*_RTL8711_IO_H_*/ - +#endif /*_RTL871X_IO_H_*/ diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index b08b9a191a34..944336e0d2e2 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -419,8 +419,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, pwep->KeyIndex |= 0x80000000; memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength); if (param->u.crypt.set_tx) { - if (r8712_set_802_11_add_wep(padapter, pwep) == - (u8)_FAIL) + if (r8712_set_802_11_add_wep(padapter, pwep)) ret = -EOPNOTSUPP; } else { /* don't update "psecuritypriv->PrivacyAlgrthm" and @@ -1585,7 +1584,7 @@ static int r8711_wx_set_enc(struct net_device *dev, } wep.KeyIndex |= 0x80000000; /* transmit key */ memcpy(wep.KeyMaterial, keybuf, wep.KeyLength); - if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL) + if (r8712_set_802_11_add_wep(padapter, &wep)) return -EOPNOTSUPP; return 0; } diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c index f3c0a9348f56..6cdc6f1a6bc6 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c @@ -320,22 +320,22 @@ u8 r8712_set_802_11_authentication_mode(struct _adapter *padapter, psecuritypriv->ndisauthtype = authmode; if (psecuritypriv->ndisauthtype > 3) psecuritypriv->AuthAlgrthm = 2; /* 802.1x */ - if (r8712_set_auth(padapter, psecuritypriv) == _SUCCESS) - ret = true; - else + if (r8712_set_auth(padapter, psecuritypriv)) ret = false; + else + ret = true; return ret; } -u8 r8712_set_802_11_add_wep(struct _adapter *padapter, - struct NDIS_802_11_WEP *wep) +int r8712_set_802_11_add_wep(struct _adapter *padapter, + struct NDIS_802_11_WEP *wep) { sint keyid; struct security_priv *psecuritypriv = &padapter->securitypriv; keyid = wep->KeyIndex & 0x3fffffff; if (keyid >= WEP_KEYS) - return false; + return -EINVAL; switch (wep->KeyLength) { case 5: psecuritypriv->PrivacyAlgrthm = _WEP40_; @@ -351,7 +351,5 @@ u8 r8712_set_802_11_add_wep(struct _adapter *padapter, wep->KeyLength); psecuritypriv->DefKeylen[keyid] = wep->KeyLength; psecuritypriv->PrivacyKeyIndex = keyid; - if (r8712_set_key(padapter, psecuritypriv, keyid) == _FAIL) - return false; - return _SUCCESS; + return r8712_set_key(padapter, psecuritypriv, keyid); } diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.h b/drivers/staging/rtl8712/rtl871x_ioctl_set.h index 8b1085aea962..e2de820f61d9 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.h +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.h @@ -28,8 +28,8 @@ u8 r8712_set_802_11_authentication_mode(struct _adapter *pdapter, u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid); -u8 r8712_set_802_11_add_wep(struct _adapter *padapter, - struct NDIS_802_11_WEP *wep); +int r8712_set_802_11_add_wep(struct _adapter *padapter, + struct NDIS_802_11_WEP *wep); u8 r8712_set_802_11_disassociate(struct _adapter *padapter); diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index 0cc879a4d43f..cabdb3549a5a 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -53,7 +53,7 @@ int r8712_init_mlme_priv(struct _adapter *padapter) pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network), GFP_ATOMIC); if (!pbuf) - return _FAIL; + return -ENOMEM; pmlmepriv->free_bss_buf = pbuf; pnetwork = (struct wlan_network *)pbuf; for (i = 0; i < MAX_BSS_CNT; i++) { @@ -67,7 +67,7 @@ int r8712_init_mlme_priv(struct _adapter *padapter) pmlmepriv->sitesurveyctrl.traffic_busy = false; /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ r8712_init_mlme_timer(padapter); - return _SUCCESS; + return 0; } struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv) @@ -1144,8 +1144,8 @@ ask_for_joinbss: return r8712_joinbss_cmd(adapter, pnetwork); } -sint r8712_set_auth(struct _adapter *adapter, - struct security_priv *psecuritypriv) +int r8712_set_auth(struct _adapter *adapter, + struct security_priv *psecuritypriv) { struct cmd_priv *pcmdpriv = &adapter->cmdpriv; struct cmd_obj *pcmd; @@ -1153,12 +1153,12 @@ sint r8712_set_auth(struct _adapter *adapter, pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); if (!pcmd) - return _FAIL; + return -ENOMEM; psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC); if (!psetauthparm) { kfree(pcmd); - return _FAIL; + return -ENOMEM; } psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm; pcmd->cmdcode = _SetAuth_CMD_; @@ -1168,25 +1168,25 @@ sint r8712_set_auth(struct _adapter *adapter, pcmd->rspsz = 0; INIT_LIST_HEAD(&pcmd->list); r8712_enqueue_cmd(pcmdpriv, pcmd); - return _SUCCESS; + return 0; } -sint r8712_set_key(struct _adapter *adapter, - struct security_priv *psecuritypriv, - sint keyid) +int r8712_set_key(struct _adapter *adapter, + struct security_priv *psecuritypriv, + sint keyid) { struct cmd_priv *pcmdpriv = &adapter->cmdpriv; struct cmd_obj *pcmd; struct setkey_parm *psetkeyparm; u8 keylen; - sint ret = _SUCCESS; + int ret; pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); if (!pcmd) - return _FAIL; + return -ENOMEM; psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC); if (!psetkeyparm) { - ret = _FAIL; + ret = -ENOMEM; goto err_free_cmd; } if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */ @@ -1211,7 +1211,7 @@ sint r8712_set_key(struct _adapter *adapter, break; case _TKIP_: if (keyid < 1 || keyid > 2) { - ret = _FAIL; + ret = -EINVAL; goto err_free_parm; } keylen = 16; @@ -1221,7 +1221,7 @@ sint r8712_set_key(struct _adapter *adapter, break; case _AES_: if (keyid < 1 || keyid > 2) { - ret = _FAIL; + ret = -EINVAL; goto err_free_parm; } keylen = 16; @@ -1230,7 +1230,7 @@ sint r8712_set_key(struct _adapter *adapter, psetkeyparm->grpkey = 1; break; default: - ret = _FAIL; + ret = -EINVAL; goto err_free_parm; } pcmd->cmdcode = _SetKey_CMD_; @@ -1240,7 +1240,7 @@ sint r8712_set_key(struct _adapter *adapter, pcmd->rspsz = 0; INIT_LIST_HEAD(&pcmd->list); r8712_enqueue_cmd(pcmdpriv, pcmd); - return ret; + return 0; err_free_parm: kfree(psetkeyparm); diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h index a160107e9801..46effb469fd4 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.h +++ b/drivers/staging/rtl8712/rtl871x_mlme.h @@ -173,10 +173,10 @@ void r8712_free_network_queue(struct _adapter *adapter); int r8712_init_mlme_priv(struct _adapter *adapter); void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv); int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv); -sint r8712_set_key(struct _adapter *adapter, - struct security_priv *psecuritypriv, sint keyid); -sint r8712_set_auth(struct _adapter *adapter, - struct security_priv *psecuritypriv); +int r8712_set_key(struct _adapter *adapter, + struct security_priv *psecuritypriv, sint keyid); +int r8712_set_auth(struct _adapter *adapter, + struct security_priv *psecuritypriv); uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss); void r8712_generate_random_ibss(u8 *pibss); u8 *r8712_get_capability_from_ie(u8 *ie); diff --git a/drivers/staging/rtl8712/rtl871x_mp.c b/drivers/staging/rtl8712/rtl871x_mp.c index edd3da05fc06..1a39a96b726f 100644 --- a/drivers/staging/rtl8712/rtl871x_mp.c +++ b/drivers/staging/rtl8712/rtl871x_mp.c @@ -35,7 +35,7 @@ static void _init_mp_priv_(struct mp_priv *pmp_priv) static int init_mp_priv(struct mp_priv *pmp_priv) { - int i, res; + int i; struct mp_xmit_frame *pmp_xmitframe; _init_mp_priv_(pmp_priv); @@ -45,8 +45,7 @@ static int init_mp_priv(struct mp_priv *pmp_priv) sizeof(struct mp_xmit_frame) + 4, GFP_ATOMIC); if (!pmp_priv->pallocated_mp_xmitframe_buf) { - res = _FAIL; - goto _exit_init_mp_priv; + return -ENOMEM; } pmp_priv->pmp_xmtframe_buf = pmp_priv->pallocated_mp_xmitframe_buf + 4 - @@ -62,9 +61,7 @@ static int init_mp_priv(struct mp_priv *pmp_priv) pmp_xmitframe++; } pmp_priv->free_mp_xmitframe_cnt = NR_MP_XMITFRAME; - res = _SUCCESS; -_exit_init_mp_priv: - return res; + return 0; } static int free_mp_priv(struct mp_priv *pmp_priv) diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c index 2beafc7742b3..23cff43437e2 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c @@ -184,19 +184,19 @@ void r8712_init_pwrctrl_priv(struct _adapter *padapter) * will raise the cpwm to be greater than or equal to P2. * Calling Context: Passive * Return Value: - * _SUCCESS: r8712_cmd_thread can issue cmds to firmware afterwards. - * _FAIL: r8712_cmd_thread can not do anything. + * 0: r8712_cmd_thread can issue cmds to firmware afterwards. + * -EINVAL: r8712_cmd_thread can not do anything. */ -sint r8712_register_cmd_alive(struct _adapter *padapter) +int r8712_register_cmd_alive(struct _adapter *padapter) { - uint res = _SUCCESS; + int res = 0; struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv; mutex_lock(&pwrctrl->mutex_lock); register_task_alive(pwrctrl, CMD_ALIVE); if (pwrctrl->cpwm < PS_STATE_S2) { r8712_set_rpwm(padapter, PS_STATE_S3); - res = _FAIL; + res = -EINVAL; } mutex_unlock(&pwrctrl->mutex_lock); return res; diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h index 11b5034f203d..dd5a79f90b1a 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.h @@ -104,7 +104,7 @@ struct pwrctrl_priv { }; void r8712_init_pwrctrl_priv(struct _adapter *adapter); -sint r8712_register_cmd_alive(struct _adapter *padapter); +int r8712_register_cmd_alive(struct _adapter *padapter); void r8712_unregister_cmd_alive(struct _adapter *padapter); void r8712_cpwm_int_hdl(struct _adapter *padapter, struct reportpwrstate_parm *preportpwrstate); diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 5298fe603437..e5092b6da4bd 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -48,7 +48,7 @@ void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv) _init_queue(&psta_recvpriv->defrag_q); } -sint _r8712_init_recv_priv(struct recv_priv *precvpriv, +void _r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) { sint i; @@ -64,7 +64,7 @@ sint _r8712_init_recv_priv(struct recv_priv *precvpriv, sizeof(union recv_frame) + RXFRAME_ALIGN_SZ, GFP_ATOMIC); if (precvpriv->pallocated_frame_buf == NULL) - return _FAIL; + return; kmemleak_not_leak(precvpriv->pallocated_frame_buf); precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ - @@ -80,7 +80,7 @@ sint _r8712_init_recv_priv(struct recv_priv *precvpriv, precvframe++; } precvpriv->rx_pending_cnt = 1; - return r8712_init_recv_priv(precvpriv, padapter); + r8712_init_recv_priv(precvpriv, padapter); } void _r8712_free_recv_priv(struct recv_priv *precvpriv) @@ -245,8 +245,7 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, if (auth_alg == 2) { /* get ether_type */ ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE; - memcpy(ðer_type, ptr, 2); - be16_to_cpus(ðer_type); + ether_type = get_unaligned_be16(ptr); if ((psta != NULL) && (psta->ieee8021x_blocked)) { /* blocked @@ -586,7 +585,7 @@ sint r8712_validate_recv_frame(struct _adapter *adapter, return retval; } -sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) +int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) { /*remove the wlanhdr and add the eth_hdr*/ sint rmv_len; @@ -629,14 +628,14 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + 2) - 24); if (!ptr) - return _FAIL; + return -ENOMEM; memcpy(ptr, get_rxmem(precvframe), 24); ptr += 24; } else { ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0))); if (!ptr) - return _FAIL; + return -ENOMEM; } memcpy(ptr, pattrib->dst, ETH_ALEN); @@ -646,10 +645,10 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) memcpy(ptr + 12, &be_tmp, 2); } - return _SUCCESS; + return 0; } -s32 r8712_recv_entry(union recv_frame *precvframe) +void r8712_recv_entry(union recv_frame *precvframe) { struct _adapter *padapter; struct recv_priv *precvpriv; @@ -667,9 +666,8 @@ s32 r8712_recv_entry(union recv_frame *precvframe) precvpriv->rx_pkts++; precvpriv->rx_bytes += (uint)(precvframe->u.hdr.rx_tail - precvframe->u.hdr.rx_data); - return ret; + return; _recv_entry_drop: precvpriv->rx_drop++; padapter->mppriv.rx_pktloss = precvpriv->rx_drop; - return ret; } diff --git a/drivers/staging/rtl8712/rtl871x_recv.h b/drivers/staging/rtl8712/rtl871x_recv.h index f87b2ff5de1c..0146a774e19d 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.h +++ b/drivers/staging/rtl8712/rtl871x_recv.h @@ -128,7 +128,7 @@ struct sta_recv_priv { /* get a free recv_frame from pfree_recv_queue */ union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue); -int r8712_free_recvframe(union recv_frame *precvframe, +void r8712_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue); void r8712_free_recvframe_queue(struct __queue *pframequeue, struct __queue *pfree_recv_queue); diff --git a/drivers/staging/rtl8712/rtl871x_rf.h b/drivers/staging/rtl8712/rtl871x_rf.h index cc54453cd424..7d98921a48fa 100644 --- a/drivers/staging/rtl8712/rtl871x_rf.h +++ b/drivers/staging/rtl8712/rtl871x_rf.h @@ -52,5 +52,4 @@ enum { RTL8712_RFC_2T2R = 0x22 }; -#endif /*_RTL8711_RF_H_*/ - +#endif /*__RTL871X_RF_H_*/ diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c index 693008bba83e..73e3d5ef3af2 100644 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ b/drivers/staging/rtl8712/rtl871x_security.c @@ -636,7 +636,7 @@ u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe) } /* The hlen doesn't include the IV */ -u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) +void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) { /* exclude ICV */ u16 pnl; u32 pnh; @@ -670,7 +670,7 @@ u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) prwskey = &psecuritypriv->XGrpKey[ ((idx >> 6) & 0x3) - 1].skey[0]; if (!psecuritypriv->binstallGrpkey) - return _FAIL; + return; } else { prwskey = &stainfo->x_UncstKey.skey[0]; } @@ -686,16 +686,8 @@ u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) arcfour_encrypt(&mycontext, payload, payload, length); *((__le32 *)crc) = cpu_to_le32(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]) - return _FAIL; - } else { - return _FAIL; } } - return _SUCCESS; } /* 3 =====AES related===== */ @@ -1019,8 +1011,8 @@ static void bitwise_xor(u8 *ina, u8 *inb, u8 *out) out[i] = ina[i] ^ inb[i]; } -static sint aes_cipher(u8 *key, uint hdrlen, - u8 *pframe, uint plen) +static void aes_cipher(u8 *key, uint hdrlen, + u8 *pframe, uint plen) { uint qc_exists, a4_exists, i, j, payload_remainder; uint num_blocks, payload_index; @@ -1140,7 +1132,6 @@ static sint aes_cipher(u8 *key, uint hdrlen, bitwise_xor(aes_out, padded_buffer, chain_buffer); for (j = 0; j < 8; j++) pframe[payload_index++] = chain_buffer[j]; - return _SUCCESS; } u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe) @@ -1193,8 +1184,8 @@ u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe) return res; } -static sint aes_decipher(u8 *key, uint hdrlen, - u8 *pframe, uint plen) +static void aes_decipher(u8 *key, uint hdrlen, + u8 *pframe, uint plen) { static u8 message[MAX_MSG_SIZE]; uint qc_exists, a4_exists, i, j, payload_remainder; @@ -1348,10 +1339,9 @@ static sint aes_decipher(u8 *key, uint hdrlen, for (j = 0; j < 8; j++) message[payload_index++] = chain_buffer[j]; /* compare the mic */ - return _SUCCESS; } -u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) +void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) { /* exclude ICV */ /* Intermediate Buffers */ sint length; @@ -1374,7 +1364,7 @@ u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) prwskey = &psecuritypriv->XGrpKey[ ((idx >> 6) & 0x3) - 1].skey[0]; if (!psecuritypriv->binstallGrpkey) - return _FAIL; + return; } else { prwskey = &stainfo->x_UncstKey.skey[0]; @@ -1384,11 +1374,8 @@ u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) prxattrib->iv_len; aes_decipher(prwskey, prxattrib->hdrlen, pframe, length); - } else { - return _FAIL; } } - return _SUCCESS; } void r8712_use_tkipkey_handler(struct timer_list *t) diff --git a/drivers/staging/rtl8712/rtl871x_security.h b/drivers/staging/rtl8712/rtl871x_security.h index 25b4d379766d..b2dda16cbd0a 100644 --- a/drivers/staging/rtl8712/rtl871x_security.h +++ b/drivers/staging/rtl8712/rtl871x_security.h @@ -209,8 +209,8 @@ void r8712_secgetmic(struct mic_data *pmicdata, u8 *dst); u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe); u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe); void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe); -u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe); -u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe); +void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe); +void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_use_tkipkey_handler(struct timer_list *t); diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 0a26d71e5340..cc5809e49e35 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -49,8 +49,8 @@ void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv) INIT_LIST_HEAD(&psta_xmitpriv->apsd); } -sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, - struct _adapter *padapter) +int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, + struct _adapter *padapter) { sint i; struct xmit_buf *pxmitbuf; @@ -79,7 +79,7 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, kmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4, GFP_ATOMIC); if (!pxmitpriv->pallocated_frame_buf) { pxmitpriv->pxmit_frame_buf = NULL; - return _FAIL; + return -ENOMEM; } pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 - ((addr_t) (pxmitpriv->pallocated_frame_buf) & 3); @@ -119,7 +119,7 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, if (!pxmitpriv->pallocated_xmitbuf) { kfree(pxmitpriv->pallocated_frame_buf); pxmitpriv->pallocated_frame_buf = NULL; - return _FAIL; + return -ENOMEM; } pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - ((addr_t)(pxmitpriv->pallocated_xmitbuf) & 3); @@ -129,12 +129,12 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, pxmitbuf->pallocated_buf = kmalloc(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ, GFP_ATOMIC); if (!pxmitbuf->pallocated_buf) - return _FAIL; + return -ENOMEM; pxmitbuf->pbuf = pxmitbuf->pallocated_buf + XMITBUF_ALIGN_SZ - ((addr_t) (pxmitbuf->pallocated_buf) & (XMITBUF_ALIGN_SZ - 1)); if (r8712_xmit_resource_alloc(padapter, pxmitbuf)) - return _FAIL; + return -ENOMEM; list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue)); pxmitbuf++; @@ -146,7 +146,7 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, tasklet_init(&pxmitpriv->xmit_tasklet, (void(*)(unsigned long))r8712_xmit_bh, (unsigned long)padapter); - return _SUCCESS; + return 0; } void _free_xmit_priv(struct xmit_priv *pxmitpriv) @@ -173,8 +173,8 @@ void _free_xmit_priv(struct xmit_priv *pxmitpriv) free_hwxmits(padapter); } -sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, - struct pkt_attrib *pattrib) +int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, + struct pkt_attrib *pattrib) { struct pkt_file pktfile; struct sta_info *psta = NULL; @@ -224,7 +224,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { /*firstly, filter packet not belongs to mp*/ if (pattrib->ether_type != 0x8712) - return _FAIL; + return -EINVAL; /* for mp storing the txcmd per packet, * according to the info of txcmd to update pattrib */ @@ -271,7 +271,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, } else { psta = r8712_get_stainfo(pstapriv, pattrib->ra); if (psta == NULL) /* drop the pkt */ - return _FAIL; + return -ENOMEM; if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) pattrib->mac_id = 5; else @@ -283,7 +283,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, pattrib->psta = psta; } else { /* if we cannot get psta => drrp the pkt */ - return _FAIL; + return -ENOMEM; } pattrib->ack_policy = 0; @@ -301,7 +301,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, pattrib->encrypt = 0; if ((pattrib->ether_type != 0x888e) && !check_fwstate(pmlmepriv, WIFI_MP_STATE)) - return _FAIL; + return -EINVAL; } else { GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast); } @@ -315,7 +315,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, pattrib->iv_len = 8; pattrib->icv_len = 4; if (padapter->securitypriv.busetkipkey == _FAIL) - return _FAIL; + return -EINVAL; break; case _AES_: pattrib->iv_len = 8; @@ -339,11 +339,11 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) pattrib->priority = (le32_to_cpu(txdesc.txdw1) >> QSEL_SHT) & 0x1f; - return _SUCCESS; + return 0; } -static sint xmitframe_addmic(struct _adapter *padapter, - struct xmit_frame *pxmitframe) +static int xmitframe_addmic(struct _adapter *padapter, + struct xmit_frame *pxmitframe) { u32 curfragnum, length; u8 *pframe, *payload, mic[8]; @@ -372,7 +372,7 @@ static sint xmitframe_addmic(struct _adapter *padapter, if (!memcmp(psecuritypriv->XGrptxmickey [psecuritypriv->XGrpKeyid].skey, null_key, 16)) - return _FAIL; + return -ENOMEM; /*start to calculate the mic code*/ r8712_secmicsetkey(&micdata, psecuritypriv-> @@ -381,7 +381,7 @@ static sint xmitframe_addmic(struct _adapter *padapter, } else { if (!memcmp(&stainfo->tkiptxmickey.skey[0], null_key, 16)) - return _FAIL; + return -ENOMEM; /* start to calculate the mic code */ r8712_secmicsetkey(&micdata, &stainfo->tkiptxmickey.skey[0]); @@ -442,7 +442,7 @@ static sint xmitframe_addmic(struct _adapter *padapter, payload = payload - pattrib->last_txcmdsz + 8; } } - return _SUCCESS; + return 0; } static sint xmitframe_swencrypt(struct _adapter *padapter, @@ -469,8 +469,8 @@ static sint xmitframe_swencrypt(struct _adapter *padapter, return _SUCCESS; } -static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, - struct pkt_attrib *pattrib) +static int make_wlanhdr(struct _adapter *padapter, u8 *hdr, + struct pkt_attrib *pattrib) { u16 *qc; @@ -509,7 +509,7 @@ static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN); } else { - return _FAIL; + return -EINVAL; } if (pattrib->encrypt) @@ -547,7 +547,7 @@ static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, } } } - return _SUCCESS; + return 0; } static sint r8712_put_snap(u8 *data, u16 h_proto) @@ -605,7 +605,7 @@ sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, pbuf_start = pxmitframe->buf_addr; ptxdesc = pbuf_start; mem_start = pbuf_start + TXDESC_OFFSET; - if (make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) + if (make_wlanhdr(padapter, mem_start, pattrib)) return _FAIL; _r8712_open_pktfile(pkt, &pktfile); _r8712_pktfile_read(&pktfile, NULL, (uint) pattrib->pkt_hdrlen); @@ -696,7 +696,7 @@ sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, memcpy(mem_start, pbuf_start + TXDESC_OFFSET, pattrib->hdrlen); } - if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) + if (xmitframe_addmic(padapter, pxmitframe)) return _FAIL; xmitframe_swencrypt(padapter, pxmitframe); return _SUCCESS; @@ -753,19 +753,18 @@ struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv) return pxmitbuf; } -int r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) +void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) { unsigned long irqL; struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; if (pxmitbuf == NULL) - return _FAIL; + return; spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); list_del_init(&pxmitbuf->list); list_add_tail(&(pxmitbuf->list), &pfree_xmitbuf_queue->queue); pxmitpriv->free_xmitbuf_cnt++; spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - return _SUCCESS; } /* @@ -894,8 +893,8 @@ static inline struct tx_servq *get_sta_pending(struct _adapter *padapter, * Will enqueue pxmitframe to the proper queue, and indicate it * to xx_pending list..... */ -sint r8712_xmit_classifier(struct _adapter *padapter, - struct xmit_frame *pxmitframe) +int r8712_xmit_classifier(struct _adapter *padapter, + struct xmit_frame *pxmitframe) { unsigned long irqL0; struct __queue *pstapending; @@ -920,7 +919,7 @@ sint r8712_xmit_classifier(struct _adapter *padapter, } } if (psta == NULL) - return _FAIL; + return -EINVAL; ptxservq = get_sta_pending(padapter, &pstapending, psta, pattrib->priority); spin_lock_irqsave(&pstapending->lock, irqL0); @@ -929,7 +928,7 @@ sint r8712_xmit_classifier(struct _adapter *padapter, list_add_tail(&pxmitframe->list, &ptxservq->sta_pending.queue); ptxservq->qcnt++; spin_unlock_irqrestore(&pstapending->lock, irqL0); - return _SUCCESS; + return 0; } static void alloc_hwxmits(struct _adapter *padapter) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index 4199cb586fb1..b14da38bf652 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -41,7 +41,7 @@ do { \ pattrib_iv[0] = txpn._byte_.TSC0;\ pattrib_iv[1] = txpn._byte_.TSC1;\ pattrib_iv[2] = txpn._byte_.TSC2;\ - pattrib_iv[3] = ((keyidx & 0x3)<<6);\ + pattrib_iv[3] = ((keyidx & 0x3) << 6);\ txpn.val = (txpn.val == 0xffffff) ? 0 : (txpn.val+1);\ } while (0) @@ -249,8 +249,8 @@ struct xmit_priv { uint free_xmitbuf_cnt; }; -int r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf); +void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, + struct xmit_buf *pxmitbuf); struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv); void r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len); struct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv); @@ -258,25 +258,25 @@ void r8712_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe); void r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pframequeue); -sint r8712_xmit_classifier(struct _adapter *padapter, - struct xmit_frame *pxmitframe); +int r8712_xmit_classifier(struct _adapter *padapter, + struct xmit_frame *pxmitframe); sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe); sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag); void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv); -sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, - struct pkt_attrib *pattrib); +int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, + struct pkt_attrib *pattrib); int r8712_txframes_sta_ac_pending(struct _adapter *padapter, struct pkt_attrib *pattrib); -sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, - struct _adapter *padapter); +int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, + struct _adapter *padapter); void _free_xmit_priv(struct xmit_priv *pxmitpriv); void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe); int r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe); int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe); -int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe); +void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe); void r8712_xmit_bh(void *priv); void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe, diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index d0daae0b8299..ba1288297ee4 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -389,7 +389,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, } /* step 4. */ status = r8712_init_drv_sw(padapter); - if (status == _FAIL) + if (status) goto error; /* step 5. read efuse/eeprom data and get mac_addr */ { diff --git a/drivers/staging/rtl8712/usb_osintf.h b/drivers/staging/rtl8712/usb_osintf.h index ddfa405d0c9b..2e512b4a564c 100644 --- a/drivers/staging/rtl8712/usb_osintf.h +++ b/drivers/staging/rtl8712/usb_osintf.h @@ -28,8 +28,8 @@ void rtl871x_intf_stop(struct _adapter *padapter); void r871x_dev_unload(struct _adapter *padapter); void r8712_stop_drv_threads(struct _adapter *padapter); void r8712_stop_drv_timers(struct _adapter *padapter); -u8 r8712_init_drv_sw(struct _adapter *padapter); -u8 r8712_free_drv_sw(struct _adapter *padapter); +int r8712_init_drv_sw(struct _adapter *padapter); +void r8712_free_drv_sw(struct _adapter *padapter); struct net_device *r8712_init_netdev(void); #endif diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h index 1a5b966a167e..be731f1a2209 100644 --- a/drivers/staging/rtl8712/wifi.h +++ b/drivers/staging/rtl8712/wifi.h @@ -300,7 +300,6 @@ static inline unsigned char *get_da(unsigned char *pframe) return da; } - static inline unsigned char *get_sa(unsigned char *pframe) { unsigned char *sa; @@ -346,8 +345,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) return sa; } - - /*----------------------------------------------------------------------------- * Below is for the security related definition *----------------------------------------------------------------------------- @@ -392,7 +389,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) #define _RESERVED47_ 47 - /* --------------------------------------------------------------------------- * Below is the fixed elements... * --------------------------------------------------------------------------- @@ -436,7 +432,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) #define _WMM_IE_Length_ 7 /* for WMM STA */ #define _WMM_Para_Element_Length_ 24 - /*----------------------------------------------------------------------------- * Below is the definition for 802.11n *------------------------------------------------------------------------------ @@ -456,7 +451,6 @@ 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 * @@ -476,7 +470,6 @@ struct ieee80211_bar { #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 - /* * struct ieee80211_ht_cap - HT capabilities * @@ -552,7 +545,6 @@ struct ieee80211_ht_addt_info { */ #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 diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c index 01d713d027b0..1f67d86c606f 100644 --- a/drivers/staging/rtl8712/xmit_linux.c +++ b/drivers/staging/rtl8712/xmit_linux.c @@ -160,7 +160,7 @@ int r8712_xmit_entry(_pkt *pkt, struct net_device *netdev) if (!xmitframe) goto _xmit_entry_drop; - if ((!r8712_update_attrib(adapter, pkt, &xmitframe->attrib))) + if (r8712_update_attrib(adapter, pkt, &xmitframe->attrib)) goto _xmit_entry_drop; adapter->ledpriv.LedControlHandler(adapter, LED_CTL_TX); diff --git a/drivers/staging/rtl8723bs/Makefile b/drivers/staging/rtl8723bs/Makefile index a12cf8dd8ed9..dfe410283ca0 100644 --- a/drivers/staging/rtl8723bs/Makefile +++ b/drivers/staging/rtl8723bs/Makefile @@ -60,7 +60,6 @@ r8723bs-y = \ os_dep/osdep_service.o \ os_dep/os_intfs.o \ os_dep/recv_linux.o \ - os_dep/rtw_proc.o \ os_dep/sdio_intf.o \ os_dep/sdio_ops_linux.o \ os_dep/wifi_regd.o \ diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index 7bd5c61b055c..6d18d23acdc0 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c @@ -13,11 +13,10 @@ extern unsigned char RTW_WPA_OUI[]; extern unsigned char WMM_OUI[]; extern unsigned char WPS_OUI[]; extern unsigned char P2P_OUI[]; -extern unsigned char WFD_OUI[]; void init_mlme_ap_info(struct adapter *padapter) { - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct sta_priv *pstapriv = &padapter->stapriv; struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; @@ -34,9 +33,9 @@ void init_mlme_ap_info(struct adapter *padapter) void free_mlme_ap_info(struct adapter *padapter) { struct sta_info *psta = NULL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; /* stop_ap_mode(padapter); */ @@ -58,9 +57,9 @@ void free_mlme_ap_info(struct adapter *padapter) static void update_BCNTIM(struct adapter *padapter) { struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct wlan_bssid_ex *pnetwork_mlmeext = &(pmlmeinfo->network); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; + struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; unsigned char *pie = pnetwork_mlmeext->IEs; /* DBG_871X("%s\n", __func__); */ @@ -83,7 +82,7 @@ static void update_BCNTIM(struct adapter *padapter) if (p != NULL && tim_ielen > 0) { tim_ielen += 2; - premainder_ie = p+tim_ielen; + premainder_ie = p + tim_ielen; tim_ie_offset = (sint)(p - pie); @@ -94,7 +93,7 @@ static void update_BCNTIM(struct adapter *padapter) } else { tim_ielen = 0; - /* calucate head_len */ + /* calculate head_len */ offset = _FIXED_IE_LENGTH_; /* get ssid_ie len */ @@ -105,7 +104,7 @@ static void update_BCNTIM(struct adapter *padapter) (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_) ); if (p != NULL) - offset += tmp_len+2; + offset += tmp_len + 2; /* get supported rates len */ p = rtw_get_ie( @@ -114,7 +113,7 @@ static void update_BCNTIM(struct adapter *padapter) (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_) ); if (p != NULL) - offset += tmp_len+2; + offset += tmp_len + 2; /* DS Parameter Set IE, len =3 */ offset += 3; @@ -135,7 +134,7 @@ static void update_BCNTIM(struct adapter *padapter) *dst_ie++ = _TIM_IE_; - if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fe)) + if ((pstapriv->tim_bitmap & 0xff00) && (pstapriv->tim_bitmap & 0x00fe)) tim_ielen = 5; else tim_ielen = 4; @@ -143,9 +142,9 @@ static void update_BCNTIM(struct adapter *padapter) *dst_ie++ = tim_ielen; *dst_ie++ = 0;/* DTIM count */ - *dst_ie++ = 1;/* DTIM peroid */ + *dst_ie++ = 1;/* DTIM period */ - if (pstapriv->tim_bitmap&BIT(0))/* for bc/mc frames */ + if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */ *dst_ie++ = BIT(0);/* bitmap ctrl */ else *dst_ie++ = 0; @@ -153,7 +152,7 @@ static void update_BCNTIM(struct adapter *padapter) if (tim_ielen == 4) { __le16 pvb; - if (pstapriv->tim_bitmap&0xff00) + if (pstapriv->tim_bitmap & 0xff00) pvb = cpu_to_le16(pstapriv->tim_bitmap >> 8); else pvb = tim_bitmap_le; @@ -188,8 +187,8 @@ u8 chk_sta_is_alive(struct sta_info *psta) /* STA_RX_PKTS_ARG(psta) */ , STA_RX_PKTS_DIFF_ARG(psta) , psta->expire_to - , psta->state&WIFI_SLEEP_STATE?"PS, ":"" - , psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":"" + , psta->state & WIFI_SLEEP_STATE ? "PS, " : "" + , psta->state & WIFI_STA_ALIVE_CHK_STATE ? "SAC, " : "" , psta->sleepq_len ); #endif @@ -292,7 +291,7 @@ void expire_timeout_chk(struct adapter *padapter) if (psta->state & WIFI_SLEEP_STATE) { if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { - /* to check if alive by another methods if staion is at ps mode. */ + /* to check if alive by another methods if station is at ps mode. */ psta->expire_to = pstapriv->expire_to; psta->state |= WIFI_STA_ALIVE_CHK_STATE; @@ -325,10 +324,10 @@ void expire_timeout_chk(struct adapter *padapter) updated = ap_free_sta(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING); } else { /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */ - if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt) + if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) && padapter->xmitpriv.free_xmitframe_cnt < (( - NR_XMITFRAME/pstapriv->asoc_list_cnt - )/2) + NR_XMITFRAME / pstapriv->asoc_list_cnt + ) / 2) ) { DBG_871X( "%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", @@ -586,8 +585,8 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; phtpriv_sta->rx_ampdu_min_spacing = ( - phtpriv_sta->ht_cap.ampdu_params_info&IEEE80211_HT_CAP_AMPDU_DENSITY - )>>2; + phtpriv_sta->ht_cap.ampdu_params_info & IEEE80211_HT_CAP_AMPDU_DENSITY + ) >> 2; /* bwmode */ if (( @@ -782,8 +781,8 @@ void start_bss_network(struct adapter *padapter, u8 *pbuf) /* check if there is wps ie, */ /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */ /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */ - if (!rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, - pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL)) + if (!rtw_get_wps_ie(pnetwork->IEs + _FIXED_IE_LENGTH_, + pnetwork->IELength - _FIXED_IE_LENGTH_, NULL, NULL)) pmlmeext->bstart_bss = true; /* todo: update wmm, ht cap */ @@ -861,7 +860,7 @@ void start_bss_network(struct adapter *padapter, u8 *pbuf) (pnetwork->IELength - sizeof(struct ndis_802_11_fix_ie)) ); if (p && ie_len) { - pht_info = (struct HT_info_element *)(p+2); + pht_info = (struct HT_info_element *)(p + 2); if (cur_channel > 14) { if ((pregpriv->bw_mode & 0xf0) > 0) @@ -916,7 +915,7 @@ void start_bss_network(struct adapter *padapter, u8 *pbuf) UpdateBrateTbl(padapter, pnetwork->SupportedRates); rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates); - /* udpate capability after cur_wireless_mode updated */ + /* update capability after cur_wireless_mode updated */ update_capinfo( padapter, rtw_get_capability((struct wlan_bssid_ex *)pnetwork) @@ -1015,7 +1014,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pbss_network->Ssid.SsidLength = ie_len; } - /* chnnel */ + /* channel */ channel = 0; pbss_network->Configuration.Length = 0; p = rtw_get_ie( @@ -1037,7 +1036,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) (pbss_network->IELength - _BEACON_IE_OFFSET_) ); if (p != NULL) { - memcpy(supportRate, p+2, ie_len); + memcpy(supportRate, p + 2, ie_len); supportRateNum = ie_len; } @@ -1049,7 +1048,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pbss_network->IELength - _BEACON_IE_OFFSET_ ); if (p != NULL) { - memcpy(supportRate+supportRateNum, p+2, ie_len); + memcpy(supportRate + supportRateNum, p + 2, ie_len); supportRateNum += ie_len; } @@ -1088,7 +1087,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) if (p && ie_len > 0) { if (rtw_parse_wpa2_ie( p, - ie_len+2, + ie_len + 2, &group_cipher, &pairwise_cipher, NULL @@ -1115,10 +1114,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)) ); - if ((p) && (!memcmp(p+2, OUI1, 4))) { + if ((p) && (!memcmp(p + 2, OUI1, 4))) { if (rtw_parse_wpa_ie( p, - ie_len+2, + ie_len + 2, &group_cipher, &pairwise_cipher, NULL @@ -1151,10 +1150,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)) ); - if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) { + if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) { pmlmepriv->qospriv.qos_option = 1; - *(p+8) |= BIT(7);/* QoS Info, support U-APSD */ + *(p + 8) |= BIT(7);/* QoS Info, support U-APSD */ /* disable all ACM bits since the WMM admission control is not supported */ *(p + 10) &= ~BIT(4); /* BE */ @@ -1180,7 +1179,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) if (p && ie_len > 0) { u8 rf_type = 0; u8 max_rx_ampdu_factor = 0; - struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2); + struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2); pHT_caps_ie = p; @@ -1205,14 +1204,14 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_RX_STBC_3R)); pht_cap->ampdu_params_info &= ~( - IEEE80211_HT_CAP_AMPDU_FACTOR|IEEE80211_HT_CAP_AMPDU_DENSITY + IEEE80211_HT_CAP_AMPDU_FACTOR | IEEE80211_HT_CAP_AMPDU_DENSITY ); 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_CAP_AMPDU_DENSITY & (0x07 << 2)); } else { - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00); + pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00); } rtw_hal_get_def_var( @@ -1230,7 +1229,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pht_cap->supp_mcs_set[1] = 0x0; } - memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len); + memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len); } /* parsing HT_INFO_IE */ @@ -1265,8 +1264,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pmlmepriv->htpriv.ht_option = false; - if ((psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) || - (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP)) { + if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) || + (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) { /* todo: */ /* ht_cap = false; */ } @@ -1341,7 +1340,7 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) MAC_ARG(addr) ); - if ((NUM_ACL-1) < pacl_list->num) + if ((NUM_ACL - 1) < pacl_list->num) return (-1); spin_lock_bh(&(pacl_node_q->lock)); @@ -1454,7 +1453,7 @@ u8 rtw_ap_set_pairwise_key(struct adapter *padapter, struct sta_info *psta) psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); if (psetstakey_para == NULL) { - kfree((u8 *) ph2c); + kfree((u8 *)ph2c); res = _FAIL; goto exit; } @@ -1604,10 +1603,10 @@ static void update_bcn_erpinfo_ie(struct adapter *padapter) struct ndis_80211_var_ie *pIE = (struct ndis_80211_var_ie *)p; if (pmlmepriv->num_sta_non_erp == 1) - pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION; + pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION; else pIE->data[0] &= ~( - RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION + RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION ); if (pmlmepriv->num_sta_no_short_preamble > 0) @@ -1662,8 +1661,8 @@ static void update_bcn_wps_ie(struct adapter *padapter) DBG_871X("%s\n", __func__); pwps_ie = rtw_get_wps_ie( - ie+_FIXED_IE_LENGTH_, - ielen-_FIXED_IE_LENGTH_, + ie + _FIXED_IE_LENGTH_, + ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen ); @@ -1675,7 +1674,7 @@ static void update_bcn_wps_ie(struct adapter *padapter) if (pwps_ie_src == NULL) return; - wps_offset = (uint)(pwps_ie-ie); + wps_offset = (uint)(pwps_ie - ie); premainder_ie = pwps_ie + wps_ielen; @@ -1688,22 +1687,22 @@ static void update_bcn_wps_ie(struct adapter *padapter) } wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */ - if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) { - memcpy(pwps_ie, pwps_ie_src, wps_ielen+2); + if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) { + memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2); pwps_ie += (wps_ielen+2); if (pbackup_remainder_ie) memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen); /* update IELength */ - pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen; + pnetwork->IELength = wps_offset + (wps_ielen + 2) + remainder_ielen; } kfree(pbackup_remainder_ie); /* deal with the case without set_tx_beacon_cmd() in update_beacon() */ #if defined(CONFIG_INTERRUPT_BASED_TXBCN) - if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { + if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { u8 sr = 0; rtw_get_wps_attr_content( @@ -1827,7 +1826,7 @@ void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx) /* op_mode -Set to 0 (HT pure) under the followign conditions +Set to 0 (HT pure) under the following conditions - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - all STAs in the BSS are 20 MHz HT in 20 MHz BSS Set to 1 (HT non-member protection) if there may be non-HT STAs @@ -2196,7 +2195,7 @@ void rtw_sta_flush(struct adapter *padapter) DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); - if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) + if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) return; spin_lock_bh(&pstapriv->asoc_list_lock); @@ -2230,7 +2229,7 @@ void sta_info_update(struct adapter *padapter, struct sta_info *psta) struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); /* update wmm cap. */ - if (WLAN_STA_WME&flags) + if (WLAN_STA_WME & flags) psta->qos_option = 1; else psta->qos_option = 0; @@ -2239,7 +2238,7 @@ void sta_info_update(struct adapter *padapter, struct sta_info *psta) psta->qos_option = 0; /* update 802.11n ht cap. */ - if (WLAN_STA_HT&flags) { + if (WLAN_STA_HT & flags) { psta->htpriv.ht_option = true; psta->qos_option = 1; } else { diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c index addc55706a3c..8d93c2f26890 100644 --- a/drivers/staging/rtl8723bs/core/rtw_cmd.c +++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c @@ -402,7 +402,7 @@ int rtw_cmd_thread(void *context) { u8 ret; struct cmd_obj *pcmd; - u8 *pcmdbuf, *prspbuf; + u8 *pcmdbuf; unsigned long cmd_start_time; unsigned long cmd_process_time; u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf); @@ -414,7 +414,6 @@ int rtw_cmd_thread(void *context) thread_enter("RTW_CMD_THREAD"); pcmdbuf = pcmdpriv->cmd_buf; - prspbuf = pcmdpriv->rsp_buf; pcmdpriv->stop_req = 0; atomic_set(&(pcmdpriv->cmdthd_running), true); @@ -768,7 +767,7 @@ exit: u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) { - u8 *auth, res = _SUCCESS; + u8 res = _SUCCESS; uint t_len = 0; struct wlan_bssid_ex *psecnetwork; struct cmd_obj *pcmd; @@ -825,7 +824,6 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network)); - auth = &psecuritypriv->authenticator_ie[0]; psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength; if ((psecnetwork->IELength-12) < (256-1)) { @@ -1819,11 +1817,6 @@ static void rtw_btinfo_hdl(struct adapter *adapter, u8 *buf, u16 buf_len) len = info->len; } -/* define DBG_PROC_SET_BTINFO_EVT */ -#ifdef DBG_PROC_SET_BTINFO_EVT - btinfo_evt_dump(RTW_DBGDUMP, info); -#endif - /* transform BT-FW btinfo to WiFI-FW C2H format and notify */ if (cmd_idx == BTINFO_WIFI_FETCH) buf[1] = 0; diff --git a/drivers/staging/rtl8723bs/core/rtw_debug.c b/drivers/staging/rtl8723bs/core/rtw_debug.c index 695a85999270..c48a8b80af4c 100644 --- a/drivers/staging/rtl8723bs/core/rtw_debug.c +++ b/drivers/staging/rtl8723bs/core/rtw_debug.c @@ -132,1310 +132,3 @@ void rf_reg_dump(void *sel, struct adapter *adapter) } } } - -#ifdef PROC_DEBUG -ssize_t proc_set_write_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u32 addr, val, len; - - if (count < 3) { - DBG_871X("argument size is less than 3\n"); - return -EFAULT; - } - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%x %x %x", &addr, &val, &len); - - if (num != 3) { - DBG_871X("invalid write_reg parameter!\n"); - return count; - } - - switch (len) { - case 1: - rtw_write8(padapter, addr, (u8)val); - break; - case 2: - rtw_write16(padapter, addr, (u16)val); - break; - case 4: - rtw_write32(padapter, addr, val); - break; - default: - DBG_871X("error write length =%d", len); - break; - } - - } - - return count; - -} - -static u32 proc_get_read_addr = 0xeeeeeeee; -static u32 proc_get_read_len = 0x4; - -int proc_get_read_reg(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - if (proc_get_read_addr == 0xeeeeeeee) { - DBG_871X_SEL_NL(m, "address not initialized\n"); - return 0; - } - - switch (proc_get_read_len) { - case 1: - DBG_871X_SEL_NL(m, "rtw_read8(0x%x) = 0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr)); - break; - case 2: - DBG_871X_SEL_NL(m, "rtw_read16(0x%x) = 0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr)); - break; - case 4: - DBG_871X_SEL_NL(m, "rtw_read32(0x%x) = 0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr)); - break; - default: - DBG_871X_SEL_NL(m, "error read length =%d\n", proc_get_read_len); - break; - } - - return 0; -} - -ssize_t proc_set_read_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - char tmp[16]; - u32 addr, len; - - if (count < 2) { - DBG_871X("argument size is less than 2\n"); - return -EFAULT; - } - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%x %x", &addr, &len); - - if (num != 2) { - DBG_871X("invalid read_reg parameter!\n"); - return count; - } - - proc_get_read_addr = addr; - - proc_get_read_len = len; - } - - return count; - -} - -int proc_get_fwstate(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - DBG_871X_SEL_NL(m, "fwstate = 0x%x\n", get_fwstate(pmlmepriv)); - - return 0; -} - -int proc_get_sec_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct security_priv *sec = &padapter->securitypriv; - - DBG_871X_SEL_NL(m, "auth_alg = 0x%x, enc_alg = 0x%x, auth_type = 0x%x, enc_type = 0x%x\n", - sec->dot11AuthAlgrthm, sec->dot11PrivacyAlgrthm, - sec->ndisauthtype, sec->ndisencryptstatus); - - DBG_871X_SEL_NL(m, "hw_decrypted =%d\n", sec->hw_decrypted); - -#ifdef DBG_SW_SEC_CNT - DBG_871X_SEL_NL(m, "wep_sw_enc_cnt =%llu, %llu, %llu\n" - , sec->wep_sw_enc_cnt_bc, sec->wep_sw_enc_cnt_mc, sec->wep_sw_enc_cnt_uc); - DBG_871X_SEL_NL(m, "wep_sw_dec_cnt =%llu, %llu, %llu\n" - , sec->wep_sw_dec_cnt_bc, sec->wep_sw_dec_cnt_mc, sec->wep_sw_dec_cnt_uc); - - DBG_871X_SEL_NL(m, "tkip_sw_enc_cnt =%llu, %llu, %llu\n" - , sec->tkip_sw_enc_cnt_bc, sec->tkip_sw_enc_cnt_mc, sec->tkip_sw_enc_cnt_uc); - DBG_871X_SEL_NL(m, "tkip_sw_dec_cnt =%llu, %llu, %llu\n" - , sec->tkip_sw_dec_cnt_bc, sec->tkip_sw_dec_cnt_mc, sec->tkip_sw_dec_cnt_uc); - - DBG_871X_SEL_NL(m, "aes_sw_enc_cnt =%llu, %llu, %llu\n" - , sec->aes_sw_enc_cnt_bc, sec->aes_sw_enc_cnt_mc, sec->aes_sw_enc_cnt_uc); - DBG_871X_SEL_NL(m, "aes_sw_dec_cnt =%llu, %llu, %llu\n" - , sec->aes_sw_dec_cnt_bc, sec->aes_sw_dec_cnt_mc, sec->aes_sw_dec_cnt_uc); -#endif /* DBG_SW_SEC_CNT */ - - return 0; -} - -int proc_get_mlmext_state(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - DBG_871X_SEL_NL(m, "pmlmeinfo->state = 0x%x\n", pmlmeinfo->state); - - return 0; -} - -int proc_get_roam_flags(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - DBG_871X_SEL_NL(m, "0x%02x\n", rtw_roam_flags(adapter)); - - return 0; -} - -ssize_t proc_set_roam_flags(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - char tmp[32]; - u8 flags; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%hhx", &flags); - - if (num == 1) - rtw_assign_roam_flags(adapter, flags); - } - - return count; - -} - -int proc_get_roam_param(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *mlme = &adapter->mlmepriv; - - DBG_871X_SEL_NL(m, "%12s %12s %11s\n", "rssi_diff_th", "scanr_exp_ms", "scan_int_ms"); - DBG_871X_SEL_NL(m, "%-12u %-12u %-11u\n" - , mlme->roam_rssi_diff_th - , mlme->roam_scanr_exp_ms - , mlme->roam_scan_int_ms - ); - - return 0; -} - -ssize_t proc_set_roam_param(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *mlme = &adapter->mlmepriv; - - char tmp[32]; - u8 rssi_diff_th; - u32 scanr_exp_ms; - u32 scan_int_ms; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%hhu %u %u", &rssi_diff_th, &scanr_exp_ms, &scan_int_ms); - - if (num >= 1) - mlme->roam_rssi_diff_th = rssi_diff_th; - if (num >= 2) - mlme->roam_scanr_exp_ms = scanr_exp_ms; - if (num >= 3) - mlme->roam_scan_int_ms = scan_int_ms; - } - - return count; - -} - -ssize_t proc_set_roam_tgt_addr(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - char tmp[32]; - u8 addr[ETH_ALEN]; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", addr, addr+1, addr+2, addr+3, addr+4, addr+5); - if (num == 6) - memcpy(adapter->mlmepriv.roam_tgt_addr, addr, ETH_ALEN); - - DBG_871X("set roam_tgt_addr to "MAC_FMT"\n", MAC_ARG(adapter->mlmepriv.roam_tgt_addr)); - } - - return count; -} - -int proc_get_qos_option(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - DBG_871X_SEL_NL(m, "qos_option =%d\n", pmlmepriv->qospriv.qos_option); - - return 0; -} - -int proc_get_ht_option(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - DBG_871X_SEL_NL(m, "ht_option =%d\n", pmlmepriv->htpriv.ht_option); - - return 0; -} - -int proc_get_rf_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - DBG_871X_SEL_NL(m, "cur_ch =%d, cur_bw =%d, cur_ch_offet =%d\n", - pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); - - DBG_871X_SEL_NL(m, "oper_ch =%d, oper_bw =%d, oper_ch_offet =%d\n", - rtw_get_oper_ch(padapter), rtw_get_oper_bw(padapter), rtw_get_oper_choffset(padapter)); - - return 0; -} - -int proc_get_survey_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct __queue *queue = &(pmlmepriv->scanned_queue); - struct wlan_network *pnetwork = NULL; - struct list_head *plist, *phead; - s32 notify_signal; - s16 notify_noise = 0; - u16 index = 0; - - spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); - phead = get_list_head(queue); - plist = phead ? get_next(phead) : NULL; - if ((!phead) || (!plist)) { - spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); - return 0; - } - - DBG_871X_SEL_NL(m, "%5s %-17s %3s %-3s %-4s %-4s %5s %s\n", "index", "bssid", "ch", "RSSI", "SdBm", "Noise", "age", "ssid"); - while (1) { - if (phead == plist) - break; - - pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); - - if (!pnetwork) - break; - - if (check_fwstate(pmlmepriv, _FW_LINKED) == true && - is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) { - notify_signal = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);/*dbm*/ - } else { - notify_signal = translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);/*dbm*/ - } - - #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR) - rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &(pnetwork->network.Configuration.DSConfig), &(notify_noise)); - #endif - - DBG_871X_SEL_NL(m, "%5d "MAC_FMT" %3d %3d %4d %4d %5d %s\n", - ++index, - MAC_ARG(pnetwork->network.MacAddress), - pnetwork->network.Configuration.DSConfig, - (int)pnetwork->network.Rssi, - notify_signal, - notify_noise, - jiffies_to_msecs(jiffies - pnetwork->last_scanned), - /*translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength),*/ - pnetwork->network.Ssid.Ssid); - plist = get_next(plist); - } - spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); - - return 0; -} - -int proc_get_ap_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct sta_info *psta; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_network *cur_network = &(pmlmepriv->cur_network); - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); - if (psta) { - int i; - struct recv_reorder_ctrl *preorder_ctrl; - - DBG_871X_SEL_NL(m, "SSID =%s\n", cur_network->network.Ssid.Ssid); - DBG_871X_SEL_NL(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr)); - DBG_871X_SEL_NL(m, "cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); - DBG_871X_SEL_NL(m, "wireless_mode = 0x%x, rtsen =%d, cts2slef =%d\n", psta->wireless_mode, psta->rtsen, psta->cts2self); - DBG_871X_SEL_NL(m, "state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); - DBG_871X_SEL_NL(m, "qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); - DBG_871X_SEL_NL(m, "bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m); - DBG_871X_SEL_NL(m, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable); - DBG_871X_SEL_NL(m, "agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); - DBG_871X_SEL_NL(m, "ldpc_cap = 0x%x, stbc_cap = 0x%x, beamform_cap = 0x%x\n", psta->htpriv.ldpc_cap, psta->htpriv.stbc_cap, psta->htpriv.beamform_cap); - - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - if (preorder_ctrl->enable) { - DBG_871X_SEL_NL(m, "tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq); - } - } - - } else { - DBG_871X_SEL_NL(m, "can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress)); - } - - return 0; -} - -int proc_get_adapter_state(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - DBG_871X_SEL_NL(m, "name =%s, bSurpriseRemoved =%d, bDriverStopped =%d\n", - dev->name, padapter->bSurpriseRemoved, padapter->bDriverStopped); - - return 0; -} - -int proc_get_trx_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct recv_priv *precvpriv = &padapter->recvpriv; - struct hw_xmit *phwxmit; - - DBG_871X_SEL_NL(m, "free_xmitbuf_cnt =%d, free_xmitframe_cnt =%d\n" - , pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt); - DBG_871X_SEL_NL(m, "free_ext_xmitbuf_cnt =%d, free_xframe_ext_cnt =%d\n" - , pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xframe_ext_cnt); - DBG_871X_SEL_NL(m, "free_recvframe_cnt =%d\n" - , precvpriv->free_recvframe_cnt); - - for (i = 0; i < 4; i++) { - phwxmit = pxmitpriv->hwxmits + i; - DBG_871X_SEL_NL(m, "%d, hwq.accnt =%d\n", i, phwxmit->accnt); - } - - return 0; -} - -int proc_get_rate_ctl(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - if (adapter->fix_rate != 0xff) { - DBG_871X_SEL_NL(m, "FIX\n"); - DBG_871X_SEL_NL(m, "0x%02x\n", adapter->fix_rate); - } else { - DBG_871X_SEL_NL(m, "RA\n"); - } - - return 0; -} - -ssize_t proc_set_rate_ctl(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u8 fix_rate; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%hhx", &fix_rate); - - if (num >= 1) - adapter->fix_rate = fix_rate; - } - - return count; -} - -ssize_t proc_set_fwdl_test_case(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - char tmp[32]; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%hhu %hhu", &g_fwdl_chksum_fail, &g_fwdl_wintint_rdy_fail); - } - - return count; -} - -ssize_t proc_set_wait_hiq_empty(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - char tmp[32]; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%u", &g_wait_hiq_empty); - } - - return count; -} - -int proc_get_suspend_resume_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct dvobj_priv *dvobj = padapter->dvobj; - struct debug_priv *pdbgpriv = &dvobj->drv_dbg; - - DBG_871X_SEL_NL(m, "dbg_sdio_alloc_irq_cnt =%d\n", pdbgpriv->dbg_sdio_alloc_irq_cnt); - DBG_871X_SEL_NL(m, "dbg_sdio_free_irq_cnt =%d\n", pdbgpriv->dbg_sdio_free_irq_cnt); - DBG_871X_SEL_NL(m, "dbg_sdio_alloc_irq_error_cnt =%d\n", pdbgpriv->dbg_sdio_alloc_irq_error_cnt); - DBG_871X_SEL_NL(m, "dbg_sdio_free_irq_error_cnt =%d\n", pdbgpriv->dbg_sdio_free_irq_error_cnt); - DBG_871X_SEL_NL(m, "dbg_sdio_init_error_cnt =%d\n", pdbgpriv->dbg_sdio_init_error_cnt); - DBG_871X_SEL_NL(m, "dbg_sdio_deinit_error_cnt =%d\n", pdbgpriv->dbg_sdio_deinit_error_cnt); - DBG_871X_SEL_NL(m, "dbg_suspend_error_cnt =%d\n", pdbgpriv->dbg_suspend_error_cnt); - DBG_871X_SEL_NL(m, "dbg_suspend_cnt =%d\n", pdbgpriv->dbg_suspend_cnt); - DBG_871X_SEL_NL(m, "dbg_resume_cnt =%d\n", pdbgpriv->dbg_resume_cnt); - DBG_871X_SEL_NL(m, "dbg_resume_error_cnt =%d\n", pdbgpriv->dbg_resume_error_cnt); - DBG_871X_SEL_NL(m, "dbg_deinit_fail_cnt =%d\n", pdbgpriv->dbg_deinit_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_carddisable_cnt =%d\n", pdbgpriv->dbg_carddisable_cnt); - DBG_871X_SEL_NL(m, "dbg_ps_insuspend_cnt =%d\n", pdbgpriv->dbg_ps_insuspend_cnt); - DBG_871X_SEL_NL(m, "dbg_dev_unload_inIPS_cnt =%d\n", pdbgpriv->dbg_dev_unload_inIPS_cnt); - DBG_871X_SEL_NL(m, "dbg_scan_pwr_state_cnt =%d\n", pdbgpriv->dbg_scan_pwr_state_cnt); - DBG_871X_SEL_NL(m, "dbg_downloadfw_pwr_state_cnt =%d\n", pdbgpriv->dbg_downloadfw_pwr_state_cnt); - DBG_871X_SEL_NL(m, "dbg_carddisable_error_cnt =%d\n", pdbgpriv->dbg_carddisable_error_cnt); - DBG_871X_SEL_NL(m, "dbg_fw_read_ps_state_fail_cnt =%d\n", pdbgpriv->dbg_fw_read_ps_state_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_leave_ips_fail_cnt =%d\n", pdbgpriv->dbg_leave_ips_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_leave_lps_fail_cnt =%d\n", pdbgpriv->dbg_leave_lps_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_h2c_leave32k_fail_cnt =%d\n", pdbgpriv->dbg_h2c_leave32k_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_diswow_dload_fw_fail_cnt =%d\n", pdbgpriv->dbg_diswow_dload_fw_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_enwow_dload_fw_fail_cnt =%d\n", pdbgpriv->dbg_enwow_dload_fw_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_ips_drvopen_fail_cnt =%d\n", pdbgpriv->dbg_ips_drvopen_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_poll_fail_cnt =%d\n", pdbgpriv->dbg_poll_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_rpwm_toggle_cnt =%d\n", pdbgpriv->dbg_rpwm_toggle_cnt); - DBG_871X_SEL_NL(m, "dbg_rpwm_timeout_fail_cnt =%d\n", pdbgpriv->dbg_rpwm_timeout_fail_cnt); - - return 0; -} - -#ifdef CONFIG_DBG_COUNTER - -int proc_get_rx_logs(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct rx_logs *rx_logs = &padapter->rx_logs; - - DBG_871X_SEL_NL(m, - "intf_rx =%d\n" - "intf_rx_err_recvframe =%d\n" - "intf_rx_err_skb =%d\n" - "intf_rx_report =%d\n" - "core_rx =%d\n" - "core_rx_pre =%d\n" - "core_rx_pre_ver_err =%d\n" - "core_rx_pre_mgmt =%d\n" - "core_rx_pre_mgmt_err_80211w =%d\n" - "core_rx_pre_mgmt_err =%d\n" - "core_rx_pre_ctrl =%d\n" - "core_rx_pre_ctrl_err =%d\n" - "core_rx_pre_data =%d\n" - "core_rx_pre_data_wapi_seq_err =%d\n" - "core_rx_pre_data_wapi_key_err =%d\n" - "core_rx_pre_data_handled =%d\n" - "core_rx_pre_data_err =%d\n" - "core_rx_pre_data_unknown =%d\n" - "core_rx_pre_unknown =%d\n" - "core_rx_enqueue =%d\n" - "core_rx_dequeue =%d\n" - "core_rx_post =%d\n" - "core_rx_post_decrypt =%d\n" - "core_rx_post_decrypt_wep =%d\n" - "core_rx_post_decrypt_tkip =%d\n" - "core_rx_post_decrypt_aes =%d\n" - "core_rx_post_decrypt_wapi =%d\n" - "core_rx_post_decrypt_hw =%d\n" - "core_rx_post_decrypt_unknown =%d\n" - "core_rx_post_decrypt_err =%d\n" - "core_rx_post_defrag_err =%d\n" - "core_rx_post_portctrl_err =%d\n" - "core_rx_post_indicate =%d\n" - "core_rx_post_indicate_in_oder =%d\n" - "core_rx_post_indicate_reoder =%d\n" - "core_rx_post_indicate_err =%d\n" - "os_indicate =%d\n" - "os_indicate_ap_mcast =%d\n" - "os_indicate_ap_forward =%d\n" - "os_indicate_ap_self =%d\n" - "os_indicate_err =%d\n" - "os_netif_ok =%d\n" - "os_netif_err =%d\n", - rx_logs->intf_rx, - rx_logs->intf_rx_err_recvframe, - rx_logs->intf_rx_err_skb, - rx_logs->intf_rx_report, - rx_logs->core_rx, - rx_logs->core_rx_pre, - rx_logs->core_rx_pre_ver_err, - rx_logs->core_rx_pre_mgmt, - rx_logs->core_rx_pre_mgmt_err_80211w, - rx_logs->core_rx_pre_mgmt_err, - rx_logs->core_rx_pre_ctrl, - rx_logs->core_rx_pre_ctrl_err, - rx_logs->core_rx_pre_data, - rx_logs->core_rx_pre_data_wapi_seq_err, - rx_logs->core_rx_pre_data_wapi_key_err, - rx_logs->core_rx_pre_data_handled, - rx_logs->core_rx_pre_data_err, - rx_logs->core_rx_pre_data_unknown, - rx_logs->core_rx_pre_unknown, - rx_logs->core_rx_enqueue, - rx_logs->core_rx_dequeue, - rx_logs->core_rx_post, - rx_logs->core_rx_post_decrypt, - rx_logs->core_rx_post_decrypt_wep, - rx_logs->core_rx_post_decrypt_tkip, - rx_logs->core_rx_post_decrypt_aes, - rx_logs->core_rx_post_decrypt_wapi, - rx_logs->core_rx_post_decrypt_hw, - rx_logs->core_rx_post_decrypt_unknown, - rx_logs->core_rx_post_decrypt_err, - rx_logs->core_rx_post_defrag_err, - rx_logs->core_rx_post_portctrl_err, - rx_logs->core_rx_post_indicate, - rx_logs->core_rx_post_indicate_in_oder, - rx_logs->core_rx_post_indicate_reoder, - rx_logs->core_rx_post_indicate_err, - rx_logs->os_indicate, - rx_logs->os_indicate_ap_mcast, - rx_logs->os_indicate_ap_forward, - rx_logs->os_indicate_ap_self, - rx_logs->os_indicate_err, - rx_logs->os_netif_ok, - rx_logs->os_netif_err - ); - - return 0; -} - -int proc_get_tx_logs(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct tx_logs *tx_logs = &padapter->tx_logs; - - DBG_871X_SEL_NL(m, - "os_tx =%d\n" - "os_tx_err_up =%d\n" - "os_tx_err_xmit =%d\n" - "os_tx_m2u =%d\n" - "os_tx_m2u_ignore_fw_linked =%d\n" - "os_tx_m2u_ignore_self =%d\n" - "os_tx_m2u_entry =%d\n" - "os_tx_m2u_entry_err_xmit =%d\n" - "os_tx_m2u_entry_err_skb =%d\n" - "os_tx_m2u_stop =%d\n" - "core_tx =%d\n" - "core_tx_err_pxmitframe =%d\n" - "core_tx_err_brtx =%d\n" - "core_tx_upd_attrib =%d\n" - "core_tx_upd_attrib_adhoc =%d\n" - "core_tx_upd_attrib_sta =%d\n" - "core_tx_upd_attrib_ap =%d\n" - "core_tx_upd_attrib_unknown =%d\n" - "core_tx_upd_attrib_dhcp =%d\n" - "core_tx_upd_attrib_icmp =%d\n" - "core_tx_upd_attrib_active =%d\n" - "core_tx_upd_attrib_err_ucast_sta =%d\n" - "core_tx_upd_attrib_err_ucast_ap_link =%d\n" - "core_tx_upd_attrib_err_sta =%d\n" - "core_tx_upd_attrib_err_link =%d\n" - "core_tx_upd_attrib_err_sec =%d\n" - "core_tx_ap_enqueue_warn_fwstate =%d\n" - "core_tx_ap_enqueue_warn_sta =%d\n" - "core_tx_ap_enqueue_warn_nosta =%d\n" - "core_tx_ap_enqueue_warn_link =%d\n" - "core_tx_ap_enqueue_warn_trigger =%d\n" - "core_tx_ap_enqueue_mcast =%d\n" - "core_tx_ap_enqueue_ucast =%d\n" - "core_tx_ap_enqueue =%d\n" - "intf_tx =%d\n" - "intf_tx_pending_ac =%d\n" - "intf_tx_pending_fw_under_survey =%d\n" - "intf_tx_pending_fw_under_linking =%d\n" - "intf_tx_pending_xmitbuf =%d\n" - "intf_tx_enqueue =%d\n" - "core_tx_enqueue =%d\n" - "core_tx_enqueue_class =%d\n" - "core_tx_enqueue_class_err_sta =%d\n" - "core_tx_enqueue_class_err_nosta =%d\n" - "core_tx_enqueue_class_err_fwlink =%d\n" - "intf_tx_direct =%d\n" - "intf_tx_direct_err_coalesce =%d\n" - "intf_tx_dequeue =%d\n" - "intf_tx_dequeue_err_coalesce =%d\n" - "intf_tx_dump_xframe =%d\n" - "intf_tx_dump_xframe_err_txdesc =%d\n" - "intf_tx_dump_xframe_err_port =%d\n", - tx_logs->os_tx, - tx_logs->os_tx_err_up, - tx_logs->os_tx_err_xmit, - tx_logs->os_tx_m2u, - tx_logs->os_tx_m2u_ignore_fw_linked, - tx_logs->os_tx_m2u_ignore_self, - tx_logs->os_tx_m2u_entry, - tx_logs->os_tx_m2u_entry_err_xmit, - tx_logs->os_tx_m2u_entry_err_skb, - tx_logs->os_tx_m2u_stop, - tx_logs->core_tx, - tx_logs->core_tx_err_pxmitframe, - tx_logs->core_tx_err_brtx, - tx_logs->core_tx_upd_attrib, - tx_logs->core_tx_upd_attrib_adhoc, - tx_logs->core_tx_upd_attrib_sta, - tx_logs->core_tx_upd_attrib_ap, - tx_logs->core_tx_upd_attrib_unknown, - tx_logs->core_tx_upd_attrib_dhcp, - tx_logs->core_tx_upd_attrib_icmp, - tx_logs->core_tx_upd_attrib_active, - tx_logs->core_tx_upd_attrib_err_ucast_sta, - tx_logs->core_tx_upd_attrib_err_ucast_ap_link, - tx_logs->core_tx_upd_attrib_err_sta, - tx_logs->core_tx_upd_attrib_err_link, - tx_logs->core_tx_upd_attrib_err_sec, - tx_logs->core_tx_ap_enqueue_warn_fwstate, - tx_logs->core_tx_ap_enqueue_warn_sta, - tx_logs->core_tx_ap_enqueue_warn_nosta, - tx_logs->core_tx_ap_enqueue_warn_link, - tx_logs->core_tx_ap_enqueue_warn_trigger, - tx_logs->core_tx_ap_enqueue_mcast, - tx_logs->core_tx_ap_enqueue_ucast, - tx_logs->core_tx_ap_enqueue, - tx_logs->intf_tx, - tx_logs->intf_tx_pending_ac, - tx_logs->intf_tx_pending_fw_under_survey, - tx_logs->intf_tx_pending_fw_under_linking, - tx_logs->intf_tx_pending_xmitbuf, - tx_logs->intf_tx_enqueue, - tx_logs->core_tx_enqueue, - tx_logs->core_tx_enqueue_class, - tx_logs->core_tx_enqueue_class_err_sta, - tx_logs->core_tx_enqueue_class_err_nosta, - tx_logs->core_tx_enqueue_class_err_fwlink, - tx_logs->intf_tx_direct, - tx_logs->intf_tx_direct_err_coalesce, - tx_logs->intf_tx_dequeue, - tx_logs->intf_tx_dequeue_err_coalesce, - tx_logs->intf_tx_dump_xframe, - tx_logs->intf_tx_dump_xframe_err_txdesc, - tx_logs->intf_tx_dump_xframe_err_port - ); - - return 0; -} - -int proc_get_int_logs(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - DBG_871X_SEL_NL(m, - "all =%d\n" - "err =%d\n" - "tbdok =%d\n" - "tbder =%d\n" - "bcnderr =%d\n" - "bcndma =%d\n" - "bcndma_e =%d\n" - "rx =%d\n" - "rx_rdu =%d\n" - "rx_fovw =%d\n" - "txfovw =%d\n" - "mgntok =%d\n" - "highdok =%d\n" - "bkdok =%d\n" - "bedok =%d\n" - "vidok =%d\n" - "vodok =%d\n", - padapter->int_logs.all, - padapter->int_logs.err, - padapter->int_logs.tbdok, - padapter->int_logs.tbder, - padapter->int_logs.bcnderr, - padapter->int_logs.bcndma, - padapter->int_logs.bcndma_e, - padapter->int_logs.rx, - padapter->int_logs.rx_rdu, - padapter->int_logs.rx_fovw, - padapter->int_logs.txfovw, - padapter->int_logs.mgntok, - padapter->int_logs.highdok, - padapter->int_logs.bkdok, - padapter->int_logs.bedok, - padapter->int_logs.vidok, - padapter->int_logs.vodok - ); - - return 0; -} - -#endif /* CONFIG_DBG_COUNTER*/ - -int proc_get_rx_signal(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - DBG_871X_SEL_NL(m, "rssi:%d\n", padapter->recvpriv.rssi); - /*DBG_871X_SEL_NL(m, "rxpwdb:%d\n", padapter->recvpriv.rxpwdb);*/ - DBG_871X_SEL_NL(m, "signal_strength:%u\n", padapter->recvpriv.signal_strength); - DBG_871X_SEL_NL(m, "signal_qual:%u\n", padapter->recvpriv.signal_qual); - DBG_871X_SEL_NL(m, "noise:%d\n", padapter->recvpriv.noise); - rtw_odm_get_perpkt_rssi(m, padapter); - #ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA - rtw_get_raw_rssi_info(m, padapter); - #endif - return 0; -} - - -int proc_get_hw_status(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct dvobj_priv *dvobj = padapter->dvobj; - struct debug_priv *pdbgpriv = &dvobj->drv_dbg; - - DBG_871X_SEL_NL(m, "RX FIFO full count: last_time =%lld, current_time =%lld, differential =%lld\n" - , pdbgpriv->dbg_rx_fifo_last_overflow, pdbgpriv->dbg_rx_fifo_curr_overflow, pdbgpriv->dbg_rx_fifo_diff_overflow); - - return 0; -} - -ssize_t proc_set_rx_signal(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u32 is_signal_dbg, signal_strength; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength); - - is_signal_dbg = is_signal_dbg == 0?0:1; - - if (is_signal_dbg && num != 2) - return count; - - signal_strength = signal_strength > 100?100:signal_strength; - - padapter->recvpriv.is_signal_dbg = is_signal_dbg; - padapter->recvpriv.signal_strength_dbg = signal_strength; - - if (is_signal_dbg) - DBG_871X("set %s %u\n", "DBG_SIGNAL_STRENGTH", signal_strength); - else - DBG_871X("set %s\n", "HW_SIGNAL_STRENGTH"); - - } - - return count; - -} - -int proc_get_ht_enable(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pregpriv) - DBG_871X_SEL_NL(m, "%d\n", pregpriv->ht_enable); - - return 0; -} - -ssize_t proc_set_ht_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%d ", &mode); - - if (pregpriv && mode < 2) { - pregpriv->ht_enable = mode; - printk("ht_enable =%d\n", pregpriv->ht_enable); - } - } - - return count; - -} - -int proc_get_bw_mode(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pregpriv) - DBG_871X_SEL_NL(m, "0x%02x\n", pregpriv->bw_mode); - - return 0; -} - -ssize_t proc_set_bw_mode(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%d ", &mode); - - if (pregpriv && mode < 2) { - - pregpriv->bw_mode = mode; - printk("bw_mode =%d\n", mode); - - } - } - - return count; - -} - -int proc_get_ampdu_enable(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pregpriv) - DBG_871X_SEL_NL(m, "%d\n", pregpriv->ampdu_enable); - - return 0; -} - -ssize_t proc_set_ampdu_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - sscanf(tmp, "%d ", &mode); - - if (pregpriv && mode < 3) { - pregpriv->ampdu_enable = mode; - printk("ampdu_enable =%d\n", mode); - } - - } - - return count; - -} - -int proc_get_rx_ampdu(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - if (pregpriv) - DBG_871X_SEL_NL(m, - "accept_addba_req = %d , 0:Reject AP's Add BA req, 1:Accept AP's Add BA req.\n", - pmlmeinfo->accept_addba_req - ); - - return 0; -} - -ssize_t proc_set_rx_ampdu(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - sscanf(tmp, "%d ", &mode); - - if (pregpriv && mode < 2) { - pmlmeinfo->accept_addba_req = mode; - DBG_871X("pmlmeinfo->accept_addba_req =%d\n", - pmlmeinfo->accept_addba_req); - if (mode == 0) { - /*tear down Rx AMPDU*/ - send_delba(padapter, 0, get_my_bssid(&(pmlmeinfo->network)));/* recipient*/ - } - } - - } - - return count; -} - -int proc_get_en_fwps(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pregpriv) - DBG_871X_SEL_NL(m, "check_fw_ps = %d , 1:enable get FW PS state , 0: disable get FW PS state\n" - , pregpriv->check_fw_ps); - - return 0; -} - -ssize_t proc_set_en_fwps(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%d ", &mode); - - if (pregpriv && mode < 2) { - pregpriv->check_fw_ps = mode; - DBG_871X("pregpriv->check_fw_ps =%d\n", pregpriv->check_fw_ps); - } - } - return count; -} - -int proc_get_rx_stbc(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pregpriv) - DBG_871X_SEL_NL(m, "%d\n", pregpriv->rx_stbc); - - return 0; -} - -ssize_t proc_set_rx_stbc(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%d ", &mode); - - if (pregpriv && (mode == 0 || mode == 1 || - mode == 2 || mode == 3)) { - pregpriv->rx_stbc = mode; - printk("rx_stbc =%d\n", mode); - } - } - - return count; - -} - -int proc_get_rssi_disp(struct seq_file *m, void *v) -{ - return 0; -} - -ssize_t proc_set_rssi_disp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u32 enable = 0; - - if (count < 1) { - DBG_8192C("argument size is less than 1\n"); - return -EFAULT; - } - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - int num = sscanf(tmp, "%x", &enable); - - if (num != 1) { - DBG_8192C("invalid set_rssi_disp parameter!\n"); - return count; - } - - if (enable) { - DBG_8192C("Linked info Function Enable\n"); - padapter->bLinkInfoDump = enable; - } else { - DBG_8192C("Linked info Function Disable\n"); - padapter->bLinkInfoDump = 0; - } - } - return count; -} - -int proc_get_all_sta_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct sta_info *psta; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct sta_priv *pstapriv = &padapter->stapriv; - int i, j; - struct list_head *plist, *phead; - struct recv_reorder_ctrl *preorder_ctrl; - - DBG_871X_SEL_NL(m, "sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap); - - spin_lock_bh(&pstapriv->sta_hash_lock); - - for (i = 0; i < NUM_STA; i++) { - phead = &(pstapriv->sta_hash[i]); - plist = get_next(phead); - - while (phead != plist) { - psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); - - plist = get_next(plist); - - DBG_871X_SEL_NL(m, "==============================\n"); - DBG_871X_SEL_NL(m, "sta's macaddr:" MAC_FMT "\n", - MAC_ARG(psta->hwaddr)); - DBG_871X_SEL_NL(m, "rtsen =%d, cts2slef =%d\n", - psta->rtsen, psta->cts2self); - DBG_871X_SEL_NL(m, "state = 0x%x, aid =%d, macid =%d, raid =%d\n", - psta->state, psta->aid, psta->mac_id, - psta->raid); - DBG_871X_SEL_NL(m, "qos_en =%d, ht_en =%d, init_rate =%d\n", - psta->qos_option, - psta->htpriv.ht_option, - psta->init_rate); - DBG_871X_SEL_NL(m, "bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n", - psta->bw_mode, psta->htpriv.ch_offset, - psta->htpriv.sgi_20m, - psta->htpriv.sgi_40m); - DBG_871X_SEL_NL(m, "ampdu_enable = %d\n", - psta->htpriv.ampdu_enable); - DBG_871X_SEL_NL(m, "agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", - psta->htpriv.agg_enable_bitmap, - psta->htpriv.candidate_tid_bitmap); - DBG_871X_SEL_NL(m, "sleepq_len =%d\n", - psta->sleepq_len); - DBG_871X_SEL_NL(m, "sta_xmitpriv.vo_q_qcnt =%d\n", - psta->sta_xmitpriv.vo_q.qcnt); - DBG_871X_SEL_NL(m, "sta_xmitpriv.vi_q_qcnt =%d\n", - psta->sta_xmitpriv.vi_q.qcnt); - DBG_871X_SEL_NL(m, "sta_xmitpriv.be_q_qcnt =%d\n", - psta->sta_xmitpriv.be_q.qcnt); - DBG_871X_SEL_NL(m, "sta_xmitpriv.bk_q_qcnt =%d\n", - psta->sta_xmitpriv.bk_q.qcnt); - - DBG_871X_SEL_NL(m, "capability = 0x%x\n", - psta->capability); - DBG_871X_SEL_NL(m, "flags = 0x%x\n", psta->flags); - DBG_871X_SEL_NL(m, "wpa_psk = 0x%x\n", psta->wpa_psk); - DBG_871X_SEL_NL(m, "wpa2_group_cipher = 0x%x\n", - psta->wpa2_group_cipher); - DBG_871X_SEL_NL(m, "wpa2_pairwise_cipher = 0x%x\n", - psta->wpa2_pairwise_cipher); - DBG_871X_SEL_NL(m, "qos_info = 0x%x\n", psta->qos_info); - DBG_871X_SEL_NL(m, "dot118021XPrivacy = 0x%x\n", - psta->dot118021XPrivacy); - - for (j = 0; j < 16; j++) { - preorder_ctrl = &psta->recvreorder_ctrl[j]; - if (preorder_ctrl->enable) - DBG_871X_SEL_NL(m, "tid =%d, indicate_seq =%d\n", - j, preorder_ctrl->indicate_seq); - } - DBG_871X_SEL_NL(m, "==============================\n"); - } - } - - spin_unlock_bh(&pstapriv->sta_hash_lock); - - return 0; -} - -int proc_get_btcoex_dbg(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter; - char buf[512] = {0}; - padapter = (struct adapter *)rtw_netdev_priv(dev); - - hal_btcoex_GetDBG(padapter, buf, 512); - - DBG_871X_SEL(m, "%s", buf); - - return 0; -} - -ssize_t proc_set_btcoex_dbg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter; - u8 tmp[80] = {0}; - u32 module[2] = {0}; - u32 num; - - padapter = (struct adapter *)rtw_netdev_priv(dev); - -/* DBG_871X("+" FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter));*/ - - if (NULL == buffer) { - DBG_871X(FUNC_ADPT_FMT ": input buffer is NULL!\n", - FUNC_ADPT_ARG(padapter)); - - return -EFAULT; - } - - if (count < 1) { - DBG_871X(FUNC_ADPT_FMT ": input length is 0!\n", - FUNC_ADPT_ARG(padapter)); - - return -EFAULT; - } - - num = count; - if (num > (sizeof(tmp) - 1)) - num = (sizeof(tmp) - 1); - - if (copy_from_user(tmp, buffer, num)) { - DBG_871X(FUNC_ADPT_FMT ": copy buffer from user space FAIL!\n", - FUNC_ADPT_ARG(padapter)); - - return -EFAULT; - } - - num = sscanf(tmp, "%x %x", module, module+1); - if (num == 1) { - if (module[0] == 0) - memset(module, 0, sizeof(module)); - else - memset(module, 0xFF, sizeof(module)); - } else if (num != 2) { - DBG_871X(FUNC_ADPT_FMT ": input(\"%s\") format incorrect!\n", - FUNC_ADPT_ARG(padapter), tmp); - - if (num == 0) - return -EFAULT; - } - - DBG_871X(FUNC_ADPT_FMT ": input 0x%08X 0x%08X\n", - FUNC_ADPT_ARG(padapter), module[0], module[1]); - hal_btcoex_SetDBG(padapter, module); - - return count; -} - -int proc_get_btcoex_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter; - const u32 bufsize = 30*100; - u8 *pbuf = NULL; - - padapter = (struct adapter *)rtw_netdev_priv(dev); - - pbuf = rtw_zmalloc(bufsize); - if (!pbuf) - return -ENOMEM; - - hal_btcoex_DisplayBtCoexInfo(padapter, pbuf, bufsize); - - DBG_871X_SEL(m, "%s\n", pbuf); - - kfree(pbuf); - - return 0; -} - -#endif diff --git a/drivers/staging/rtl8723bs/core/rtw_io.c b/drivers/staging/rtl8723bs/core/rtw_io.c index a92bc19b196a..57168578663a 100644 --- a/drivers/staging/rtl8723bs/core/rtw_io.c +++ b/drivers/staging/rtl8723bs/core/rtw_io.c @@ -142,7 +142,7 @@ u32 _rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem) u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem); struct io_priv *pio_priv = &adapter->iopriv; struct intf_hdl *pintfhdl = &(pio_priv->intf); - u32 ret = _SUCCESS; + u32 ret; _write_port = pintfhdl->io_ops._write_port; diff --git a/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c b/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c index 8eb0ff57925f..eb08569db5ea 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c +++ b/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c @@ -9,13 +9,6 @@ #include <drv_types.h> #include <rtw_debug.h> -#define IS_MAC_ADDRESS_BROADCAST(addr) \ -(\ - ((addr[0] == 0xff) && (addr[1] == 0xff) && \ - (addr[2] == 0xff) && (addr[3] == 0xff) && \ - (addr[4] == 0xff) && (addr[5] == 0xff)) ? true : false \ -) - u8 rtw_validate_bssid(u8 *bssid) { u8 ret = true; diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 4285844420cb..2128886c9924 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -295,11 +295,7 @@ static void init_mlme_ext_priv_value(struct adapter *padapter) init_mlme_default_rate_set(padapter); - if (pmlmeext->cur_channel > 14) - pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB; - else - pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; - + pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; pmlmeext->sitesurvey_res.state = SCAN_DISABLE; pmlmeext->sitesurvey_res.channel_idx = 0; pmlmeext->sitesurvey_res.bss_cnt = 0; @@ -459,9 +455,8 @@ static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, RT_CHANNEL_ return chanset_size; } -int init_mlme_ext_priv(struct adapter *padapter) +void init_mlme_ext_priv(struct adapter *padapter) { - int res = _SUCCESS; struct registry_priv *pregistrypriv = &padapter->registrypriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; @@ -488,9 +483,6 @@ int init_mlme_ext_priv(struct adapter *padapter) #ifdef DBG_FIXED_CHAN pmlmeext->fixed_chan = 0xFF; #endif - - return res; - } void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) @@ -1882,7 +1874,6 @@ unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame) unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame) { - unsigned int ret = _FAIL; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; u8 *pframe = precv_frame->u.hdr.rx_data; @@ -1914,7 +1905,7 @@ unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_fr } exit: - return ret; + return _FAIL; } unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame) diff --git a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c index ae7fb7046c93..4075de07e0a9 100644 --- a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c @@ -103,7 +103,7 @@ static bool rtw_pwr_unassociated_idle(struct adapter *adapter) bool ret = false; - if (adapter_to_pwrctl(adapter)->bpower_saving == true) { + if (adapter_to_pwrctl(adapter)->bpower_saving) { /* DBG_871X("%s: already in LPS or IPS mode\n", __func__); */ goto exit; } @@ -167,7 +167,7 @@ void rtw_ps_processor(struct adapter *padapter) goto exit; } - if (pwrpriv->bInSuspend == true) {/* system suspend or autosuspend */ + if (pwrpriv->bInSuspend) {/* system suspend or autosuspend */ pdbgpriv->dbg_ps_insuspend_cnt++; DBG_871X("%s, pwrpriv->bInSuspend == true ignore this process\n", __func__); return; @@ -219,10 +219,9 @@ void traffic_check_for_leave_lps(struct adapter *padapter, u8 tx, u32 tx_packets if (jiffies_to_msecs(jiffies - start_time) > 2000) { /* 2 sec == watch dog timer */ if (xmit_cnt > 8) { - if ((adapter_to_pwrctl(padapter)->bLeisurePs) - && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) - && (hal_btcoex_IsBtControlLps(padapter) == false) - ) { + if (adapter_to_pwrctl(padapter)->bLeisurePs + && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) + && !(hal_btcoex_IsBtControlLps(padapter))) { DBG_871X("leave lps via Tx = %d\n", xmit_cnt); bLeaveLPS = true; } @@ -234,10 +233,9 @@ void traffic_check_for_leave_lps(struct adapter *padapter, u8 tx, u32 tx_packets } else { /* from rx path */ if (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4/*2*/) { - if ((adapter_to_pwrctl(padapter)->bLeisurePs) - && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) - && (hal_btcoex_IsBtControlLps(padapter) == false) - ) { + if (adapter_to_pwrctl(padapter)->bLeisurePs + && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) + && !(hal_btcoex_IsBtControlLps(padapter))) { DBG_871X("leave lps via Rx = %d\n", pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); bLeaveLPS = true; } @@ -267,7 +265,7 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) pslv = PS_STATE(pslv); - if (pwrpriv->brpwmtimeout == true) { + if (pwrpriv->brpwmtimeout) { DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __func__, pslv); } else { if ((pwrpriv->rpwm == pslv) @@ -278,8 +276,7 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) } } - if ((padapter->bSurpriseRemoved == true) || - (padapter->hw_init_completed == false)) { + if ((padapter->bSurpriseRemoved) || !(padapter->hw_init_completed)) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n", __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed)); @@ -289,7 +286,7 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) return; } - if (padapter->bDriverStopped == true) { + if (padapter->bDriverStopped) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv)); @@ -355,14 +352,14 @@ static u8 PS_RDY_CHECK(struct adapter *padapter) struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) - if (true == pwrpriv->bInSuspend && pwrpriv->wowlan_mode) + if (pwrpriv->bInSuspend && pwrpriv->wowlan_mode) return true; - else if (true == pwrpriv->bInSuspend && pwrpriv->wowlan_ap_mode) + else if (pwrpriv->bInSuspend && pwrpriv->wowlan_ap_mode) return true; - else if (true == pwrpriv->bInSuspend) + else if (pwrpriv->bInSuspend) return false; #else - if (true == pwrpriv->bInSuspend) + if (pwrpriv->bInSuspend) return false; #endif @@ -381,7 +378,7 @@ static u8 PS_RDY_CHECK(struct adapter *padapter) ) return false; - if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false)) { + if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && !(padapter->securitypriv.binstallGrpkey)) { DBG_871X("Group handshake still in progress !!!\n"); return false; } @@ -417,13 +414,9 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a /* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */ if (ps_mode == PS_MODE_ACTIVE) { - if (1 - && (((hal_btcoex_IsBtControlLps(padapter) == false) - ) - || ((hal_btcoex_IsBtControlLps(padapter) == true) - && (hal_btcoex_IsLpsOn(padapter) == false)) - ) - ) { + if (!(hal_btcoex_IsBtControlLps(padapter)) + || (hal_btcoex_IsBtControlLps(padapter) + && !(hal_btcoex_IsLpsOn(padapter)))) { DBG_871X(FUNC_ADPT_FMT" Leave 802.11 power save - %s\n", FUNC_ADPT_ARG(padapter), msg); @@ -431,8 +424,7 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a rtw_set_rpwm(padapter, PS_STATE_S4); #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) - if (pwrpriv->wowlan_mode == true || - pwrpriv->wowlan_ap_mode == true) { + if (pwrpriv->wowlan_mode || pwrpriv->wowlan_ap_mode) { unsigned long start_time; u32 delay_ms; u8 val8; @@ -461,8 +453,8 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a } } else { if ((PS_RDY_CHECK(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) - || ((hal_btcoex_IsBtControlLps(padapter) == true) - && (hal_btcoex_IsLpsOn(padapter) == true)) + || ((hal_btcoex_IsBtControlLps(padapter)) + && (hal_btcoex_IsLpsOn(padapter))) ) { u8 pslv; @@ -481,8 +473,8 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a if (pwrpriv->alives == 0) pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && (hal_btcoex_IsBtControlLps(padapter))) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -513,10 +505,10 @@ s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms) start_time = jiffies; while (1) { rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake); - if (true == bAwake) + if (bAwake) break; - if (true == padapter->bSurpriseRemoved) { + if (padapter->bSurpriseRemoved) { err = -2; DBG_871X("%s: device surprise removed!!\n", __func__); break; @@ -544,7 +536,7 @@ void LPS_Enter(struct adapter *padapter, const char *msg) int n_assoc_iface = 0; char buf[32] = {0}; - if (hal_btcoex_IsBtControlLps(padapter) == true) + if (hal_btcoex_IsBtControlLps(padapter)) return; /* Skip lps enter request if number of assocated adapters is not 1 */ @@ -557,8 +549,8 @@ void LPS_Enter(struct adapter *padapter, const char *msg) if (get_iface_type(padapter) != IFACE_PORT0) return; - if (PS_RDY_CHECK(dvobj->padapters) == false) - return; + if (!PS_RDY_CHECK(dvobj->padapters)) + return; if (pwrpriv->bLeisurePs) { /* Idle for a while if we connect to AP a while ago. */ @@ -589,7 +581,7 @@ void LPS_Leave(struct adapter *padapter, const char *msg) /* DBG_871X("+LeisurePSLeave\n"); */ - if (hal_btcoex_IsBtControlLps(padapter) == true) + if (hal_btcoex_IsBtControlLps(padapter)) return; if (pwrpriv->bLeisurePs) { @@ -615,13 +607,13 @@ void LeaveAllPowerSaveModeDirect(struct adapter *Adapter) DBG_871X("%s.....\n", __func__); - if (true == Adapter->bSurpriseRemoved) { + if (Adapter->bSurpriseRemoved) { DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved =%d Skip!\n", FUNC_ADPT_ARG(Adapter), Adapter->bSurpriseRemoved); return; } - if ((check_fwstate(pmlmepriv, _FW_LINKED) == true)) { /* connect */ + if (check_fwstate(pmlmepriv, _FW_LINKED)) { /* connect */ if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) { DBG_871X("%s: Driver Already Leave LPS\n", __func__); @@ -637,7 +629,7 @@ void LeaveAllPowerSaveModeDirect(struct adapter *Adapter) rtw_lps_ctrl_wk_cmd(pri_padapter, LPS_CTRL_LEAVE, 0); } else { if (pwrpriv->rf_pwrstate == rf_off) - if (false == ips_leave(pri_padapter)) + if (!ips_leave(pri_padapter)) DBG_871X("======> ips_leave fail.............\n"); } } @@ -675,7 +667,7 @@ void LeaveAllPowerSaveMode(struct adapter *Adapter) LPS_Leave_check(Adapter); } else { if (adapter_to_pwrctl(Adapter)->rf_pwrstate == rf_off) { - if (false == ips_leave(Adapter)) + if (!ips_leave(Adapter)) DBG_871X("======> ips_leave fail.............\n"); } } @@ -698,15 +690,14 @@ void LPS_Leave_check( while (1) { mutex_lock(&pwrpriv->lock); - if ((padapter->bSurpriseRemoved == true) - || (padapter->hw_init_completed == false) - || (pwrpriv->pwr_mode == PS_MODE_ACTIVE) - ) + if (padapter->bSurpriseRemoved + || !(padapter->hw_init_completed) + || (pwrpriv->pwr_mode == PS_MODE_ACTIVE)) bReady = true; mutex_unlock(&pwrpriv->lock); - if (true == bReady) + if (bReady) break; if (jiffies_to_msecs(jiffies - start_time) > 100) { @@ -830,12 +821,12 @@ static void pwr_rpwm_timeout_handler(struct timer_list *t) _set_workitem(&pwrpriv->rpwmtimeoutwi); } -static __inline void register_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag) +static inline void register_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag) { pwrctrl->alives |= tag; } -static __inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag) +static inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag) { pwrctrl->alives &= ~tag; } @@ -870,7 +861,7 @@ s32 rtw_register_task_alive(struct adapter *padapter, u32 task) register_task_alive(pwrctrl, task); - if (pwrctrl->bFwCurrentInPSMode == true) { + if (pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: task = 0x%x cpwm = 0x%02x alives = 0x%08x\n", __func__, task, pwrctrl->cpwm, pwrctrl->alives)); @@ -910,8 +901,8 @@ void rtw_unregister_task_alive(struct adapter *padapter, u32 task) pwrctrl = adapter_to_pwrctl(padapter); pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && hal_btcoex_IsBtControlLps(padapter)) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -924,7 +915,7 @@ void rtw_unregister_task_alive(struct adapter *padapter, u32 task) unregister_task_alive(pwrctrl, task); if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE) - && (pwrctrl->bFwCurrentInPSMode == true)) { + && pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: cpwm = 0x%02x alives = 0x%08x\n", __func__, pwrctrl->cpwm, pwrctrl->alives)); @@ -965,7 +956,7 @@ s32 rtw_register_tx_alive(struct adapter *padapter) register_task_alive(pwrctrl, XMIT_ALIVE); - if (pwrctrl->bFwCurrentInPSMode == true) { + if (pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("rtw_register_tx_alive: cpwm = 0x%02x alives = 0x%08x\n", pwrctrl->cpwm, pwrctrl->alives)); @@ -1014,7 +1005,7 @@ s32 rtw_register_cmd_alive(struct adapter *padapter) register_task_alive(pwrctrl, CMD_ALIVE); - if (pwrctrl->bFwCurrentInPSMode == true) { + if (pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_, ("rtw_register_cmd_alive: cpwm = 0x%02x alives = 0x%08x\n", pwrctrl->cpwm, pwrctrl->alives)); @@ -1051,8 +1042,8 @@ void rtw_unregister_tx_alive(struct adapter *padapter) pwrctrl = adapter_to_pwrctl(padapter); pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && hal_btcoex_IsBtControlLps(padapter)) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -1065,7 +1056,7 @@ void rtw_unregister_tx_alive(struct adapter *padapter) unregister_task_alive(pwrctrl, XMIT_ALIVE); if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE) - && (pwrctrl->bFwCurrentInPSMode == true)) { + && pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: cpwm = 0x%02x alives = 0x%08x\n", __func__, pwrctrl->cpwm, pwrctrl->alives)); @@ -1093,8 +1084,8 @@ void rtw_unregister_cmd_alive(struct adapter *padapter) pwrctrl = adapter_to_pwrctl(padapter); pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && hal_btcoex_IsBtControlLps(padapter)) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -1107,7 +1098,7 @@ void rtw_unregister_cmd_alive(struct adapter *padapter) unregister_task_alive(pwrctrl, CMD_ALIVE); if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE) - && (pwrctrl->bFwCurrentInPSMode == true)) { + && pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_, ("%s: cpwm = 0x%02x alives = 0x%08x\n", __func__, pwrctrl->cpwm, pwrctrl->alives)); @@ -1237,7 +1228,7 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal DBG_871X("%s wait ps_processing done\n", __func__); } - if (pwrpriv->bInternalAutoSuspend == false && pwrpriv->bInSuspend) { + if (!(pwrpriv->bInternalAutoSuspend) && pwrpriv->bInSuspend) { DBG_871X("%s wait bInSuspend...\n", __func__); while (pwrpriv->bInSuspend && jiffies_to_msecs(jiffies - start) <= 3000 @@ -1251,19 +1242,19 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal } /* System suspend is not allowed to wakeup */ - if ((pwrpriv->bInternalAutoSuspend == false) && (true == pwrpriv->bInSuspend)) { + if (!(pwrpriv->bInternalAutoSuspend) && pwrpriv->bInSuspend) { ret = _FAIL; goto exit; } /* block??? */ - if ((pwrpriv->bInternalAutoSuspend == true) && (padapter->net_closed == true)) { + if (pwrpriv->bInternalAutoSuspend && padapter->net_closed) { ret = _FAIL; goto exit; } /* I think this should be check in IPS, LPS, autosuspend functions... */ - if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + if (check_fwstate(pmlmepriv, _FW_LINKED)) { ret = _SUCCESS; goto exit; } diff --git a/drivers/staging/rtl8723bs/core/rtw_security.c b/drivers/staging/rtl8723bs/core/rtw_security.c index 979056c3d397..57cfe06d7d73 100644 --- a/drivers/staging/rtl8723bs/core/rtw_security.c +++ b/drivers/staging/rtl8723bs/core/rtw_security.c @@ -2290,8 +2290,7 @@ static void gf_mulx(u8 *pad) static void aes_encrypt_deinit(void *ctx) { - memset(ctx, 0, AES_PRIV_SIZE); - kfree(ctx); + kzfree(ctx); } diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c index 76c50377f0fe..ea3ea2a6b314 100644 --- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c @@ -451,7 +451,7 @@ void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigne mutex_unlock(&(adapter_to_dvobj(padapter)->setch_mutex)); } -__inline u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork) +inline u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork) { return pnetwork->MacAddress; } @@ -1996,11 +1996,6 @@ void adaptive_early_32k(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len) } } -void beacon_timing_control(struct adapter *padapter) -{ - rtw_hal_bcn_related_reg_setting(padapter); -} - void rtw_alloc_macid(struct adapter *padapter, struct sta_info *psta) { int i; diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c index 8e4caeeb4070..dd349c506da8 100644 --- a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c +++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c @@ -1758,7 +1758,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( static s32 up, dn, m, n, WaitCount; s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */ u8 retryCount = 0, btInfoExt; - bool bWifiBusy = false; BTC_PRINT( BTC_MSG_ALGORITHM, @@ -1766,11 +1765,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( ("[BTCoex], TdmaDurationAdjustForAcl()\n") ); - if (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY == wifiStatus) - bWifiBusy = true; - else - bWifiBusy = false; - if ( (BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == wifiStatus) || (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN == wifiStatus) || diff --git a/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h index aad86570b59c..7150d54d49ab 100644 --- a/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h +++ b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h @@ -532,7 +532,6 @@ typedef struct _BTC_COEXIST { extern BTC_COEXIST GLBtCoexist; -u8 EXhalbtcoutsrc_InitlizeVariables(void *Adapter); void EXhalbtcoutsrc_PowerOnSetting(PBTC_COEXIST pBtCoexist); void EXhalbtcoutsrc_InitHwConfig(PBTC_COEXIST pBtCoexist, u8 bWifiOnly); void EXhalbtcoutsrc_InitCoexDm(PBTC_COEXIST pBtCoexist); diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 5257287b4f4d..6e4a1fcb8790 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -389,7 +389,6 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) u8 *pu8; s32 *pS4Tmp; u32 *pU4Tmp; - u8 *pU1Tmp; u8 ret; @@ -403,7 +402,6 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) pu8 = pOutBuf; pS4Tmp = pOutBuf; pU4Tmp = pOutBuf; - pU1Tmp = pOutBuf; ret = true; switch (getType) { @@ -484,10 +482,8 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) *pU4Tmp = BTC_WIFI_BW_LEGACY; else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_20) *pU4Tmp = BTC_WIFI_BW_HT20; - else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) - *pU4Tmp = BTC_WIFI_BW_HT40; else - *pU4Tmp = BTC_WIFI_BW_HT40; /* todo */ + *pU4Tmp = BTC_WIFI_BW_HT40; break; case BTC_GET_U4_WIFI_TRAFFIC_DIRECTION: @@ -516,32 +512,32 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) break; case BTC_GET_U1_WIFI_DOT11_CHNL: - *pU1Tmp = padapter->mlmeextpriv.cur_channel; + *pu8 = padapter->mlmeextpriv.cur_channel; break; case BTC_GET_U1_WIFI_CENTRAL_CHNL: - *pU1Tmp = pHalData->CurrentChannel; + *pu8 = pHalData->CurrentChannel; break; case BTC_GET_U1_WIFI_HS_CHNL: - *pU1Tmp = 0; + *pu8 = 0; ret = false; break; case BTC_GET_U1_MAC_PHY_MODE: - *pU1Tmp = BTC_SMSP; + *pu8 = BTC_SMSP; /* *pU1Tmp = BTC_DMSP; */ /* *pU1Tmp = BTC_DMDP; */ /* *pU1Tmp = BTC_MP_UNKNOWN; */ break; case BTC_GET_U1_AP_NUM: - *pU1Tmp = halbtcoutsrc_GetWifiScanAPNum(padapter); + *pu8 = halbtcoutsrc_GetWifiScanAPNum(padapter); break; /* 1Ant =========== */ case BTC_GET_U1_LPS_MODE: - *pU1Tmp = padapter->dvobj->pwrctl_priv.pwr_mode; + *pu8 = padapter->dvobj->pwrctl_priv.pwr_mode; break; default: @@ -959,9 +955,13 @@ static u8 EXhalbtcoutsrc_BindBtCoexWithAdapter(void *padapter) return true; } -u8 EXhalbtcoutsrc_InitlizeVariables(void *padapter) +void hal_btcoex_Initialize(void *padapter) { - PBTC_COEXIST pBtCoexist = &GLBtCoexist; + PBTC_COEXIST pBtCoexist; + + memset(&GLBtCoexist, 0, sizeof(GLBtCoexist)); + + pBtCoexist = &GLBtCoexist; /* pBtCoexist->statistics.cntBind++; */ @@ -1001,8 +1001,6 @@ u8 EXhalbtcoutsrc_InitlizeVariables(void *padapter) GLBtcWiFiInScanState = false; GLBtcWiFiInIQKState = false; - - return true; } void EXhalbtcoutsrc_PowerOnSetting(PBTC_COEXIST pBtCoexist) @@ -1337,7 +1335,7 @@ void hal_btcoex_SetBTCoexist(struct adapter *padapter, u8 bBtExist) *true Enable BT co-exist mechanism *false Disable BT co-exist mechanism */ -u8 hal_btcoex_IsBtExist(struct adapter *padapter) +bool hal_btcoex_IsBtExist(struct adapter *padapter) { struct hal_com_data *pHalData; @@ -1384,12 +1382,6 @@ void hal_btcoex_SetSingleAntPath(struct adapter *padapter, u8 singleAntPath) EXhalbtcoutsrc_SetSingleAntPath(singleAntPath); } -u8 hal_btcoex_Initialize(struct adapter *padapter) -{ - memset(&GLBtCoexist, 0, sizeof(GLBtCoexist)); - return EXhalbtcoutsrc_InitlizeVariables((void *)padapter); -} - void hal_btcoex_PowerOnSetting(struct adapter *padapter) { EXhalbtcoutsrc_PowerOnSetting(&GLBtCoexist); @@ -1477,9 +1469,9 @@ void hal_btcoex_SetManualControl(struct adapter *padapter, u8 bmanual) GLBtCoexist.bManualControl = bmanual; } -u8 hal_btcoex_IsBtControlLps(struct adapter *padapter) +bool hal_btcoex_IsBtControlLps(struct adapter *padapter) { - if (hal_btcoex_IsBtExist(padapter) == false) + if (!hal_btcoex_IsBtExist(padapter)) return false; if (GLBtCoexist.btInfo.bBtDisabled) @@ -1491,9 +1483,9 @@ u8 hal_btcoex_IsBtControlLps(struct adapter *padapter) return false; } -u8 hal_btcoex_IsLpsOn(struct adapter *padapter) +bool hal_btcoex_IsLpsOn(struct adapter *padapter) { - if (hal_btcoex_IsBtExist(padapter) == false) + if (!hal_btcoex_IsBtExist(padapter)) return false; if (GLBtCoexist.btInfo.bBtDisabled) diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c index 638b12ae6ee9..eddd56abbb2d 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com.c +++ b/drivers/staging/rtl8723bs/hal/hal_com.c @@ -152,10 +152,7 @@ bool HAL_IsLegalChannel(struct adapter *Adapter, u32 Channel) { bool bLegalChannel = true; - if (Channel > 14) { - bLegalChannel = false; - DBG_871X("Channel > 14 but wireless_mode do not support 5G\n"); - } else if ((Channel <= 14) && (Channel >= 1)) { + if ((Channel <= 14) && (Channel >= 1)) { if (IsSupported24G(Adapter->registrypriv.wireless_mode) == false) { bLegalChannel = false; DBG_871X("(Channel <= 14) && (Channel >= 1) but wireless_mode do not support 2.4G\n"); diff --git a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c index 336764464e7d..6539bee9b5ba 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c @@ -2040,24 +2040,6 @@ void PHY_SetTxPowerLimit( } } -u8 PHY_GetTxPowerIndex( - struct adapter *padapter, - u8 RFPath, - u8 Rate, - enum CHANNEL_WIDTH BandWidth, - u8 Channel -) -{ - return PHY_GetTxPowerIndex_8723B(padapter, RFPath, Rate, BandWidth, Channel); -} - -void PHY_SetTxPowerIndex( - struct adapter *padapter, u32 PowerIndex, u8 RFPath, u8 Rate -) -{ - PHY_SetTxPowerIndex_8723B(padapter, PowerIndex, RFPath, Rate); -} - void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan) { struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); diff --git a/drivers/staging/rtl8723bs/hal/hal_intf.c b/drivers/staging/rtl8723bs/hal/hal_intf.c index acb25978a46c..7d8f21f32fb9 100644 --- a/drivers/staging/rtl8723bs/hal/hal_intf.c +++ b/drivers/staging/rtl8723bs/hal/hal_intf.c @@ -369,7 +369,7 @@ void rtw_hal_dm_watchdog_in_lps(struct adapter *padapter) } } -void rtw_hal_bcn_related_reg_setting(struct adapter *padapter) +void beacon_timing_control(struct adapter *padapter) { if (padapter->HalFunc.SetBeaconRelatedRegistersHandler) padapter->HalFunc.SetBeaconRelatedRegistersHandler(padapter); diff --git a/drivers/staging/rtl8723bs/hal/hal_phy.c b/drivers/staging/rtl8723bs/hal/hal_phy.c deleted file mode 100644 index 24a9d8f783f0..000000000000 --- a/drivers/staging/rtl8723bs/hal/hal_phy.c +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#define _HAL_PHY_C_ - -#include <drv_types.h> - -/* */ -/* ==> RF shadow Operation API Code Section!!! */ -/* */ -/*----------------------------------------------------------------------------- - * Function: PHY_RFShadowRead - * PHY_RFShadowWrite - * PHY_RFShadowCompare - * PHY_RFShadowRecorver - * PHY_RFShadowCompareAll - * PHY_RFShadowRecorverAll - * PHY_RFShadowCompareFlagSet - * PHY_RFShadowRecorverFlagSet - * - * Overview: When we set RF register, we must write shadow at first. - * When we are running, we must compare shadow abd locate error addr. - * Decide to recorver or not. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 11/20/2008 MHC Create Version 0. - * - *---------------------------------------------------------------------------*/ -u32 PHY_RFShadowRead(IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset) -{ - return RF_Shadow[eRFPath][Offset].Value; - -} /* PHY_RFShadowRead */ - - -void PHY_RFShadowWrite( - IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset, IN u32 Data -) -{ - RF_Shadow[eRFPath][Offset].Value = (Data & bRFRegOffsetMask); - RF_Shadow[eRFPath][Offset].Driver_Write = true; - -} /* PHY_RFShadowWrite */ - - -bool PHY_RFShadowCompare(IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset) -{ - u32 reg; - /* Check if we need to check the register */ - if (RF_Shadow[eRFPath][Offset].Compare == true) { - reg = rtw_hal_read_rfreg(Adapter, eRFPath, Offset, bRFRegOffsetMask); - /* Compare shadow and real rf register for 20bits!! */ - if (RF_Shadow[eRFPath][Offset].Value != reg) { - /* Locate error position. */ - RF_Shadow[eRFPath][Offset].ErrorOrNot = true; - /* RT_TRACE(COMP_INIT, DBG_LOUD, */ - /* PHY_RFShadowCompare RF-%d Addr%02lx Err = %05lx\n", */ - /* eRFPath, Offset, reg)); */ - } - return RF_Shadow[eRFPath][Offset].ErrorOrNot; - } - return false; -} /* PHY_RFShadowCompare */ - - -void PHY_RFShadowRecorver(IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset) -{ - /* Check if the address is error */ - if (RF_Shadow[eRFPath][Offset].ErrorOrNot == true) { - /* Check if we need to recorver the register. */ - if (RF_Shadow[eRFPath][Offset].Recorver == true) { - rtw_hal_write_rfreg(Adapter, eRFPath, Offset, bRFRegOffsetMask, - RF_Shadow[eRFPath][Offset].Value); - /* RT_TRACE(COMP_INIT, DBG_LOUD, */ - /* PHY_RFShadowRecorver RF-%d Addr%02lx=%05lx", */ - /* eRFPath, Offset, RF_Shadow[eRFPath][Offset].Value)); */ - } - } - -} /* PHY_RFShadowRecorver */ - - -void PHY_RFShadowCompareAll(IN PADAPTER Adapter) -{ - u8 eRFPath = 0; - u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); - - for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { - for (Offset = 0; Offset < maxReg; Offset++) { - PHY_RFShadowCompare(Adapter, eRFPath, Offset); - } - } - -} /* PHY_RFShadowCompareAll */ - - -void PHY_RFShadowRecorverAll(IN PADAPTER Adapter) -{ - u8 eRFPath = 0; - u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); - - for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { - for (Offset = 0; Offset < maxReg; Offset++) { - PHY_RFShadowRecorver(Adapter, eRFPath, Offset); - } - } - -} /* PHY_RFShadowRecorverAll */ - - -void -PHY_RFShadowCompareFlagSet( - IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset, IN u8 Type -) -{ - /* Set True or False!!! */ - RF_Shadow[eRFPath][Offset].Compare = Type; - -} /* PHY_RFShadowCompareFlagSet */ - - -void PHY_RFShadowRecorverFlagSet( - IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset, IN u8 Type -) -{ - /* Set True or False!!! */ - RF_Shadow[eRFPath][Offset].Recorver = Type; - -} /* PHY_RFShadowRecorverFlagSet */ - - -void PHY_RFShadowCompareFlagSetAll(IN PADAPTER Adapter) -{ - u8 eRFPath = 0; - u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); - - for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { - for (Offset = 0; Offset < maxReg; Offset++) { - /* 2008/11/20 MH For S3S4 test, we only check reg 26/27 now!!!! */ - if (Offset != 0x26 && Offset != 0x27) - PHY_RFShadowCompareFlagSet(Adapter, eRFPath, Offset, false); - else - PHY_RFShadowCompareFlagSet(Adapter, eRFPath, Offset, true); - } - } - -} /* PHY_RFShadowCompareFlagSetAll */ diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c index e3f4307f3d20..aa6631ee4ea7 100644 --- a/drivers/staging/rtl8723bs/hal/odm.c +++ b/drivers/staging/rtl8723bs/hal/odm.c @@ -339,13 +339,9 @@ void ODM_TXPowerTrackingCheck(PDM_ODM_T pDM_Odm); void odm_RateAdaptiveMaskInit(PDM_ODM_T pDM_Odm); -void odm_TXPowerTrackingThermalMeterInit(PDM_ODM_T pDM_Odm); - void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm); -void odm_TXPowerTrackingCheckCE(PDM_ODM_T pDM_Odm); - /* Remove Edca by Yu Chen */ @@ -1259,13 +1255,11 @@ void odm_RSSIMonitorCheckCE(PDM_ODM_T pDM_Odm) int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff; u8 sta_cnt = 0; u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */ - bool FirstConnect = false; pRA_T pRA_Table = &pDM_Odm->DM_RA_Table; if (pDM_Odm->bLinked != true) return; - FirstConnect = (pDM_Odm->bLinked) && (pRA_Table->firstconnect == false); pRA_Table->firstconnect = pDM_Odm->bLinked; /* if (check_fwstate(&Adapter->mlmepriv, WIFI_AP_STATE|WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == true) */ @@ -1324,11 +1318,6 @@ void odm_RSSIMonitorCheckCE(PDM_ODM_T pDM_Odm) /* 3 Tx Power Tracking */ /* 3 ============================================================ */ -void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm) -{ - odm_TXPowerTrackingThermalMeterInit(pDM_Odm); -} - static u8 getSwingIndex(PDM_ODM_T pDM_Odm) { struct adapter *Adapter = pDM_Odm->Adapter; @@ -1353,7 +1342,7 @@ static u8 getSwingIndex(PDM_ODM_T pDM_Odm) return i; } -void odm_TXPowerTrackingThermalMeterInit(PDM_ODM_T pDM_Odm) +void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm) { u8 defaultSwingIndex = getSwingIndex(pDM_Odm); u8 p = 0; @@ -1397,14 +1386,8 @@ void odm_TXPowerTrackingThermalMeterInit(PDM_ODM_T pDM_Odm) } - void ODM_TXPowerTrackingCheck(PDM_ODM_T pDM_Odm) { - odm_TXPowerTrackingCheckCE(pDM_Odm); -} - -void odm_TXPowerTrackingCheckCE(PDM_ODM_T pDM_Odm) -{ struct adapter *Adapter = pDM_Odm->Adapter; if (!(pDM_Odm->SupportAbility & ODM_RF_TX_PWR_TRACK)) diff --git a/drivers/staging/rtl8723bs/hal/odm.h b/drivers/staging/rtl8723bs/hal/odm.h index 6ba77bb70889..fba3b9e1491b 100644 --- a/drivers/staging/rtl8723bs/hal/odm.h +++ b/drivers/staging/rtl8723bs/hal/odm.h @@ -1365,10 +1365,6 @@ extern u32 TxScalingTable_Jaguar[TXSCALE_TABLE_SIZE]; #define SWAW_STEP_PEAK 0 #define SWAW_STEP_DETERMINE 1 -/* Remove DIG by yuchen */ - -void ODM_SetAntenna(PDM_ODM_T pDM_Odm, u8 Antenna); - /* Remove BB power saving by Yuchen */ #define dm_CheckTXPowerTracking ODM_TXPowerTrackingCheck diff --git a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c index a73304639226..95edd148ac24 100644 --- a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c +++ b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c @@ -11,11 +11,6 @@ static void odm_SetCrystalCap(void *pDM_VOID, u8 CrystalCap) { PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack; - bool bEEPROMCheck; - struct adapter *Adapter = pDM_Odm->Adapter; - struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); - - bEEPROMCheck = pHalData->EEPROMVersion >= 0x01; if (pCfoTrack->CrystalCap == CrystalCap) return; diff --git a/drivers/staging/rtl8723bs/hal/odm_HWConfig.c b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c index 49fa814068b8..71919a3d81ab 100644 --- a/drivers/staging/rtl8723bs/hal/odm_HWConfig.c +++ b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c @@ -89,7 +89,6 @@ static void odm_RxPhyStatus92CSeries_Parsing( u8 RSSI, total_rssi = 0; bool isCCKrate = false; u8 rf_rx_num = 0; - u8 cck_highpwr = 0; u8 LNA_idx, VGA_idx; PPHY_STATUS_RPT_8192CD_T pPhyStaRpt = (PPHY_STATUS_RPT_8192CD_T)pPhyStatus; @@ -107,16 +106,10 @@ static void odm_RxPhyStatus92CSeries_Parsing( /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */ /* */ - /* if (pHalData->eRFPowerState == eRfOn) */ - cck_highpwr = pDM_Odm->bCckHighPower; - /* else */ - /* cck_highpwr = false; */ - cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a ; /* 2011.11.28 LukeLee: 88E use different LNA & VGA gain table */ /* The RSSI formula should be modified according to the gain table */ - /* In 88E, cck_highpwr is always set to 1 */ LNA_idx = ((cck_agc_rpt & 0xE0)>>5); VGA_idx = (cck_agc_rpt & 0x1F); rx_pwr_all = odm_CCKRSSI_8723B(LNA_idx, VGA_idx); diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c index 080e974914b6..7760fd0eb6c9 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c @@ -1300,7 +1300,7 @@ static void rtl8723b_set_FwScanOffloadInfo_cmd(struct adapter *padapter, PRSVDPA } #endif /* CONFIG_PNO_SUPPORT */ -static void rtl8723b_set_FwWoWlanRelated_cmd(struct adapter *padapter, u8 enable) +void rtl8723b_set_wowlan_cmd(struct adapter *padapter, u8 enable) { struct security_priv *psecpriv = &padapter->securitypriv; struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(padapter); @@ -1346,11 +1346,6 @@ static void rtl8723b_set_FwWoWlanRelated_cmd(struct adapter *padapter, u8 enable DBG_871X_LEVEL(_drv_always_, "-%s()-\n", __func__); } - -void rtl8723b_set_wowlan_cmd(struct adapter *padapter, u8 enable) -{ - rtl8723b_set_FwWoWlanRelated_cmd(padapter, enable); -} #endif /* CONFIG_WOWLAN */ #ifdef CONFIG_AP_WOWLAN @@ -1398,7 +1393,7 @@ static void rtl8723b_set_Fw_AP_Offload_Cmd(struct adapter *padapter, u8 bFuncEn) H2C_AP_OFFLOAD_LEN, u1H2CAPOffloadCtrlParm); } -static void rtl8723b_set_AP_FwWoWlan_cmd(struct adapter *padapter, u8 enable) +void rtl8723b_set_ap_wowlan_cmd(struct adapter *padapter, u8 enable) { DBG_871X_LEVEL(_drv_always_, "+%s()+: enable =%d\n", __func__, enable); if (enable) { @@ -1411,12 +1406,6 @@ static void rtl8723b_set_AP_FwWoWlan_cmd(struct adapter *padapter, u8 enable) rtl8723b_set_Fw_AP_Offload_Cmd(padapter, enable); msleep(10); DBG_871X_LEVEL(_drv_always_, "-%s()-\n", __func__); - return ; -} - -void rtl8723b_set_ap_wowlan_cmd(struct adapter *padapter, u8 enable) -{ - rtl8723b_set_AP_FwWoWlan_cmd(padapter, enable); } #endif /* CONFIG_AP_WOWLAN */ diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c index 25c75b977666..6df2b58bdc67 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c @@ -431,14 +431,12 @@ static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter) u8 sz8723BBRegFile[] = RTL8723B_PHY_REG; u8 sz8723AGCTableFile[] = RTL8723B_AGC_TAB; u8 sz8723BBBRegPgFile[] = RTL8723B_PHY_REG_PG; - u8 sz8723BBRegMpFile[] = RTL8723B_PHY_REG_MP; u8 sz8723BRFTxPwrLmtFile[] = RTL8723B_TXPWR_LMT; - u8 *pszBBRegFile = NULL, *pszAGCTableFile = NULL, *pszBBRegPgFile = NULL, *pszBBRegMpFile = NULL, *pszRFTxPwrLmtFile = NULL; + u8 *pszBBRegFile = NULL, *pszAGCTableFile = NULL, *pszBBRegPgFile = NULL, *pszRFTxPwrLmtFile = NULL; pszBBRegFile = sz8723BBRegFile; pszAGCTableFile = sz8723AGCTableFile; pszBBRegPgFile = sz8723BBBRegPgFile; - pszBBRegMpFile = sz8723BBRegMpFile; pszRFTxPwrLmtFile = sz8723BRFTxPwrLmtFile; /* Read Tx Power Limit File */ @@ -585,7 +583,7 @@ int PHY_RFConfig8723B(struct adapter *Adapter) * <20120830, Kordan> **************************************************************************************************************/ -void PHY_SetTxPowerIndex_8723B( +void PHY_SetTxPowerIndex( struct adapter *Adapter, u32 PowerIndex, u8 RFPath, @@ -668,7 +666,7 @@ void PHY_SetTxPowerIndex_8723B( } } -u8 PHY_GetTxPowerIndex_8723B( +u8 PHY_GetTxPowerIndex( struct adapter *padapter, u8 RFPath, u8 Rate, diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c index e23b39ab16c5..0f3301091258 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c @@ -486,7 +486,6 @@ initbuferror: } if (precvpriv->pallocated_recv_buf) { - n = NR_RECVBUFF * sizeof(struct recv_buf) + 4; kfree(precvpriv->pallocated_recv_buf); precvpriv->pallocated_recv_buf = NULL; } @@ -503,7 +502,7 @@ exit: */ void rtl8723bs_free_recv_priv(struct adapter *padapter) { - u32 i, n; + u32 i; struct recv_priv *precvpriv; struct recv_buf *precvbuf; @@ -515,9 +514,8 @@ void rtl8723bs_free_recv_priv(struct adapter *padapter) /* 3 2. free all recv buffers */ precvbuf = (struct recv_buf *)precvpriv->precv_buf; if (precvbuf) { - n = NR_RECVBUFF; precvpriv->free_recv_buf_queue_cnt = 0; - for (i = 0; i < n ; i++) { + for (i = 0; i < NR_RECVBUFF; i++) { list_del_init(&precvbuf->list); rtw_os_recvbuf_resource_free(padapter, precvbuf); precvbuf++; @@ -526,7 +524,6 @@ void rtl8723bs_free_recv_priv(struct adapter *padapter) } if (precvpriv->pallocated_recv_buf) { - n = NR_RECVBUFF * sizeof(struct recv_buf) + 4; kfree(precvpriv->pallocated_recv_buf); precvpriv->pallocated_recv_buf = NULL; } diff --git a/drivers/staging/rtl8723bs/include/autoconf.h b/drivers/staging/rtl8723bs/include/autoconf.h index 196aca3aed7b..8f4c1e734473 100644 --- a/drivers/staging/rtl8723bs/include/autoconf.h +++ b/drivers/staging/rtl8723bs/include/autoconf.h @@ -57,9 +57,5 @@ #define DBG 0 /* for ODM & BTCOEX debug */ #endif /* !DEBUG */ -#ifdef CONFIG_PROC_FS -#define PROC_DEBUG -#endif - /* define DBG_XMIT_BUF */ /* define DBG_XMIT_BUF_EXT */ diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h index 96346ce064aa..8d7fce1e39b7 100644 --- a/drivers/staging/rtl8723bs/include/drv_types.h +++ b/drivers/staging/rtl8723bs/include/drv_types.h @@ -478,7 +478,7 @@ struct sdio_data intf_data; #define dvobj_to_pwrctl(dvobj) (&(dvobj->pwrctl_priv)) #define pwrctl_to_dvobj(pwrctl) container_of(pwrctl, struct dvobj_priv, pwrctl_priv) -__inline static struct device *dvobj_to_dev(struct dvobj_priv *dvobj) +static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj) { /* todo: get interface type from dvobj and the return the dev accordingly */ #ifdef RTW_DVOBJ_CHIP_HW_TYPE @@ -576,8 +576,6 @@ struct adapter { int bup; struct net_device_stats stats; struct iw_statistics iwstats; - struct proc_dir_entry *dir_dev;/* for proc directory */ - struct proc_dir_entry *dir_odm; struct wireless_dev *rtw_wdev; struct rtw_wdev_priv wdev_data; @@ -636,14 +634,14 @@ struct adapter { /* define RTW_DISABLE_FUNC(padapter, func) (atomic_add(&adapter_to_dvobj(padapter)->disable_func, (func))) */ /* define RTW_ENABLE_FUNC(padapter, func) (atomic_sub(&adapter_to_dvobj(padapter)->disable_func, (func))) */ -__inline static void RTW_DISABLE_FUNC(struct adapter *padapter, int func_bit) +static inline void RTW_DISABLE_FUNC(struct adapter *padapter, int func_bit) { int df = atomic_read(&adapter_to_dvobj(padapter)->disable_func); df |= func_bit; atomic_set(&adapter_to_dvobj(padapter)->disable_func, df); } -__inline static void RTW_ENABLE_FUNC(struct adapter *padapter, int func_bit) +static inline void RTW_ENABLE_FUNC(struct adapter *padapter, int func_bit) { int df = atomic_read(&adapter_to_dvobj(padapter)->disable_func); df &= ~(func_bit); diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h index 6f7514be998f..eb03813fdcb9 100644 --- a/drivers/staging/rtl8723bs/include/hal_btcoex.h +++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h @@ -22,13 +22,13 @@ typedef struct _BT_COEXIST void DBG_BT_INFO(u8 *dbgmsg); void hal_btcoex_SetBTCoexist(struct adapter *padapter, u8 bBtExist); -u8 hal_btcoex_IsBtExist(struct adapter *padapter); +bool hal_btcoex_IsBtExist(struct adapter *padapter); bool hal_btcoex_IsBtDisabled(struct adapter *); void hal_btcoex_SetChipType(struct adapter *padapter, u8 chipType); void hal_btcoex_SetPgAntNum(struct adapter *padapter, u8 antNum); void hal_btcoex_SetSingleAntPath(struct adapter *padapter, u8 singleAntPath); -u8 hal_btcoex_Initialize(struct adapter *padapter); +void hal_btcoex_Initialize(void *padapter); void hal_btcoex_PowerOnSetting(struct adapter *padapter); void hal_btcoex_InitHwConfig(struct adapter *padapter, u8 bWifiOnly); @@ -47,8 +47,8 @@ void hal_btcoex_Handler(struct adapter *padapter); s32 hal_btcoex_IsBTCoexCtrlAMPDUSize(struct adapter *padapter); void hal_btcoex_SetManualControl(struct adapter *padapter, u8 bmanual); -u8 hal_btcoex_IsBtControlLps(struct adapter *); -u8 hal_btcoex_IsLpsOn(struct adapter *); +bool hal_btcoex_IsBtControlLps(struct adapter *padapter); +bool hal_btcoex_IsLpsOn(struct adapter *padapter); u8 hal_btcoex_RpwmVal(struct adapter *); u8 hal_btcoex_LpsVal(struct adapter *); u32 hal_btcoex_GetRaMask(struct adapter *); diff --git a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h index f841546584a7..9167f1e7827f 100644 --- a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h +++ b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h @@ -213,23 +213,6 @@ PHY_GetTxPowerTrackingOffset( u8 RFPath ); -u8 -PHY_GetTxPowerIndex( -struct adapter * padapter, -u8 RFPath, -u8 Rate, -enum CHANNEL_WIDTH BandWidth, -u8 Channel - ); - -void -PHY_SetTxPowerIndex( -struct adapter * padapter, -u32 PowerIndex, -u8 RFPath, -u8 Rate - ); - void Hal_ChannelPlanToRegulation( struct adapter * Adapter, diff --git a/drivers/staging/rtl8723bs/include/hal_intf.h b/drivers/staging/rtl8723bs/include/hal_intf.h index 3a0c3d079d50..24926ebaf950 100644 --- a/drivers/staging/rtl8723bs/include/hal_intf.h +++ b/drivers/staging/rtl8723bs/include/hal_intf.h @@ -362,7 +362,7 @@ void rtw_hal_add_ra_tid(struct adapter *padapter, u32 bitmap, u8 *arg, u8 rssi_l void rtw_hal_start_thread(struct adapter *padapter); void rtw_hal_stop_thread(struct adapter *padapter); -void rtw_hal_bcn_related_reg_setting(struct adapter *padapter); +void beacon_timing_control(struct adapter *padapter); u32 rtw_hal_read_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask); void rtw_hal_write_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data); diff --git a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h index 640427f407e3..b40868b2e76f 100644 --- a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h +++ b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h @@ -65,7 +65,7 @@ int PHY_RFConfig8723B(struct adapter *Adapter ); s32 PHY_MACConfig8723B(struct adapter *padapter); void -PHY_SetTxPowerIndex_8723B( +PHY_SetTxPowerIndex( struct adapter * Adapter, u32 PowerIndex, u8 RFPath, @@ -73,7 +73,7 @@ u8 Rate ); u8 -PHY_GetTxPowerIndex_8723B( +PHY_GetTxPowerIndex( struct adapter * padapter, u8 RFPath, u8 Rate, diff --git a/drivers/staging/rtl8723bs/include/osdep_intf.h b/drivers/staging/rtl8723bs/include/osdep_intf.h index 40313d17a242..fa16139fcce6 100644 --- a/drivers/staging/rtl8723bs/include/osdep_intf.h +++ b/drivers/staging/rtl8723bs/include/osdep_intf.h @@ -64,8 +64,6 @@ u16 rtw_recv_select_queue(struct sk_buff *skb); int rtw_ndev_notifier_register(void); void rtw_ndev_notifier_unregister(void); -#include "../os_dep/rtw_proc.h" - void rtw_ips_dev_unload(struct adapter *padapter); int rtw_ips_pwr_up(struct adapter *padapter); diff --git a/drivers/staging/rtl8723bs/include/osdep_service.h b/drivers/staging/rtl8723bs/include/osdep_service.h index d2616af95ffa..81a9c19ecc6a 100644 --- a/drivers/staging/rtl8723bs/include/osdep_service.h +++ b/drivers/staging/rtl8723bs/include/osdep_service.h @@ -110,12 +110,12 @@ int _rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb); extern void _rtw_init_queue(struct __queue *pqueue); -static __inline void thread_enter(char *name) +static inline void thread_enter(char *name) { allow_signal(SIGTERM); } -__inline static void flush_signals_thread(void) +static inline void flush_signals_thread(void) { if (signal_pending (current)) { @@ -125,7 +125,7 @@ __inline static void flush_signals_thread(void) #define rtw_warn_on(condition) WARN_ON(condition) -__inline static int rtw_bug_check(void *parg1, void *parg2, void *parg3, void *parg4) +static inline int rtw_bug_check(void *parg1, void *parg2, void *parg3, void *parg4) { int ret = true; @@ -136,7 +136,7 @@ __inline static int rtw_bug_check(void *parg1, void *parg2, void *parg3, void *p #define _RND(sz, r) ((((sz)+((r)-1))/(r))*(r)) #define RND4(x) (((x >> 2) + (((x & 3) == 0) ? 0: 1)) << 2) -__inline static u32 _RND4(u32 sz) +static inline u32 _RND4(u32 sz) { u32 val; @@ -147,7 +147,7 @@ __inline static u32 _RND4(u32 sz) } -__inline static u32 _RND8(u32 sz) +static inline u32 _RND8(u32 sz) { u32 val; diff --git a/drivers/staging/rtl8723bs/include/osdep_service_linux.h b/drivers/staging/rtl8723bs/include/osdep_service_linux.h index 2f1b51e614fb..c582ede1ac12 100644 --- a/drivers/staging/rtl8723bs/include/osdep_service_linux.h +++ b/drivers/staging/rtl8723bs/include/osdep_service_linux.h @@ -64,12 +64,12 @@ typedef struct work_struct _workitem; -__inline static struct list_head *get_next(struct list_head *list) +static inline struct list_head *get_next(struct list_head *list) { return list->next; } -__inline static struct list_head *get_list_head(struct __queue *queue) +static inline struct list_head *get_list_head(struct __queue *queue) { return (&(queue->queue)); } @@ -78,28 +78,28 @@ __inline static struct list_head *get_list_head(struct __queue *queue) #define LIST_CONTAINOR(ptr, type, member) \ container_of(ptr, type, member) -__inline static void _set_timer(_timer *ptimer, u32 delay_time) +static inline void _set_timer(_timer *ptimer, u32 delay_time) { mod_timer(ptimer , (jiffies+(delay_time*HZ/1000))); } -__inline static void _cancel_timer(_timer *ptimer, u8 *bcancelled) +static inline void _cancel_timer(_timer *ptimer, u8 *bcancelled) { del_timer_sync(ptimer); *bcancelled = true;/* true == 1; false == 0 */ } -__inline static void _init_workitem(_workitem *pwork, void *pfunc, void *cntx) +static inline void _init_workitem(_workitem *pwork, void *pfunc, void *cntx) { INIT_WORK(pwork, pfunc); } -__inline static void _set_workitem(_workitem *pwork) +static inline void _set_workitem(_workitem *pwork) { schedule_work(pwork); } -__inline static void _cancel_workitem_sync(_workitem *pwork) +static inline void _cancel_workitem_sync(_workitem *pwork) { cancel_work_sync(pwork); } diff --git a/drivers/staging/rtl8723bs/include/rtw_debug.h b/drivers/staging/rtl8723bs/include/rtw_debug.h index 216d9492575e..22fc5d730d7b 100644 --- a/drivers/staging/rtl8723bs/include/rtw_debug.h +++ b/drivers/staging/rtl8723bs/include/rtw_debug.h @@ -267,81 +267,4 @@ void mac_reg_dump(void *sel, struct adapter *adapter); void bb_reg_dump(void *sel, struct adapter *adapter); void rf_reg_dump(void *sel, struct adapter *adapter); -#ifdef PROC_DEBUG -ssize_t proc_set_write_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_read_reg(struct seq_file *m, void *v); -ssize_t proc_set_read_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_fwstate(struct seq_file *m, void *v); -int proc_get_sec_info(struct seq_file *m, void *v); -int proc_get_mlmext_state(struct seq_file *m, void *v); - -int proc_get_roam_flags(struct seq_file *m, void *v); -ssize_t proc_set_roam_flags(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_roam_param(struct seq_file *m, void *v); -ssize_t proc_set_roam_param(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -ssize_t proc_set_roam_tgt_addr(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_qos_option(struct seq_file *m, void *v); -int proc_get_ht_option(struct seq_file *m, void *v); -int proc_get_rf_info(struct seq_file *m, void *v); -int proc_get_survey_info(struct seq_file *m, void *v); -int proc_get_ap_info(struct seq_file *m, void *v); -int proc_get_adapter_state(struct seq_file *m, void *v); -int proc_get_trx_info(struct seq_file *m, void *v); -int proc_get_rate_ctl(struct seq_file *m, void *v); -ssize_t proc_set_rate_ctl(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_suspend_resume_info(struct seq_file *m, void *v); - -ssize_t proc_set_fwdl_test_case(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -ssize_t proc_set_wait_hiq_empty(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_all_sta_info(struct seq_file *m, void *v); - -int proc_get_rx_signal(struct seq_file *m, void *v); -ssize_t proc_set_rx_signal(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_hw_status(struct seq_file *m, void *v); - -int proc_get_ht_enable(struct seq_file *m, void *v); -ssize_t proc_set_ht_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_bw_mode(struct seq_file *m, void *v); -ssize_t proc_set_bw_mode(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_ampdu_enable(struct seq_file *m, void *v); -ssize_t proc_set_ampdu_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_rx_ampdu(struct seq_file *m, void *v); -ssize_t proc_set_rx_ampdu(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_rx_stbc(struct seq_file *m, void *v); -ssize_t proc_set_rx_stbc(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_en_fwps(struct seq_file *m, void *v); -ssize_t proc_set_en_fwps(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -/* int proc_get_two_path_rssi(struct seq_file *m, void *v); */ -int proc_get_rssi_disp(struct seq_file *m, void *v); -ssize_t proc_set_rssi_disp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_btcoex_dbg(struct seq_file *m, void *v); -ssize_t proc_set_btcoex_dbg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_btcoex_info(struct seq_file *m, void *v); - -int proc_get_odm_dbg_comp(struct seq_file *m, void *v); -ssize_t proc_set_odm_dbg_comp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_odm_dbg_level(struct seq_file *m, void *v); -ssize_t proc_set_odm_dbg_level(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_odm_adaptivity(struct seq_file *m, void *v); -ssize_t proc_set_odm_adaptivity(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -#ifdef CONFIG_DBG_COUNTER -int proc_get_rx_logs(struct seq_file *m, void *v); -int proc_get_tx_logs(struct seq_file *m, void *v); -int proc_get_int_logs(struct seq_file *m, void *v); -#endif - -#endif /* PROC_DEBUG */ - #endif /* __RTW_DEBUG_H__ */ diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme.h b/drivers/staging/rtl8723bs/include/rtw_mlme.h index d3c07d1c36e9..362737b83c3a 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme.h @@ -81,15 +81,13 @@ enum dot11AuthAlgrthmNum { }; /* Scan type including active and passive scan. */ -typedef enum _RT_SCAN_TYPE -{ +typedef enum _RT_SCAN_TYPE { SCAN_PASSIVE, SCAN_ACTIVE, SCAN_MIX, }RT_SCAN_TYPE, *PRT_SCAN_TYPE; -enum _BAND -{ +enum _BAND { GHZ24_50 = 0, GHZ_50, GHZ_24, @@ -498,13 +496,13 @@ extern sint rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv); extern sint rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, sint keyid, u8 set_tx, bool enqueue); extern sint rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv); -__inline static u8 *get_bssid(struct mlme_priv *pmlmepriv) +static inline u8 *get_bssid(struct mlme_priv *pmlmepriv) { /* if sta_mode:pmlmepriv->cur_network.network.MacAddress => bssid */ /* if adhoc_mode:pmlmepriv->cur_network.network.MacAddress => ibss mac address */ return pmlmepriv->cur_network.network.MacAddress; } -__inline static sint check_fwstate(struct mlme_priv *pmlmepriv, sint state) +static inline sint check_fwstate(struct mlme_priv *pmlmepriv, sint state) { if (pmlmepriv->fw_state & state) return true; @@ -512,7 +510,7 @@ __inline static sint check_fwstate(struct mlme_priv *pmlmepriv, sint state) return false; } -__inline static sint get_fwstate(struct mlme_priv *pmlmepriv) +static inline sint get_fwstate(struct mlme_priv *pmlmepriv) { return pmlmepriv->fw_state; } @@ -524,7 +522,7 @@ __inline static sint get_fwstate(struct mlme_priv *pmlmepriv) * ### NOTE:#### (!!!!) * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock */ -__inline static void set_fwstate(struct mlme_priv *pmlmepriv, sint state) +static inline void set_fwstate(struct mlme_priv *pmlmepriv, sint state) { pmlmepriv->fw_state |= state; /* FOR HW integration */ @@ -533,7 +531,7 @@ __inline static void set_fwstate(struct mlme_priv *pmlmepriv, sint state) } } -__inline static void _clr_fwstate_(struct mlme_priv *pmlmepriv, sint state) +static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, sint state) { pmlmepriv->fw_state &= ~state; /* FOR HW integration */ @@ -546,7 +544,7 @@ __inline static void _clr_fwstate_(struct mlme_priv *pmlmepriv, sint state) * No Limit on the calling context, * therefore set it to be the critical section... */ -__inline static void clr_fwstate(struct mlme_priv *pmlmepriv, sint state) +static inline void clr_fwstate(struct mlme_priv *pmlmepriv, sint state) { spin_lock_bh(&pmlmepriv->lock); if (check_fwstate(pmlmepriv, state) == true) @@ -554,7 +552,7 @@ __inline static void clr_fwstate(struct mlme_priv *pmlmepriv, sint state) spin_unlock_bh(&pmlmepriv->lock); } -__inline static void set_scanned_network_val(struct mlme_priv *pmlmepriv, sint val) +static inline void set_scanned_network_val(struct mlme_priv *pmlmepriv, sint val) { spin_lock_bh(&pmlmepriv->lock); pmlmepriv->num_of_scanned = val; diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h index 733bb9425448..fd3cf955c9f8 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h @@ -535,7 +535,7 @@ struct mlme_ext_priv }; void init_mlme_default_rate_set(struct adapter *padapter); -int init_mlme_ext_priv(struct adapter *padapter); +void init_mlme_ext_priv(struct adapter *padapter); int init_hw_mlme_ext(struct adapter *padapter); void free_mlme_ext_priv (struct mlme_ext_priv *pmlmeext); extern void init_mlme_ext_timer(struct adapter *padapter); @@ -650,7 +650,6 @@ void report_del_sta_event(struct adapter *padapter, unsigned char* MacAddr, unsi void report_add_sta_event(struct adapter *padapter, unsigned char* MacAddr, int cam_idx); void report_wmm_edca_update(struct adapter *padapter); -void beacon_timing_control(struct adapter *padapter); u8 chk_bmc_sleepq_cmd(struct adapter *padapter); extern u8 set_tx_beacon_cmd(struct adapter *padapter); unsigned int setup_beacon_frame(struct adapter *padapter, unsigned char *beacon_frame); diff --git a/drivers/staging/rtl8723bs/include/rtw_recv.h b/drivers/staging/rtl8723bs/include/rtw_recv.h index 5de946e66302..012d8f54814f 100644 --- a/drivers/staging/rtl8723bs/include/rtw_recv.h +++ b/drivers/staging/rtl8723bs/include/rtw_recv.h @@ -405,7 +405,7 @@ struct recv_buf *rtw_dequeue_recvbuf (struct __queue *queue); void rtw_reordering_ctrl_timeout_handler(struct timer_list *t); -__inline static u8 *get_rxmem(union recv_frame *precvframe) +static inline u8 *get_rxmem(union recv_frame *precvframe) { /* always return rx_head... */ if (precvframe == NULL) @@ -414,7 +414,7 @@ __inline static u8 *get_rxmem(union recv_frame *precvframe) return precvframe->u.hdr.rx_head; } -__inline static u8 *get_recvframe_data(union recv_frame *precvframe) +static inline u8 *get_recvframe_data(union recv_frame *precvframe) { /* alwasy return rx_data */ @@ -425,7 +425,7 @@ __inline static u8 *get_recvframe_data(union recv_frame *precvframe) } -__inline static u8 *recvframe_pull(union recv_frame *precvframe, sint sz) +static inline u8 *recvframe_pull(union recv_frame *precvframe, sint sz) { /* rx_data += sz; move rx_data sz bytes hereafter */ @@ -450,7 +450,7 @@ __inline static u8 *recvframe_pull(union recv_frame *precvframe, sint sz) } -__inline static u8 *recvframe_put(union recv_frame *precvframe, sint sz) +static inline u8 *recvframe_put(union recv_frame *precvframe, sint sz) { /* rx_tai += sz; move rx_tail sz bytes hereafter */ @@ -479,7 +479,7 @@ __inline static u8 *recvframe_put(union recv_frame *precvframe, sint sz) -__inline static u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz) +static inline u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz) { /* rmv data from rx_tail (by yitsen) */ @@ -503,7 +503,7 @@ __inline static u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz) } -__inline static union recv_frame *rxmem_to_recvframe(u8 *rxmem) +static inline union recv_frame *rxmem_to_recvframe(u8 *rxmem) { /* due to the design of 2048 bytes alignment of recv_frame, we can reference the union recv_frame */ /* from any given member of recv_frame. */ @@ -513,13 +513,13 @@ __inline static union recv_frame *rxmem_to_recvframe(u8 *rxmem) } -__inline static sint get_recvframe_len(union recv_frame *precvframe) +static inline sint get_recvframe_len(union recv_frame *precvframe) { return precvframe->u.hdr.len; } -__inline static s32 translate_percentage_to_dbm(u32 SignalStrengthIndex) +static inline s32 translate_percentage_to_dbm(u32 SignalStrengthIndex) { s32 SignalPower; /* in dBm. */ diff --git a/drivers/staging/rtl8723bs/include/sta_info.h b/drivers/staging/rtl8723bs/include/sta_info.h index b9df42d0677e..3acce5630f8e 100644 --- a/drivers/staging/rtl8723bs/include/sta_info.h +++ b/drivers/staging/rtl8723bs/include/sta_info.h @@ -348,7 +348,7 @@ struct sta_priv { }; -__inline static u32 wifi_mac_hash(u8 *mac) +static inline u32 wifi_mac_hash(u8 *mac) { u32 x; diff --git a/drivers/staging/rtl8723bs/include/wifi.h b/drivers/staging/rtl8723bs/include/wifi.h index 8c50bbb20f3b..2faf83704ff0 100644 --- a/drivers/staging/rtl8723bs/include/wifi.h +++ b/drivers/staging/rtl8723bs/include/wifi.h @@ -347,7 +347,7 @@ enum WIFI_REG_DOMAIN { (addr[4] == 0xff) && (addr[5] == 0xff)) ? true : false \ ) -__inline static int IS_MCAST(unsigned char *da) +static inline int IS_MCAST(unsigned char *da) { if ((*da) & 0x01) return true; @@ -355,20 +355,20 @@ __inline static int IS_MCAST(unsigned char *da) return false; } -__inline static unsigned char * get_ra(unsigned char *pframe) +static inline unsigned char * get_ra(unsigned char *pframe) { unsigned char *ra; ra = GetAddr1Ptr(pframe); return ra; } -__inline static unsigned char * get_ta(unsigned char *pframe) +static inline unsigned char * get_ta(unsigned char *pframe) { unsigned char *ta; ta = GetAddr2Ptr(pframe); return ta; } -__inline static unsigned char * get_da(unsigned char *pframe) +static inline unsigned char * get_da(unsigned char *pframe) { unsigned char *da; unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); @@ -392,7 +392,7 @@ __inline static unsigned char * get_da(unsigned char *pframe) } -__inline static unsigned char * get_sa(unsigned char *pframe) +static inline unsigned char * get_sa(unsigned char *pframe) { unsigned char *sa; unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); @@ -415,7 +415,7 @@ __inline static unsigned char * get_sa(unsigned char *pframe) return sa; } -__inline static unsigned char * get_hdr_bssid(unsigned char *pframe) +static inline unsigned char * get_hdr_bssid(unsigned char *pframe) { unsigned char *sa = NULL; unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); @@ -439,7 +439,7 @@ __inline static unsigned char * get_hdr_bssid(unsigned char *pframe) } -__inline static int IsFrameTypeCtrl(unsigned char *pframe) +static inline int IsFrameTypeCtrl(unsigned char *pframe) { if (WIFI_CTRL_TYPE == GetFrameType(pframe)) return true; diff --git a/drivers/staging/rtl8723bs/include/wlan_bssdef.h b/drivers/staging/rtl8723bs/include/wlan_bssdef.h index 88890b1c3c4c..723fc5b546ef 100644 --- a/drivers/staging/rtl8723bs/include/wlan_bssdef.h +++ b/drivers/staging/rtl8723bs/include/wlan_bssdef.h @@ -223,7 +223,7 @@ struct wlan_bssid_ex { u8 IEs[MAX_IE_SZ]; /* timestamp, beacon interval, and capability information) */ } __packed; -__inline static uint get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss) +static inline uint get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss) { return (sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + bss->IELength); } diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 9bc685632651..f819abb756dc 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -19,8 +19,6 @@ #define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 5000 /* ms */ #define RTW_MAX_NUM_PMKIDS 4 -#define RTW_CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ - static const u32 rtw_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, @@ -2024,8 +2022,6 @@ static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev)); - padapter->mlmepriv.not_indic_disco = true; - old_type = rtw_wdev->iftype; rtw_set_to_roam(padapter, 0); @@ -2047,8 +2043,6 @@ static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) } leave_ibss: - padapter->mlmepriv.not_indic_disco = false; - return 0; } @@ -2246,8 +2240,6 @@ static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev, DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev)); - padapter->mlmepriv.not_indic_disco = true; - rtw_set_to_roam(padapter, 0); rtw_scan_abort(padapter); @@ -2261,8 +2253,6 @@ static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev, rtw_free_assoc_resources(padapter, 1); rtw_pwr_wakeup(padapter); - padapter->mlmepriv.not_indic_disco = false; - DBG_871X(FUNC_NDEV_FMT" return 0\n", FUNC_NDEV_ARG(ndev)); return 0; } diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c index 99e6b1028f71..d1b199e3e5bd 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c @@ -21,13 +21,10 @@ #define RATE_COUNT 4 /* combo scan */ -#define WEXT_CSCAN_AMOUNT 9 -#define WEXT_CSCAN_BUF_LEN 360 #define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00" #define WEXT_CSCAN_HEADER_SIZE 12 #define WEXT_CSCAN_SSID_SECTION 'S' #define WEXT_CSCAN_CHANNEL_SECTION 'C' -#define WEXT_CSCAN_NPROBE_SECTION 'N' #define WEXT_CSCAN_ACTV_DWELL_SECTION 'A' #define WEXT_CSCAN_PASV_DWELL_SECTION 'P' #define WEXT_CSCAN_HOME_DWELL_SECTION 'H' @@ -215,8 +212,6 @@ static char *translate_scan(struct adapter *padapter, } else if (ht_cap) { if (mcs_rate&0x8000) { /* MCS15 */ max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130); - } else if (mcs_rate&0x0080) { /* MCS7 */ - max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); } else { /* default MCS7 */ /* DBG_871X("wx_get_scan, mcs_rate_bitmap = 0x%x\n", mcs_rate); */ max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); @@ -4912,7 +4907,6 @@ static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_ s32 k; const iw_handler *priv; /* Private ioctl */ const struct iw_priv_args *priv_args; /* Private ioctl description */ - u32 num_priv; /* Number of ioctl */ u32 num_priv_args; /* Number of descriptions */ iw_handler handler; int temp; @@ -4948,7 +4942,6 @@ static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_ priv = rtw_private_handler; priv_args = rtw_private_args; - num_priv = ARRAY_SIZE(rtw_private_handler); num_priv_args = ARRAY_SIZE(rtw_private_args); if (num_priv_args == 0) { diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index 544e799d0a03..ec3a75485233 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -239,9 +239,6 @@ static void loadparam(struct adapter *padapter, _nic_hdl pnetdev) registry_par->channel = (u8)rtw_channel; registry_par->wireless_mode = (u8)rtw_wireless_mode; - if (registry_par->channel > 14) - registry_par->channel = 1; - registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense ; registry_par->vcs_type = (u8)rtw_vcs_type; registry_par->rts_thresh = (u16)rtw_rts_thresh; @@ -448,12 +445,6 @@ static int rtw_ndev_notifier_call(struct notifier_block *nb, unsigned long state DBG_871X_LEVEL(_drv_info_, FUNC_NDEV_FMT " state:%lu\n", FUNC_NDEV_ARG(dev), state); - switch (state) { - case NETDEV_CHANGENAME: - rtw_adapter_proc_replace(dev); - break; - } - return NOTIFY_DONE; } @@ -478,7 +469,6 @@ static int rtw_ndev_init(struct net_device *dev) DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(adapter)); strncpy(adapter->old_ifname, dev->name, IFNAMSIZ); - rtw_adapter_proc_init(dev); return 0; } @@ -488,7 +478,6 @@ static void rtw_ndev_uninit(struct net_device *dev) struct adapter *adapter = rtw_netdev_priv(dev); DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(adapter)); - rtw_adapter_proc_deinit(dev); } static const struct net_device_ops rtw_netdev_ops = { @@ -768,11 +757,7 @@ u8 rtw_init_drv_sw(struct adapter *padapter) goto exit; } - if (init_mlme_ext_priv(padapter) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init mlme_ext_priv\n")); - ret8 = _FAIL; - goto exit; - } + init_mlme_ext_priv(padapter); if (_rtw_init_xmit_priv(&padapter->xmitpriv, padapter) == _FAIL) { DBG_871X("Can't _rtw_init_xmit_priv\n"); @@ -1361,13 +1346,12 @@ void rtw_suspend_wow(struct adapter *padapter) #endif /* ifdef CONFIG_WOWLAN */ #ifdef CONFIG_AP_WOWLAN -int rtw_suspend_ap_wow(struct adapter *padapter) +void rtw_suspend_ap_wow(struct adapter *padapter) { u8 ch, bw, offset; struct net_device *pnetdev = padapter->pnetdev; struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); struct wowlan_ioctl_param poidparam; - int ret = _SUCCESS; DBG_871X("==> " FUNC_ADPT_FMT " entry....\n", FUNC_ADPT_ARG(padapter)); @@ -1409,7 +1393,6 @@ int rtw_suspend_ap_wow(struct adapter *padapter) rtw_set_ps_mode(padapter, PS_MODE_MIN, 0, 0, "AP-WOWLAN"); DBG_871X("<== " FUNC_ADPT_FMT " exit....\n", FUNC_ADPT_ARG(padapter)); - return ret; } #endif /* ifdef CONFIG_AP_WOWLAN */ diff --git a/drivers/staging/rtl8723bs/os_dep/osdep_service.c b/drivers/staging/rtl8723bs/os_dep/osdep_service.c index 62fdd24ba427..25a80041ce87 100644 --- a/drivers/staging/rtl8723bs/os_dep/osdep_service.c +++ b/drivers/staging/rtl8723bs/os_dep/osdep_service.c @@ -318,13 +318,9 @@ error: void rtw_buf_free(u8 **buf, u32 *buf_len) { - u32 ori_len; - if (!buf || !buf_len) return; - ori_len = *buf_len; - if (*buf) { *buf_len = 0; kfree(*buf); diff --git a/drivers/staging/rtl8723bs/os_dep/rtw_proc.c b/drivers/staging/rtl8723bs/os_dep/rtw_proc.c deleted file mode 100644 index 5f950fda48ea..000000000000 --- a/drivers/staging/rtl8723bs/os_dep/rtw_proc.c +++ /dev/null @@ -1,779 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * - * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ - -#include <drv_types.h> -#include <rtw_debug.h> -#include "rtw_proc.h" - -#ifdef PROC_DEBUG - -static struct proc_dir_entry *rtw_proc; - -#define RTW_PROC_NAME "rtl8723bs" - -#define get_proc_net init_net.proc_net - -inline struct proc_dir_entry *rtw_proc_create_dir(const char *name, struct proc_dir_entry *parent, void *data) -{ - struct proc_dir_entry *entry; - - entry = proc_mkdir_data(name, S_IRUGO|S_IXUGO, parent, data); - - return entry; -} - -inline struct proc_dir_entry *rtw_proc_create_entry(const char *name, struct proc_dir_entry *parent, - const struct file_operations *fops, void *data) -{ - struct proc_dir_entry *entry; - - entry = proc_create_data(name, S_IFREG|S_IRUGO, parent, fops, data); - - return entry; -} - -static int proc_get_dummy(struct seq_file *m, void *v) -{ - return 0; -} - -static int proc_get_drv_version(struct seq_file *m, void *v) -{ - dump_drv_version(m); - return 0; -} - -static int proc_get_log_level(struct seq_file *m, void *v) -{ - dump_log_level(m); - return 0; -} - -static ssize_t proc_set_log_level(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - char tmp[32]; - int log_level; - - if (count < 1) - return -EINVAL; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%d ", &log_level); - if (log_level >= _drv_always_ && log_level <= _drv_debug_) { - GlobalDebugLevel = log_level; - printk("%d\n", GlobalDebugLevel); - } - } else { - return -EFAULT; - } - - return count; -} - -/* -* rtw_drv_proc: -* init/deinit when register/unregister driver -*/ -static const struct rtw_proc_hdl drv_proc_hdls[] = { - {"ver_info", proc_get_drv_version, NULL}, - {"log_level", proc_get_log_level, proc_set_log_level}, -}; - -static const int drv_proc_hdls_num = sizeof(drv_proc_hdls) / sizeof(struct rtw_proc_hdl); - -static int rtw_drv_proc_open(struct inode *inode, struct file *file) -{ - /* struct net_device *dev = proc_get_parent_data(inode); */ - ssize_t index = (ssize_t)PDE_DATA(inode); - const struct rtw_proc_hdl *hdl = drv_proc_hdls+index; - - return single_open(file, hdl->show, NULL); -} - -static ssize_t rtw_drv_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) -{ - ssize_t index = (ssize_t)PDE_DATA(file_inode(file)); - const struct rtw_proc_hdl *hdl = drv_proc_hdls+index; - ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *, void *) = hdl->write; - - if (write) - return write(file, buffer, count, pos, NULL); - - return -EROFS; -} - -static const struct file_operations rtw_drv_proc_fops = { - .owner = THIS_MODULE, - .open = rtw_drv_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = rtw_drv_proc_write, -}; - -int rtw_drv_proc_init(void) -{ - int ret = _FAIL; - ssize_t i; - struct proc_dir_entry *entry = NULL; - - if (rtw_proc) { - rtw_warn_on(1); - goto exit; - } - - rtw_proc = rtw_proc_create_dir(RTW_PROC_NAME, get_proc_net, NULL); - - if (!rtw_proc) { - rtw_warn_on(1); - goto exit; - } - - for (i = 0; i < drv_proc_hdls_num; i++) { - entry = rtw_proc_create_entry(drv_proc_hdls[i].name, rtw_proc, &rtw_drv_proc_fops, (void *)i); - if (!entry) { - rtw_warn_on(1); - goto exit; - } - } - - ret = _SUCCESS; - -exit: - return ret; -} - -void rtw_drv_proc_deinit(void) -{ - int i; - - if (!rtw_proc) - return; - - for (i = 0; i < drv_proc_hdls_num; i++) - remove_proc_entry(drv_proc_hdls[i].name, rtw_proc); - - remove_proc_entry(RTW_PROC_NAME, get_proc_net); - rtw_proc = NULL; -} - -static int proc_get_sd_f0_reg_dump(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - sd_f0_reg_dump(m, adapter); - - return 0; -} - -static int proc_get_mac_reg_dump(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - mac_reg_dump(m, adapter); - - return 0; -} - -static int proc_get_bb_reg_dump(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - bb_reg_dump(m, adapter); - - return 0; -} - -static int proc_get_rf_reg_dump(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - rf_reg_dump(m, adapter); - - return 0; -} -static int proc_get_linked_info_dump(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - if (padapter) - DBG_871X_SEL_NL(m, "linked_info_dump :%s\n", (padapter->bLinkInfoDump)?"enable":"disable"); - - return 0; -} - -static ssize_t proc_set_linked_info_dump(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - char tmp[2]; - int mode = 0; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - if (padapter) { - /* padapter->bLinkInfoDump = mode; */ - /* DBG_871X("linked_info_dump =%s\n", (padapter->bLinkInfoDump)?"enable":"disable"); */ - linked_info_dump(padapter, mode); - } - - } - - return count; - -} - -static int proc_get_rx_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct dvobj_priv *psdpriv = padapter->dvobj; - struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; - - /* Counts of packets whose seq_num is less than preorder_ctrl->indicate_seq, Ex delay, retransmission, redundant packets and so on */ - DBG_871X_SEL_NL(m,"Counts of Packets Whose Seq_Num Less Than Reorder Control Seq_Num: %llu\n", (unsigned long long)pdbgpriv->dbg_rx_ampdu_drop_count); - /* How many times the Rx Reorder Timer is triggered. */ - DBG_871X_SEL_NL(m,"Rx Reorder Time-out Trigger Counts: %llu\n", (unsigned long long)pdbgpriv->dbg_rx_ampdu_forced_indicate_count); - /* Total counts of packets loss */ - DBG_871X_SEL_NL(m,"Rx Packet Loss Counts: %llu\n", (unsigned long long)pdbgpriv->dbg_rx_ampdu_loss_count); - DBG_871X_SEL_NL(m,"Duplicate Management Frame Drop Count: %llu\n", (unsigned long long)pdbgpriv->dbg_rx_dup_mgt_frame_drop_count); - DBG_871X_SEL_NL(m,"AMPDU BA window shift Count: %llu\n", (unsigned long long)pdbgpriv->dbg_rx_ampdu_window_shift_cnt); - return 0; -} - - -static ssize_t proc_reset_rx_info(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct dvobj_priv *psdpriv = padapter->dvobj; - struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; - char cmd[32]; - if (buffer && !copy_from_user(cmd, buffer, sizeof(cmd))) { - if ('0' == cmd[0]) { - pdbgpriv->dbg_rx_ampdu_drop_count = 0; - pdbgpriv->dbg_rx_ampdu_forced_indicate_count = 0; - pdbgpriv->dbg_rx_ampdu_loss_count = 0; - pdbgpriv->dbg_rx_dup_mgt_frame_drop_count = 0; - pdbgpriv->dbg_rx_ampdu_window_shift_cnt = 0; - } - } - - return count; -} - -static int proc_get_cam(struct seq_file *m, void *v) -{ - return 0; -} - -static ssize_t proc_set_cam(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter; - - char tmp[32]; - char cmd[5]; - u8 id; - - adapter = (struct adapter *)rtw_netdev_priv(dev); - if (!adapter) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - /* c <id>: clear specific cam entry */ - /* wfc <id>: write specific cam entry from cam cache */ - - int num = sscanf(tmp, "%4s %hhu", cmd, &id); - - if (num < 2) - return count; - if (id >= TOTAL_CAM_ENTRY) - return -EINVAL; - - if (strcmp("c", cmd) == 0) { - _clear_cam_entry(adapter, id); - adapter->securitypriv.hw_decrypted = false; /* temporarily set this for TX path to use SW enc */ - } else if (strcmp("wfc", cmd) == 0) { - write_cam_from_cache(adapter, id); - } - } - - return count; -} - -static int proc_get_cam_cache(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); - u8 i; - - DBG_871X_SEL_NL(m, "cam bitmap:0x%016llx\n", dvobj->cam_ctl.bitmap); - - DBG_871X_SEL_NL(m, "%-2s %-6s %-17s %-32s %-3s %-7s" - /* %-2s %-2s %-4s %-5s" */ - "\n" - , "id", "ctrl", "addr", "key", "kid", "type" - /* "MK", "GK", "MFB", "valid" */ - ); - - for (i = 0; i < 32; i++) { - if (dvobj->cam_cache[i].ctrl != 0) - DBG_871X_SEL_NL(m, "%2u 0x%04x "MAC_FMT" "KEY_FMT" %3u %-7s" - /* %2u %2u 0x%02x %5u" */ - "\n", i - , dvobj->cam_cache[i].ctrl - , MAC_ARG(dvobj->cam_cache[i].mac) - , KEY_ARG(dvobj->cam_cache[i].key) - , (dvobj->cam_cache[i].ctrl)&0x03 - , security_type_str(((dvobj->cam_cache[i].ctrl)>>2)&0x07) - /* ((dvobj->cam_cache[i].ctrl)>>5)&0x01 */ - /* ((dvobj->cam_cache[i].ctrl)>>6)&0x01 */ - /* ((dvobj->cam_cache[i].ctrl)>>8)&0x7f */ - /* ((dvobj->cam_cache[i].ctrl)>>15)&0x01 */ - ); - } - - return 0; -} - -/* -* rtw_adapter_proc: -* init/deinit when register/unregister net_device -*/ -static const struct rtw_proc_hdl adapter_proc_hdls[] = { - {"write_reg", proc_get_dummy, proc_set_write_reg}, - {"read_reg", proc_get_read_reg, proc_set_read_reg}, - {"fwstate", proc_get_fwstate, NULL}, - {"sec_info", proc_get_sec_info, NULL}, - {"mlmext_state", proc_get_mlmext_state, NULL}, - {"qos_option", proc_get_qos_option, NULL}, - {"ht_option", proc_get_ht_option, NULL}, - {"rf_info", proc_get_rf_info, NULL}, - {"survey_info", proc_get_survey_info, NULL}, - {"ap_info", proc_get_ap_info, NULL}, - {"adapter_state", proc_get_adapter_state, NULL}, - {"trx_info", proc_get_trx_info, NULL}, - {"rate_ctl", proc_get_rate_ctl, proc_set_rate_ctl}, - {"cam", proc_get_cam, proc_set_cam}, - {"cam_cache", proc_get_cam_cache, NULL}, - {"suspend_info", proc_get_suspend_resume_info, NULL}, - {"rx_info", proc_get_rx_info, proc_reset_rx_info}, - - {"roam_flags", proc_get_roam_flags, proc_set_roam_flags}, - {"roam_param", proc_get_roam_param, proc_set_roam_param}, - {"roam_tgt_addr", proc_get_dummy, proc_set_roam_tgt_addr}, - - {"sd_f0_reg_dump", proc_get_sd_f0_reg_dump, NULL}, - - {"fwdl_test_case", proc_get_dummy, proc_set_fwdl_test_case}, - {"wait_hiq_empty", proc_get_dummy, proc_set_wait_hiq_empty}, - - {"mac_reg_dump", proc_get_mac_reg_dump, NULL}, - {"bb_reg_dump", proc_get_bb_reg_dump, NULL}, - {"rf_reg_dump", proc_get_rf_reg_dump, NULL}, - - {"all_sta_info", proc_get_all_sta_info, NULL}, - - {"rx_signal", proc_get_rx_signal, proc_set_rx_signal}, - {"hw_info", proc_get_hw_status, NULL}, - - {"ht_enable", proc_get_ht_enable, proc_set_ht_enable}, - {"bw_mode", proc_get_bw_mode, proc_set_bw_mode}, - {"ampdu_enable", proc_get_ampdu_enable, proc_set_ampdu_enable}, - {"rx_stbc", proc_get_rx_stbc, proc_set_rx_stbc}, - {"rx_ampdu", proc_get_rx_ampdu, proc_set_rx_ampdu}, - - {"en_fwps", proc_get_en_fwps, proc_set_en_fwps}, - - /* path_rssi", proc_get_two_path_rssi, NULL}, */ - {"rssi_disp", proc_get_rssi_disp, proc_set_rssi_disp}, - - {"btcoex_dbg", proc_get_btcoex_dbg, proc_set_btcoex_dbg}, - {"btcoex", proc_get_btcoex_info, NULL}, - - {"linked_info_dump", proc_get_linked_info_dump, proc_set_linked_info_dump}, -#ifdef CONFIG_DBG_COUNTER - {"rx_logs", proc_get_rx_logs, NULL}, - {"tx_logs", proc_get_tx_logs, NULL}, - {"int_logs", proc_get_int_logs, NULL}, -#endif -}; - -static const int adapter_proc_hdls_num = sizeof(adapter_proc_hdls) / sizeof(struct rtw_proc_hdl); - -static int rtw_adapter_proc_open(struct inode *inode, struct file *file) -{ - ssize_t index = (ssize_t)PDE_DATA(inode); - const struct rtw_proc_hdl *hdl = adapter_proc_hdls+index; - - return single_open(file, hdl->show, proc_get_parent_data(inode)); -} - -static ssize_t rtw_adapter_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) -{ - ssize_t index = (ssize_t)PDE_DATA(file_inode(file)); - const struct rtw_proc_hdl *hdl = adapter_proc_hdls+index; - ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *, void *) = hdl->write; - - if (write) - return write(file, buffer, count, pos, ((struct seq_file *)file->private_data)->private); - - return -EROFS; -} - -static const struct file_operations rtw_adapter_proc_fops = { - .owner = THIS_MODULE, - .open = rtw_adapter_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = rtw_adapter_proc_write, -}; - -int proc_get_odm_dbg_comp(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - rtw_odm_dbg_comp_msg(m, adapter); - - return 0; -} - -ssize_t proc_set_odm_dbg_comp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - - u64 dbg_comp; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%llx", &dbg_comp); - - if (num != 1) - return count; - - rtw_odm_dbg_comp_set(adapter, dbg_comp); - } - - return count; -} - -int proc_get_odm_dbg_level(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - rtw_odm_dbg_level_msg(m, adapter); - - return 0; -} - -ssize_t proc_set_odm_dbg_level(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - - u32 dbg_level; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%u", &dbg_level); - - if (num != 1) - return count; - - rtw_odm_dbg_level_set(adapter, dbg_level); - } - - return count; -} - -static int proc_get_odm_ability(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - rtw_odm_ability_msg(m, adapter); - - return 0; -} - -static ssize_t proc_set_odm_ability(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - - u32 ability; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%x", &ability); - - if (num != 1) - return count; - - rtw_odm_ability_set(adapter, ability); - } - - return count; -} - -int proc_get_odm_adaptivity(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - rtw_odm_adaptivity_parm_msg(m, padapter); - - return 0; -} - -ssize_t proc_set_odm_adaptivity(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u32 TH_L2H_ini; - s8 TH_EDCCA_HL_diff; - u32 IGI_Base; - int ForceEDCCA; - u8 AdapEn_RSSI; - u8 IGI_LowerBound; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%x %hhd %x %d %hhu %hhu", - &TH_L2H_ini, &TH_EDCCA_HL_diff, &IGI_Base, &ForceEDCCA, &AdapEn_RSSI, &IGI_LowerBound); - - if (num != 6) - return count; - - rtw_odm_adaptivity_parm_set(padapter, (s8)TH_L2H_ini, TH_EDCCA_HL_diff, (s8)IGI_Base, (bool)ForceEDCCA, AdapEn_RSSI, IGI_LowerBound); - } - - return count; -} - -/* -* rtw_odm_proc: -* init/deinit when register/unregister net_device, along with rtw_adapter_proc -*/ -static const struct rtw_proc_hdl odm_proc_hdls[] = { - {"dbg_comp", proc_get_odm_dbg_comp, proc_set_odm_dbg_comp}, - {"dbg_level", proc_get_odm_dbg_level, proc_set_odm_dbg_level}, - {"ability", proc_get_odm_ability, proc_set_odm_ability}, - {"adaptivity", proc_get_odm_adaptivity, proc_set_odm_adaptivity}, -}; - -static const int odm_proc_hdls_num = sizeof(odm_proc_hdls) / sizeof(struct rtw_proc_hdl); - -static int rtw_odm_proc_open(struct inode *inode, struct file *file) -{ - ssize_t index = (ssize_t)PDE_DATA(inode); - const struct rtw_proc_hdl *hdl = odm_proc_hdls+index; - - return single_open(file, hdl->show, proc_get_parent_data(inode)); -} - -static ssize_t rtw_odm_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) -{ - ssize_t index = (ssize_t)PDE_DATA(file_inode(file)); - const struct rtw_proc_hdl *hdl = odm_proc_hdls+index; - ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *, void *) = hdl->write; - - if (write) - return write(file, buffer, count, pos, ((struct seq_file *)file->private_data)->private); - - return -EROFS; -} - -static const struct file_operations rtw_odm_proc_fops = { - .owner = THIS_MODULE, - .open = rtw_odm_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = rtw_odm_proc_write, -}; - -static struct proc_dir_entry *rtw_odm_proc_init(struct net_device *dev) -{ - struct proc_dir_entry *dir_odm = NULL; - struct proc_dir_entry *entry = NULL; - struct adapter *adapter = rtw_netdev_priv(dev); - ssize_t i; - - if (!adapter->dir_dev) { - rtw_warn_on(1); - goto exit; - } - - if (adapter->dir_odm) { - rtw_warn_on(1); - goto exit; - } - - dir_odm = rtw_proc_create_dir("odm", adapter->dir_dev, dev); - if (!dir_odm) { - rtw_warn_on(1); - goto exit; - } - - adapter->dir_odm = dir_odm; - - for (i = 0; i < odm_proc_hdls_num; i++) { - entry = rtw_proc_create_entry(odm_proc_hdls[i].name, dir_odm, &rtw_odm_proc_fops, (void *)i); - if (!entry) { - rtw_warn_on(1); - goto exit; - } - } - -exit: - return dir_odm; -} - -static void rtw_odm_proc_deinit(struct adapter *adapter) -{ - struct proc_dir_entry *dir_odm = NULL; - int i; - - dir_odm = adapter->dir_odm; - - if (!dir_odm) { - rtw_warn_on(1); - return; - } - - for (i = 0; i < odm_proc_hdls_num; i++) - remove_proc_entry(odm_proc_hdls[i].name, dir_odm); - - remove_proc_entry("odm", adapter->dir_dev); - - adapter->dir_odm = NULL; -} - -struct proc_dir_entry *rtw_adapter_proc_init(struct net_device *dev) -{ - struct proc_dir_entry *drv_proc = rtw_proc; - struct proc_dir_entry *dir_dev = NULL; - struct proc_dir_entry *entry = NULL; - struct adapter *adapter = rtw_netdev_priv(dev); - ssize_t i; - - if (!drv_proc) { - rtw_warn_on(1); - goto exit; - } - - if (adapter->dir_dev) { - rtw_warn_on(1); - goto exit; - } - - dir_dev = rtw_proc_create_dir(dev->name, drv_proc, dev); - if (!dir_dev) { - rtw_warn_on(1); - goto exit; - } - - adapter->dir_dev = dir_dev; - - for (i = 0; i < adapter_proc_hdls_num; i++) { - entry = rtw_proc_create_entry(adapter_proc_hdls[i].name, dir_dev, &rtw_adapter_proc_fops, (void *)i); - if (!entry) { - rtw_warn_on(1); - goto exit; - } - } - - rtw_odm_proc_init(dev); - -exit: - return dir_dev; -} - -void rtw_adapter_proc_deinit(struct net_device *dev) -{ - struct proc_dir_entry *drv_proc = rtw_proc; - struct proc_dir_entry *dir_dev = NULL; - struct adapter *adapter = rtw_netdev_priv(dev); - int i; - - dir_dev = adapter->dir_dev; - - if (!dir_dev) { - rtw_warn_on(1); - return; - } - - for (i = 0; i < adapter_proc_hdls_num; i++) - remove_proc_entry(adapter_proc_hdls[i].name, dir_dev); - - rtw_odm_proc_deinit(adapter); - - remove_proc_entry(dev->name, drv_proc); - - adapter->dir_dev = NULL; -} - -void rtw_adapter_proc_replace(struct net_device *dev) -{ - struct proc_dir_entry *drv_proc = rtw_proc; - struct proc_dir_entry *dir_dev = NULL; - struct adapter *adapter = rtw_netdev_priv(dev); - int i; - - dir_dev = adapter->dir_dev; - - if (!dir_dev) { - rtw_warn_on(1); - return; - } - - for (i = 0; i < adapter_proc_hdls_num; i++) - remove_proc_entry(adapter_proc_hdls[i].name, dir_dev); - - rtw_odm_proc_deinit(adapter); - - remove_proc_entry(adapter->old_ifname, drv_proc); - - adapter->dir_dev = NULL; - - rtw_adapter_proc_init(dev); - -} - -#endif /* PROC_DEBUG */ diff --git a/drivers/staging/rtl8723bs/os_dep/rtw_proc.h b/drivers/staging/rtl8723bs/os_dep/rtw_proc.h deleted file mode 100644 index c7e6f62b61ef..000000000000 --- a/drivers/staging/rtl8723bs/os_dep/rtw_proc.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTW_PROC_H__ -#define __RTW_PROC_H__ - -#include <linux/proc_fs.h> -#include <linux/seq_file.h> - -struct rtw_proc_hdl { - char *name; - int (*show)(struct seq_file *, void *); - ssize_t (*write)(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -}; - -#ifdef PROC_DEBUG - -int rtw_drv_proc_init(void); -void rtw_drv_proc_deinit(void); -struct proc_dir_entry *rtw_adapter_proc_init(struct net_device *dev); -void rtw_adapter_proc_deinit(struct net_device *dev); -void rtw_adapter_proc_replace(struct net_device *dev); - -#else //!PROC_DEBUG - -static inline int rtw_drv_proc_init(void) {return 0;} -static inline void rtw_drv_proc_deinit(void) {} -static inline struct proc_dir_entry *rtw_adapter_proc_init(struct net_device *dev){return NULL;} -static inline void rtw_adapter_proc_deinit(struct net_device *dev){} -static inline void rtw_adapter_proc_replace(struct net_device *dev){} - -#endif //!PROC_DEBUG - -#endif //__RTW_PROC_H__ diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c index 540a7eed621d..d3784c44f6d0 100644 --- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c @@ -371,7 +371,7 @@ static struct adapter *rtw_sdio_if1_init(struct dvobj_priv *dvobj, const struct rtw_hal_chip_configure(padapter); - hal_btcoex_Initialize(padapter); + hal_btcoex_Initialize((void *) padapter); /* 3 6. read efuse/eeprom data */ rtw_hal_read_chip_info(padapter); @@ -620,12 +620,10 @@ static int __init rtw_drv_entry(void) #endif /* BTCOEXVERSION */ sdio_drvpriv.drv_registered = true; - rtw_drv_proc_init(); ret = sdio_register_driver(&sdio_drvpriv.r871xs_drv); if (ret != 0) { sdio_drvpriv.drv_registered = false; - rtw_drv_proc_deinit(); rtw_ndev_notifier_unregister(); DBG_871X("%s: register driver failed!!(%d)\n", __func__, ret); goto exit; @@ -646,7 +644,6 @@ static void __exit rtw_drv_halt(void) sdio_unregister_driver(&sdio_drvpriv.r871xs_drv); - rtw_drv_proc_deinit(); rtw_ndev_notifier_unregister(); DBG_871X_LEVEL(_drv_always_, "module exit success\n"); diff --git a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c index aa2f62acc994..578b9f734231 100644 --- a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c +++ b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c @@ -33,11 +33,6 @@ REG_RULE(2467 - 10, 2472 + 10, 40, 0, 20, \ NL80211_RRF_PASSIVE_SCAN) -/* 2G chan 14, PASSIVS SCAN, NO OFDM (B only) */ -#define RTW_2GHZ_CH14 \ - REG_RULE(2484 - 10, 2484 + 10, 40, 0, 20, \ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) - static const struct ieee80211_regdomain rtw_regdom_rd = { .n_reg_rules = 3, .alpha2 = "99", diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 1128eec3bd08..e853fa9cc950 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -3842,7 +3842,7 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - int retval = STATUS_FAIL; + int retval; int bufflen; unsigned int lun = SCSI_LUN(srb); u8 *buf = NULL; diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c index 8277d7895608..561851cc8780 100644 --- a/drivers/staging/rts5208/rtsx_transport.c +++ b/drivers/staging/rts5208/rtsx_transport.c @@ -393,10 +393,9 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, *offset = 0; *index = *index + 1; } - if ((i == (sg_cnt - 1)) || !resid) - option = RTSX_SG_VALID | RTSX_SG_END | RTSX_SG_TRANS_DATA; - else - option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA; + option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA; + if ((i == sg_cnt - 1) || !resid) + option |= RTSX_SG_END; rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option); @@ -541,10 +540,9 @@ static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, dev_dbg(rtsx_dev(chip), "DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len); + option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA; if (j == (sg_cnt - 1)) - option = RTSX_SG_VALID | RTSX_SG_END | RTSX_SG_TRANS_DATA; - else - option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA; + option |= RTSX_SG_END; rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option); diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index a06045344301..25c31496757e 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -2573,17 +2573,13 @@ SD_UNLOCK_ENTRY: retval = sd_sdr_tuning(chip); if (retval != STATUS_SUCCESS) { - if (sd20_mode) { + retval = sd_init_power(chip); + if (retval != STATUS_SUCCESS) goto status_fail; - } else { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - try_sdio = false; - sd20_mode = true; - goto switch_fail; - } + try_sdio = false; + sd20_mode = true; + goto switch_fail; } sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, @@ -2598,17 +2594,13 @@ SD_UNLOCK_ENTRY: if (read_lba0) { retval = sd_read_lba0(chip); if (retval != STATUS_SUCCESS) { - if (sd20_mode) { + retval = sd_init_power(chip); + if (retval != STATUS_SUCCESS) goto status_fail; - } else { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - try_sdio = false; - sd20_mode = true; - goto switch_fail; - } + try_sdio = false; + sd20_mode = true; + goto switch_fail; } } } diff --git a/drivers/staging/sm750fb/ddk750.h b/drivers/staging/sm750fb/ddk750.h index 482c1c6ba422..64ef4d258a91 100644 --- a/drivers/staging/sm750fb/ddk750.h +++ b/drivers/staging/sm750fb/ddk750.h @@ -2,9 +2,6 @@ /* * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) * - * All rights are reserved. Reproduction or in part is prohibited - * without the written consent of the copyright owner. - * * RegSC.h --- SM718 SDK * This file contains the definitions for the System Configuration registers. */ diff --git a/drivers/staging/sm750fb/ddk750_swi2c.c b/drivers/staging/sm750fb/ddk750_swi2c.c index 5c0ac747ea2b..0ef8d4ff2ef9 100644 --- a/drivers/staging/sm750fb/ddk750_swi2c.c +++ b/drivers/staging/sm750fb/ddk750_swi2c.c @@ -2,9 +2,6 @@ /* * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) * - * All rights are reserved. Reproduction or in part is prohibited - * without the written consent of the copyright owner. - * * swi2c.c --- SM750/SM718 DDK * This file contains the source code for I2C using software * implementation. diff --git a/drivers/staging/sm750fb/ddk750_swi2c.h b/drivers/staging/sm750fb/ddk750_swi2c.h index 5868feea791b..dfa166060da7 100644 --- a/drivers/staging/sm750fb/ddk750_swi2c.h +++ b/drivers/staging/sm750fb/ddk750_swi2c.h @@ -2,9 +2,6 @@ /* * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) * - * All rights are reserved. Reproduction or in part is prohibited - * without the written consent of the copyright owner. - * * swi2c.h --- SM750/SM718 DDK * This file contains the definitions for i2c using software * implementation. diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h index f738e7f99e96..47897e81ec58 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h +++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h @@ -56,7 +56,7 @@ struct vchiq_mmal_port { /* component port belongs to, allows simple deref */ struct vchiq_mmal_component *component; - struct vchiq_mmal_port *connected; /* port conencted to */ + struct vchiq_mmal_port *connected; /* port connected to */ /* buffer info */ struct vchiq_mmal_port_buffer minimum_buffer; 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 61c69f353cdb..8dc730cfe7a6 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 @@ -141,10 +141,8 @@ int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state) return PTR_ERR(g_regs); irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(dev, "failed to get IRQ\n"); + if (irq <= 0) return irq; - } err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, "VCHIQ doorbell", state); 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 cc4383d1ec3e..b1595b13dea8 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -2824,7 +2824,6 @@ vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; char entity[16]; int *entity_uc; - int local_uc, local_entity_uc; if (!arm_state) goto out; @@ -2849,8 +2848,8 @@ vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) ret = VCHIQ_ERROR; goto unlock; } - local_uc = --arm_state->videocore_use_count; - local_entity_uc = --(*entity_uc); + --arm_state->videocore_use_count; + --(*entity_uc); if (!vchiq_videocore_wanted(state)) { if (vchiq_platform_use_suspend_timer() && 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 183f5cf887e0..56a23a297fa4 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -3322,13 +3322,13 @@ vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state, char buf[80]; int len; - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " %s: slots %d-%d tx_pos=%x recycle=%x", label, shared->slot_first, shared->slot_last, shared->tx_pos, shared->slot_queue_recycle); vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Slots claimed:"); vchiq_dump(dump_context, buf, len + 1); @@ -3336,7 +3336,7 @@ vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state, struct vchiq_slot_info slot_info = *SLOT_INFO_FROM_INDEX(state, i); if (slot_info.use_count != slot_info.release_count) { - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " %d: %d/%d", i, slot_info.use_count, slot_info.release_count); vchiq_dump(dump_context, buf, len + 1); @@ -3344,7 +3344,7 @@ vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state, } for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++) { - len = snprintf(buf, sizeof(buf), " DEBUG: %s = %d(%x)", + len = scnprintf(buf, sizeof(buf), " DEBUG: %s = %d(%x)", debug_names[i], shared->debug[i], shared->debug[i]); vchiq_dump(dump_context, buf, len + 1); } @@ -3357,11 +3357,11 @@ vchiq_dump_state(void *dump_context, struct vchiq_state *state) int len; int i; - len = snprintf(buf, sizeof(buf), "State %d: %s", state->id, + len = scnprintf(buf, sizeof(buf), "State %d: %s", state->id, conn_state_names[state->conn_state]); vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " tx_pos=%x(@%pK), rx_pos=%x(@%pK)", state->local->tx_pos, state->tx_data + (state->local_tx_pos & VCHIQ_SLOT_MASK), @@ -3369,13 +3369,13 @@ vchiq_dump_state(void *dump_context, struct vchiq_state *state) state->rx_data + (state->rx_pos & VCHIQ_SLOT_MASK)); vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Version: %d (min %d)", VCHIQ_VERSION, VCHIQ_VERSION_MIN); vchiq_dump(dump_context, buf, len + 1); if (VCHIQ_ENABLE_STATS) { - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Stats: ctrl_tx_count=%d, ctrl_rx_count=%d, " "error_count=%d", state->stats.ctrl_tx_count, state->stats.ctrl_rx_count, @@ -3383,7 +3383,7 @@ vchiq_dump_state(void *dump_context, struct vchiq_state *state) vchiq_dump(dump_context, buf, len + 1); } - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Slots: %d available (%d data), %d recyclable, %d stalls " "(%d data)", ((state->slot_queue_available * VCHIQ_SLOT_SIZE) - @@ -3416,7 +3416,7 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) char buf[80]; int len; - len = snprintf(buf, sizeof(buf), "Service %u: %s (ref %u)", + len = scnprintf(buf, sizeof(buf), "Service %u: %s (ref %u)", service->localport, srvstate_names[service->srvstate], service->ref_count - 1); /*Don't include the lock just taken*/ @@ -3428,17 +3428,17 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) int tx_pending, rx_pending; if (service->remoteport != VCHIQ_PORT_FREE) { - int len2 = snprintf(remoteport, sizeof(remoteport), + int len2 = scnprintf(remoteport, sizeof(remoteport), "%u", service->remoteport); if (service->public_fourcc != VCHIQ_FOURCC_INVALID) - snprintf(remoteport + len2, + scnprintf(remoteport + len2, sizeof(remoteport) - len2, " (client %x)", service->client_id); } else strcpy(remoteport, "n/a"); - len += snprintf(buf + len, sizeof(buf) - len, + len += scnprintf(buf + len, sizeof(buf) - len, " '%c%c%c%c' remote %s (msg use %d/%d, slot use %d/%d)", VCHIQ_FOURCC_AS_4CHARS(fourcc), remoteport, @@ -3455,7 +3455,7 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) rx_pending = service->bulk_rx.local_insert - service->bulk_rx.remote_insert; - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Bulk: tx_pending=%d (size %d)," " rx_pending=%d (size %d)", tx_pending, @@ -3468,7 +3468,7 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) if (VCHIQ_ENABLE_STATS) { vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Ctrl: tx_count=%d, tx_bytes=%llu, " "rx_count=%d, rx_bytes=%llu", service->stats.ctrl_tx_count, @@ -3477,7 +3477,7 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) service->stats.ctrl_rx_bytes); vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Bulk: tx_count=%d, tx_bytes=%llu, " "rx_count=%d, rx_bytes=%llu", service->stats.bulk_tx_count, @@ -3486,7 +3486,7 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) service->stats.bulk_rx_bytes); vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " %d quota stalls, %d slot stalls, " "%d bulk stalls, %d aborted, %d errors", service->stats.quota_stalls, @@ -3562,9 +3562,9 @@ void vchiq_log_dump_mem(const char *label, u32 addr, const void *void_mem, for (offset = 0; offset < 16; offset++) { if (offset < num_bytes) - s += snprintf(s, 4, "%02x ", mem[offset]); + s += scnprintf(s, 4, "%02x ", mem[offset]); else - s += snprintf(s, 4, " "); + s += scnprintf(s, 4, " "); } for (offset = 0; offset < 16; offset++) { diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 9def0748ffee..4e9cfacf75f2 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -287,12 +287,12 @@ static u16 vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context, buf->duration_a = vnt_get_duration_le(priv, tx_context->pkt_type, need_ack); buf->duration_b = vnt_get_duration_le(priv, - PK_TYPE_11B, need_ack); + PK_TYPE_11B, need_ack); } buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate); buf->time_stamp_off_b = vnt_time_stamp_off(priv, - priv->top_cck_basic_rate); + priv->top_cck_basic_rate); tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); @@ -325,7 +325,7 @@ static u16 vnt_rxtx_datahead_g_fb(struct vnt_usb_send_context *tx_context, buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate); buf->time_stamp_off_b = vnt_time_stamp_off(priv, - priv->top_cck_basic_rate); + priv->top_cck_basic_rate); tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); @@ -655,7 +655,7 @@ static u16 vnt_rxtx_ab(struct vnt_usb_send_context *tx_context, u8 need_ack = tx_context->need_ack; buf->rrv_time = vnt_rxtx_rsvtime_le16(priv, tx_context->pkt_type, - frame_len, current_rate, need_ack); + frame_len, current_rate, need_ack); if (need_mic) head = &tx_head->tx_ab.tx.mic.head; @@ -1036,7 +1036,7 @@ static int vnt_beacon_xmit(struct vnt_private *priv, struct sk_buff *skb) /* Get Duration and TimeStampOff */ short_head->duration = vnt_get_duration_le(priv, - PK_TYPE_11B, false); + PK_TYPE_11B, false); short_head->time_stamp_off = vnt_time_stamp_off(priv, current_rate); } diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index ff351a7a0876..d3304df6bd53 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -216,7 +216,7 @@ static void vnt_submit_rx_urb_complete(struct urb *urb) } urb->transfer_buffer = skb_put(rcb->skb, - skb_tailroom(rcb->skb)); + skb_tailroom(rcb->skb)); } if (usb_submit_urb(urb, GFP_ATOMIC)) { diff --git a/drivers/staging/wilc1000/microchip,wilc1000,sdio.txt b/drivers/staging/wilc1000/microchip,wilc1000,sdio.txt index 4f7d1c2be4d0..da5235950a70 100644 --- a/drivers/staging/wilc1000/microchip,wilc1000,sdio.txt +++ b/drivers/staging/wilc1000/microchip,wilc1000,sdio.txt @@ -10,7 +10,9 @@ Required properties: Optional: - bus-width : Number of data lines wired up the slot. Default 1 bit. - +- rtc_clk : Clock connected on the rtc clock line. Must be assigned + a frequency with assigned-clocks property, and must be + connected to a clock provider. Examples: mmc1: mmc@fc000000 { @@ -24,6 +26,10 @@ mmc1: mmc@fc000000 { wilc_sdio@0 { compatible = "microchip,wilc1000-sdio"; irq-gpios = <&pioC 27 0>; + clocks = <&pck1>; + clock-names = "rtc_clk"; + assigned-clocks = <&pck1>; + assigned-clock-rates = <32768>; status = "okay"; reg = <0>; bus-width = <4>; diff --git a/drivers/staging/wilc1000/microchip,wilc1000,spi.txt b/drivers/staging/wilc1000/microchip,wilc1000,spi.txt index 87db87b2d901..34236932dbb6 100644 --- a/drivers/staging/wilc1000/microchip,wilc1000,spi.txt +++ b/drivers/staging/wilc1000/microchip,wilc1000,spi.txt @@ -9,6 +9,10 @@ Required properties: - reg : Chip select address of device - irq-gpios : Connect to a host IRQ +Optional: +- rtc_clk : Clock connected on the rtc clock line. Must be assigned + a frequency with assigned-clocks property, and must be + connected to a clock provider. Examples: @@ -21,6 +25,10 @@ spi1: spi@fc018000 { spi-max-frequency = <48000000>; reg = <0>; irq-gpios = <&pioC 27 0>; + clocks = <&pck1>; + clock-names = "rtc_clk"; + assigned-clocks = <&pck1>; + assigned-clock-rates = <32768>; status = "okay"; }; }; diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 9345cabe3c93..f2b7d5a1be17 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -248,7 +248,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, goto error; } - if (vif->obtaining_ip || vif->connecting) { + if (vif->connecting) { netdev_err(vif->ndev, "Don't do obss scan\n"); result = -EBUSY; goto error; @@ -679,13 +679,7 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, if (mac_status == WILC_MAC_STATUS_CONNECTED && conn_info->status == WLAN_STATUS_SUCCESS) { ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid); - wilc_set_power_mgmt(vif, 0, 0); - hif_drv->hif_state = HOST_IF_CONNECTED; - - vif->obtaining_ip = true; - mod_timer(&vif->during_ip_timer, - jiffies + msecs_to_jiffies(10000)); } else { hif_drv->hif_state = HOST_IF_IDLE; } @@ -708,15 +702,11 @@ static inline void host_int_handle_disconnect(struct wilc_vif *vif) handle_scan_done(vif, SCAN_EVENT_ABORTED); } - if (hif_drv->conn_info.conn_result) { - vif->obtaining_ip = false; - wilc_set_power_mgmt(vif, 0, 0); - + if (hif_drv->conn_info.conn_result) hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0, hif_drv->conn_info.arg); - } else { + else netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); - } eth_zero_addr(hif_drv->assoc_bssid); @@ -772,9 +762,6 @@ int wilc_disconnect(struct wilc_vif *vif) wid.val = (s8 *)&dummy_reason_code; wid.size = sizeof(char); - vif->obtaining_ip = false; - wilc_set_power_mgmt(vif, 0, 0); - result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); if (result) { netdev_err(vif->ndev, "Failed to send disconnect\n"); @@ -811,15 +798,6 @@ int wilc_disconnect(struct wilc_vif *vif) return 0; } -void wilc_resolve_disconnect_aberration(struct wilc_vif *vif) -{ - if (!vif->hif_drv) - return; - if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP || - vif->hif_drv->hif_state == HOST_IF_CONNECTING) - wilc_disconnect(vif); -} - int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) { struct wid wid_list[5]; @@ -924,7 +902,7 @@ static int handle_remain_on_chan(struct wilc_vif *vif, if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) return -EBUSY; - if (vif->obtaining_ip || vif->connecting) + if (vif->connecting) return -EBUSY; remain_on_chan_flag = true; @@ -1069,13 +1047,9 @@ static void handle_scan_timer(struct work_struct *work) static void handle_scan_complete(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc *wilc = msg->vif->wilc; del_timer(&msg->vif->hif_drv->scan_timer); - if (!wilc_wlan_get_num_conn_ifcs(wilc)) - wilc_chip_sleep_manually(wilc); - handle_scan_done(msg->vif, SCAN_EVENT_DONE); kfree(msg); @@ -1426,18 +1400,14 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel) return result; } -int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, - u8 ifc_id) +int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode, + u8 ifc_id) { struct wid wid; - struct host_if_drv *hif_drv = vif->hif_drv; int result; struct wilc_drv_handler drv; - if (!hif_drv) - return -EFAULT; - - wid.id = WID_SET_DRV_HANDLER; + wid.id = WID_SET_OPERATION_MODE; wid.type = WID_STR; wid.size = sizeof(drv); wid.val = (u8 *)&drv; @@ -1452,26 +1422,6 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, return result; } -int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode) -{ - struct wid wid; - struct wilc_op_mode op_mode; - int result; - - wid.id = WID_SET_OPERATION_MODE; - wid.type = WID_INT; - wid.size = sizeof(op_mode); - wid.val = (u8 *)&op_mode; - - op_mode.mode = cpu_to_le32(mode); - - result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); - if (result) - netdev_err(vif->ndev, "Failed to set operation mode\n"); - - return result; -} - s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val) { struct wid wid; @@ -1610,7 +1560,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) *hif_drv_handler = hif_drv; vif->hif_drv = hif_drv; - vif->obtaining_ip = false; if (wilc->clients_count == 0) mutex_init(&wilc->deinit_lock); @@ -1648,8 +1597,6 @@ int wilc_deinit(struct wilc_vif *vif) del_timer_sync(&vif->periodic_rssi); del_timer_sync(&hif_drv->remain_on_ch_timer); - wilc_set_wfi_drv_handler(vif, 0, 0, 0); - if (hif_drv->usr_scan_req.scan_result) { hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL, hif_drv->usr_scan_req.arg); @@ -2024,9 +1971,6 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) int result; s8 power_mode; - if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled) - return 0; - if (enabled) power_mode = WILC_FW_MIN_FAST_PS; else diff --git a/drivers/staging/wilc1000/wilc_hif.h b/drivers/staging/wilc1000/wilc_hif.h index be1d2497cde9..ac5fe57f872b 100644 --- a/drivers/staging/wilc1000/wilc_hif.h +++ b/drivers/staging/wilc1000/wilc_hif.h @@ -219,11 +219,9 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie, void *user_arg); int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie); void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); -int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, - u8 ifc_id); -int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); +int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode, + u8 ifc_id); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); -void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power); int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power); diff --git a/drivers/staging/wilc1000/wilc_mon.c b/drivers/staging/wilc1000/wilc_mon.c index 7d7933d40924..d6f14f69ad64 100644 --- a/drivers/staging/wilc1000/wilc_mon.c +++ b/drivers/staging/wilc1000/wilc_mon.c @@ -35,8 +35,7 @@ void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size) return; /* Get WILC header */ - memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); - le32_to_cpus(&header); + header = get_unaligned_le32(buff - HOST_HDR_OFFSET); /* * The packet offset field contain info about what type of management * the frame we are dealing with and ack status diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c index 565e2b5d0616..508acb8bb089 100644 --- a/drivers/staging/wilc1000/wilc_netdev.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -11,6 +11,7 @@ #include <linux/inetdevice.h> #include "wilc_wfi_cfgoperations.h" +#include "wilc_wlan_cfg.h" #define WILC_MULTICAST_TABLE_SIZE 8 @@ -59,7 +60,7 @@ static int init_irq(struct net_device *dev) ret = request_threaded_irq(wl->dev_irq_num, isr_uh_routine, isr_bh_routine, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "WILC_IRQ", dev); if (ret < 0) netdev_err(dev, "Failed to request IRQ\n"); @@ -474,7 +475,7 @@ static void wilc_wlan_deinitialize(struct net_device *dev) wlan_deinitialize_threads(dev); deinit_irq(dev); - wilc_wlan_stop(wl); + wilc_wlan_stop(wl, vif); wilc_wlan_cleanup(dev); wlan_deinit_locks(dev); @@ -503,12 +504,6 @@ static int wlan_initialize_threads(struct net_device *dev) return 0; } -static int dev_state_ev_handler(struct notifier_block *this, - unsigned long event, void *ptr); -static struct notifier_block g_dev_notifier = { - .notifier_call = dev_state_ev_handler -}; - static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) { int ret = 0; @@ -574,12 +569,11 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) ret = -EIO; goto fail_fw_start; } - register_inetaddr_notifier(&g_dev_notifier); wl->initialized = true; return 0; fail_fw_start: - wilc_wlan_stop(wl); + wilc_wlan_stop(wl, vif); fail_irq_enable: if (!wl->dev_irq_num && @@ -632,10 +626,8 @@ static int wilc_mac_open(struct net_device *ndev) return ret; } - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), vif->iftype, - vif->idx); - wilc_set_operation_mode(vif, vif->iftype); - + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype, + vif->idx); wilc_get_mac_address(vif, mac_add); netdev_dbg(ndev, "Mac address: %pM\n", mac_add); ether_addr_copy(ndev->dev_addr, mac_add); @@ -780,7 +772,6 @@ static int wilc_mac_close(struct net_device *ndev) if (wl->open_ifcs == 0) { netdev_dbg(ndev, "Deinitializing wilc1000\n"); wl->close = 1; - unregister_inetaddr_notifier(&g_dev_notifier); wilc_wlan_deinitialize(ndev); } @@ -863,63 +854,6 @@ static const struct net_device_ops wilc_netdev_ops = { .ndo_set_rx_mode = wilc_set_multicast_list, }; -static int dev_state_ev_handler(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct in_ifaddr *dev_iface = ptr; - struct wilc_priv *priv; - struct host_if_drv *hif_drv; - struct net_device *dev; - struct wilc_vif *vif; - - if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) - return NOTIFY_DONE; - - dev = (struct net_device *)dev_iface->ifa_dev->dev; - if (dev->netdev_ops != &wilc_netdev_ops) - return NOTIFY_DONE; - - if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) - return NOTIFY_DONE; - - vif = netdev_priv(dev); - priv = &vif->priv; - - hif_drv = (struct host_if_drv *)priv->hif_drv; - - switch (event) { - case NETDEV_UP: - if (vif->iftype == WILC_STATION_MODE || - vif->iftype == WILC_CLIENT_MODE) { - hif_drv->ifc_up = 1; - vif->obtaining_ip = false; - del_timer(&vif->during_ip_timer); - } - - if (vif->wilc->enable_ps) - wilc_set_power_mgmt(vif, 1, 0); - - break; - - case NETDEV_DOWN: - if (vif->iftype == WILC_STATION_MODE || - vif->iftype == WILC_CLIENT_MODE) { - hif_drv->ifc_up = 0; - vif->obtaining_ip = false; - wilc_set_power_mgmt(vif, 0, 0); - } - - wilc_resolve_disconnect_aberration(vif); - - break; - - default: - break; - } - - return NOTIFY_DONE; -} - void wilc_netdev_cleanup(struct wilc *wilc) { int i; diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 4c1c81fed11f..c787c5da8f2b 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -4,6 +4,7 @@ * All rights reserved. */ +#include <linux/clk.h> #include <linux/mmc/sdio_func.h> #include <linux/mmc/host.h> @@ -151,6 +152,12 @@ static int wilc_sdio_probe(struct sdio_func *func, wilc->dev = &func->dev; wilc->gpio_irq = gpio; + wilc->rtc_clk = devm_clk_get(&func->card->dev, "rtc_clk"); + if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + else if (!IS_ERR(wilc->rtc_clk)) + clk_prepare_enable(wilc->rtc_clk); + dev_info(&func->dev, "Driver Initializing success\n"); return 0; } @@ -162,6 +169,10 @@ static void wilc_sdio_remove(struct sdio_func *func) /* free the GPIO in module remove */ if (wilc->gpio_irq) gpiod_put(wilc->gpio_irq); + + if (!IS_ERR(wilc->rtc_clk)) + clk_disable_unprepare(wilc->rtc_clk); + wilc_netdev_cleanup(wilc); } @@ -193,9 +204,10 @@ static int wilc_sdio_suspend(struct device *dev) dev_info(dev, "sdio suspend\n"); chip_wakeup(wilc); - if (!wilc->suspend_event) { - wilc_chip_sleep_manually(wilc); - } else { + if (!IS_ERR(wilc->rtc_clk)) + clk_disable_unprepare(wilc->rtc_clk); + + if (wilc->suspend_event) { host_sleep_notify(wilc); chip_allow_sleep(wilc); } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 736eedef23b6..22f21831649b 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -70,15 +70,6 @@ struct wilc_p2p_mgmt_data { static const u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09}; static const u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03}; -#define WILC_IP_TIMEOUT_MS 15000 - -static void clear_during_ip(struct timer_list *t) -{ - struct wilc_vif *vif = from_timer(vif, t, during_ip_timer); - - vif->obtaining_ip = false; -} - static void cfg_scan_result(enum scan_event scan_event, struct wilc_rcvd_net_info *info, void *user_void) { @@ -176,7 +167,6 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status, } else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF) { u16 reason = 0; - vif->obtaining_ip = false; priv->p2p.local_random = 0x01; priv->p2p.recv_random = 0x00; priv->p2p.is_wilc_ie = false; @@ -1038,8 +1028,7 @@ void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size) s32 freq; __le16 fc; - memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); - le32_to_cpus(&header); + header = get_unaligned_le32(buff - HOST_HDR_OFFSET); pkt_offset = GET_PKT_OFFSET(header); if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { @@ -1404,8 +1393,7 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, if (!priv->hif_drv) return -EIO; - if (vif->wilc->enable_ps) - wilc_set_power_mgmt(vif, enabled, timeout); + wilc_set_power_mgmt(vif, enabled, timeout); return 0; } @@ -1421,8 +1409,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->p2p.local_random = 0x01; priv->p2p.recv_random = 0x00; priv->p2p.is_wilc_ie = false; - vif->obtaining_ip = false; - del_timer(&vif->during_ip_timer); switch (type) { case NL80211_IFTYPE_STATION: @@ -1433,13 +1419,11 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) wilc_wfi_deinit_mon_interface(wl, true); vif->iftype = WILC_STATION_MODE; - wilc_set_operation_mode(vif, WILC_STATION_MODE); + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_STATION_MODE, vif->idx); memset(priv->assoc_stainfo.sta_associated_bss, 0, WILC_MAX_NUM_STA * ETH_ALEN); - - wl->enable_ps = true; - wilc_set_power_mgmt(vif, 1, 0); break; case NL80211_IFTYPE_P2P_CLIENT: @@ -1448,37 +1432,26 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->wdev.iftype = type; vif->monitor_flag = 0; vif->iftype = WILC_CLIENT_MODE; - wilc_set_operation_mode(vif, WILC_STATION_MODE); - - wl->enable_ps = false; - wilc_set_power_mgmt(vif, 0, 0); + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_STATION_MODE, vif->idx); break; case NL80211_IFTYPE_AP: - wl->enable_ps = false; dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; vif->iftype = WILC_AP_MODE; - if (wl->initialized) { - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), - 0, vif->idx); - wilc_set_operation_mode(vif, WILC_AP_MODE); - wilc_set_power_mgmt(vif, 0, 0); - } + if (wl->initialized) + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_AP_MODE, vif->idx); break; case NL80211_IFTYPE_P2P_GO: - vif->obtaining_ip = true; - mod_timer(&vif->during_ip_timer, - jiffies + msecs_to_jiffies(WILC_IP_TIMEOUT_MS)); - wilc_set_operation_mode(vif, WILC_AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; vif->iftype = WILC_GO_MODE; - - wl->enable_ps = false; - wilc_set_power_mgmt(vif, 0, 0); + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_AP_MODE, vif->idx); break; default: @@ -1500,7 +1473,6 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, netdev_err(dev, "Error in setting channel\n"); wilc_wlan_set_bssid(dev, dev->dev_addr, WILC_AP_MODE); - wilc_set_power_mgmt(vif, 0, 0); return wilc_add_beacon(vif, settings->beacon_interval, settings->dtim_period, &settings->beacon); @@ -1687,16 +1659,16 @@ static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) vif->monitor_flag = 0; mutex_lock(&wl->vif_mutex); - wilc_set_wfi_drv_handler(vif, 0, 0, 0); - for (i = vif->idx; i < wl->vif_num ; i++) { + wilc_set_operation_mode(vif, 0, 0, 0); + for (i = vif->idx; i < wl->vif_num; i++) { if ((i + 1) >= wl->vif_num) { wl->vif[i] = NULL; } else { vif = wl->vif[i + 1]; vif->idx = i; wl->vif[i] = vif; - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), - vif->iftype, vif->idx); + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + vif->iftype, vif->idx); } } wl->vif_num--; @@ -1851,7 +1823,6 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type, *wilc = wl; wl->io_type = io_type; wl->hif_func = ops; - wl->enable_ps = false; wl->chip_ps_state = WILC_CHIP_WAKEDUP; INIT_LIST_HEAD(&wl->txq_head.list); INIT_LIST_HEAD(&wl->rxq_head.list); @@ -1949,8 +1920,6 @@ int wilc_init_host_int(struct net_device *net) struct wilc_vif *vif = netdev_priv(net); struct wilc_priv *priv = &vif->priv; - timer_setup(&vif->during_ip_timer, clear_during_ip, 0); - priv->p2p_listen_state = false; mutex_init(&priv->scan_req_lock); @@ -1973,8 +1942,6 @@ void wilc_deinit_host_int(struct net_device *net) mutex_destroy(&priv->scan_req_lock); ret = wilc_deinit(vif); - del_timer_sync(&vif->during_ip_timer); - if (ret) netdev_err(net, "Error while deinitializing host interface\n"); } diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 1e74a08e7cf1..978a8bdbfc40 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -203,7 +203,6 @@ struct wilc_vif { struct net_device *ndev; u8 mode; struct timer_list during_ip_timer; - bool obtaining_ip; struct timer_list periodic_rssi; struct rf_info periodic_stat; struct tcp_ack_filter ack_filter; @@ -217,6 +216,7 @@ struct wilc { int io_type; s8 mac_status; struct gpio_desc *gpio_irq; + struct clk *rtc_clk; bool initialized; int dev_irq_num; int close; @@ -262,7 +262,6 @@ struct wilc { struct device *dev; bool suspend_event; - bool enable_ps; int clients_count; struct workqueue_struct *hif_workqueue; enum chip_ps_states chip_ps_state; diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index d46876edcfeb..771d8cb68dc1 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -455,20 +455,6 @@ void chip_wakeup(struct wilc *wilc) } EXPORT_SYMBOL_GPL(chip_wakeup); -void wilc_chip_sleep_manually(struct wilc *wilc) -{ - if (wilc->chip_ps_state != WILC_CHIP_WAKEDUP) - return; - acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); - - chip_allow_sleep(wilc); - wilc->hif_func->hif_write_reg(wilc, 0x10a8, 1); - - wilc->chip_ps_state = WILC_CHIP_SLEEPING_MANUAL; - release_bus(wilc, WILC_BUS_RELEASE_ONLY); -} -EXPORT_SYMBOL_GPL(wilc_chip_sleep_manually); - void host_wakeup_notify(struct wilc *wilc) { acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); @@ -703,8 +689,7 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size) do { buff_ptr = buffer + offset; - memcpy(&header, buff_ptr, 4); - le32_to_cpus(&header); + header = get_unaligned_le32(buff_ptr); is_cfg_packet = (header >> 31) & 0x1; pkt_offset = (header >> 22) & 0x1ff; @@ -773,26 +758,6 @@ static void wilc_unknown_isr_ext(struct wilc *wilc) wilc->hif_func->hif_clear_int_ext(wilc, 0); } -static void wilc_pllupdate_isr_ext(struct wilc *wilc, u32 int_stats) -{ - int trials = 10; - - wilc->hif_func->hif_clear_int_ext(wilc, PLL_INT_CLR); - - if (wilc->io_type == WILC_HIF_SDIO) - mdelay(WILC_PLL_TO_SDIO); - else - mdelay(WILC_PLL_TO_SPI); - - while (!(is_wilc1000(wilc_get_chipid(wilc, true)) && --trials)) - mdelay(1); -} - -static void wilc_sleeptimer_isr_ext(struct wilc *wilc, u32 int_stats1) -{ - wilc->hif_func->hif_clear_int_ext(wilc, SLEEP_INT_CLR); -} - static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) { u32 offset = wilc->rx_buffer_offset; @@ -842,15 +807,9 @@ void wilc_handle_isr(struct wilc *wilc) acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); wilc->hif_func->hif_read_int(wilc, &int_status); - if (int_status & PLL_INT_EXT) - wilc_pllupdate_isr_ext(wilc, int_status); - if (int_status & DATA_INT_EXT) wilc_wlan_handle_isr_ext(wilc, int_status); - if (int_status & SLEEP_INT_EXT) - wilc_sleeptimer_isr_ext(wilc, int_status); - if (!(int_status & (ALL_INT_EXT))) wilc_unknown_isr_ext(wilc); @@ -874,10 +833,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, offset = 0; do { - memcpy(&addr, &buffer[offset], 4); - memcpy(&size, &buffer[offset + 4], 4); - le32_to_cpus(&addr); - le32_to_cpus(&size); + addr = get_unaligned_le32(&buffer[offset]); + size = get_unaligned_le32(&buffer[offset + 4]); acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); offset += 8; while (((int)size) && (offset < buffer_size)) { @@ -985,72 +942,52 @@ int wilc_wlan_start(struct wilc *wilc) return (ret < 0) ? ret : 0; } -int wilc_wlan_stop(struct wilc *wilc) +int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) { u32 reg = 0; int ret; - u8 timeout = 10; acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); - ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); + ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); if (!ret) { + netdev_err(vif->ndev, "Error while reading reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return -EIO; } - reg &= ~BIT(10); - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); + ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, + (reg | WILC_ABORT_REQ_BIT)); if (!ret) { + netdev_err(vif->ndev, "Error while writing reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return -EIO; } - do { - ret = wilc->hif_func->hif_read_reg(wilc, - WILC_GLB_RESET_0, ®); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; - } - - if ((reg & BIT(10))) { - reg &= ~BIT(10); - ret = wilc->hif_func->hif_write_reg(wilc, - WILC_GLB_RESET_0, - reg); - timeout--; - } else { - ret = wilc->hif_func->hif_read_reg(wilc, - WILC_GLB_RESET_0, - ®); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; - } - break; - } - - } while (timeout); - reg = (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(8) | BIT(9) | BIT(26) | - BIT(29) | BIT(30) | BIT(31)); - - wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); - reg = (u32)~BIT(10); + ret = wilc->hif_func->hif_read_reg(wilc, WILC_FW_HOST_COMM, ®); + if (!ret) { + netdev_err(vif->ndev, "Error while reading reg\n"); + release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + return -EIO; + } + reg = BIT(0); - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); + ret = wilc->hif_func->hif_write_reg(wilc, WILC_FW_HOST_COMM, reg); + if (!ret) { + netdev_err(vif->ndev, "Error while writing reg\n"); + release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + return -EIO; + } release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return 0; } void wilc_wlan_cleanup(struct net_device *dev) { struct txq_entry_t *tqe; struct rxq_entry_t *rqe; - u32 reg = 0; - int ret; struct wilc_vif *vif = netdev_priv(dev); struct wilc *wilc = vif->wilc; @@ -1075,23 +1012,6 @@ void wilc_wlan_cleanup(struct net_device *dev) wilc->rx_buffer = NULL; kfree(wilc->tx_buffer); wilc->tx_buffer = NULL; - - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); - - ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return; - } - - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, - (reg | ABORT_INT)); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return; - } - - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); wilc->hif_func->hif_deinit(NULL); } @@ -1196,11 +1116,6 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, return ret_size; } -int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size) -{ - return wilc_wlan_cfg_get_wid_value(wl, wid, buffer, buffer_size); -} - int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count) { diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index d2eef7b4c3b7..7469fa47d588 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -98,6 +98,7 @@ #define WILC_VMM_TBL_RX_SHADOW_BASE WILC_AHB_SHARE_MEM_BASE #define WILC_VMM_TBL_RX_SHADOW_SIZE 256 +#define WILC_FW_HOST_COMM 0x13c0 #define WILC_GP_REG_0 0x149c #define WILC_GP_REG_1 0x14a0 @@ -127,9 +128,7 @@ #define WILC_CFG_RSP_STATUS 2 #define WILC_CFG_RSP_SCAN 3 -#define WILC_PLL_TO_SDIO 4 -#define WILC_PLL_TO_SPI 2 -#define ABORT_INT BIT(31) +#define WILC_ABORT_REQ_BIT BIT(31) #define WILC_RX_BUFF_SIZE (96 * 1024) #define WILC_TX_BUFF_SIZE (64 * 1024) @@ -184,14 +183,10 @@ #define EN_VMM BIT(8) #define DATA_INT_EXT INT_0 -#define PLL_INT_EXT INT_1 -#define SLEEP_INT_EXT INT_2 -#define ALL_INT_EXT (DATA_INT_EXT | PLL_INT_EXT | SLEEP_INT_EXT) -#define NUM_INT_EXT 3 +#define ALL_INT_EXT DATA_INT_EXT +#define NUM_INT_EXT 1 #define DATA_INT_CLR CLR_INT0 -#define PLL_INT_CLR CLR_INT1 -#define SLEEP_INT_CLR CLR_INT2 #define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM) #define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM) @@ -280,7 +275,7 @@ struct wilc_vif; int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size); int wilc_wlan_start(struct wilc *wilc); -int wilc_wlan_stop(struct wilc *wilc); +int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif); int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, u32 buffer_size, void (*tx_complete_fn)(void *, int)); @@ -291,12 +286,8 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, u32 buffer_size, int commit, u32 drv_handler); int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, u32 drv_handler); -int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, - u32 buffer_size); int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, u32 buffer_size, void (*func)(void *, int)); -void wilc_chip_sleep_manually(struct wilc *wilc); - void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value); int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc); netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev); diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index 9dc5de4eb08d..3f53807cee0f 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -52,57 +52,35 @@ static const struct wilc_cfg_str g_cfg_str[] = { static int wilc_wlan_cfg_set_byte(u8 *frame, u32 offset, u16 id, u8 val8) { - u8 *buf; - if ((offset + 4) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = 1; - buf[3] = 0; - buf[4] = val8; + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(1, &frame[offset + 2]); + frame[offset + 4] = val8; return 5; } static int wilc_wlan_cfg_set_hword(u8 *frame, u32 offset, u16 id, u16 val16) { - u8 *buf; - if ((offset + 5) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = 2; - buf[3] = 0; - buf[4] = (u8)val16; - buf[5] = (u8)(val16 >> 8); + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(2, &frame[offset + 2]); + put_unaligned_le16(val16, &frame[offset + 4]); return 6; } static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32) { - u8 *buf; - if ((offset + 7) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = 4; - buf[3] = 0; - buf[4] = (u8)val32; - buf[5] = (u8)(val32 >> 8); - buf[6] = (u8)(val32 >> 16); - buf[7] = (u8)(val32 >> 24); + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(4, &frame[offset + 2]); + put_unaligned_le32(val32, &frame[offset + 4]); return 8; } @@ -110,46 +88,35 @@ static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32) static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str, u32 size) { - u8 *buf; - if ((offset + size + 4) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = (u8)size; - buf[3] = (u8)(size >> 8); - + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(size, &frame[offset + 2]); if (str && size != 0) - memcpy(&buf[4], str, size); + memcpy(&frame[offset + 4], str, size); return (size + 4); } static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size) { - u8 *buf; u32 i; u8 checksum = 0; if ((offset + size + 5) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = (u8)size; - buf[3] = (u8)(size >> 8); + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(size, &frame[offset + 2]); if ((b) && size != 0) { - memcpy(&buf[4], b, size); + memcpy(&frame[offset + 4], b, size); for (i = 0; i < size; i++) - checksum += buf[i + 4]; + checksum += frame[offset + i + 4]; } - buf[size + 4] = checksum; + frame[offset + size + 4] = checksum; return (size + 5); } @@ -307,21 +274,16 @@ int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size) int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id) { - u8 *buf; - if ((offset + 2) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); + put_unaligned_le16(id, &frame[offset]); return 2; } -int wilc_wlan_cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, - u32 buffer_size) +int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, + u32 buffer_size) { u32 type = (wid >> 12) & 0xf; int i, ret = 0; diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.h b/drivers/staging/wilc1000/wilc_wlan_cfg.h index e5ca6cea0682..614c5673f232 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.h +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.h @@ -44,8 +44,8 @@ struct wilc_cfg { struct wilc; int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size); int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id); -int wilc_wlan_cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, - u32 buffer_size); +int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, + u32 buffer_size); void wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size, struct wilc_cfg_rsp *rsp); int wilc_wlan_cfg_init(struct wilc *wl); diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index b89d0e0f04cc..70eac586f80c 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -724,7 +724,6 @@ enum { /* NMAC Integer WID list */ /* Custom Integer WID list */ WID_GET_INACTIVE_TIME = 0x2084, - WID_SET_OPERATION_MODE = 0X2086, /* EMAC String WID list */ WID_SSID = 0x3000, WID_FIRMWARE_VERSION = 0x3001, @@ -755,9 +754,9 @@ enum { WID_MODEL_NAME = 0x3027, /*Added for CAPI tool */ WID_MODEL_NUM = 0x3028, /*Added for CAPI tool */ WID_DEVICE_NAME = 0x3029, /*Added for CAPI tool */ - WID_SET_DRV_HANDLER = 0x3079, /* NMAC String WID list */ + WID_SET_OPERATION_MODE = 0x3079, WID_11N_P_ACTION_REQ = 0x3080, WID_HUT_TEST_ID = 0x3081, WID_PMKID_INFO = 0x3082, diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index ab734534093b..28d372a0663a 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -226,11 +226,9 @@ usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, /*---------------------------------------------------*/ /* Low level req/resp CTLX formatters and submitters */ -static int +static inline int hfa384x_docmd(struct hfa384x *hw, - enum cmd_mode mode, - struct hfa384x_metacmd *cmd, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); + struct hfa384x_metacmd *cmd); static int hfa384x_dorrid(struct hfa384x *hw, @@ -250,21 +248,17 @@ hfa384x_dowrid(struct hfa384x *hw, static int hfa384x_dormem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); + unsigned int len); static int hfa384x_dowmem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); + unsigned int len); static int hfa384x_isgood_pdrcode(u16 pdrcode); @@ -820,99 +814,6 @@ static void hfa384x_cb_status(struct hfa384x *hw, } } -static inline int hfa384x_docmd_wait(struct hfa384x *hw, - struct hfa384x_metacmd *cmd) -{ - return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL); -} - -static inline int -hfa384x_docmd_async(struct hfa384x *hw, - struct hfa384x_metacmd *cmd, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_docmd(hw, DOASYNC, cmd, cmdcb, usercb, usercb_data); -} - -static inline int -hfa384x_dorrid_wait(struct hfa384x *hw, u16 rid, void *riddata, - unsigned int riddatalen) -{ - return hfa384x_dorrid(hw, DOWAIT, - rid, riddata, riddatalen, NULL, NULL, NULL); -} - -static inline int -hfa384x_dorrid_async(struct hfa384x *hw, - u16 rid, void *riddata, unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dorrid(hw, DOASYNC, - rid, riddata, riddatalen, - cmdcb, usercb, usercb_data); -} - -static inline int -hfa384x_dowrid_wait(struct hfa384x *hw, u16 rid, void *riddata, - unsigned int riddatalen) -{ - return hfa384x_dowrid(hw, DOWAIT, - rid, riddata, riddatalen, NULL, NULL, NULL); -} - -static inline int -hfa384x_dowrid_async(struct hfa384x *hw, - u16 rid, void *riddata, unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dowrid(hw, DOASYNC, - rid, riddata, riddatalen, - cmdcb, usercb, usercb_data); -} - -static inline int -hfa384x_dormem_wait(struct hfa384x *hw, - u16 page, u16 offset, void *data, unsigned int len) -{ - return hfa384x_dormem(hw, DOWAIT, - page, offset, data, len, NULL, NULL, NULL); -} - -static inline int -hfa384x_dormem_async(struct hfa384x *hw, - u16 page, u16 offset, void *data, unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dormem(hw, DOASYNC, - page, offset, data, len, - cmdcb, usercb, usercb_data); -} - -static inline int -hfa384x_dowmem_wait(struct hfa384x *hw, - u16 page, u16 offset, void *data, unsigned int len) -{ - return hfa384x_dowmem(hw, DOWAIT, - page, offset, data, len, NULL, NULL, NULL); -} - -static inline int -hfa384x_dowmem_async(struct hfa384x *hw, - u16 page, - u16 offset, - void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dowmem(hw, DOASYNC, - page, offset, data, len, - cmdcb, usercb, usercb_data); -} - /*---------------------------------------------------------------- * hfa384x_cmd_initialize * @@ -944,7 +845,7 @@ int hfa384x_cmd_initialize(struct hfa384x *hw) cmd.parm1 = 0; cmd.parm2 = 0; - result = hfa384x_docmd_wait(hw, &cmd); + result = hfa384x_docmd(hw, &cmd); pr_debug("cmdresp.init: status=0x%04x, resp0=0x%04x, resp1=0x%04x, resp2=0x%04x\n", cmd.result.status, @@ -990,7 +891,7 @@ int hfa384x_cmd_disable(struct hfa384x *hw, u16 macport) cmd.parm1 = 0; cmd.parm2 = 0; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -1024,7 +925,7 @@ int hfa384x_cmd_enable(struct hfa384x *hw, u16 macport) cmd.parm1 = 0; cmd.parm2 = 0; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -1067,7 +968,7 @@ int hfa384x_cmd_monitor(struct hfa384x *hw, u16 enable) cmd.parm1 = 0; cmd.parm2 = 0; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -1124,7 +1025,7 @@ int hfa384x_cmd_download(struct hfa384x *hw, u16 mode, u16 lowaddr, cmd.parm1 = highaddr; cmd.parm2 = codelen; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -1284,13 +1185,8 @@ cleanup: * * Arguments: * hw device structure - * mode DOWAIT or DOASYNC * cmd cmd structure. Includes all arguments and result * data points. All in host order. in host order - * cmdcb command-specific callback - * usercb user callback for async calls, NULL for DOWAIT calls - * usercb_data user supplied data pointer for async calls, NULL - * for DOWAIT calls * * Returns: * 0 success @@ -1306,11 +1202,9 @@ cleanup: * process *---------------------------------------------------------------- */ -static int +static inline int hfa384x_docmd(struct hfa384x *hw, - enum cmd_mode mode, - struct hfa384x_metacmd *cmd, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) + struct hfa384x_metacmd *cmd) { int result; struct hfa384x_usbctlx *ctlx; @@ -1333,15 +1227,15 @@ hfa384x_docmd(struct hfa384x *hw, pr_debug("cmdreq: cmd=0x%04x parm0=0x%04x parm1=0x%04x parm2=0x%04x\n", cmd->cmd, cmd->parm0, cmd->parm1, cmd->parm2); - ctlx->reapable = mode; - ctlx->cmdcb = cmdcb; - ctlx->usercb = usercb; - ctlx->usercb_data = usercb_data; + ctlx->reapable = DOWAIT; + ctlx->cmdcb = NULL; + ctlx->usercb = NULL; + ctlx->usercb_data = NULL; result = hfa384x_usbctlx_submit(hw, ctlx); if (result != 0) { kfree(ctlx); - } else if (mode == DOWAIT) { + } else { struct usbctlx_cmd_completor cmd_completor; struct usbctlx_completor *completor; @@ -1540,14 +1434,10 @@ done: * * Arguments: * hw device structure - * mode DOWAIT or DOASYNC * page MAC address space page (CMD format) * offset MAC address space offset * data Ptr to data buffer to receive read * len Length of the data to read (max == 2048) - * cmdcb command callback for async calls, NULL for DOWAIT calls - * usercb user callback for async calls, NULL for DOWAIT calls - * usercb_data user supplied data pointer for async calls * * Returns: * 0 success @@ -1559,18 +1449,15 @@ done: * Side effects: * * Call context: - * interrupt (DOASYNC) - * process (DOWAIT or DOASYNC) + * process (DOWAIT) *---------------------------------------------------------------- */ static int hfa384x_dormem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) + unsigned int len) { int result; struct hfa384x_usbctlx *ctlx; @@ -1598,15 +1485,15 @@ hfa384x_dormem(struct hfa384x *hw, pr_debug("pktsize=%zd\n", ROUNDUP64(sizeof(ctlx->outbuf.rmemreq))); - ctlx->reapable = mode; - ctlx->cmdcb = cmdcb; - ctlx->usercb = usercb; - ctlx->usercb_data = usercb_data; + ctlx->reapable = DOWAIT; + ctlx->cmdcb = NULL; + ctlx->usercb = NULL; + ctlx->usercb_data = NULL; result = hfa384x_usbctlx_submit(hw, ctlx); if (result != 0) { kfree(ctlx); - } else if (mode == DOWAIT) { + } else { struct usbctlx_rmem_completor completor; result = @@ -1632,14 +1519,10 @@ done: * * Arguments: * hw device structure - * mode DOWAIT or DOASYNC * page MAC address space page (CMD format) * offset MAC address space offset * data Ptr to data buffer containing write data * len Length of the data to read (max == 2048) - * cmdcb command callback for async calls, NULL for DOWAIT calls - * usercb user callback for async calls, NULL for DOWAIT calls - * usercb_data user supplied data pointer for async calls. * * Returns: * 0 success @@ -1652,17 +1535,15 @@ done: * * Call context: * interrupt (DOWAIT) - * process (DOWAIT or DOASYNC) + * process (DOWAIT) *---------------------------------------------------------------- */ static int hfa384x_dowmem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) + unsigned int len) { int result; struct hfa384x_usbctlx *ctlx; @@ -1689,15 +1570,15 @@ hfa384x_dowmem(struct hfa384x *hw, sizeof(ctlx->outbuf.wmemreq.offset) + sizeof(ctlx->outbuf.wmemreq.page) + len; - ctlx->reapable = mode; - ctlx->cmdcb = cmdcb; - ctlx->usercb = usercb; - ctlx->usercb_data = usercb_data; + ctlx->reapable = DOWAIT; + ctlx->cmdcb = NULL; + ctlx->usercb = NULL; + ctlx->usercb_data = NULL; result = hfa384x_usbctlx_submit(hw, ctlx); if (result != 0) { kfree(ctlx); - } else if (mode == DOWAIT) { + } else { struct usbctlx_cmd_completor completor; struct hfa384x_cmdresult wmemresult; @@ -2004,10 +1885,10 @@ int hfa384x_drvr_flashdl_write(struct hfa384x *hw, u32 daddr, writelen = writelen > HFA384x_USB_RWMEM_MAXLEN ? HFA384x_USB_RWMEM_MAXLEN : writelen; - result = hfa384x_dowmem_wait(hw, - writepage, - writeoffset, - writebuf, writelen); + result = hfa384x_dowmem(hw, + writepage, + writeoffset, + writebuf, writelen); } /* set the download 'write flash' mode */ @@ -2061,7 +1942,7 @@ exit_proc: */ int hfa384x_drvr_getconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { - return hfa384x_dorrid_wait(hw, rid, buf, len); + return hfa384x_dorrid(hw, DOWAIT, rid, buf, len, NULL, NULL, NULL); } /*---------------------------------------------------------------- @@ -2094,8 +1975,8 @@ hfa384x_drvr_setconfig_async(struct hfa384x *hw, void *buf, u16 len, ctlx_usercb_t usercb, void *usercb_data) { - return hfa384x_dowrid_async(hw, rid, buf, len, - hfa384x_cb_status, usercb, usercb_data); + return hfa384x_dowrid(hw, DOASYNC, rid, buf, len, hfa384x_cb_status, + usercb, usercb_data); } /*---------------------------------------------------------------- @@ -2261,12 +2142,11 @@ int hfa384x_drvr_ramdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len) currlen = HFA384x_USB_RWMEM_MAXLEN; /* Do blocking ctlx */ - result = hfa384x_dowmem_wait(hw, - currpage, - curroffset, - data + - (i * HFA384x_USB_RWMEM_MAXLEN), - currlen); + result = hfa384x_dowmem(hw, + currpage, + curroffset, + data + (i * HFA384x_USB_RWMEM_MAXLEN), + currlen); if (result) break; @@ -2338,8 +2218,8 @@ int hfa384x_drvr_readpda(struct hfa384x *hw, void *buf, unsigned int len) curroffset = HFA384x_ADDR_CMD_MKOFF(pdaloc[i].cardaddr); /* units of bytes */ - result = hfa384x_dormem_wait(hw, currpage, curroffset, buf, - len); + result = hfa384x_dormem(hw, currpage, curroffset, buf, + len); if (result) { netdev_warn(hw->wlandev->netdev, @@ -2422,7 +2302,7 @@ int hfa384x_drvr_readpda(struct hfa384x *hw, void *buf, unsigned int len) */ int hfa384x_drvr_setconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { - return hfa384x_dowrid_wait(hw, rid, buf, len); + return hfa384x_dowrid(hw, DOWAIT, rid, buf, len, NULL, NULL, NULL); } /*---------------------------------------------------------------- diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 1eba5fa28d8f..7d7d77b04255 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -126,13 +126,6 @@ static int prism2mib_privacyinvoked(struct mibrec *mib, struct p80211msg_dot11req_mibset *msg, void *data); -static int prism2mib_excludeunencrypted(struct mibrec *mib, - int isget, - struct wlandevice *wlandev, - struct hfa384x *hw, - struct p80211msg_dot11req_mibset *msg, - void *data); - static int prism2mib_fragmentationthreshold(struct mibrec *mib, int isget, @@ -176,7 +169,7 @@ static struct mibrec mibtab[] = { {DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED, F_STA | F_READ | F_WRITE, HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_EXCLUDE, 0, - prism2mib_excludeunencrypted}, + prism2mib_flag}, /* dot11mac MIB's */ @@ -594,41 +587,6 @@ static int prism2mib_privacyinvoked(struct mibrec *mib, } /* - * prism2mib_excludeunencrypted - * - * Get/set the dot11ExcludeUnencrypted value. - * - * MIB record parameters: - * parm1 Prism2 RID value. - * parm2 Bit value for ExcludeUnencrypted flag. - * parm3 Not used. - * - * Arguments: - * mib MIB record. - * isget MIBGET/MIBSET flag. - * wlandev wlan device structure. - * priv "priv" structure. - * hw "hw" structure. - * msg Message structure. - * data Data buffer. - * - * Returns: - * 0 - Success. - * ~0 - Error. - * - */ - -static int prism2mib_excludeunencrypted(struct mibrec *mib, - int isget, - struct wlandevice *wlandev, - struct hfa384x *hw, - struct p80211msg_dot11req_mibset *msg, - void *data) -{ - return prism2mib_flag(mib, isget, wlandev, hw, msg, data); -} - -/* * prism2mib_fragmentationthreshold * * Get/set the fragmentation threshold. diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index fb5441399131..8f25496188aa 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -846,7 +846,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER, snum, HFA384x_RID_NICSERIALNUMBER_LEN); if (!result) { - netdev_info(wlandev->netdev, "Prism2 card SN: %*pEhp\n", + netdev_info(wlandev->netdev, "Prism2 card SN: %*pE\n", HFA384x_RID_NICSERIALNUMBER_LEN, snum); } else { netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n"); diff --git a/fs/Kconfig b/fs/Kconfig index bfb1c6095c7a..669d46550e6d 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -261,6 +261,7 @@ source "fs/romfs/Kconfig" source "fs/pstore/Kconfig" source "fs/sysv/Kconfig" source "fs/ufs/Kconfig" +source "fs/erofs/Kconfig" endif # MISC_FILESYSTEMS diff --git a/fs/Makefile b/fs/Makefile index d60089fd689b..b2e4973a0bea 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -130,3 +130,4 @@ obj-$(CONFIG_F2FS_FS) += f2fs/ obj-$(CONFIG_CEPH_FS) += ceph/ obj-$(CONFIG_PSTORE) += pstore/ obj-$(CONFIG_EFIVAR_FS) += efivarfs/ +obj-$(CONFIG_EROFS_FS) += erofs/ diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig new file mode 100644 index 000000000000..9d634d3a1845 --- /dev/null +++ b/fs/erofs/Kconfig @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config EROFS_FS + tristate "EROFS filesystem support" + depends on BLOCK + help + EROFS (Enhanced Read-Only File System) is a lightweight + read-only file system with modern designs (eg. page-sized + blocks, inline xattrs/data, etc.) for scenarios which need + high-performance read-only requirements, e.g. Android OS + for mobile phones and LIVECDs. + + It also provides fixed-sized output compression support, + which improves storage density, keeps relatively higher + compression ratios, which is more useful to achieve high + performance for embedded devices with limited memory. + + If unsure, say N. + +config EROFS_FS_DEBUG + bool "EROFS debugging feature" + depends on EROFS_FS + help + Print debugging messages and enable more BUG_ONs which check + filesystem consistency and find potential issues aggressively, + which can be used for Android eng build, for example. + + For daily use, say N. + +config EROFS_FS_XATTR + bool "EROFS extended attributes" + depends on EROFS_FS + default y + help + Extended attributes are name:value pairs associated with inodes by + the kernel or by users (see the attr(5) manual page, or visit + <http://acl.bestbits.at/> for details). + + If unsure, say N. + +config EROFS_FS_POSIX_ACL + bool "EROFS Access Control Lists" + depends on EROFS_FS_XATTR + select FS_POSIX_ACL + default y + help + Posix Access Control Lists (ACLs) support permissions for users and + groups beyond the owner/group/world scheme. + + To learn more about Access Control Lists, visit the POSIX ACLs for + Linux website <http://acl.bestbits.at/>. + + If you don't know what Access Control Lists are, say N. + +config EROFS_FS_SECURITY + bool "EROFS Security Labels" + depends on EROFS_FS_XATTR + default y + help + Security labels provide an access control facility to support Linux + Security Models (LSMs) accepted by AppArmor, SELinux, Smack and TOMOYO + Linux. This option enables an extended attribute handler for file + security labels in the erofs filesystem, so that it requires enabling + the extended attribute support in advance. + + If you are not using a security module, say N. + +config EROFS_FS_ZIP + bool "EROFS Data Compression Support" + depends on EROFS_FS + select LZ4_DECOMPRESS + default y + help + Enable fixed-sized output compression for EROFS. + + If you don't want to enable compression feature, say N. + +config EROFS_FS_CLUSTER_PAGE_LIMIT + int "EROFS Cluster Pages Hard Limit" + depends on EROFS_FS_ZIP + range 1 256 + default "1" + help + Indicates maximum # of pages of a compressed + physical cluster. + + For example, if files in a image were compressed + into 8k-unit, hard limit should not be configured + less than 2. Otherwise, the image will be refused + to mount on this kernel. + diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile new file mode 100644 index 000000000000..46f2aa4ba46c --- /dev/null +++ b/fs/erofs/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only + +EROFS_VERSION = "1.0" + +ccflags-y += -DEROFS_VERSION=\"$(EROFS_VERSION)\" + +obj-$(CONFIG_EROFS_FS) += erofs.o +erofs-objs := super.o inode.o data.o namei.o dir.o utils.o +erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o +erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o + diff --git a/drivers/staging/erofs/compress.h b/fs/erofs/compress.h index c43aa3374d28..07d279fd5d67 100644 --- a/drivers/staging/erofs/compress.h +++ b/fs/erofs/compress.h @@ -1,7 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* - * linux/drivers/staging/erofs/compress.h - * * Copyright (C) 2019 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> diff --git a/drivers/staging/erofs/data.c b/fs/erofs/data.c index cc31c3e5984c..8a9fcbd0e8ac 100644 --- a/drivers/staging/erofs/data.c +++ b/fs/erofs/data.c @@ -1,39 +1,27 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/data.c - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "internal.h" #include <linux/prefetch.h> #include <trace/events/erofs.h> -static inline void read_endio(struct bio *bio) +static void erofs_readendio(struct bio *bio) { - struct super_block *const sb = bio->bi_private; struct bio_vec *bvec; blk_status_t err = bio->bi_status; struct bvec_iter_all iter_all; - if (time_to_inject(EROFS_SB(sb), FAULT_READ_IO)) { - erofs_show_injection_info(FAULT_READ_IO); - err = BLK_STS_IOERR; - } - bio_for_each_segment_all(bvec, bio, iter_all) { struct page *page = bvec->bv_page; /* page is already locked */ DBG_BUGON(PageUptodate(page)); - if (unlikely(err)) + if (err) SetPageError(page); else SetPageUptodate(page); @@ -44,72 +32,13 @@ static inline void read_endio(struct bio *bio) bio_put(bio); } -/* prio -- true is used for dir */ -struct page *__erofs_get_meta_page(struct super_block *sb, - erofs_blk_t blkaddr, bool prio, bool nofail) +struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr) { struct inode *const bd_inode = sb->s_bdev->bd_inode; struct address_space *const mapping = bd_inode->i_mapping; - /* prefer retrying in the allocator to blindly looping below */ - const gfp_t gfp = mapping_gfp_constraint(mapping, ~__GFP_FS) | - (nofail ? __GFP_NOFAIL : 0); - unsigned int io_retries = nofail ? EROFS_IO_MAX_RETRIES_NOFAIL : 0; - struct page *page; - int err; - -repeat: - page = find_or_create_page(mapping, blkaddr, gfp); - if (unlikely(!page)) { - DBG_BUGON(nofail); - return ERR_PTR(-ENOMEM); - } - DBG_BUGON(!PageLocked(page)); - - if (!PageUptodate(page)) { - struct bio *bio; - - bio = erofs_grab_bio(sb, blkaddr, 1, sb, read_endio, nofail); - if (IS_ERR(bio)) { - DBG_BUGON(nofail); - err = PTR_ERR(bio); - goto err_out; - } - - err = bio_add_page(bio, page, PAGE_SIZE, 0); - if (unlikely(err != PAGE_SIZE)) { - err = -EFAULT; - goto err_out; - } - __submit_bio(bio, REQ_OP_READ, - REQ_META | (prio ? REQ_PRIO : 0)); - - lock_page(page); - - /* this page has been truncated by others */ - if (unlikely(page->mapping != mapping)) { -unlock_repeat: - unlock_page(page); - put_page(page); - goto repeat; - } - - /* more likely a read error */ - if (unlikely(!PageUptodate(page))) { - if (io_retries) { - --io_retries; - goto unlock_repeat; - } - err = -EIO; - goto err_out; - } - } - return page; - -err_out: - unlock_page(page); - put_page(page); - return ERR_PTR(err); + return read_cache_page_gfp(mapping, blkaddr, + mapping_gfp_constraint(mapping, ~__GFP_FS)); } static int erofs_map_blocks_flatmode(struct inode *inode, @@ -119,14 +48,15 @@ static int erofs_map_blocks_flatmode(struct inode *inode, int err = 0; erofs_blk_t nblocks, lastblk; u64 offset = map->m_la; - struct erofs_vnode *vi = EROFS_V(inode); + struct erofs_inode *vi = EROFS_I(inode); + bool tailendpacking = (vi->datalayout == EROFS_INODE_FLAT_INLINE); trace_erofs_map_blocks_flatmode_enter(inode, map, flags); nblocks = DIV_ROUND_UP(inode->i_size, PAGE_SIZE); - lastblk = nblocks - is_inode_flat_inline(inode); + lastblk = nblocks - tailendpacking; - if (unlikely(offset >= inode->i_size)) { + if (offset >= inode->i_size) { /* leave out-of-bound access unmapped */ map->m_flags = 0; map->m_plen = 0; @@ -139,7 +69,7 @@ static int erofs_map_blocks_flatmode(struct inode *inode, if (offset < blknr_to_addr(lastblk)) { map->m_pa = blknr_to_addr(vi->raw_blkaddr) + map->m_la; map->m_plen = blknr_to_addr(lastblk) - offset; - } else if (is_inode_flat_inline(inode)) { + } else if (tailendpacking) { /* 2 - inode inline B: inode, [xattrs], inline last blk... */ struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); @@ -147,17 +77,21 @@ static int erofs_map_blocks_flatmode(struct inode *inode, vi->xattr_isize + erofs_blkoff(map->m_la); map->m_plen = inode->i_size - offset; - /* inline data should locate in one meta block */ + /* inline data should be located in one meta block */ if (erofs_blkoff(map->m_pa) + map->m_plen > PAGE_SIZE) { + erofs_err(inode->i_sb, + "inline data cross block boundary @ nid %llu", + vi->nid); DBG_BUGON(1); - err = -EIO; + err = -EFSCORRUPTED; goto err_out; } map->m_flags |= EROFS_MAP_META; } else { - errln("internal error @ nid: %llu (size %llu), m_la 0x%llx", - vi->nid, inode->i_size, map->m_la); + erofs_err(inode->i_sb, + "internal error @ nid: %llu (size %llu), m_la 0x%llx", + vi->nid, inode->i_size, map->m_la); DBG_BUGON(1); err = -EIO; goto err_out; @@ -174,7 +108,7 @@ err_out: int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map, int flags) { - if (unlikely(is_inode_layout_compression(inode))) { + if (erofs_inode_is_data_compressed(EROFS_I(inode)->datalayout)) { int err = z_erofs_map_blocks_iter(inode, map, flags); if (map->mpage) { @@ -205,18 +139,12 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio, goto has_updated; } - if (cleancache_get_page(page) == 0) { - err = 0; - SetPageUptodate(page); - goto has_updated; - } - /* note that for readpage case, bio also equals to NULL */ if (bio && /* not continuous */ *last_block + 1 != current_block) { submit_bio_retry: - __submit_bio(bio, REQ_OP_READ, 0); + submit_bio(bio); bio = NULL; } @@ -228,11 +156,11 @@ submit_bio_retry: unsigned int blkoff; err = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW); - if (unlikely(err)) + if (err) goto err_out; /* zero out the holed page */ - if (unlikely(!(map.m_flags & EROFS_MAP_MAPPED))) { + if (!(map.m_flags & EROFS_MAP_MAPPED)) { zero_user_segment(page, 0, PAGE_SIZE); SetPageUptodate(page); @@ -253,7 +181,7 @@ submit_bio_retry: DBG_BUGON(map.m_plen > PAGE_SIZE); - ipage = erofs_get_meta_page(inode->i_sb, blknr, 0); + ipage = erofs_get_meta_page(inode->i_sb, blknr); if (IS_ERR(ipage)) { err = PTR_ERR(ipage); @@ -286,13 +214,13 @@ submit_bio_retry: if (nblocks > BIO_MAX_PAGES) nblocks = BIO_MAX_PAGES; - bio = erofs_grab_bio(sb, blknr, nblocks, sb, - read_endio, false); - if (IS_ERR(bio)) { - err = PTR_ERR(bio); - bio = NULL; - goto err_out; - } + bio = bio_alloc(GFP_NOIO, nblocks); + + bio->bi_end_io = erofs_readendio; + bio_set_dev(bio, sb->s_bdev); + bio->bi_iter.bi_sector = (sector_t)blknr << + LOG_SECTORS_PER_BLOCK; + bio->bi_opf = REQ_OP_READ; } err = bio_add_page(bio, page, PAGE_SIZE, 0); @@ -323,9 +251,8 @@ has_updated: /* if updated manually, continuous pages has a gap */ if (bio) submit_bio_out: - __submit_bio(bio, REQ_OP_READ, 0); - - return unlikely(err) ? ERR_PTR(err) : NULL; + submit_bio(bio); + return err ? ERR_PTR(err) : NULL; } /* @@ -375,7 +302,7 @@ static int erofs_raw_access_readpages(struct file *filp, if (IS_ERR(bio)) { pr_err("%s, readahead error at page %lu of nid %llu\n", __func__, page->index, - EROFS_V(mapping->host)->nid); + EROFS_I(mapping->host)->nid); bio = NULL; } @@ -387,14 +314,47 @@ static int erofs_raw_access_readpages(struct file *filp, DBG_BUGON(!list_empty(pages)); /* the rare case (end in gaps) */ - if (unlikely(bio)) - __submit_bio(bio, REQ_OP_READ, 0); + if (bio) + submit_bio(bio); return 0; } +static int erofs_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int create) +{ + struct erofs_map_blocks map = { + .m_la = iblock << 9, + }; + int err; + + err = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW); + if (err) + return err; + + if (map.m_flags & EROFS_MAP_MAPPED) + bh->b_blocknr = erofs_blknr(map.m_pa); + + return err; +} + +static sector_t erofs_bmap(struct address_space *mapping, sector_t block) +{ + struct inode *inode = mapping->host; + + if (EROFS_I(inode)->datalayout == EROFS_INODE_FLAT_INLINE) { + erofs_blk_t blks = i_size_read(inode) >> LOG_BLOCK_SIZE; + + if (block >> LOG_SECTORS_PER_BLOCK >= blks) + return 0; + } + + return generic_block_bmap(mapping, block, erofs_get_block); +} + /* for uncompressed (aligned) files and raw access for other files */ const struct address_space_operations erofs_raw_access_aops = { .readpage = erofs_raw_access_readpage, .readpages = erofs_raw_access_readpages, + .bmap = erofs_bmap, }; diff --git a/drivers/staging/erofs/decompressor.c b/fs/erofs/decompressor.c index 1fb0abb98dff..19f89f9fb10c 100644 --- a/drivers/staging/erofs/decompressor.c +++ b/fs/erofs/decompressor.c @@ -1,12 +1,11 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/decompressor.c - * * Copyright (C) 2019 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> */ #include "compress.h" +#include <linux/module.h> #include <linux/lz4.h> #ifndef LZ4_DISTANCE_MAX /* history window size */ @@ -29,8 +28,8 @@ struct z_erofs_decompressor { char *name; }; -static int lz4_prepare_destpages(struct z_erofs_decompress_req *rq, - struct list_head *pagepool) +static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq, + struct list_head *pagepool) { const unsigned int nr = PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT; @@ -74,15 +73,9 @@ static int lz4_prepare_destpages(struct z_erofs_decompress_req *rq, victim = availables[--top]; get_page(victim); } else { - if (!list_empty(pagepool)) { - victim = lru_to_page(pagepool); - list_del(&victim->lru); - DBG_BUGON(page_ref_count(victim) != 1); - } else { - victim = alloc_pages(GFP_KERNEL, 0); - if (!victim) - return -ENOMEM; - } + victim = erofs_allocpage(pagepool, GFP_KERNEL, false); + if (!victim) + return -ENOMEM; victim->mapping = Z_EROFS_MAPPING_STAGING; } rq->out[i] = victim; @@ -117,7 +110,7 @@ static void *generic_copy_inplace_data(struct z_erofs_decompress_req *rq, return tmp; } -static int lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) +static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) { unsigned int inputmargin, inlen; u8 *src; @@ -125,14 +118,15 @@ static int lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) int ret; if (rq->inputsize > PAGE_SIZE) - return -ENOTSUPP; + return -EOPNOTSUPP; src = kmap_atomic(*rq->in); inputmargin = 0; support_0padding = false; /* decompression inplace is only safe when 0padding is enabled */ - if (EROFS_SB(rq->sb)->requirements & EROFS_REQUIREMENT_LZ4_0PADDING) { + if (EROFS_SB(rq->sb)->feature_incompat & + EROFS_FEATURE_INCOMPAT_LZ4_0PADDING) { support_0padding = true; while (!src[inputmargin & ~PAGE_MASK]) @@ -167,9 +161,8 @@ static int lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) inlen, rq->outputsize, rq->outputsize); if (ret < 0) { - errln("%s, failed to decompress, in[%p, %u, %u] out[%p, %u]", - __func__, src + inputmargin, inlen, inputmargin, - out, rq->outputsize); + erofs_err(rq->sb, "failed to decompress, in[%u, %u] out[%u]", + inlen, inputmargin, rq->outputsize); WARN_ON(1); print_hex_dump(KERN_DEBUG, "[ in]: ", DUMP_PREFIX_OFFSET, 16, 1, src + inputmargin, inlen, true); @@ -190,8 +183,8 @@ static struct z_erofs_decompressor decompressors[] = { .name = "shifted" }, [Z_EROFS_COMPRESSION_LZ4] = { - .prepare_destpages = lz4_prepare_destpages, - .decompress = lz4_decompress, + .prepare_destpages = z_erofs_lz4_prepare_destpages, + .decompress = z_erofs_lz4_decompress, .name = "lz4" }, }; @@ -223,15 +216,15 @@ static void copy_from_pcpubuf(struct page **out, const char *dst, } } -static int decompress_generic(struct z_erofs_decompress_req *rq, - struct list_head *pagepool) +static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq, + struct list_head *pagepool) { const unsigned int nrpages_out = PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT; const struct z_erofs_decompressor *alg = decompressors + rq->alg; unsigned int dst_maptype; void *dst; - int ret; + int ret, i; if (nrpages_out == 1 && !rq->inplace_io) { DBG_BUGON(!*rq->out); @@ -269,9 +262,19 @@ static int decompress_generic(struct z_erofs_decompress_req *rq, goto dstmap_out; } - dst = erofs_vmap(rq->out, nrpages_out); + i = 0; + while (1) { + dst = vm_map_ram(rq->out, nrpages_out, -1, PAGE_KERNEL); + + /* retry two more times (totally 3 times) */ + if (dst || ++i >= 3) + break; + vm_unmap_aliases(); + } + if (!dst) return -ENOMEM; + dst_maptype = 2; dstmap_out: @@ -280,12 +283,12 @@ dstmap_out: if (!dst_maptype) kunmap_atomic(dst); else if (dst_maptype == 2) - erofs_vunmap(dst, nrpages_out); + vm_unmap_ram(dst, nrpages_out); return ret; } -static int shifted_decompress(const struct z_erofs_decompress_req *rq, - struct list_head *pagepool) +static int z_erofs_shifted_transform(const struct z_erofs_decompress_req *rq, + struct list_head *pagepool) { const unsigned int nrpages_out = PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT; @@ -329,7 +332,7 @@ int z_erofs_decompress(struct z_erofs_decompress_req *rq, struct list_head *pagepool) { if (rq->alg == Z_EROFS_COMPRESSION_SHIFTED) - return shifted_decompress(rq, pagepool); - return decompress_generic(rq, pagepool); + return z_erofs_shifted_transform(rq, pagepool); + return z_erofs_decompress_generic(rq, pagepool); } diff --git a/drivers/staging/erofs/dir.c b/fs/erofs/dir.c index dbf6a151886c..d28c623dfef9 100644 --- a/drivers/staging/erofs/dir.c +++ b/fs/erofs/dir.c @@ -1,28 +1,11 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/dir.c - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "internal.h" -static const unsigned char erofs_filetype_table[EROFS_FT_MAX] = { - [EROFS_FT_UNKNOWN] = DT_UNKNOWN, - [EROFS_FT_REG_FILE] = DT_REG, - [EROFS_FT_DIR] = DT_DIR, - [EROFS_FT_CHRDEV] = DT_CHR, - [EROFS_FT_BLKDEV] = DT_BLK, - [EROFS_FT_FIFO] = DT_FIFO, - [EROFS_FT_SOCK] = DT_SOCK, - [EROFS_FT_SYMLINK] = DT_LNK, -}; - static void debug_one_dentry(unsigned char d_type, const char *de_name, unsigned int de_namelen) { @@ -33,12 +16,12 @@ static void debug_one_dentry(unsigned char d_type, const char *de_name, memcpy(dbg_namebuf, de_name, de_namelen); dbg_namebuf[de_namelen] = '\0'; - debugln("found dirent %s de_len %u d_type %d", dbg_namebuf, - de_namelen, d_type); + erofs_dbg("found dirent %s de_len %u d_type %d", dbg_namebuf, + de_namelen, d_type); #endif } -static int erofs_fill_dentries(struct dir_context *ctx, +static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx, void *dentry_blk, unsigned int *ofs, unsigned int nameoff, unsigned int maxsize) { @@ -50,10 +33,7 @@ static int erofs_fill_dentries(struct dir_context *ctx, unsigned int de_namelen; unsigned char d_type; - if (de->file_type < EROFS_FT_MAX) - d_type = erofs_filetype_table[de->file_type]; - else - d_type = DT_UNKNOWN; + d_type = fs_ftype_to_dtype(de->file_type); nameoff = le16_to_cpu(de->nameoff); de_name = (char *)dentry_blk + nameoff; @@ -65,10 +45,12 @@ static int erofs_fill_dentries(struct dir_context *ctx, de_namelen = le16_to_cpu(de[1].nameoff) - nameoff; /* a corrupted entry is found */ - if (unlikely(nameoff + de_namelen > maxsize || - de_namelen > EROFS_NAME_LEN)) { + if (nameoff + de_namelen > maxsize || + de_namelen > EROFS_NAME_LEN) { + erofs_err(dir->i_sb, "bogus dirent @ nid %llu", + EROFS_I(dir)->nid); DBG_BUGON(1); - return -EIO; + return -EFSCORRUPTED; } debug_one_dentry(d_type, de_name, de_namelen); @@ -99,19 +81,27 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx) unsigned int nameoff, maxsize; dentry_page = read_mapping_page(mapping, i, NULL); - if (IS_ERR(dentry_page)) - continue; + if (dentry_page == ERR_PTR(-ENOMEM)) { + err = -ENOMEM; + break; + } else if (IS_ERR(dentry_page)) { + erofs_err(dir->i_sb, + "fail to readdir of logical block %u of nid %llu", + i, EROFS_I(dir)->nid); + err = -EFSCORRUPTED; + break; + } de = (struct erofs_dirent *)kmap(dentry_page); nameoff = le16_to_cpu(de->nameoff); - if (unlikely(nameoff < sizeof(struct erofs_dirent) || - nameoff >= PAGE_SIZE)) { - errln("%s, invalid de[0].nameoff %u", - __func__, nameoff); - - err = -EIO; + if (nameoff < sizeof(struct erofs_dirent) || + nameoff >= PAGE_SIZE) { + erofs_err(dir->i_sb, + "invalid de[0].nameoff %u @ nid %llu", + nameoff, EROFS_I(dir)->nid); + err = -EFSCORRUPTED; goto skip_this; } @@ -119,15 +109,16 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx) dirsize - ctx->pos + ofs, PAGE_SIZE); /* search dirents at the arbitrary position */ - if (unlikely(initial)) { + if (initial) { initial = false; ofs = roundup(ofs, sizeof(struct erofs_dirent)); - if (unlikely(ofs >= nameoff)) + if (ofs >= nameoff) goto skip_this; } - err = erofs_fill_dentries(ctx, de, &ofs, nameoff, maxsize); + err = erofs_fill_dentries(dir, ctx, de, &ofs, + nameoff, maxsize); skip_this: kunmap(dentry_page); @@ -135,7 +126,7 @@ skip_this: ctx->pos = blknr_to_addr(i) + ofs; - if (unlikely(err)) + if (err) break; ++i; ofs = 0; diff --git a/drivers/staging/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h index 9f61abb7c1ca..b1ee5654750d 100644 --- a/drivers/staging/erofs/erofs_fs.h +++ b/fs/erofs/erofs_fs.h @@ -1,53 +1,48 @@ -/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 - * - * linux/drivers/staging/erofs/erofs_fs.h +/* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */ +/* + * EROFS (Enhanced ROM File System) on-disk format definition * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is dual-licensed; you may select either the GNU General Public - * License version 2 or Apache License, Version 2.0. See the file COPYING - * in the main directory of the Linux distribution for more details. */ #ifndef __EROFS_FS_H #define __EROFS_FS_H -/* Enhanced(Extended) ROM File System */ -#define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 #define EROFS_SUPER_OFFSET 1024 /* - * Any bits that aren't in EROFS_ALL_REQUIREMENTS should be - * incompatible with this kernel version. + * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should + * be incompatible with this kernel version. */ -#define EROFS_REQUIREMENT_LZ4_0PADDING 0x00000001 -#define EROFS_ALL_REQUIREMENTS EROFS_REQUIREMENT_LZ4_0PADDING +#define EROFS_FEATURE_INCOMPAT_LZ4_0PADDING 0x00000001 +#define EROFS_ALL_FEATURE_INCOMPAT EROFS_FEATURE_INCOMPAT_LZ4_0PADDING +/* 128-byte erofs on-disk super block */ struct erofs_super_block { -/* 0 */__le32 magic; /* in the little endian */ -/* 4 */__le32 checksum; /* crc32c(super_block) */ -/* 8 */__le32 features; /* (aka. feature_compat) */ -/* 12 */__u8 blkszbits; /* support block_size == PAGE_SIZE only */ -/* 13 */__u8 reserved; - -/* 14 */__le16 root_nid; -/* 16 */__le64 inos; /* total valid ino # (== f_files - f_favail) */ - -/* 24 */__le64 build_time; /* inode v1 time derivation */ -/* 32 */__le32 build_time_nsec; -/* 36 */__le32 blocks; /* used for statfs */ -/* 40 */__le32 meta_blkaddr; -/* 44 */__le32 xattr_blkaddr; -/* 48 */__u8 uuid[16]; /* 128-bit uuid for volume */ -/* 64 */__u8 volume_name[16]; /* volume name */ -/* 80 */__le32 requirements; /* (aka. feature_incompat) */ - -/* 84 */__u8 reserved2[44]; -} __packed; /* 128 bytes */ + __le32 magic; /* file system magic number */ + __le32 checksum; /* crc32c(super_block) */ + __le32 feature_compat; + __u8 blkszbits; /* support block_size == PAGE_SIZE only */ + __u8 reserved; + + __le16 root_nid; /* nid of root directory */ + __le64 inos; /* total valid ino # (== f_files - f_favail) */ + + __le64 build_time; /* inode v1 time derivation */ + __le32 build_time_nsec; /* inode v1 time derivation in nano scale */ + __le32 blocks; /* used for statfs */ + __le32 meta_blkaddr; /* start block address of metadata area */ + __le32 xattr_blkaddr; /* start block address of shared xattr area */ + __u8 uuid[16]; /* 128-bit uuid for volume */ + __u8 volume_name[16]; /* volume name */ + __le32 feature_incompat; + + __u8 reserved2[44]; +}; /* - * erofs inode data mapping: + * erofs inode datalayout (i_format in on-disk inode): * 0 - inode plain without inline data A: * inode, [xattrs], ... | ... | no-holed data * 1 - inode VLE compression B (legacy): @@ -59,63 +54,64 @@ struct erofs_super_block { * 4~7 - reserved */ enum { - EROFS_INODE_FLAT_PLAIN, - EROFS_INODE_FLAT_COMPRESSION_LEGACY, - EROFS_INODE_FLAT_INLINE, - EROFS_INODE_FLAT_COMPRESSION, - EROFS_INODE_LAYOUT_MAX + EROFS_INODE_FLAT_PLAIN = 0, + EROFS_INODE_FLAT_COMPRESSION_LEGACY = 1, + EROFS_INODE_FLAT_INLINE = 2, + EROFS_INODE_FLAT_COMPRESSION = 3, + EROFS_INODE_DATALAYOUT_MAX }; -static bool erofs_inode_is_data_compressed(unsigned int datamode) +static inline bool erofs_inode_is_data_compressed(unsigned int datamode) { - if (datamode == EROFS_INODE_FLAT_COMPRESSION) - return true; - return datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY; + return datamode == EROFS_INODE_FLAT_COMPRESSION || + datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY; } /* bit definitions of inode i_advise */ #define EROFS_I_VERSION_BITS 1 -#define EROFS_I_DATA_MAPPING_BITS 3 +#define EROFS_I_DATALAYOUT_BITS 3 #define EROFS_I_VERSION_BIT 0 -#define EROFS_I_DATA_MAPPING_BIT 1 +#define EROFS_I_DATALAYOUT_BIT 1 -struct erofs_inode_v1 { -/* 0 */__le16 i_advise; +/* 32-byte reduced form of an ondisk inode */ +struct erofs_inode_compact { + __le16 i_format; /* inode format hints */ /* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ -/* 2 */__le16 i_xattr_icount; -/* 4 */__le16 i_mode; -/* 6 */__le16 i_nlink; -/* 8 */__le32 i_size; -/* 12 */__le32 i_reserved; -/* 16 */union { + __le16 i_xattr_icount; + __le16 i_mode; + __le16 i_nlink; + __le32 i_size; + __le32 i_reserved; + union { /* file total compressed blocks for data mapping 1 */ __le32 compressed_blocks; __le32 raw_blkaddr; /* for device files, used to indicate old/new device # */ __le32 rdev; - } i_u __packed; -/* 20 */__le32 i_ino; /* only used for 32-bit stat compatibility */ -/* 24 */__le16 i_uid; -/* 26 */__le16 i_gid; -/* 28 */__le32 i_checksum; -} __packed; + } i_u; + __le32 i_ino; /* only used for 32-bit stat compatibility */ + __le16 i_uid; + __le16 i_gid; + __le32 i_reserved2; +}; /* 32 bytes on-disk inode */ -#define EROFS_INODE_LAYOUT_V1 0 +#define EROFS_INODE_LAYOUT_COMPACT 0 /* 64 bytes on-disk inode */ -#define EROFS_INODE_LAYOUT_V2 1 +#define EROFS_INODE_LAYOUT_EXTENDED 1 -struct erofs_inode_v2 { - __le16 i_advise; +/* 64-byte complete form of an ondisk inode */ +struct erofs_inode_extended { + __le16 i_format; /* inode format hints */ - /* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ +/* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ __le16 i_xattr_icount; __le16 i_mode; - __le16 i_reserved; /* 8 bytes */ - __le64 i_size; /* 16 bytes */ + __le16 i_reserved; + __le64 i_size; union { /* file total compressed blocks for data mapping 1 */ __le32 compressed_blocks; @@ -123,19 +119,18 @@ struct erofs_inode_v2 { /* for device files, used to indicate old/new device # */ __le32 rdev; - } i_u __packed; + } i_u; /* only used for 32-bit stat compatibility */ - __le32 i_ino; /* 24 bytes */ + __le32 i_ino; __le32 i_uid; __le32 i_gid; - __le64 i_ctime; /* 32 bytes */ + __le64 i_ctime; __le32 i_ctime_nsec; __le32 i_nlink; - __u8 i_reserved2[12]; - __le32 i_checksum; /* 64 bytes */ -} __packed; + __u8 i_reserved2[16]; +}; #define EROFS_MAX_SHARED_XATTRS (128) /* h_shared_count between 129 ... 255 are special # */ @@ -153,11 +148,11 @@ struct erofs_inode_v2 { * for read-only fs, no need to introduce h_refcount */ struct erofs_xattr_ibody_header { - __le32 h_checksum; + __le32 h_reserved; __u8 h_shared_count; - __u8 h_reserved[7]; + __u8 h_reserved2[7]; __le32 h_shared_xattrs[0]; /* shared xattr id array */ -} __packed; +}; /* Name indexes */ #define EROFS_XATTR_INDEX_USER 1 @@ -174,22 +169,28 @@ struct erofs_xattr_entry { __le16 e_value_size; /* size of attribute value */ /* followed by e_name and e_value */ char e_name[0]; /* attribute name */ -} __packed; +}; -#define ondisk_xattr_ibody_size(count) ({\ - u32 __count = le16_to_cpu(count); \ - ((__count) == 0) ? 0 : \ - sizeof(struct erofs_xattr_ibody_header) + \ - sizeof(__u32) * ((__count) - 1); }) +static inline unsigned int erofs_xattr_ibody_size(__le16 i_xattr_icount) +{ + if (!i_xattr_icount) + return 0; + + return sizeof(struct erofs_xattr_ibody_header) + + sizeof(__u32) * (le16_to_cpu(i_xattr_icount) - 1); +} #define EROFS_XATTR_ALIGN(size) round_up(size, sizeof(struct erofs_xattr_entry)) -#define EROFS_XATTR_ENTRY_SIZE(entry) EROFS_XATTR_ALIGN( \ - sizeof(struct erofs_xattr_entry) + \ - (entry)->e_name_len + le16_to_cpu((entry)->e_value_size)) -/* available compression algorithm types */ +static inline unsigned int erofs_xattr_entry_size(struct erofs_xattr_entry *e) +{ + return EROFS_XATTR_ALIGN(sizeof(struct erofs_xattr_entry) + + e->e_name_len + le16_to_cpu(e->e_value_size)); +} + +/* available compression algorithm types (for h_algorithmtype) */ enum { - Z_EROFS_COMPRESSION_LZ4, + Z_EROFS_COMPRESSION_LZ4 = 0, Z_EROFS_COMPRESSION_MAX }; @@ -222,7 +223,7 @@ struct z_erofs_map_header { #define Z_EROFS_VLE_LEGACY_HEADER_PADDING 8 /* - * Z_EROFS Variable-sized Logical Extent cluster type: + * Fixed-sized output compression ondisk Logical Extent cluster type: * 0 - literal (uncompressed) cluster * 1 - compressed cluster (for the head logical cluster) * 2 - compressed cluster (for the other logical clusters) @@ -247,10 +248,10 @@ struct z_erofs_map_header { * (di_advise could be 0, 1 or 2) */ enum { - Z_EROFS_VLE_CLUSTER_TYPE_PLAIN, - Z_EROFS_VLE_CLUSTER_TYPE_HEAD, - Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD, - Z_EROFS_VLE_CLUSTER_TYPE_RESERVED, + Z_EROFS_VLE_CLUSTER_TYPE_PLAIN = 0, + Z_EROFS_VLE_CLUSTER_TYPE_HEAD = 1, + Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD = 2, + Z_EROFS_VLE_CLUSTER_TYPE_RESERVED = 3, Z_EROFS_VLE_CLUSTER_TYPE_MAX }; @@ -272,8 +273,8 @@ struct z_erofs_vle_decompressed_index { * [1] - pointing to the tail cluster */ __le16 delta[2]; - } di_u __packed; /* 8 bytes */ -} __packed; + } di_u; +}; #define Z_EROFS_VLE_LEGACY_INDEX_ALIGN(size) \ (round_up(size, sizeof(struct z_erofs_vle_decompressed_index)) + \ @@ -281,24 +282,17 @@ struct z_erofs_vle_decompressed_index { /* dirent sorts in alphabet order, thus we can do binary search */ struct erofs_dirent { - __le64 nid; /* 0, node number */ - __le16 nameoff; /* 8, start offset of file name */ - __u8 file_type; /* 10, file type */ - __u8 reserved; /* 11, reserved */ + __le64 nid; /* node number */ + __le16 nameoff; /* start offset of file name */ + __u8 file_type; /* file type */ + __u8 reserved; /* reserved */ } __packed; -/* file types used in inode_info->flags */ -enum { - EROFS_FT_UNKNOWN, - EROFS_FT_REG_FILE, - EROFS_FT_DIR, - EROFS_FT_CHRDEV, - EROFS_FT_BLKDEV, - EROFS_FT_FIFO, - EROFS_FT_SOCK, - EROFS_FT_SYMLINK, - EROFS_FT_MAX -}; +/* + * EROFS file types should match generic FT_* types and + * it seems no need to add BUILD_BUG_ONs since potential + * unmatchness will break other fses as well... + */ #define EROFS_NAME_LEN 255 @@ -306,8 +300,8 @@ enum { static inline void erofs_check_ondisk_layout_definitions(void) { BUILD_BUG_ON(sizeof(struct erofs_super_block) != 128); - BUILD_BUG_ON(sizeof(struct erofs_inode_v1) != 32); - BUILD_BUG_ON(sizeof(struct erofs_inode_v2) != 64); + BUILD_BUG_ON(sizeof(struct erofs_inode_compact) != 32); + BUILD_BUG_ON(sizeof(struct erofs_inode_extended) != 64); BUILD_BUG_ON(sizeof(struct erofs_xattr_ibody_header) != 12); BUILD_BUG_ON(sizeof(struct erofs_xattr_entry) != 4); BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8); diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c new file mode 100644 index 000000000000..3350ab65d892 --- /dev/null +++ b/fs/erofs/inode.c @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang <gaoxiang25@huawei.com> + */ +#include "xattr.h" + +#include <trace/events/erofs.h> + +/* no locking */ +static int erofs_read_inode(struct inode *inode, void *data) +{ + struct erofs_inode *vi = EROFS_I(inode); + struct erofs_inode_compact *dic = data; + struct erofs_inode_extended *die; + + 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; + + 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; + } + + switch (erofs_inode_version(ifmt)) { + case EROFS_INODE_LAYOUT_EXTENDED: + die = data; + + vi->inode_isize = sizeof(struct erofs_inode_extended); + vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount); + + inode->i_mode = le16_to_cpu(die->i_mode); + switch (inode->i_mode & S_IFMT) { + case S_IFREG: + case S_IFDIR: + case S_IFLNK: + vi->raw_blkaddr = le32_to_cpu(die->i_u.raw_blkaddr); + break; + case S_IFCHR: + case S_IFBLK: + inode->i_rdev = + new_decode_dev(le32_to_cpu(die->i_u.rdev)); + break; + case S_IFIFO: + case S_IFSOCK: + inode->i_rdev = 0; + break; + default: + goto bogusimode; + } + i_uid_write(inode, le32_to_cpu(die->i_uid)); + i_gid_write(inode, le32_to_cpu(die->i_gid)); + set_nlink(inode, le32_to_cpu(die->i_nlink)); + + /* ns timestamp */ + inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = + le64_to_cpu(die->i_ctime); + inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = + le32_to_cpu(die->i_ctime_nsec); + + inode->i_size = le64_to_cpu(die->i_size); + + /* total blocks for compressed files */ + if (erofs_inode_is_data_compressed(vi->datalayout)) + nblks = le32_to_cpu(die->i_u.compressed_blocks); + break; + case EROFS_INODE_LAYOUT_COMPACT: + vi->inode_isize = sizeof(struct erofs_inode_compact); + vi->xattr_isize = erofs_xattr_ibody_size(dic->i_xattr_icount); + + inode->i_mode = le16_to_cpu(dic->i_mode); + switch (inode->i_mode & S_IFMT) { + case S_IFREG: + case S_IFDIR: + case S_IFLNK: + vi->raw_blkaddr = le32_to_cpu(dic->i_u.raw_blkaddr); + break; + case S_IFCHR: + case S_IFBLK: + inode->i_rdev = + new_decode_dev(le32_to_cpu(dic->i_u.rdev)); + break; + case S_IFIFO: + case S_IFSOCK: + inode->i_rdev = 0; + break; + default: + goto bogusimode; + } + i_uid_write(inode, le16_to_cpu(dic->i_uid)); + i_gid_write(inode, le16_to_cpu(dic->i_gid)); + set_nlink(inode, le16_to_cpu(dic->i_nlink)); + + /* use build time to derive all file time */ + inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = + sbi->build_time; + inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = + sbi->build_time_nsec; + + inode->i_size = le32_to_cpu(dic->i_size); + if (erofs_inode_is_data_compressed(vi->datalayout)) + nblks = le32_to_cpu(dic->i_u.compressed_blocks); + break; + default: + 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; + } + + if (!nblks) + /* measure inode.i_blocks as generic filesystems */ + inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9; + else + inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK; + return 0; + +bogusimode: + erofs_err(inode->i_sb, "bogus i_mode (%o) @ nid %llu", + inode->i_mode, vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; +} + +static int erofs_fill_symlink(struct inode *inode, void *data, + unsigned int m_pofs) +{ + struct erofs_inode *vi = EROFS_I(inode); + char *lnk; + + /* if it cannot be handled with fast symlink scheme */ + if (vi->datalayout != EROFS_INODE_FLAT_INLINE || + inode->i_size >= PAGE_SIZE) { + inode->i_op = &erofs_symlink_iops; + return 0; + } + + lnk = kmalloc(inode->i_size + 1, GFP_KERNEL); + if (!lnk) + return -ENOMEM; + + m_pofs += vi->inode_isize + vi->xattr_isize; + /* inline symlink data shouldn't cross page boundary as well */ + if (m_pofs + inode->i_size > PAGE_SIZE) { + kfree(lnk); + erofs_err(inode->i_sb, + "inline data cross block boundary @ nid %llu", + vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; + } + + memcpy(lnk, data + m_pofs, inode->i_size); + lnk[inode->i_size] = '\0'; + + inode->i_link = lnk; + inode->i_op = &erofs_fast_symlink_iops; + return 0; +} + +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; + + 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)); + 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) { + case S_IFREG: + inode->i_op = &erofs_generic_iops; + inode->i_fop = &generic_ro_fops; + break; + case S_IFDIR: + inode->i_op = &erofs_dir_iops; + inode->i_fop = &erofs_dir_fops; + break; + case S_IFLNK: + err = erofs_fill_symlink(inode, data, ofs); + if (err) + goto out_unlock; + inode_nohighmem(inode); + break; + case S_IFCHR: + case S_IFBLK: + case S_IFIFO: + case S_IFSOCK: + inode->i_op = &erofs_generic_iops; + init_special_inode(inode, inode->i_mode, inode->i_rdev); + goto out_unlock; + default: + err = -EFSCORRUPTED; + goto out_unlock; + } + + if (erofs_inode_is_data_compressed(vi->datalayout)) { + err = z_erofs_fill_inode(inode); + goto out_unlock; + } + inode->i_mapping->a_ops = &erofs_raw_access_aops; + +out_unlock: + unlock_page(page); + put_page(page); + return err; +} + +/* + * erofs nid is 64bits, but i_ino is 'unsigned long', therefore + * we should do more for 32-bit platform to find the right inode. + */ +static int erofs_ilookup_test_actor(struct inode *inode, void *opaque) +{ + const erofs_nid_t nid = *(erofs_nid_t *)opaque; + + return EROFS_I(inode)->nid == nid; +} + +static int erofs_iget_set_actor(struct inode *inode, void *opaque) +{ + const erofs_nid_t nid = *(erofs_nid_t *)opaque; + + inode->i_ino = erofs_inode_hash(nid); + return 0; +} + +static inline struct inode *erofs_iget_locked(struct super_block *sb, + erofs_nid_t nid) +{ + const unsigned long hashval = erofs_inode_hash(nid); + + return iget5_locked(sb, hashval, erofs_ilookup_test_actor, + erofs_iget_set_actor, &nid); +} + +struct inode *erofs_iget(struct super_block *sb, + erofs_nid_t nid, + bool isdir) +{ + struct inode *inode = erofs_iget_locked(sb, nid); + + if (!inode) + return ERR_PTR(-ENOMEM); + + if (inode->i_state & I_NEW) { + int err; + struct erofs_inode *vi = EROFS_I(inode); + + vi->nid = nid; + + err = erofs_fill_inode(inode, isdir); + if (!err) + unlock_new_inode(inode); + else { + iget_failed(inode); + inode = ERR_PTR(err); + } + } + return inode; +} + +int erofs_getattr(const struct path *path, struct kstat *stat, + u32 request_mask, unsigned int query_flags) +{ + struct inode *const inode = d_inode(path->dentry); + + if (erofs_inode_is_data_compressed(EROFS_I(inode)->datalayout)) + stat->attributes |= STATX_ATTR_COMPRESSED; + + stat->attributes |= STATX_ATTR_IMMUTABLE; + stat->attributes_mask |= (STATX_ATTR_COMPRESSED | + STATX_ATTR_IMMUTABLE); + + generic_fillattr(inode, stat); + return 0; +} + +const struct inode_operations erofs_generic_iops = { + .getattr = erofs_getattr, +#ifdef CONFIG_EROFS_FS_XATTR + .listxattr = erofs_listxattr, +#endif + .get_acl = erofs_get_acl, +}; + +const struct inode_operations erofs_symlink_iops = { + .get_link = page_get_link, + .getattr = erofs_getattr, +#ifdef CONFIG_EROFS_FS_XATTR + .listxattr = erofs_listxattr, +#endif + .get_acl = erofs_get_acl, +}; + +const struct inode_operations erofs_fast_symlink_iops = { + .get_link = simple_get_link, + .getattr = erofs_getattr, +#ifdef CONFIG_EROFS_FS_XATTR + .listxattr = erofs_listxattr, +#endif + .get_acl = erofs_get_acl, +}; + diff --git a/drivers/staging/erofs/internal.h b/fs/erofs/internal.h index 963cc1b8b896..544a453f3076 100644 --- a/drivers/staging/erofs/internal.h +++ b/fs/erofs/internal.h @@ -1,17 +1,11 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * linux/drivers/staging/erofs/internal.h - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ -#ifndef __INTERNAL_H -#define __INTERNAL_H +#ifndef __EROFS_INTERNAL_H +#define __EROFS_INTERNAL_H #include <linux/fs.h> #include <linux/dcache.h> @@ -19,7 +13,7 @@ #include <linux/pagemap.h> #include <linux/bio.h> #include <linux/buffer_head.h> -#include <linux/cleancache.h> +#include <linux/magic.h> #include <linux/slab.h> #include <linux/vmalloc.h> #include "erofs_fs.h" @@ -28,82 +22,58 @@ #undef pr_fmt #define pr_fmt(fmt) "erofs: " fmt -#define errln(x, ...) pr_err(x "\n", ##__VA_ARGS__) -#define infoln(x, ...) pr_info(x "\n", ##__VA_ARGS__) +__printf(3, 4) void _erofs_err(struct super_block *sb, + const char *function, const char *fmt, ...); +#define erofs_err(sb, fmt, ...) \ + _erofs_err(sb, __func__, fmt "\n", ##__VA_ARGS__) +__printf(3, 4) void _erofs_info(struct super_block *sb, + const char *function, const char *fmt, ...); +#define erofs_info(sb, fmt, ...) \ + _erofs_info(sb, __func__, fmt "\n", ##__VA_ARGS__) #ifdef CONFIG_EROFS_FS_DEBUG -#define debugln(x, ...) pr_debug(x "\n", ##__VA_ARGS__) - -#define dbg_might_sleep might_sleep +#define erofs_dbg(x, ...) pr_debug(x "\n", ##__VA_ARGS__) #define DBG_BUGON BUG_ON #else -#define debugln(x, ...) ((void)0) - -#define dbg_might_sleep() ((void)0) +#define erofs_dbg(x, ...) ((void)0) #define DBG_BUGON(x) ((void)(x)) -#endif - -enum { - FAULT_KMALLOC, - FAULT_READ_IO, - FAULT_MAX, -}; - -#ifdef CONFIG_EROFS_FAULT_INJECTION -extern const char *erofs_fault_name[FAULT_MAX]; -#define IS_FAULT_SET(fi, type) ((fi)->inject_type & (1 << (type))) - -struct erofs_fault_info { - atomic_t inject_ops; - unsigned int inject_rate; - unsigned int inject_type; -}; -#endif - -#ifdef CONFIG_EROFS_FS_ZIP_CACHE_BIPOLAR -#define EROFS_FS_ZIP_CACHE_LVL (2) -#elif defined(EROFS_FS_ZIP_CACHE_UNIPOLAR) -#define EROFS_FS_ZIP_CACHE_LVL (1) -#else -#define EROFS_FS_ZIP_CACHE_LVL (0) -#endif - -#if (!defined(EROFS_FS_HAS_MANAGED_CACHE) && (EROFS_FS_ZIP_CACHE_LVL > 0)) -#define EROFS_FS_HAS_MANAGED_CACHE -#endif +#endif /* !CONFIG_EROFS_FS_DEBUG */ /* EROFS_SUPER_MAGIC_V1 to represent the whole file system */ #define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1 typedef u64 erofs_nid_t; +typedef u64 erofs_off_t; +/* data type for filesystem-wide blocks number */ +typedef u32 erofs_blk_t; struct erofs_sb_info { +#ifdef CONFIG_EROFS_FS_ZIP /* list for all registered superblocks, mainly for shrinker */ struct list_head list; struct mutex umount_mutex; - u32 blocks; - u32 meta_blkaddr; -#ifdef CONFIG_EROFS_FS_XATTR - u32 xattr_blkaddr; -#endif - - /* inode slot unit size in bit shift */ - unsigned char islotbits; -#ifdef CONFIG_EROFS_FS_ZIP - /* cluster size in bit shift */ - unsigned char clusterbits; - /* the dedicated workstation for compression */ struct radix_tree_root workstn_tree; /* threshold for decompression synchronously */ unsigned int max_sync_decompress_pages; -#ifdef EROFS_FS_HAS_MANAGED_CACHE + unsigned int shrinker_run_no; + + /* current strategy of how to use managed cache */ + unsigned char cache_strategy; + + /* pseudo inode to manage cached pages */ struct inode *managed_cache; +#endif /* CONFIG_EROFS_FS_ZIP */ + u32 blocks; + u32 meta_blkaddr; +#ifdef CONFIG_EROFS_FS_XATTR + u32 xattr_blkaddr; #endif -#endif + /* inode slot unit size in bit shift */ + unsigned char islotbits; u32 build_time_nsec; u64 build_time; @@ -115,76 +85,30 @@ struct erofs_sb_info { u8 uuid[16]; /* 128-bit uuid for volume */ u8 volume_name[16]; /* volume name */ - u32 requirements; - - char *dev_name; + u32 feature_incompat; unsigned int mount_opt; - unsigned int shrinker_run_no; - -#ifdef CONFIG_EROFS_FAULT_INJECTION - struct erofs_fault_info fault_info; /* For fault injection */ -#endif }; -#ifdef CONFIG_EROFS_FAULT_INJECTION -#define erofs_show_injection_info(type) \ - infoln("inject %s in %s of %pS", erofs_fault_name[type], \ - __func__, __builtin_return_address(0)) - -static inline bool time_to_inject(struct erofs_sb_info *sbi, int type) -{ - struct erofs_fault_info *ffi = &sbi->fault_info; - - if (!ffi->inject_rate) - return false; - - if (!IS_FAULT_SET(ffi, type)) - return false; - - atomic_inc(&ffi->inject_ops); - if (atomic_read(&ffi->inject_ops) >= ffi->inject_rate) { - atomic_set(&ffi->inject_ops, 0); - return true; - } - return false; -} -#else -static inline bool time_to_inject(struct erofs_sb_info *sbi, int type) -{ - return false; -} - -static inline void erofs_show_injection_info(int type) -{ -} -#endif - -static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, - size_t size, gfp_t flags) -{ - if (time_to_inject(sbi, FAULT_KMALLOC)) { - erofs_show_injection_info(FAULT_KMALLOC); - return NULL; - } - return kmalloc(size, flags); -} - #define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) #define EROFS_I_SB(inode) ((struct erofs_sb_info *)(inode)->i_sb->s_fs_info) /* Mount flags set via mount options or defaults */ #define EROFS_MOUNT_XATTR_USER 0x00000010 #define EROFS_MOUNT_POSIX_ACL 0x00000020 -#define EROFS_MOUNT_FAULT_INJECTION 0x00000040 #define clear_opt(sbi, option) ((sbi)->mount_opt &= ~EROFS_MOUNT_##option) #define set_opt(sbi, option) ((sbi)->mount_opt |= EROFS_MOUNT_##option) #define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) #ifdef CONFIG_EROFS_FS_ZIP -#define erofs_workstn_lock(sbi) xa_lock(&(sbi)->workstn_tree) -#define erofs_workstn_unlock(sbi) xa_unlock(&(sbi)->workstn_tree) +enum { + EROFS_ZIP_CACHE_DISABLED, + EROFS_ZIP_CACHE_READAHEAD, + EROFS_ZIP_CACHE_READAROUND +}; + +#define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) /* basic unit of the workstation of a super_block */ struct erofs_workgroup { @@ -195,8 +119,6 @@ struct erofs_workgroup { atomic_t refcount; }; -#define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) - #if defined(CONFIG_SMP) static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp, int val) @@ -253,50 +175,14 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) DBG_BUGON(v == EROFS_LOCKED_MAGIC); return v; } -#endif - -int erofs_workgroup_put(struct erofs_workgroup *grp); -struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, - pgoff_t index, bool *tag); -int erofs_register_workgroup(struct super_block *sb, - struct erofs_workgroup *grp, bool tag); -unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink, bool cleanup); -void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); - -#ifdef EROFS_FS_HAS_MANAGED_CACHE -int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, - struct erofs_workgroup *egrp); -int erofs_try_to_free_cached_page(struct address_space *mapping, - struct page *page); - -#define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) -static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, - struct page *page) -{ - return page->mapping == MNGD_MAPPING(sbi); -} -#else -#define MNGD_MAPPING(sbi) (NULL) -static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, - struct page *page) { return false; } -#endif - -#define DEFAULT_MAX_SYNC_DECOMPRESS_PAGES 3 - -static inline bool __should_decompress_synchronously(struct erofs_sb_info *sbi, - unsigned int nr) -{ - return nr <= sbi->max_sync_decompress_pages; -} +#endif /* !CONFIG_SMP */ -int __init z_erofs_init_zip_subsystem(void); -void z_erofs_exit_zip_subsystem(void); +/* hard limit of pages per compressed cluster */ +#define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) +#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES #else -/* dummy initializer/finalizer for the decompression subsystem */ -static inline int z_erofs_init_zip_subsystem(void) { return 0; } -static inline void z_erofs_exit_zip_subsystem(void) {} -#endif +#define EROFS_PCPUBUF_NR_PAGES 0 +#endif /* !CONFIG_EROFS_FS_ZIP */ /* we strictly follow PAGE_SIZE and no buffer head yet */ #define LOG_BLOCK_SIZE PAGE_SHIFT @@ -315,23 +201,6 @@ static inline void z_erofs_exit_zip_subsystem(void) {} #define ROOT_NID(sb) ((sb)->root_nid) -#ifdef CONFIG_EROFS_FS_ZIP -/* hard limit of pages per compressed cluster */ -#define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) - -/* page count of a compressed cluster */ -#define erofs_clusterpages(sbi) ((1 << (sbi)->clusterbits) / PAGE_SIZE) - -#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES -#else -#define EROFS_PCPUBUF_NR_PAGES 0 -#endif - -typedef u64 erofs_off_t; - -/* data type for filesystem-wide blocks number */ -typedef u32 erofs_blk_t; - #define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ) #define erofs_blkoff(addr) ((addr) % EROFS_BLKSIZ) #define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ) @@ -342,25 +211,25 @@ static inline erofs_off_t iloc(struct erofs_sb_info *sbi, erofs_nid_t nid) } /* atomic flag definitions */ -#define EROFS_V_EA_INITED_BIT 0 -#define EROFS_V_Z_INITED_BIT 1 +#define EROFS_I_EA_INITED_BIT 0 +#define EROFS_I_Z_INITED_BIT 1 /* bitlock definitions (arranged in reverse order) */ -#define EROFS_V_BL_XATTR_BIT (BITS_PER_LONG - 1) -#define EROFS_V_BL_Z_BIT (BITS_PER_LONG - 2) +#define EROFS_I_BL_XATTR_BIT (BITS_PER_LONG - 1) +#define EROFS_I_BL_Z_BIT (BITS_PER_LONG - 2) -struct erofs_vnode { +struct erofs_inode { erofs_nid_t nid; /* atomic flags (including bitlocks) */ unsigned long flags; - unsigned char datamode; + unsigned char datalayout; unsigned char inode_isize; unsigned short xattr_isize; - unsigned xattr_shared_count; - unsigned *xattr_shared_xattrs; + unsigned int xattr_shared_count; + unsigned int *xattr_shared_xattrs; union { erofs_blk_t raw_blkaddr; @@ -371,40 +240,39 @@ struct erofs_vnode { unsigned char z_logical_clusterbits; unsigned char z_physical_clusterbits[2]; }; -#endif +#endif /* CONFIG_EROFS_FS_ZIP */ }; /* the corresponding vfs inode */ struct inode vfs_inode; }; -#define EROFS_V(ptr) \ - container_of(ptr, struct erofs_vnode, vfs_inode) +#define EROFS_I(ptr) \ + container_of(ptr, struct erofs_inode, vfs_inode) -#define __inode_advise(x, bit, bits) \ - (((x) >> (bit)) & ((1 << (bits)) - 1)) - -#define __inode_version(advise) \ - __inode_advise(advise, EROFS_I_VERSION_BIT, \ - EROFS_I_VERSION_BITS) - -#define __inode_data_mapping(advise) \ - __inode_advise(advise, EROFS_I_DATA_MAPPING_BIT,\ - EROFS_I_DATA_MAPPING_BITS) - -static inline unsigned long inode_datablocks(struct inode *inode) +static inline unsigned long erofs_inode_datablocks(struct inode *inode) { /* since i_size cannot be changed */ return DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ); } -static inline bool is_inode_layout_compression(struct inode *inode) +static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit, + unsigned int bits) { - return erofs_inode_is_data_compressed(EROFS_V(inode)->datamode); + + return (value >> bit) & ((1 << bits) - 1); } -static inline bool is_inode_flat_inline(struct inode *inode) + +static inline unsigned int erofs_inode_version(unsigned int value) { - return EROFS_V(inode)->datamode == EROFS_INODE_FLAT_INLINE; + return erofs_bitrange(value, EROFS_I_VERSION_BIT, + EROFS_I_VERSION_BITS); +} + +static inline unsigned int erofs_inode_datalayout(unsigned int value) +{ + return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT, + EROFS_I_DATALAYOUT_BITS); } extern const struct super_operations erofs_sops; @@ -472,81 +340,20 @@ int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, int flags); #else -static inline int z_erofs_fill_inode(struct inode *inode) { return -ENOTSUPP; } +static inline int z_erofs_fill_inode(struct inode *inode) { return -EOPNOTSUPP; } static inline int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, int flags) { - return -ENOTSUPP; + return -EOPNOTSUPP; } -#endif +#endif /* !CONFIG_EROFS_FS_ZIP */ /* data.c */ -static inline struct bio * -erofs_grab_bio(struct super_block *sb, - erofs_blk_t blkaddr, unsigned int nr_pages, void *bi_private, - bio_end_io_t endio, bool nofail) -{ - const gfp_t gfp = GFP_NOIO; - struct bio *bio; - - do { - if (nr_pages == 1) { - bio = bio_alloc(gfp | (nofail ? __GFP_NOFAIL : 0), 1); - if (unlikely(!bio)) { - DBG_BUGON(nofail); - return ERR_PTR(-ENOMEM); - } - break; - } - bio = bio_alloc(gfp, nr_pages); - nr_pages /= 2; - } while (unlikely(!bio)); - - bio->bi_end_io = endio; - bio_set_dev(bio, sb->s_bdev); - bio->bi_iter.bi_sector = (sector_t)blkaddr << LOG_SECTORS_PER_BLOCK; - bio->bi_private = bi_private; - return bio; -} - -static inline void __submit_bio(struct bio *bio, unsigned op, unsigned op_flags) -{ - bio_set_op_attrs(bio, op, op_flags); - submit_bio(bio); -} - -#ifndef CONFIG_EROFS_FS_IO_MAX_RETRIES -#define EROFS_IO_MAX_RETRIES_NOFAIL 0 -#else -#define EROFS_IO_MAX_RETRIES_NOFAIL CONFIG_EROFS_FS_IO_MAX_RETRIES -#endif - -struct page *__erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr, - bool prio, bool nofail); - -static inline struct page *erofs_get_meta_page(struct super_block *sb, - erofs_blk_t blkaddr, bool prio) -{ - return __erofs_get_meta_page(sb, blkaddr, prio, false); -} - -static inline struct page *erofs_get_meta_page_nofail(struct super_block *sb, - erofs_blk_t blkaddr, bool prio) -{ - return __erofs_get_meta_page(sb, blkaddr, prio, true); -} +struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr); int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); -static inline struct page * -erofs_get_inline_page(struct inode *inode, - erofs_blk_t blkaddr) -{ - return erofs_get_meta_page(inode->i_sb, - blkaddr, S_ISDIR(inode->i_mode)); -} - /* inode.c */ static inline unsigned long erofs_inode_hash(erofs_nid_t nid) { @@ -561,16 +368,6 @@ extern const struct inode_operations erofs_generic_iops; extern const struct inode_operations erofs_symlink_iops; extern const struct inode_operations erofs_fast_symlink_iops; -static inline void set_inode_fast_symlink(struct inode *inode) -{ - inode->i_op = &erofs_fast_symlink_iops; -} - -static inline bool is_inode_fast_symlink(struct inode *inode) -{ - return inode->i_op == &erofs_fast_symlink_iops; -} - struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid, bool dir); int erofs_getattr(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int query_flags); @@ -584,37 +381,8 @@ int erofs_namei(struct inode *dir, struct qstr *name, /* dir.c */ extern const struct file_operations erofs_dir_fops; -static inline void *erofs_vmap(struct page **pages, unsigned int count) -{ -#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM - int i = 0; - - while (1) { - void *addr = vm_map_ram(pages, count, -1, PAGE_KERNEL); - /* retry two more times (totally 3 times) */ - if (addr || ++i >= 3) - return addr; - vm_unmap_aliases(); - } - return NULL; -#else - return vmap(pages, count, VM_MAP, PAGE_KERNEL); -#endif -} - -static inline void erofs_vunmap(const void *mem, unsigned int count) -{ -#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM - vm_unmap_ram(mem, count); -#else - vunmap(mem); -#endif -} - -/* utils.c */ -extern struct shrinker erofs_shrinker_info; - -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); +/* utils.c / zdata.c */ +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail); #if (EROFS_PCPUBUF_NR_PAGES > 0) void *erofs_get_pcpubuf(unsigned int pagenr); @@ -625,18 +393,39 @@ void *erofs_get_pcpubuf(unsigned int pagenr); #else static inline void *erofs_get_pcpubuf(unsigned int pagenr) { - return ERR_PTR(-ENOTSUPP); + return ERR_PTR(-EOPNOTSUPP); } #define erofs_put_pcpubuf(buf) do {} while (0) #endif -void erofs_register_super(struct super_block *sb); -void erofs_unregister_super(struct super_block *sb); +#ifdef CONFIG_EROFS_FS_ZIP +int erofs_workgroup_put(struct erofs_workgroup *grp); +struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, + pgoff_t index, bool *tag); +int erofs_register_workgroup(struct super_block *sb, + struct erofs_workgroup *grp, bool tag); +void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); +void erofs_shrinker_register(struct super_block *sb); +void erofs_shrinker_unregister(struct super_block *sb); +int __init erofs_init_shrinker(void); +void erofs_exit_shrinker(void); +int __init z_erofs_init_zip_subsystem(void); +void z_erofs_exit_zip_subsystem(void); +int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, + struct erofs_workgroup *egrp); +int erofs_try_to_free_cached_page(struct address_space *mapping, + struct page *page); +#else +static inline void erofs_shrinker_register(struct super_block *sb) {} +static inline void erofs_shrinker_unregister(struct super_block *sb) {} +static inline int erofs_init_shrinker(void) { return 0; } +static inline void erofs_exit_shrinker(void) {} +static inline int z_erofs_init_zip_subsystem(void) { return 0; } +static inline void z_erofs_exit_zip_subsystem(void) {} +#endif /* !CONFIG_EROFS_FS_ZIP */ -#ifndef lru_to_page -#define lru_to_page(head) (list_entry((head)->prev, struct page, lru)) -#endif +#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ -#endif +#endif /* __EROFS_INTERNAL_H */ diff --git a/drivers/staging/erofs/namei.c b/fs/erofs/namei.c index fd3ae78d0ba5..3abbecbf73de 100644 --- a/drivers/staging/erofs/namei.c +++ b/fs/erofs/namei.c @@ -1,16 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/namei.c - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ -#include "internal.h" #include "xattr.h" #include <trace/events/erofs.h> @@ -21,9 +14,9 @@ struct erofs_qstr { }; /* based on the end of qn is accurate and it must have the trailing '\0' */ -static inline int dirnamecmp(const struct erofs_qstr *qn, - const struct erofs_qstr *qd, - unsigned int *matched) +static inline int erofs_dirnamecmp(const struct erofs_qstr *qn, + const struct erofs_qstr *qd, + unsigned int *matched) { unsigned int i = *matched; @@ -71,16 +64,16 @@ static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name, unsigned int matched = min(startprfx, endprfx); struct erofs_qstr dname = { .name = data + nameoff, - .end = unlikely(mid >= ndirents - 1) ? + .end = mid >= ndirents - 1 ? data + dirblksize : data + nameoff_from_disk(de[mid + 1].nameoff, dirblksize) }; /* string comparison without already matched prefix */ - int ret = dirnamecmp(name, &dname, &matched); + int ret = erofs_dirnamecmp(name, &dname, &matched); - if (unlikely(!ret)) { + if (!ret) { return de + mid; } else if (ret > 0) { head = mid + 1; @@ -105,7 +98,7 @@ static struct page *find_target_block_classic(struct inode *dir, startprfx = endprfx = 0; head = 0; - back = inode_datablocks(dir) - 1; + back = erofs_inode_datablocks(dir) - 1; while (head <= back) { const int mid = head + (back - head) / 2; @@ -120,11 +113,14 @@ static struct page *find_target_block_classic(struct inode *dir, unsigned int matched; struct erofs_qstr dname; - if (unlikely(!ndirents)) { - DBG_BUGON(1); + if (!ndirents) { kunmap_atomic(de); put_page(page); - page = ERR_PTR(-EIO); + erofs_err(dir->i_sb, + "corrupted dir block %d @ nid %llu", + mid, EROFS_I(dir)->nid); + DBG_BUGON(1); + page = ERR_PTR(-EFSCORRUPTED); goto out; } @@ -139,10 +135,10 @@ static struct page *find_target_block_classic(struct inode *dir, EROFS_BLKSIZ); /* string comparison without already matched prefix */ - diff = dirnamecmp(name, &dname, &matched); + diff = erofs_dirnamecmp(name, &dname, &matched); kunmap_atomic(de); - if (unlikely(!diff)) { + if (!diff) { *_ndirents = 0; goto out; } else if (diff > 0) { @@ -179,7 +175,7 @@ int erofs_namei(struct inode *dir, struct erofs_dirent *de; struct erofs_qstr qn; - if (unlikely(!dir->i_size)) + if (!dir->i_size) return -ENOENT; qn.name = name->name; @@ -226,7 +222,7 @@ static struct dentry *erofs_lookup(struct inode *dir, trace_erofs_lookup(dir, dentry, flags); /* file name exceeds fs limit */ - if (unlikely(dentry->d_name.len > EROFS_NAME_LEN)) + if (dentry->d_name.len > EROFS_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); /* false uninitialized warnings on gcc 4.8.x */ @@ -235,12 +231,12 @@ static struct dentry *erofs_lookup(struct inode *dir, if (err == -ENOENT) { /* negative dentry */ inode = NULL; - } else if (unlikely(err)) { + } else if (err) { inode = ERR_PTR(err); } else { - debugln("%s, %s (nid %llu) found, d_type %u", __func__, - dentry->d_name.name, nid, d_type); - inode = erofs_iget(dir->i_sb, nid, d_type == EROFS_FT_DIR); + erofs_dbg("%s, %s (nid %llu) found, d_type %u", __func__, + dentry->d_name.name, nid, d_type); + inode = erofs_iget(dir->i_sb, nid, d_type == FT_DIR); } return d_splice_alias(inode, dentry); } diff --git a/fs/erofs/super.c b/fs/erofs/super.c new file mode 100644 index 000000000000..caf9a95173b0 --- /dev/null +++ b/fs/erofs/super.c @@ -0,0 +1,615 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang <gaoxiang25@huawei.com> + */ +#include <linux/module.h> +#include <linux/buffer_head.h> +#include <linux/statfs.h> +#include <linux/parser.h> +#include <linux/seq_file.h> +#include "xattr.h" + +#define CREATE_TRACE_POINTS +#include <trace/events/erofs.h> + +static struct kmem_cache *erofs_inode_cachep __read_mostly; + +void _erofs_err(struct super_block *sb, const char *function, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + pr_err("(device %s): %s: %pV", sb->s_id, function, &vaf); + va_end(args); +} + +void _erofs_info(struct super_block *sb, const char *function, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + pr_info("(device %s): %pV", sb->s_id, &vaf); + va_end(args); +} + +static void erofs_inode_init_once(void *ptr) +{ + struct erofs_inode *vi = ptr; + + inode_init_once(&vi->vfs_inode); +} + +static struct inode *erofs_alloc_inode(struct super_block *sb) +{ + struct erofs_inode *vi = + kmem_cache_alloc(erofs_inode_cachep, GFP_KERNEL); + + if (!vi) + return NULL; + + /* zero out everything except vfs_inode */ + memset(vi, 0, offsetof(struct erofs_inode, vfs_inode)); + return &vi->vfs_inode; +} + +static void erofs_free_inode(struct inode *inode) +{ + struct erofs_inode *vi = EROFS_I(inode); + + /* be careful of RCU symlink path */ + if (inode->i_op == &erofs_fast_symlink_iops) + kfree(inode->i_link); + kfree(vi->xattr_shared_xattrs); + + kmem_cache_free(erofs_inode_cachep, vi); +} + +static bool check_layout_compatibility(struct super_block *sb, + struct erofs_super_block *dsb) +{ + const unsigned int feature = le32_to_cpu(dsb->feature_incompat); + + EROFS_SB(sb)->feature_incompat = feature; + + /* check if current kernel meets all mandatory requirements */ + if (feature & (~EROFS_ALL_FEATURE_INCOMPAT)) { + erofs_err(sb, + "unidentified incompatible feature %x, please upgrade kernel version", + feature & ~EROFS_ALL_FEATURE_INCOMPAT); + return false; + } + return true; +} + +static int erofs_read_superblock(struct super_block *sb) +{ + struct erofs_sb_info *sbi; + struct page *page; + struct erofs_super_block *dsb; + unsigned int blkszbits; + void *data; + int ret; + + page = read_mapping_page(sb->s_bdev->bd_inode->i_mapping, 0, NULL); + if (!page) { + erofs_err(sb, "cannot read erofs superblock"); + return -EIO; + } + + sbi = EROFS_SB(sb); + + data = kmap_atomic(page); + dsb = (struct erofs_super_block *)(data + EROFS_SUPER_OFFSET); + + ret = -EINVAL; + if (le32_to_cpu(dsb->magic) != EROFS_SUPER_MAGIC_V1) { + erofs_err(sb, "cannot find valid erofs superblock"); + goto out; + } + + blkszbits = dsb->blkszbits; + /* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */ + if (blkszbits != LOG_BLOCK_SIZE) { + erofs_err(sb, "blksize %u isn't supported on this platform", + 1 << blkszbits); + goto out; + } + + if (!check_layout_compatibility(sb, dsb)) + goto out; + + sbi->blocks = le32_to_cpu(dsb->blocks); + sbi->meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr); +#ifdef CONFIG_EROFS_FS_XATTR + sbi->xattr_blkaddr = le32_to_cpu(dsb->xattr_blkaddr); +#endif + sbi->islotbits = ilog2(sizeof(struct erofs_inode_compact)); + sbi->root_nid = le16_to_cpu(dsb->root_nid); + sbi->inos = le64_to_cpu(dsb->inos); + + sbi->build_time = le64_to_cpu(dsb->build_time); + sbi->build_time_nsec = le32_to_cpu(dsb->build_time_nsec); + + memcpy(&sb->s_uuid, dsb->uuid, sizeof(dsb->uuid)); + + ret = strscpy(sbi->volume_name, dsb->volume_name, + sizeof(dsb->volume_name)); + if (ret < 0) { /* -E2BIG */ + erofs_err(sb, "bad volume name without NIL terminator"); + ret = -EFSCORRUPTED; + goto out; + } + ret = 0; +out: + kunmap_atomic(data); + put_page(page); + return ret; +} + +#ifdef CONFIG_EROFS_FS_ZIP +static int erofs_build_cache_strategy(struct super_block *sb, + substring_t *args) +{ + struct erofs_sb_info *sbi = EROFS_SB(sb); + const char *cs = match_strdup(args); + int err = 0; + + if (!cs) { + erofs_err(sb, "Not enough memory to store cache strategy"); + return -ENOMEM; + } + + if (!strcmp(cs, "disabled")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_DISABLED; + } else if (!strcmp(cs, "readahead")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_READAHEAD; + } else if (!strcmp(cs, "readaround")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; + } else { + erofs_err(sb, "Unrecognized cache strategy \"%s\"", cs); + err = -EINVAL; + } + kfree(cs); + return err; +} +#else +static int erofs_build_cache_strategy(struct super_block *sb, + substring_t *args) +{ + erofs_info(sb, "EROFS compression is disabled, so cache strategy is ignored"); + return 0; +} +#endif + +/* set up default EROFS parameters */ +static void erofs_default_options(struct erofs_sb_info *sbi) +{ +#ifdef CONFIG_EROFS_FS_ZIP + sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; + sbi->max_sync_decompress_pages = 3; +#endif +#ifdef CONFIG_EROFS_FS_XATTR + set_opt(sbi, XATTR_USER); +#endif +#ifdef CONFIG_EROFS_FS_POSIX_ACL + set_opt(sbi, POSIX_ACL); +#endif +} + +enum { + Opt_user_xattr, + Opt_nouser_xattr, + Opt_acl, + Opt_noacl, + Opt_cache_strategy, + Opt_err +}; + +static match_table_t erofs_tokens = { + {Opt_user_xattr, "user_xattr"}, + {Opt_nouser_xattr, "nouser_xattr"}, + {Opt_acl, "acl"}, + {Opt_noacl, "noacl"}, + {Opt_cache_strategy, "cache_strategy=%s"}, + {Opt_err, NULL} +}; + +static int erofs_parse_options(struct super_block *sb, char *options) +{ + substring_t args[MAX_OPT_ARGS]; + char *p; + int err; + + if (!options) + return 0; + + while ((p = strsep(&options, ","))) { + int token; + + if (!*p) + continue; + + args[0].to = args[0].from = NULL; + token = match_token(p, erofs_tokens, args); + + switch (token) { +#ifdef CONFIG_EROFS_FS_XATTR + case Opt_user_xattr: + set_opt(EROFS_SB(sb), XATTR_USER); + break; + case Opt_nouser_xattr: + clear_opt(EROFS_SB(sb), XATTR_USER); + break; +#else + case Opt_user_xattr: + erofs_info(sb, "user_xattr options not supported"); + break; + case Opt_nouser_xattr: + erofs_info(sb, "nouser_xattr options not supported"); + break; +#endif +#ifdef CONFIG_EROFS_FS_POSIX_ACL + case Opt_acl: + set_opt(EROFS_SB(sb), POSIX_ACL); + break; + case Opt_noacl: + clear_opt(EROFS_SB(sb), POSIX_ACL); + break; +#else + case Opt_acl: + erofs_info(sb, "acl options not supported"); + break; + case Opt_noacl: + erofs_info(sb, "noacl options not supported"); + break; +#endif + case Opt_cache_strategy: + err = erofs_build_cache_strategy(sb, args); + if (err) + return err; + break; + default: + erofs_err(sb, "Unrecognized mount option \"%s\" or missing value", p); + return -EINVAL; + } + } + return 0; +} + +#ifdef CONFIG_EROFS_FS_ZIP +static const struct address_space_operations managed_cache_aops; + +static int erofs_managed_cache_releasepage(struct page *page, gfp_t gfp_mask) +{ + int ret = 1; /* 0 - busy */ + struct address_space *const mapping = page->mapping; + + DBG_BUGON(!PageLocked(page)); + DBG_BUGON(mapping->a_ops != &managed_cache_aops); + + if (PagePrivate(page)) + ret = erofs_try_to_free_cached_page(mapping, page); + + return ret; +} + +static void erofs_managed_cache_invalidatepage(struct page *page, + unsigned int offset, + unsigned int length) +{ + const unsigned int stop = length + offset; + + DBG_BUGON(!PageLocked(page)); + + /* Check for potential overflow in debug mode */ + DBG_BUGON(stop > PAGE_SIZE || stop < length); + + if (offset == 0 && stop == PAGE_SIZE) + while (!erofs_managed_cache_releasepage(page, GFP_NOFS)) + cond_resched(); +} + +static const struct address_space_operations managed_cache_aops = { + .releasepage = erofs_managed_cache_releasepage, + .invalidatepage = erofs_managed_cache_invalidatepage, +}; + +static int erofs_init_managed_cache(struct super_block *sb) +{ + struct erofs_sb_info *const sbi = EROFS_SB(sb); + struct inode *const inode = new_inode(sb); + + if (!inode) + return -ENOMEM; + + set_nlink(inode, 1); + inode->i_size = OFFSET_MAX; + + inode->i_mapping->a_ops = &managed_cache_aops; + mapping_set_gfp_mask(inode->i_mapping, + GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE); + sbi->managed_cache = inode; + return 0; +} +#else +static int erofs_init_managed_cache(struct super_block *sb) { return 0; } +#endif + +static int erofs_fill_super(struct super_block *sb, void *data, int silent) +{ + struct inode *inode; + struct erofs_sb_info *sbi; + int err; + + sb->s_magic = EROFS_SUPER_MAGIC; + + if (!sb_set_blocksize(sb, EROFS_BLKSIZ)) { + erofs_err(sb, "failed to set erofs blksize"); + return -EINVAL; + } + + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); + if (!sbi) + return -ENOMEM; + + sb->s_fs_info = sbi; + err = erofs_read_superblock(sb); + if (err) + return err; + + sb->s_flags |= SB_RDONLY | SB_NOATIME; + sb->s_maxbytes = MAX_LFS_FILESIZE; + sb->s_time_gran = 1; + + sb->s_op = &erofs_sops; + +#ifdef CONFIG_EROFS_FS_XATTR + sb->s_xattr = erofs_xattr_handlers; +#endif + /* set erofs default mount options */ + erofs_default_options(sbi); + + err = erofs_parse_options(sb, data); + if (err) + return err; + + if (test_opt(sbi, POSIX_ACL)) + sb->s_flags |= SB_POSIXACL; + else + sb->s_flags &= ~SB_POSIXACL; + +#ifdef CONFIG_EROFS_FS_ZIP + INIT_RADIX_TREE(&sbi->workstn_tree, GFP_ATOMIC); +#endif + + /* get the root inode */ + inode = erofs_iget(sb, ROOT_NID(sbi), true); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + if (!S_ISDIR(inode->i_mode)) { + erofs_err(sb, "rootino(nid %llu) is not a directory(i_mode %o)", + ROOT_NID(sbi), inode->i_mode); + iput(inode); + return -EINVAL; + } + + sb->s_root = d_make_root(inode); + if (!sb->s_root) + return -ENOMEM; + + erofs_shrinker_register(sb); + /* sb->s_umount is already locked, SB_ACTIVE and SB_BORN are not set */ + err = erofs_init_managed_cache(sb); + if (err) + return err; + + erofs_info(sb, "mounted with opts: %s, root inode @ nid %llu.", + (char *)data, ROOT_NID(sbi)); + return 0; +} + +static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super); +} + +/* + * could be triggered after deactivate_locked_super() + * is called, thus including umount and failed to initialize. + */ +static void erofs_kill_sb(struct super_block *sb) +{ + struct erofs_sb_info *sbi; + + WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); + + kill_block_super(sb); + + sbi = EROFS_SB(sb); + if (!sbi) + return; + kfree(sbi); + sb->s_fs_info = NULL; +} + +/* called when ->s_root is non-NULL */ +static void erofs_put_super(struct super_block *sb) +{ + struct erofs_sb_info *const sbi = EROFS_SB(sb); + + DBG_BUGON(!sbi); + + erofs_shrinker_unregister(sb); +#ifdef CONFIG_EROFS_FS_ZIP + iput(sbi->managed_cache); + sbi->managed_cache = NULL; +#endif +} + +static struct file_system_type erofs_fs_type = { + .owner = THIS_MODULE, + .name = "erofs", + .mount = erofs_mount, + .kill_sb = erofs_kill_sb, + .fs_flags = FS_REQUIRES_DEV, +}; +MODULE_ALIAS_FS("erofs"); + +static int __init erofs_module_init(void) +{ + int err; + + erofs_check_ondisk_layout_definitions(); + + erofs_inode_cachep = kmem_cache_create("erofs_inode", + sizeof(struct erofs_inode), 0, + SLAB_RECLAIM_ACCOUNT, + erofs_inode_init_once); + if (!erofs_inode_cachep) { + err = -ENOMEM; + goto icache_err; + } + + err = erofs_init_shrinker(); + if (err) + goto shrinker_err; + + err = z_erofs_init_zip_subsystem(); + if (err) + goto zip_err; + + err = register_filesystem(&erofs_fs_type); + if (err) + goto fs_err; + + return 0; + +fs_err: + z_erofs_exit_zip_subsystem(); +zip_err: + erofs_exit_shrinker(); +shrinker_err: + kmem_cache_destroy(erofs_inode_cachep); +icache_err: + return err; +} + +static void __exit erofs_module_exit(void) +{ + unregister_filesystem(&erofs_fs_type); + z_erofs_exit_zip_subsystem(); + erofs_exit_shrinker(); + + /* Ensure all RCU free inodes are safe before cache is destroyed. */ + rcu_barrier(); + kmem_cache_destroy(erofs_inode_cachep); +} + +/* get filesystem statistics */ +static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb = dentry->d_sb; + struct erofs_sb_info *sbi = EROFS_SB(sb); + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); + + buf->f_type = sb->s_magic; + buf->f_bsize = EROFS_BLKSIZ; + buf->f_blocks = sbi->blocks; + buf->f_bfree = buf->f_bavail = 0; + + buf->f_files = ULLONG_MAX; + buf->f_ffree = ULLONG_MAX - sbi->inos; + + buf->f_namelen = EROFS_NAME_LEN; + + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); + return 0; +} + +static int erofs_show_options(struct seq_file *seq, struct dentry *root) +{ + struct erofs_sb_info *sbi __maybe_unused = EROFS_SB(root->d_sb); + +#ifdef CONFIG_EROFS_FS_XATTR + if (test_opt(sbi, XATTR_USER)) + seq_puts(seq, ",user_xattr"); + else + seq_puts(seq, ",nouser_xattr"); +#endif +#ifdef CONFIG_EROFS_FS_POSIX_ACL + if (test_opt(sbi, POSIX_ACL)) + seq_puts(seq, ",acl"); + else + seq_puts(seq, ",noacl"); +#endif +#ifdef CONFIG_EROFS_FS_ZIP + if (sbi->cache_strategy == EROFS_ZIP_CACHE_DISABLED) { + seq_puts(seq, ",cache_strategy=disabled"); + } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAHEAD) { + seq_puts(seq, ",cache_strategy=readahead"); + } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAROUND) { + seq_puts(seq, ",cache_strategy=readaround"); + } else { + seq_puts(seq, ",cache_strategy=(unknown)"); + DBG_BUGON(1); + } +#endif + return 0; +} + +static int erofs_remount(struct super_block *sb, int *flags, char *data) +{ + struct erofs_sb_info *sbi = EROFS_SB(sb); + unsigned int org_mnt_opt = sbi->mount_opt; + int err; + + DBG_BUGON(!sb_rdonly(sb)); + err = erofs_parse_options(sb, data); + if (err) + goto out; + + if (test_opt(sbi, POSIX_ACL)) + sb->s_flags |= SB_POSIXACL; + else + sb->s_flags &= ~SB_POSIXACL; + + *flags |= SB_RDONLY; + return 0; +out: + sbi->mount_opt = org_mnt_opt; + return err; +} + +const struct super_operations erofs_sops = { + .put_super = erofs_put_super, + .alloc_inode = erofs_alloc_inode, + .free_inode = erofs_free_inode, + .statfs = erofs_statfs, + .show_options = erofs_show_options, + .remount_fs = erofs_remount, +}; + +module_init(erofs_module_init); +module_exit(erofs_module_exit); + +MODULE_DESCRIPTION("Enhanced ROM File System"); +MODULE_AUTHOR("Gao Xiang, Chao Yu, Miao Xie, CONSUMER BG, HUAWEI Inc."); +MODULE_LICENSE("GPL"); + diff --git a/drivers/staging/erofs/include/linux/tagptr.h b/fs/erofs/tagptr.h index ccd106dbd48e..a72897c86744 100644 --- a/drivers/staging/erofs/include/linux/tagptr.h +++ b/fs/erofs/tagptr.h @@ -1,11 +1,11 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * Tagged pointer implementation +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * A tagged pointer implementation * * Copyright (C) 2018 Gao Xiang <gaoxiang25@huawei.com> */ -#ifndef _LINUX_TAGPTR_H -#define _LINUX_TAGPTR_H +#ifndef __EROFS_FS_TAGPTR_H +#define __EROFS_FS_TAGPTR_H #include <linux/types.h> #include <linux/build_bug.h> @@ -106,5 +106,5 @@ tagptr_init(o, cmpxchg(&ptptr->v, o.v, n.v)); }) ptptr->v &= ~tags; \ *ptptr; }) -#endif +#endif /* __EROFS_FS_TAGPTR_H */ diff --git a/drivers/staging/erofs/utils.c b/fs/erofs/utils.c index 4bbd3bf34acd..d92b3e753a6f 100644 --- a/drivers/staging/erofs/utils.c +++ b/fs/erofs/utils.c @@ -1,28 +1,22 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/utils.c - * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ - #include "internal.h" #include <linux/pagevec.h> -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp) +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail) { struct page *page; if (!list_empty(pool)) { page = lru_to_page(pool); + DBG_BUGON(page_ref_count(page) != 1); list_del(&page->lru); } else { - page = alloc_pages(gfp | __GFP_NOFAIL, 0); + page = alloc_pages(gfp | (nofail ? __GFP_NOFAIL : 0), 0); } return page; } @@ -39,10 +33,10 @@ void *erofs_get_pcpubuf(unsigned int pagenr) } #endif +#ifdef CONFIG_EROFS_FS_ZIP /* global shrink count (for all mounted EROFS instances) */ static atomic_long_t erofs_global_shrink_cnt; -#ifdef CONFIG_EROFS_FS_ZIP #define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount) #define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount) @@ -52,14 +46,14 @@ static int erofs_workgroup_get(struct erofs_workgroup *grp) repeat: o = erofs_wait_on_workgroup_freezed(grp); - if (unlikely(o <= 0)) + if (o <= 0) return -1; - if (unlikely(atomic_cmpxchg(&grp->refcount, o, o + 1) != o)) + if (atomic_cmpxchg(&grp->refcount, o, o + 1) != o) goto repeat; /* decrease refcount paired by erofs_workgroup_put */ - if (unlikely(o == 1)) + if (o == 1) atomic_long_dec(&erofs_global_shrink_cnt); return 0; } @@ -97,7 +91,7 @@ int erofs_register_workgroup(struct super_block *sb, int err; /* grp shouldn't be broken or used before */ - if (unlikely(atomic_read(&grp->refcount) != 1)) { + if (atomic_read(&grp->refcount) != 1) { DBG_BUGON(1); return -EINVAL; } @@ -107,27 +101,26 @@ int erofs_register_workgroup(struct super_block *sb, return err; sbi = EROFS_SB(sb); - erofs_workstn_lock(sbi); + xa_lock(&sbi->workstn_tree); grp = xa_tag_pointer(grp, tag); /* * Bump up reference count before making this workgroup * visible to other users in order to avoid potential UAF - * without serialized by erofs_workstn_lock. + * without serialized by workstn_lock. */ __erofs_workgroup_get(grp); - err = radix_tree_insert(&sbi->workstn_tree, - grp->index, grp); - if (unlikely(err)) + err = radix_tree_insert(&sbi->workstn_tree, grp->index, grp); + if (err) /* * it's safe to decrease since the workgroup isn't visible * and refcount >= 2 (cannot be freezed). */ __erofs_workgroup_put(grp); - erofs_workstn_unlock(sbi); + xa_unlock(&sbi->workstn_tree); radix_tree_preload_end(); return err; } @@ -149,8 +142,6 @@ int erofs_workgroup_put(struct erofs_workgroup *grp) return count; } -#ifdef EROFS_FS_HAS_MANAGED_CACHE -/* for cache-managed case, customized reclaim paths exist */ static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp) { erofs_workgroup_unfreeze(grp, 0); @@ -162,18 +153,18 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, bool cleanup) { /* - * for managed cache enabled, the refcount of workgroups - * themselves could be < 0 (freezed). So there is no guarantee - * that all refcount > 0 if managed cache is enabled. + * If managed cache is on, refcount of workgroups + * themselves could be < 0 (freezed). In other words, + * there is no guarantee that all refcounts > 0. */ if (!erofs_workgroup_try_to_freeze(grp, 1)) return false; /* - * note that all cached pages should be unlinked - * before delete it from the radix tree. - * Otherwise some cached pages of an orphan old workgroup - * could be still linked after the new one is available. + * Note that all cached pages should be unattached + * before deleted from the radix tree. Otherwise some + * cached pages could be still attached to the orphan + * old workgroup when the new one is available in the tree. */ if (erofs_try_to_free_all_cached_pages(sbi, grp)) { erofs_workgroup_unfreeze(grp, 1); @@ -181,7 +172,7 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, } /* - * it is impossible to fail after the workgroup is freezed, + * It's impossible to fail after the workgroup is freezed, * however in order to avoid some race conditions, add a * DBG_BUGON to observe this in advance. */ @@ -189,40 +180,16 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, grp->index)) != grp); /* - * if managed cache is enable, the last refcount - * should indicate the related workstation. + * If managed cache is on, last refcount should indicate + * the related workstation. */ erofs_workgroup_unfreeze_final(grp); return true; } -#else -/* for nocache case, no customized reclaim path at all */ -static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, - struct erofs_workgroup *grp, - bool cleanup) -{ - int cnt = atomic_read(&grp->refcount); - - DBG_BUGON(cnt <= 0); - DBG_BUGON(cleanup && cnt != 1); - - if (cnt > 1) - return false; - - DBG_BUGON(xa_untag_pointer(radix_tree_delete(&sbi->workstn_tree, - grp->index)) != grp); - - /* (rarely) could be grabbed again when freeing */ - erofs_workgroup_put(grp); - return true; -} - -#endif - -unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink, - bool cleanup) +static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, + unsigned long nr_shrink, + bool cleanup) { pgoff_t first_index = 0; void *batch[PAGEVEC_SIZE]; @@ -230,7 +197,7 @@ unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, int i, found; repeat: - erofs_workstn_lock(sbi); + xa_lock(&sbi->workstn_tree); found = radix_tree_gang_lookup(&sbi->workstn_tree, batch, first_index, PAGEVEC_SIZE); @@ -245,18 +212,16 @@ repeat: continue; ++freed; - if (unlikely(!--nr_shrink)) + if (!--nr_shrink) break; } - erofs_workstn_unlock(sbi); + xa_unlock(&sbi->workstn_tree); if (i && nr_shrink) goto repeat; return freed; } -#endif - /* protected by 'erofs_sb_list_lock' */ static unsigned int shrinker_run_no; @@ -264,7 +229,7 @@ static unsigned int shrinker_run_no; static DEFINE_SPINLOCK(erofs_sb_list_lock); static LIST_HEAD(erofs_sb_list); -void erofs_register_super(struct super_block *sb) +void erofs_shrinker_register(struct super_block *sb) { struct erofs_sb_info *sbi = EROFS_SB(sb); @@ -275,11 +240,17 @@ void erofs_register_super(struct super_block *sb) spin_unlock(&erofs_sb_list_lock); } -void erofs_unregister_super(struct super_block *sb) +void erofs_shrinker_unregister(struct super_block *sb) { + struct erofs_sb_info *const sbi = EROFS_SB(sb); + + mutex_lock(&sbi->umount_mutex); + erofs_shrink_workstation(sbi, ~0UL, true); + spin_lock(&erofs_sb_list_lock); - list_del(&EROFS_SB(sb)->list); + list_del(&sbi->list); spin_unlock(&erofs_sb_list_lock); + mutex_unlock(&sbi->umount_mutex); } static unsigned long erofs_shrink_count(struct shrinker *shrink, @@ -299,9 +270,9 @@ static unsigned long erofs_shrink_scan(struct shrinker *shrink, unsigned long freed = 0; spin_lock(&erofs_sb_list_lock); - do + do { run_no = ++shrinker_run_no; - while (run_no == 0); + } while (run_no == 0); /* Iterate over all mounted superblocks and try to shrink them */ p = erofs_sb_list.next; @@ -323,9 +294,7 @@ static unsigned long erofs_shrink_scan(struct shrinker *shrink, spin_unlock(&erofs_sb_list_lock); sbi->shrinker_run_no = run_no; -#ifdef CONFIG_EROFS_FS_ZIP freed += erofs_shrink_workstation(sbi, nr, false); -#endif spin_lock(&erofs_sb_list_lock); /* Get the next list element before we move this one */ @@ -345,9 +314,20 @@ static unsigned long erofs_shrink_scan(struct shrinker *shrink, return freed; } -struct shrinker erofs_shrinker_info = { +static struct shrinker erofs_shrinker_info = { .scan_objects = erofs_shrink_scan, .count_objects = erofs_shrink_count, .seeks = DEFAULT_SEEKS, }; +int __init erofs_init_shrinker(void) +{ + return register_shrinker(&erofs_shrinker_info); +} + +void erofs_exit_shrinker(void) +{ + unregister_shrinker(&erofs_shrinker_info); +} +#endif /* !CONFIG_EROFS_FS_ZIP */ + diff --git a/drivers/staging/erofs/xattr.c b/fs/erofs/xattr.c index df40654b9fbb..a13a78725c57 100644 --- a/drivers/staging/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -1,14 +1,8 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/xattr.c - * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include <linux/security.h> #include "xattr.h" @@ -25,7 +19,7 @@ struct xattr_iter { static inline void xattr_iter_end(struct xattr_iter *it, bool atomic) { /* the only user of kunmap() is 'init_inode_xattrs' */ - if (unlikely(!atomic)) + if (!atomic) kunmap(it->page); else kunmap_atomic(it->kaddr); @@ -44,7 +38,7 @@ static inline void xattr_iter_end_final(struct xattr_iter *it) static int init_inode_xattrs(struct inode *inode) { - struct erofs_vnode *const vi = EROFS_V(inode); + struct erofs_inode *const vi = EROFS_I(inode); struct xattr_iter it; unsigned int i; struct erofs_xattr_ibody_header *ih; @@ -54,14 +48,14 @@ static int init_inode_xattrs(struct inode *inode) int ret = 0; /* the most case is that xattrs of this inode are initialized. */ - if (test_bit(EROFS_V_EA_INITED_BIT, &vi->flags)) + if (test_bit(EROFS_I_EA_INITED_BIT, &vi->flags)) return 0; - if (wait_on_bit_lock(&vi->flags, EROFS_V_BL_XATTR_BIT, TASK_KILLABLE)) + if (wait_on_bit_lock(&vi->flags, EROFS_I_BL_XATTR_BIT, TASK_KILLABLE)) return -ERESTARTSYS; /* someone has initialized xattrs for us? */ - if (test_bit(EROFS_V_EA_INITED_BIT, &vi->flags)) + if (test_bit(EROFS_I_EA_INITED_BIT, &vi->flags)) goto out_unlock; /* @@ -73,14 +67,17 @@ static int init_inode_xattrs(struct inode *inode) * undefined right now (maybe use later with some new sb feature). */ if (vi->xattr_isize == sizeof(struct erofs_xattr_ibody_header)) { - errln("xattr_isize %d of nid %llu is not supported yet", - vi->xattr_isize, vi->nid); - ret = -ENOTSUPP; + erofs_err(inode->i_sb, + "xattr_isize %d of nid %llu is not supported yet", + vi->xattr_isize, vi->nid); + ret = -EOPNOTSUPP; goto out_unlock; } else if (vi->xattr_isize < sizeof(struct erofs_xattr_ibody_header)) { - if (unlikely(vi->xattr_isize)) { + if (vi->xattr_isize) { + erofs_err(inode->i_sb, + "bogus xattr ibody @ nid %llu", vi->nid); DBG_BUGON(1); - ret = -EIO; + ret = -EFSCORRUPTED; goto out_unlock; /* xattr ondisk layout error */ } ret = -ENOATTR; @@ -92,7 +89,7 @@ static int init_inode_xattrs(struct inode *inode) it.blkaddr = erofs_blknr(iloc(sbi, vi->nid) + vi->inode_isize); it.ofs = erofs_blkoff(iloc(sbi, vi->nid) + vi->inode_isize); - it.page = erofs_get_inline_page(inode, it.blkaddr); + it.page = erofs_get_meta_page(sb, it.blkaddr); if (IS_ERR(it.page)) { ret = PTR_ERR(it.page); goto out_unlock; @@ -117,13 +114,12 @@ static int init_inode_xattrs(struct inode *inode) it.ofs += sizeof(struct erofs_xattr_ibody_header); for (i = 0; i < vi->xattr_shared_count; ++i) { - if (unlikely(it.ofs >= EROFS_BLKSIZ)) { + if (it.ofs >= EROFS_BLKSIZ) { /* cannot be unaligned */ - BUG_ON(it.ofs != EROFS_BLKSIZ); + DBG_BUGON(it.ofs != EROFS_BLKSIZ); xattr_iter_end(&it, atomic_map); - it.page = erofs_get_meta_page(sb, ++it.blkaddr, - S_ISDIR(inode->i_mode)); + it.page = erofs_get_meta_page(sb, ++it.blkaddr); if (IS_ERR(it.page)) { kfree(vi->xattr_shared_xattrs); vi->xattr_shared_xattrs = NULL; @@ -141,10 +137,10 @@ static int init_inode_xattrs(struct inode *inode) } xattr_iter_end(&it, atomic_map); - set_bit(EROFS_V_EA_INITED_BIT, &vi->flags); + set_bit(EROFS_I_EA_INITED_BIT, &vi->flags); out_unlock: - clear_and_wake_up_bit(EROFS_V_BL_XATTR_BIT, &vi->flags); + clear_and_wake_up_bit(EROFS_I_BL_XATTR_BIT, &vi->flags); return ret; } @@ -173,7 +169,7 @@ static inline int xattr_iter_fixup(struct xattr_iter *it) it->blkaddr += erofs_blknr(it->ofs); - it->page = erofs_get_meta_page(it->sb, it->blkaddr, false); + it->page = erofs_get_meta_page(it->sb, it->blkaddr); if (IS_ERR(it->page)) { int err = PTR_ERR(it->page); @@ -189,13 +185,13 @@ static inline int xattr_iter_fixup(struct xattr_iter *it) static int inline_xattr_iter_begin(struct xattr_iter *it, struct inode *inode) { - struct erofs_vnode *const vi = EROFS_V(inode); + struct erofs_inode *const vi = EROFS_I(inode); struct erofs_sb_info *const sbi = EROFS_SB(inode->i_sb); unsigned int xattr_header_sz, inline_xattr_ofs; xattr_header_sz = inlinexattr_header_size(inode); - if (unlikely(xattr_header_sz >= vi->xattr_isize)) { - BUG_ON(xattr_header_sz > vi->xattr_isize); + if (xattr_header_sz >= vi->xattr_isize) { + DBG_BUGON(xattr_header_sz > vi->xattr_isize); return -ENOATTR; } @@ -204,7 +200,7 @@ static int inline_xattr_iter_begin(struct xattr_iter *it, it->blkaddr = erofs_blknr(iloc(sbi, vi->nid) + inline_xattr_ofs); it->ofs = erofs_blkoff(iloc(sbi, vi->nid) + inline_xattr_ofs); - it->page = erofs_get_inline_page(inode, it->blkaddr); + it->page = erofs_get_meta_page(inode->i_sb, it->blkaddr); if (IS_ERR(it->page)) return PTR_ERR(it->page); @@ -236,9 +232,13 @@ static int xattr_foreach(struct xattr_iter *it, */ entry = *(struct erofs_xattr_entry *)(it->kaddr + it->ofs); if (tlimit) { - unsigned int entry_sz = EROFS_XATTR_ENTRY_SIZE(&entry); + unsigned int entry_sz = erofs_xattr_entry_size(&entry); - BUG_ON(*tlimit < entry_sz); + /* xattr on-disk corruption: xattr entry beyond xattr_isize */ + if (*tlimit < entry_sz) { + DBG_BUGON(1); + return -EFSCORRUPTED; + } *tlimit -= entry_sz; } @@ -257,7 +257,7 @@ static int xattr_foreach(struct xattr_iter *it, while (processed < entry.e_name_len) { if (it->ofs >= EROFS_BLKSIZ) { - BUG_ON(it->ofs > EROFS_BLKSIZ); + DBG_BUGON(it->ofs > EROFS_BLKSIZ); err = xattr_iter_fixup(it); if (err) @@ -292,7 +292,7 @@ static int xattr_foreach(struct xattr_iter *it, while (processed < value_sz) { if (it->ofs >= EROFS_BLKSIZ) { - BUG_ON(it->ofs > EROFS_BLKSIZ); + DBG_BUGON(it->ofs > EROFS_BLKSIZ); err = xattr_iter_fixup(it); if (err) @@ -386,7 +386,7 @@ static int inline_getxattr(struct inode *inode, struct getxattr_iter *it) static int shared_getxattr(struct inode *inode, struct getxattr_iter *it) { - struct erofs_vnode *const vi = EROFS_V(inode); + struct erofs_inode *const vi = EROFS_I(inode); struct super_block *const sb = inode->i_sb; struct erofs_sb_info *const sbi = EROFS_SB(sb); unsigned int i; @@ -402,7 +402,7 @@ static int shared_getxattr(struct inode *inode, struct getxattr_iter *it) if (i) xattr_iter_end(&it->it, true); - it->it.page = erofs_get_meta_page(sb, blkaddr, false); + it->it.page = erofs_get_meta_page(sb, blkaddr); if (IS_ERR(it->it.page)) return PTR_ERR(it->it.page); @@ -437,7 +437,7 @@ int erofs_getxattr(struct inode *inode, int index, int ret; struct getxattr_iter it; - if (unlikely(!name)) + if (!name) return -EINVAL; ret = init_inode_xattrs(inode); @@ -609,7 +609,7 @@ static int inline_listxattr(struct listxattr_iter *it) static int shared_listxattr(struct listxattr_iter *it) { struct inode *const inode = d_inode(it->dentry); - struct erofs_vnode *const vi = EROFS_V(inode); + struct erofs_inode *const vi = EROFS_I(inode); struct super_block *const sb = inode->i_sb; struct erofs_sb_info *const sbi = EROFS_SB(sb); unsigned int i; @@ -624,7 +624,7 @@ static int shared_listxattr(struct listxattr_iter *it) if (i) xattr_iter_end(&it->it, true); - it->it.page = erofs_get_meta_page(sb, blkaddr, false); + it->it.page = erofs_get_meta_page(sb, blkaddr); if (IS_ERR(it->it.page)) return PTR_ERR(it->it.page); diff --git a/drivers/staging/erofs/xattr.h b/fs/erofs/xattr.h index 35ba5ac2139a..3585b84d2f20 100644 --- a/drivers/staging/erofs/xattr.h +++ b/fs/erofs/xattr.h @@ -1,14 +1,8 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * linux/drivers/staging/erofs/xattr.h - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #ifndef __EROFS_XATTR_H #define __EROFS_XATTR_H @@ -20,14 +14,14 @@ /* Attribute not found */ #define ENOATTR ENODATA -static inline unsigned inlinexattr_header_size(struct inode *inode) +static inline unsigned int inlinexattr_header_size(struct inode *inode) { - return sizeof(struct erofs_xattr_ibody_header) - + sizeof(u32) * EROFS_V(inode)->xattr_shared_count; + return sizeof(struct erofs_xattr_ibody_header) + + sizeof(u32) * EROFS_I(inode)->xattr_shared_count; } -static inline erofs_blk_t -xattrblock_addr(struct erofs_sb_info *sbi, unsigned xattr_id) +static inline erofs_blk_t xattrblock_addr(struct erofs_sb_info *sbi, + unsigned int xattr_id) { #ifdef CONFIG_EROFS_FS_XATTR return sbi->xattr_blkaddr + @@ -37,19 +31,20 @@ xattrblock_addr(struct erofs_sb_info *sbi, unsigned xattr_id) #endif } -static inline unsigned -xattrblock_offset(struct erofs_sb_info *sbi, unsigned xattr_id) +static inline unsigned int xattrblock_offset(struct erofs_sb_info *sbi, + unsigned int xattr_id) { return (xattr_id * sizeof(__u32)) % EROFS_BLKSIZ; } +#ifdef CONFIG_EROFS_FS_XATTR extern const struct xattr_handler erofs_xattr_user_handler; extern const struct xattr_handler erofs_xattr_trusted_handler; #ifdef CONFIG_EROFS_FS_SECURITY extern const struct xattr_handler erofs_xattr_security_handler; #endif -static inline const struct xattr_handler *erofs_xattr_handler(unsigned index) +static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx) { static const struct xattr_handler *xattr_handler_map[] = { [EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler, @@ -63,29 +58,29 @@ static const struct xattr_handler *xattr_handler_map[] = { [EROFS_XATTR_INDEX_SECURITY] = &erofs_xattr_security_handler, #endif }; - return index && index < ARRAY_SIZE(xattr_handler_map) ? - xattr_handler_map[index] : NULL; + + return idx && idx < ARRAY_SIZE(xattr_handler_map) ? + xattr_handler_map[idx] : NULL; } -#ifdef CONFIG_EROFS_FS_XATTR extern const struct xattr_handler *erofs_xattr_handlers[]; int erofs_getxattr(struct inode *, int, const char *, void *, size_t); ssize_t erofs_listxattr(struct dentry *, char *, size_t); #else -static int __maybe_unused erofs_getxattr(struct inode *inode, int index, - const char *name, - void *buffer, size_t buffer_size) +static inline int erofs_getxattr(struct inode *inode, int index, + const char *name, void *buffer, + size_t buffer_size) { - return -ENOTSUPP; + return -EOPNOTSUPP; } -static ssize_t __maybe_unused erofs_listxattr(struct dentry *dentry, - char *buffer, size_t buffer_size) +static inline ssize_t erofs_listxattr(struct dentry *dentry, + char *buffer, size_t buffer_size) { - return -ENOTSUPP; + return -EOPNOTSUPP; } -#endif +#endif /* !CONFIG_EROFS_FS_XATTR */ #ifdef CONFIG_EROFS_FS_POSIX_ACL struct posix_acl *erofs_get_acl(struct inode *inode, int type); diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c new file mode 100644 index 000000000000..96e34c90f814 --- /dev/null +++ b/fs/erofs/zdata.c @@ -0,0 +1,1431 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang <gaoxiang25@huawei.com> + */ +#include "zdata.h" +#include "compress.h" +#include <linux/prefetch.h> + +#include <trace/events/erofs.h> + +/* + * a compressed_pages[] placeholder in order to avoid + * being filled with file pages for in-place decompression. + */ +#define PAGE_UNALLOCATED ((void *)0x5F0E4B1D) + +/* how to allocate cached pages for a pcluster */ +enum z_erofs_cache_alloctype { + DONTALLOC, /* don't allocate any cached pages */ + DELAYEDALLOC, /* delayed allocation (at the time of submitting io) */ +}; + +/* + * tagged pointer with 1-bit tag for all compressed pages + * tag 0 - the page is just found with an extra page reference + */ +typedef tagptr1_t compressed_page_t; + +#define tag_compressed_page_justfound(page) \ + tagptr_fold(compressed_page_t, page, 1) + +static struct workqueue_struct *z_erofs_workqueue __read_mostly; +static struct kmem_cache *pcluster_cachep __read_mostly; + +void z_erofs_exit_zip_subsystem(void) +{ + destroy_workqueue(z_erofs_workqueue); + kmem_cache_destroy(pcluster_cachep); +} + +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, + onlinecpus + onlinecpus / 4); + return z_erofs_workqueue ? 0 : -ENOMEM; +} + +static void z_erofs_pcluster_init_once(void *ptr) +{ + struct z_erofs_pcluster *pcl = ptr; + struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); + unsigned int i; + + mutex_init(&cl->lock); + cl->nr_pages = 0; + cl->vcnt = 0; + for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i) + pcl->compressed_pages[i] = NULL; +} + +static void z_erofs_pcluster_init_always(struct z_erofs_pcluster *pcl) +{ + struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); + + atomic_set(&pcl->obj.refcount, 1); + + DBG_BUGON(cl->nr_pages); + DBG_BUGON(cl->vcnt); +} + +int __init z_erofs_init_zip_subsystem(void) +{ + pcluster_cachep = kmem_cache_create("erofs_compress", + Z_EROFS_WORKGROUP_SIZE, 0, + SLAB_RECLAIM_ACCOUNT, + z_erofs_pcluster_init_once); + if (pcluster_cachep) { + if (!z_erofs_init_workqueue()) + return 0; + + kmem_cache_destroy(pcluster_cachep); + } + return -ENOMEM; +} + +enum z_erofs_collectmode { + COLLECT_SECONDARY, + COLLECT_PRIMARY, + /* + * The current collection was the tail of an exist chain, in addition + * that the previous processed chained collections are all decided to + * be hooked up to it. + * A new chain will be created for the remaining collections which are + * not processed yet, therefore different from COLLECT_PRIMARY_FOLLOWED, + * the next collection cannot reuse the whole page safely in + * the following scenario: + * ________________________________________________________________ + * | tail (partial) page | head (partial) page | + * | (belongs to the next cl) | (belongs to the current cl) | + * |_______PRIMARY_FOLLOWED_______|________PRIMARY_HOOKED___________| + */ + COLLECT_PRIMARY_HOOKED, + COLLECT_PRIMARY_FOLLOWED_NOINPLACE, + /* + * The current collection has been linked with the owned chain, and + * could also be linked with the remaining collections, which means + * if the processing page is the tail page of the collection, thus + * the current collection can safely use the whole page (since + * the previous collection is under control) for in-place I/O, as + * illustrated below: + * ________________________________________________________________ + * | tail (partial) page | head (partial) page | + * | (of the current cl) | (of the previous collection) | + * | PRIMARY_FOLLOWED or | | + * |_____PRIMARY_HOOKED___|____________PRIMARY_FOLLOWED____________| + * + * [ (*) the above page can be used as inplace I/O. ] + */ + COLLECT_PRIMARY_FOLLOWED, +}; + +struct z_erofs_collector { + struct z_erofs_pagevec_ctor vector; + + struct z_erofs_pcluster *pcl, *tailpcl; + struct z_erofs_collection *cl; + struct page **compressedpages; + z_erofs_next_pcluster_t owned_head; + + enum z_erofs_collectmode mode; +}; + +struct z_erofs_decompress_frontend { + struct inode *const inode; + + struct z_erofs_collector clt; + struct erofs_map_blocks map; + + /* used for applying cache strategy on the fly */ + bool backmost; + erofs_off_t headoffset; +}; + +#define COLLECTOR_INIT() { \ + .owned_head = Z_EROFS_PCLUSTER_TAIL, \ + .mode = COLLECT_PRIMARY_FOLLOWED } + +#define DECOMPRESS_FRONTEND_INIT(__i) { \ + .inode = __i, .clt = COLLECTOR_INIT(), \ + .backmost = true, } + +static struct page *z_pagemap_global[Z_EROFS_VMAP_GLOBAL_PAGES]; +static DEFINE_MUTEX(z_pagemap_global_lock); + +static void preload_compressed_pages(struct z_erofs_collector *clt, + struct address_space *mc, + enum z_erofs_cache_alloctype type, + struct list_head *pagepool) +{ + const struct z_erofs_pcluster *pcl = clt->pcl; + const unsigned int clusterpages = BIT(pcl->clusterbits); + struct page **pages = clt->compressedpages; + pgoff_t index = pcl->obj.index + (pages - pcl->compressed_pages); + bool standalone = true; + + if (clt->mode < COLLECT_PRIMARY_FOLLOWED) + return; + + for (; pages < pcl->compressed_pages + clusterpages; ++pages) { + struct page *page; + compressed_page_t t; + + /* the compressed page was loaded before */ + if (READ_ONCE(*pages)) + continue; + + page = find_get_page(mc, index); + + if (page) { + t = tag_compressed_page_justfound(page); + } else if (type == DELAYEDALLOC) { + t = tagptr_init(compressed_page_t, PAGE_UNALLOCATED); + } else { /* DONTALLOC */ + if (standalone) + clt->compressedpages = pages; + standalone = false; + continue; + } + + if (!cmpxchg_relaxed(pages, NULL, tagptr_cast_ptr(t))) + continue; + + if (page) + put_page(page); + } + + if (standalone) /* downgrade to PRIMARY_FOLLOWED_NOINPLACE */ + clt->mode = COLLECT_PRIMARY_FOLLOWED_NOINPLACE; +} + +/* called by erofs_shrinker to get rid of all compressed_pages */ +int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, + struct erofs_workgroup *grp) +{ + struct z_erofs_pcluster *const pcl = + container_of(grp, struct z_erofs_pcluster, obj); + struct address_space *const mapping = MNGD_MAPPING(sbi); + const unsigned int clusterpages = BIT(pcl->clusterbits); + int i; + + /* + * refcount of workgroup is now freezed as 1, + * therefore no need to worry about available decompression users. + */ + for (i = 0; i < clusterpages; ++i) { + struct page *page = pcl->compressed_pages[i]; + + if (!page) + continue; + + /* block other users from reclaiming or migrating the page */ + if (!trylock_page(page)) + return -EBUSY; + + if (page->mapping != mapping) + continue; + + /* barrier is implied in the following 'unlock_page' */ + WRITE_ONCE(pcl->compressed_pages[i], NULL); + set_page_private(page, 0); + ClearPagePrivate(page); + + unlock_page(page); + put_page(page); + } + return 0; +} + +int erofs_try_to_free_cached_page(struct address_space *mapping, + struct page *page) +{ + struct z_erofs_pcluster *const pcl = (void *)page_private(page); + const unsigned int clusterpages = BIT(pcl->clusterbits); + int ret = 0; /* 0 - busy */ + + if (erofs_workgroup_try_to_freeze(&pcl->obj, 1)) { + unsigned int i; + + for (i = 0; i < clusterpages; ++i) { + if (pcl->compressed_pages[i] == page) { + WRITE_ONCE(pcl->compressed_pages[i], NULL); + ret = 1; + break; + } + } + erofs_workgroup_unfreeze(&pcl->obj, 1); + + if (ret) { + ClearPagePrivate(page); + put_page(page); + } + } + return ret; +} + +/* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ +static inline bool z_erofs_try_inplace_io(struct z_erofs_collector *clt, + struct page *page) +{ + struct z_erofs_pcluster *const pcl = clt->pcl; + const unsigned int clusterpages = BIT(pcl->clusterbits); + + while (clt->compressedpages < pcl->compressed_pages + clusterpages) { + if (!cmpxchg(clt->compressedpages++, NULL, page)) + return true; + } + return false; +} + +/* callers must be with collection lock held */ +static int z_erofs_attach_page(struct z_erofs_collector *clt, + struct page *page, + enum z_erofs_page_type type) +{ + int ret; + bool occupied; + + /* give priority for inplaceio */ + if (clt->mode >= COLLECT_PRIMARY && + type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && + z_erofs_try_inplace_io(clt, page)) + return 0; + + ret = z_erofs_pagevec_enqueue(&clt->vector, + page, type, &occupied); + clt->cl->vcnt += (unsigned int)ret; + + return ret ? 0 : -EAGAIN; +} + +static enum z_erofs_collectmode +try_to_claim_pcluster(struct z_erofs_pcluster *pcl, + z_erofs_next_pcluster_t *owned_head) +{ + /* let's claim these following types of pclusters */ +retry: + if (pcl->next == Z_EROFS_PCLUSTER_NIL) { + /* type 1, nil pcluster */ + if (cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_NIL, + *owned_head) != Z_EROFS_PCLUSTER_NIL) + goto retry; + + *owned_head = &pcl->next; + /* lucky, I am the followee :) */ + return COLLECT_PRIMARY_FOLLOWED; + } else if (pcl->next == Z_EROFS_PCLUSTER_TAIL) { + /* + * type 2, link to the end of a existing open chain, + * be careful that its submission itself is governed + * by the original owned chain. + */ + if (cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, + *owned_head) != Z_EROFS_PCLUSTER_TAIL) + goto retry; + *owned_head = Z_EROFS_PCLUSTER_TAIL; + return COLLECT_PRIMARY_HOOKED; + } + return COLLECT_PRIMARY; /* :( better luck next time */ +} + +static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) +{ + struct erofs_workgroup *grp; + struct z_erofs_pcluster *pcl; + struct z_erofs_collection *cl; + unsigned int length; + bool tag; + + grp = erofs_find_workgroup(inode->i_sb, map->m_pa >> PAGE_SHIFT, &tag); + if (!grp) + return NULL; + + pcl = container_of(grp, struct z_erofs_pcluster, obj); + if (clt->owned_head == &pcl->next || pcl == clt->tailpcl) { + DBG_BUGON(1); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); + } + + cl = z_erofs_primarycollection(pcl); + if (cl->pageofs != (map->m_la & ~PAGE_MASK)) { + DBG_BUGON(1); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); + } + + length = READ_ONCE(pcl->length); + if (length & Z_EROFS_PCLUSTER_FULL_LENGTH) { + if ((map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) > length) { + DBG_BUGON(1); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); + } + } else { + unsigned int llen = map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT; + + if (map->m_flags & EROFS_MAP_FULL_MAPPED) + llen |= Z_EROFS_PCLUSTER_FULL_LENGTH; + + while (llen > length && + length != cmpxchg_relaxed(&pcl->length, length, llen)) { + cpu_relax(); + length = READ_ONCE(pcl->length); + } + } + mutex_lock(&cl->lock); + /* used to check tail merging loop due to corrupted images */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = pcl; + clt->mode = try_to_claim_pcluster(pcl, &clt->owned_head); + /* clean tailpcl if the current owned_head is Z_EROFS_PCLUSTER_TAIL */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = NULL; + clt->pcl = pcl; + clt->cl = cl; + return cl; +} + +static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) +{ + struct z_erofs_pcluster *pcl; + struct z_erofs_collection *cl; + int err; + + /* no available workgroup, let's allocate one */ + pcl = kmem_cache_alloc(pcluster_cachep, GFP_NOFS); + if (!pcl) + return ERR_PTR(-ENOMEM); + + z_erofs_pcluster_init_always(pcl); + pcl->obj.index = map->m_pa >> PAGE_SHIFT; + + pcl->length = (map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) | + (map->m_flags & EROFS_MAP_FULL_MAPPED ? + Z_EROFS_PCLUSTER_FULL_LENGTH : 0); + + if (map->m_flags & EROFS_MAP_ZIPPED) + pcl->algorithmformat = Z_EROFS_COMPRESSION_LZ4; + else + pcl->algorithmformat = Z_EROFS_COMPRESSION_SHIFTED; + + pcl->clusterbits = EROFS_I(inode)->z_physical_clusterbits[0]; + pcl->clusterbits -= PAGE_SHIFT; + + /* new pclusters should be claimed as type 1, primary and followed */ + pcl->next = clt->owned_head; + clt->mode = COLLECT_PRIMARY_FOLLOWED; + + cl = z_erofs_primarycollection(pcl); + cl->pageofs = map->m_la & ~PAGE_MASK; + + /* + * lock all primary followed works before visible to others + * and mutex_trylock *never* fails for a new pcluster. + */ + mutex_trylock(&cl->lock); + + err = erofs_register_workgroup(inode->i_sb, &pcl->obj, 0); + if (err) { + mutex_unlock(&cl->lock); + kmem_cache_free(pcluster_cachep, pcl); + return ERR_PTR(-EAGAIN); + } + /* used to check tail merging loop due to corrupted images */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = pcl; + clt->owned_head = &pcl->next; + clt->pcl = pcl; + clt->cl = cl; + return cl; +} + +static int z_erofs_collector_begin(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) +{ + struct z_erofs_collection *cl; + + DBG_BUGON(clt->cl); + + /* must be Z_EROFS_PCLUSTER_TAIL or pointed to previous collection */ + DBG_BUGON(clt->owned_head == Z_EROFS_PCLUSTER_NIL); + DBG_BUGON(clt->owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + + if (!PAGE_ALIGNED(map->m_pa)) { + DBG_BUGON(1); + return -EINVAL; + } + +repeat: + cl = cllookup(clt, inode, map); + if (!cl) { + cl = clregister(clt, inode, map); + + if (cl == ERR_PTR(-EAGAIN)) + goto repeat; + } + + if (IS_ERR(cl)) + return PTR_ERR(cl); + + z_erofs_pagevec_ctor_init(&clt->vector, Z_EROFS_NR_INLINE_PAGEVECS, + cl->pagevec, cl->vcnt); + + clt->compressedpages = clt->pcl->compressed_pages; + if (clt->mode <= COLLECT_PRIMARY) /* cannot do in-place I/O */ + clt->compressedpages += Z_EROFS_CLUSTER_MAX_PAGES; + return 0; +} + +/* + * keep in mind that no referenced pclusters will be freed + * only after a RCU grace period. + */ +static void z_erofs_rcu_callback(struct rcu_head *head) +{ + struct z_erofs_collection *const cl = + container_of(head, struct z_erofs_collection, rcu); + + kmem_cache_free(pcluster_cachep, + container_of(cl, struct z_erofs_pcluster, + primary_collection)); +} + +void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) +{ + struct z_erofs_pcluster *const pcl = + container_of(grp, struct z_erofs_pcluster, obj); + struct z_erofs_collection *const cl = z_erofs_primarycollection(pcl); + + call_rcu(&cl->rcu, z_erofs_rcu_callback); +} + +static void z_erofs_collection_put(struct z_erofs_collection *cl) +{ + struct z_erofs_pcluster *const pcl = + container_of(cl, struct z_erofs_pcluster, primary_collection); + + erofs_workgroup_put(&pcl->obj); +} + +static bool z_erofs_collector_end(struct z_erofs_collector *clt) +{ + struct z_erofs_collection *cl = clt->cl; + + if (!cl) + return false; + + z_erofs_pagevec_ctor_exit(&clt->vector, false); + mutex_unlock(&cl->lock); + + /* + * if all pending pages are added, don't hold its reference + * any longer if the pcluster isn't hosted by ourselves. + */ + if (clt->mode < COLLECT_PRIMARY_FOLLOWED_NOINPLACE) + z_erofs_collection_put(cl); + + clt->cl = NULL; + return true; +} + +static inline struct page *__stagingpage_alloc(struct list_head *pagepool, + gfp_t gfp) +{ + struct page *page = erofs_allocpage(pagepool, gfp, true); + + page->mapping = Z_EROFS_MAPPING_STAGING; + return page; +} + +static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, + unsigned int cachestrategy, + erofs_off_t la) +{ + if (cachestrategy <= EROFS_ZIP_CACHE_DISABLED) + return false; + + if (fe->backmost) + return true; + + return cachestrategy >= EROFS_ZIP_CACHE_READAROUND && + la < fe->headoffset; +} + +static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, + struct page *page, + struct list_head *pagepool) +{ + struct inode *const inode = fe->inode; + struct erofs_sb_info *const sbi __maybe_unused = EROFS_I_SB(inode); + struct erofs_map_blocks *const map = &fe->map; + struct z_erofs_collector *const clt = &fe->clt; + const loff_t offset = page_offset(page); + bool tight = (clt->mode >= COLLECT_PRIMARY_HOOKED); + + enum z_erofs_cache_alloctype cache_strategy; + enum z_erofs_page_type page_type; + unsigned int cur, end, spiltted, index; + int err = 0; + + /* register locked file pages as online pages in pack */ + z_erofs_onlinepage_init(page); + + spiltted = 0; + end = PAGE_SIZE; +repeat: + cur = end - 1; + + /* lucky, within the range of the current map_blocks */ + if (offset + cur >= map->m_la && + offset + cur < map->m_la + map->m_llen) { + /* didn't get a valid collection previously (very rare) */ + if (!clt->cl) + goto restart_now; + goto hitted; + } + + /* go ahead the next map_blocks */ + erofs_dbg("%s: [out-of-range] pos %llu", __func__, offset + cur); + + if (z_erofs_collector_end(clt)) + fe->backmost = false; + + map->m_la = offset + cur; + map->m_llen = 0; + err = z_erofs_map_blocks_iter(inode, map, 0); + if (err) + goto err_out; + +restart_now: + if (!(map->m_flags & EROFS_MAP_MAPPED)) + goto hitted; + + err = z_erofs_collector_begin(clt, inode, map); + if (err) + goto err_out; + + /* preload all compressed pages (maybe downgrade role if necessary) */ + if (should_alloc_managed_pages(fe, sbi->cache_strategy, map->m_la)) + cache_strategy = DELAYEDALLOC; + else + cache_strategy = DONTALLOC; + + preload_compressed_pages(clt, MNGD_MAPPING(sbi), + cache_strategy, pagepool); + + tight &= (clt->mode >= COLLECT_PRIMARY_HOOKED); +hitted: + cur = end - min_t(unsigned int, offset + end - map->m_la, end); + if (!(map->m_flags & EROFS_MAP_MAPPED)) { + zero_user_segment(page, cur, end); + goto next_part; + } + + /* let's derive page type */ + page_type = cur ? Z_EROFS_VLE_PAGE_TYPE_HEAD : + (!spiltted ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : + (tight ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : + Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED)); + + if (cur) + tight &= (clt->mode >= COLLECT_PRIMARY_FOLLOWED); + +retry: + err = z_erofs_attach_page(clt, page, page_type); + /* should allocate an additional staging page for pagevec */ + if (err == -EAGAIN) { + struct page *const newpage = + __stagingpage_alloc(pagepool, GFP_NOFS); + + err = z_erofs_attach_page(clt, newpage, + Z_EROFS_PAGE_TYPE_EXCLUSIVE); + if (!err) + goto retry; + } + + if (err) + goto err_out; + + index = page->index - (map->m_la >> PAGE_SHIFT); + + z_erofs_onlinepage_fixup(page, index, true); + + /* bump up the number of spiltted parts of a page */ + ++spiltted; + /* also update nr_pages */ + clt->cl->nr_pages = max_t(pgoff_t, clt->cl->nr_pages, index + 1); +next_part: + /* can be used for verification */ + map->m_llen = offset + cur - map->m_la; + + end = cur; + if (end > 0) + goto repeat; + +out: + z_erofs_onlinepage_endio(page); + + erofs_dbg("%s, finish page: %pK spiltted: %u map->m_llen %llu", + __func__, page, spiltted, map->m_llen); + return err; + + /* if some error occurred while processing this page */ +err_out: + SetPageError(page); + goto out; +} + +static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) +{ + tagptr1_t t = tagptr_init(tagptr1_t, ptr); + struct z_erofs_unzip_io *io = tagptr_unfold_ptr(t); + bool background = tagptr_unfold_tags(t); + + if (!background) { + unsigned long flags; + + spin_lock_irqsave(&io->u.wait.lock, flags); + if (!atomic_add_return(bios, &io->pending_bios)) + wake_up_locked(&io->u.wait); + spin_unlock_irqrestore(&io->u.wait.lock, flags); + return; + } + + if (!atomic_add_return(bios, &io->pending_bios)) + queue_work(z_erofs_workqueue, &io->u.work); +} + +static inline void z_erofs_vle_read_endio(struct bio *bio) +{ + struct erofs_sb_info *sbi = NULL; + blk_status_t err = bio->bi_status; + struct bio_vec *bvec; + struct bvec_iter_all iter_all; + + bio_for_each_segment_all(bvec, bio, iter_all) { + struct page *page = bvec->bv_page; + bool cachemngd = false; + + DBG_BUGON(PageUptodate(page)); + DBG_BUGON(!page->mapping); + + if (!sbi && !z_erofs_page_is_staging(page)) + sbi = EROFS_SB(page->mapping->host->i_sb); + + /* sbi should already be gotten if the page is managed */ + if (sbi) + cachemngd = erofs_page_is_managed(sbi, page); + + if (err) + SetPageError(page); + else if (cachemngd) + SetPageUptodate(page); + + if (cachemngd) + unlock_page(page); + } + + z_erofs_vle_unzip_kickoff(bio->bi_private, -1); + bio_put(bio); +} + +static int z_erofs_decompress_pcluster(struct super_block *sb, + struct z_erofs_pcluster *pcl, + struct list_head *pagepool) +{ + struct erofs_sb_info *const sbi = EROFS_SB(sb); + const unsigned int clusterpages = BIT(pcl->clusterbits); + struct z_erofs_pagevec_ctor ctor; + unsigned int i, outputsize, llen, nr_pages; + struct page *pages_onstack[Z_EROFS_VMAP_ONSTACK_PAGES]; + struct page **pages, **compressed_pages, *page; + + enum z_erofs_page_type page_type; + bool overlapped, partial; + struct z_erofs_collection *cl; + int err; + + might_sleep(); + cl = z_erofs_primarycollection(pcl); + DBG_BUGON(!READ_ONCE(cl->nr_pages)); + + mutex_lock(&cl->lock); + nr_pages = cl->nr_pages; + + if (nr_pages <= Z_EROFS_VMAP_ONSTACK_PAGES) { + pages = pages_onstack; + } else if (nr_pages <= Z_EROFS_VMAP_GLOBAL_PAGES && + mutex_trylock(&z_pagemap_global_lock)) { + pages = z_pagemap_global; + } else { + gfp_t gfp_flags = GFP_KERNEL; + + if (nr_pages > Z_EROFS_VMAP_GLOBAL_PAGES) + gfp_flags |= __GFP_NOFAIL; + + pages = kvmalloc_array(nr_pages, sizeof(struct page *), + gfp_flags); + + /* fallback to global pagemap for the lowmem scenario */ + if (!pages) { + mutex_lock(&z_pagemap_global_lock); + pages = z_pagemap_global; + } + } + + for (i = 0; i < nr_pages; ++i) + pages[i] = NULL; + + err = 0; + z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_NR_INLINE_PAGEVECS, + cl->pagevec, 0); + + for (i = 0; i < cl->vcnt; ++i) { + unsigned int pagenr; + + page = z_erofs_pagevec_dequeue(&ctor, &page_type); + + /* all pages in pagevec ought to be valid */ + DBG_BUGON(!page); + DBG_BUGON(!page->mapping); + + if (z_erofs_put_stagingpage(pagepool, page)) + continue; + + if (page_type == Z_EROFS_VLE_PAGE_TYPE_HEAD) + pagenr = 0; + else + pagenr = z_erofs_onlinepage_index(page); + + DBG_BUGON(pagenr >= nr_pages); + + /* + * currently EROFS doesn't support multiref(dedup), + * so here erroring out one multiref page. + */ + if (pages[pagenr]) { + DBG_BUGON(1); + SetPageError(pages[pagenr]); + z_erofs_onlinepage_endio(pages[pagenr]); + err = -EFSCORRUPTED; + } + pages[pagenr] = page; + } + z_erofs_pagevec_ctor_exit(&ctor, true); + + overlapped = false; + compressed_pages = pcl->compressed_pages; + + for (i = 0; i < clusterpages; ++i) { + unsigned int pagenr; + + page = compressed_pages[i]; + + /* all compressed pages ought to be valid */ + DBG_BUGON(!page); + DBG_BUGON(!page->mapping); + + if (!z_erofs_page_is_staging(page)) { + if (erofs_page_is_managed(sbi, page)) { + if (!PageUptodate(page)) + err = -EIO; + continue; + } + + /* + * only if non-head page can be selected + * for inplace decompression + */ + pagenr = z_erofs_onlinepage_index(page); + + DBG_BUGON(pagenr >= nr_pages); + if (pages[pagenr]) { + DBG_BUGON(1); + SetPageError(pages[pagenr]); + z_erofs_onlinepage_endio(pages[pagenr]); + err = -EFSCORRUPTED; + } + pages[pagenr] = page; + + overlapped = true; + } + + /* PG_error needs checking for inplaced and staging pages */ + if (PageError(page)) { + DBG_BUGON(PageUptodate(page)); + err = -EIO; + } + } + + if (err) + goto out; + + llen = pcl->length >> Z_EROFS_PCLUSTER_LENGTH_BIT; + if (nr_pages << PAGE_SHIFT >= cl->pageofs + llen) { + outputsize = llen; + partial = !(pcl->length & Z_EROFS_PCLUSTER_FULL_LENGTH); + } else { + outputsize = (nr_pages << PAGE_SHIFT) - cl->pageofs; + partial = true; + } + + err = z_erofs_decompress(&(struct z_erofs_decompress_req) { + .sb = sb, + .in = compressed_pages, + .out = pages, + .pageofs_out = cl->pageofs, + .inputsize = PAGE_SIZE, + .outputsize = outputsize, + .alg = pcl->algorithmformat, + .inplace_io = overlapped, + .partial_decoding = partial + }, pagepool); + +out: + /* must handle all compressed pages before endding pages */ + for (i = 0; i < clusterpages; ++i) { + page = compressed_pages[i]; + + if (erofs_page_is_managed(sbi, page)) + continue; + + /* recycle all individual staging pages */ + (void)z_erofs_put_stagingpage(pagepool, page); + + WRITE_ONCE(compressed_pages[i], NULL); + } + + for (i = 0; i < nr_pages; ++i) { + page = pages[i]; + if (!page) + continue; + + DBG_BUGON(!page->mapping); + + /* recycle all individual staging pages */ + if (z_erofs_put_stagingpage(pagepool, page)) + continue; + + if (err < 0) + SetPageError(page); + + z_erofs_onlinepage_endio(page); + } + + if (pages == z_pagemap_global) + mutex_unlock(&z_pagemap_global_lock); + else if (pages != pages_onstack) + kvfree(pages); + + cl->nr_pages = 0; + cl->vcnt = 0; + + /* all cl locks MUST be taken before the following line */ + WRITE_ONCE(pcl->next, Z_EROFS_PCLUSTER_NIL); + + /* all cl locks SHOULD be released right now */ + mutex_unlock(&cl->lock); + + z_erofs_collection_put(cl); + return err; +} + +static void z_erofs_vle_unzip_all(struct super_block *sb, + struct z_erofs_unzip_io *io, + struct list_head *pagepool) +{ + z_erofs_next_pcluster_t owned = io->head; + + while (owned != Z_EROFS_PCLUSTER_TAIL_CLOSED) { + struct z_erofs_pcluster *pcl; + + /* no possible that 'owned' equals Z_EROFS_WORK_TPTR_TAIL */ + DBG_BUGON(owned == Z_EROFS_PCLUSTER_TAIL); + + /* no possible that 'owned' equals NULL */ + DBG_BUGON(owned == Z_EROFS_PCLUSTER_NIL); + + pcl = container_of(owned, struct z_erofs_pcluster, next); + owned = READ_ONCE(pcl->next); + + z_erofs_decompress_pcluster(sb, pcl, pagepool); + } +} + +static void z_erofs_vle_unzip_wq(struct work_struct *work) +{ + struct z_erofs_unzip_io_sb *iosb = + container_of(work, struct z_erofs_unzip_io_sb, io.u.work); + LIST_HEAD(pagepool); + + DBG_BUGON(iosb->io.head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &pagepool); + + put_pages_list(&pagepool); + kvfree(iosb); +} + +static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, + unsigned int nr, + struct list_head *pagepool, + struct address_space *mc, + gfp_t gfp) +{ + /* determined at compile time to avoid too many #ifdefs */ + const bool nocache = __builtin_constant_p(mc) ? !mc : false; + const pgoff_t index = pcl->obj.index; + bool tocache = false; + + struct address_space *mapping; + struct page *oldpage, *page; + + compressed_page_t t; + int justfound; + +repeat: + page = READ_ONCE(pcl->compressed_pages[nr]); + oldpage = page; + + if (!page) + goto out_allocpage; + + /* + * the cached page has not been allocated and + * an placeholder is out there, prepare it now. + */ + if (!nocache && page == PAGE_UNALLOCATED) { + tocache = true; + goto out_allocpage; + } + + /* process the target tagged pointer */ + t = tagptr_init(compressed_page_t, page); + justfound = tagptr_unfold_tags(t); + page = tagptr_unfold_ptr(t); + + mapping = READ_ONCE(page->mapping); + + /* + * if managed cache is disabled, it's no way to + * get such a cached-like page. + */ + if (nocache) { + /* if managed cache is disabled, it is impossible `justfound' */ + DBG_BUGON(justfound); + + /* and it should be locked, not uptodate, and not truncated */ + DBG_BUGON(!PageLocked(page)); + DBG_BUGON(PageUptodate(page)); + DBG_BUGON(!mapping); + goto out; + } + + /* + * unmanaged (file) pages are all locked solidly, + * therefore it is impossible for `mapping' to be NULL. + */ + if (mapping && mapping != mc) + /* ought to be unmanaged pages */ + goto out; + + lock_page(page); + + /* only true if page reclaim goes wrong, should never happen */ + DBG_BUGON(justfound && PagePrivate(page)); + + /* the page is still in manage cache */ + if (page->mapping == mc) { + WRITE_ONCE(pcl->compressed_pages[nr], page); + + ClearPageError(page); + if (!PagePrivate(page)) { + /* + * impossible to be !PagePrivate(page) for + * the current restriction as well if + * the page is already in compressed_pages[]. + */ + DBG_BUGON(!justfound); + + justfound = 0; + set_page_private(page, (unsigned long)pcl); + SetPagePrivate(page); + } + + /* no need to submit io if it is already up-to-date */ + if (PageUptodate(page)) { + unlock_page(page); + page = NULL; + } + goto out; + } + + /* + * the managed page has been truncated, it's unsafe to + * reuse this one, let's allocate a new cache-managed page. + */ + DBG_BUGON(page->mapping); + DBG_BUGON(!justfound); + + tocache = true; + unlock_page(page); + put_page(page); +out_allocpage: + page = __stagingpage_alloc(pagepool, gfp); + if (oldpage != cmpxchg(&pcl->compressed_pages[nr], oldpage, page)) { + list_add(&page->lru, pagepool); + cpu_relax(); + goto repeat; + } + if (nocache || !tocache) + goto out; + if (add_to_page_cache_lru(page, mc, index + nr, gfp)) { + page->mapping = Z_EROFS_MAPPING_STAGING; + goto out; + } + + set_page_private(page, (unsigned long)pcl); + SetPagePrivate(page); +out: /* the only exit (for tracing and debugging) */ + return page; +} + +static struct z_erofs_unzip_io *jobqueue_init(struct super_block *sb, + struct z_erofs_unzip_io *io, + bool foreground) +{ + struct z_erofs_unzip_io_sb *iosb; + + if (foreground) { + /* waitqueue available for foreground io */ + DBG_BUGON(!io); + + init_waitqueue_head(&io->u.wait); + atomic_set(&io->pending_bios, 0); + goto out; + } + + iosb = kvzalloc(sizeof(*iosb), GFP_KERNEL | __GFP_NOFAIL); + DBG_BUGON(!iosb); + + /* initialize fields in the allocated descriptor */ + io = &iosb->io; + iosb->sb = sb; + INIT_WORK(&io->u.work, z_erofs_vle_unzip_wq); +out: + io->head = Z_EROFS_PCLUSTER_TAIL_CLOSED; + return io; +} + +/* define decompression jobqueue types */ +enum { + JQ_BYPASS, + JQ_SUBMIT, + NR_JOBQUEUES, +}; + +static void *jobqueueset_init(struct super_block *sb, + z_erofs_next_pcluster_t qtail[], + struct z_erofs_unzip_io *q[], + struct z_erofs_unzip_io *fgq, + bool forcefg) +{ + /* + * if managed cache is enabled, bypass jobqueue is needed, + * no need to read from device for all pclusters in this queue. + */ + q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); + qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; + + q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg); + qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; + + return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg)); +} + +static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, + z_erofs_next_pcluster_t qtail[], + z_erofs_next_pcluster_t owned_head) +{ + z_erofs_next_pcluster_t *const submit_qtail = qtail[JQ_SUBMIT]; + z_erofs_next_pcluster_t *const bypass_qtail = qtail[JQ_BYPASS]; + + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + if (owned_head == Z_EROFS_PCLUSTER_TAIL) + owned_head = Z_EROFS_PCLUSTER_TAIL_CLOSED; + + WRITE_ONCE(pcl->next, Z_EROFS_PCLUSTER_TAIL_CLOSED); + + WRITE_ONCE(*submit_qtail, owned_head); + WRITE_ONCE(*bypass_qtail, &pcl->next); + + qtail[JQ_BYPASS] = &pcl->next; +} + +static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], + unsigned int nr_bios, + bool force_fg) +{ + /* + * although background is preferred, no one is pending for submission. + * don't issue workqueue for decompression but drop it directly instead. + */ + if (force_fg || nr_bios) + return false; + + kvfree(container_of(q[JQ_SUBMIT], struct z_erofs_unzip_io_sb, io)); + return true; +} + +static bool z_erofs_vle_submit_all(struct super_block *sb, + z_erofs_next_pcluster_t owned_head, + struct list_head *pagepool, + struct z_erofs_unzip_io *fgq, + bool force_fg) +{ + struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); + z_erofs_next_pcluster_t qtail[NR_JOBQUEUES]; + struct z_erofs_unzip_io *q[NR_JOBQUEUES]; + struct bio *bio; + void *bi_private; + /* since bio will be NULL, no need to initialize last_index */ + pgoff_t uninitialized_var(last_index); + bool force_submit = false; + unsigned int nr_bios; + + if (owned_head == Z_EROFS_PCLUSTER_TAIL) + return false; + + force_submit = false; + bio = NULL; + nr_bios = 0; + bi_private = jobqueueset_init(sb, qtail, q, fgq, force_fg); + + /* by default, all need io submission */ + q[JQ_SUBMIT]->head = owned_head; + + do { + struct z_erofs_pcluster *pcl; + unsigned int clusterpages; + pgoff_t first_index; + struct page *page; + unsigned int i = 0, bypass = 0; + int err; + + /* no possible 'owned_head' equals the following */ + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_NIL); + + pcl = container_of(owned_head, struct z_erofs_pcluster, next); + + clusterpages = BIT(pcl->clusterbits); + + /* close the main owned chain at first */ + owned_head = cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, + Z_EROFS_PCLUSTER_TAIL_CLOSED); + + first_index = pcl->obj.index; + force_submit |= (first_index != last_index + 1); + +repeat: + page = pickup_page_for_submission(pcl, i, pagepool, + MNGD_MAPPING(sbi), + GFP_NOFS); + if (!page) { + force_submit = true; + ++bypass; + goto skippage; + } + + if (bio && force_submit) { +submit_bio_retry: + submit_bio(bio); + bio = NULL; + } + + if (!bio) { + bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES); + + bio->bi_end_io = z_erofs_vle_read_endio; + bio_set_dev(bio, sb->s_bdev); + bio->bi_iter.bi_sector = (sector_t)(first_index + i) << + LOG_SECTORS_PER_BLOCK; + bio->bi_private = bi_private; + bio->bi_opf = REQ_OP_READ; + + ++nr_bios; + } + + err = bio_add_page(bio, page, PAGE_SIZE, 0); + if (err < PAGE_SIZE) + goto submit_bio_retry; + + force_submit = false; + last_index = first_index + i; +skippage: + if (++i < clusterpages) + goto repeat; + + if (bypass < clusterpages) + qtail[JQ_SUBMIT] = &pcl->next; + else + move_to_bypass_jobqueue(pcl, qtail, owned_head); + } while (owned_head != Z_EROFS_PCLUSTER_TAIL); + + if (bio) + submit_bio(bio); + + if (postsubmit_is_all_bypassed(q, nr_bios, force_fg)) + return true; + + z_erofs_vle_unzip_kickoff(bi_private, nr_bios); + return true; +} + +static void z_erofs_submit_and_unzip(struct super_block *sb, + struct z_erofs_collector *clt, + struct list_head *pagepool, + bool force_fg) +{ + struct z_erofs_unzip_io io[NR_JOBQUEUES]; + + if (!z_erofs_vle_submit_all(sb, clt->owned_head, + pagepool, io, force_fg)) + return; + + /* decompress no I/O pclusters immediately */ + z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); + + if (!force_fg) + return; + + /* wait until all bios are completed */ + wait_event(io[JQ_SUBMIT].u.wait, + !atomic_read(&io[JQ_SUBMIT].pending_bios)); + + /* let's synchronous decompression */ + z_erofs_vle_unzip_all(sb, &io[JQ_SUBMIT], pagepool); +} + +static int z_erofs_vle_normalaccess_readpage(struct file *file, + struct page *page) +{ + struct inode *const inode = page->mapping->host; + struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); + int err; + LIST_HEAD(pagepool); + + trace_erofs_readpage(page, false); + + f.headoffset = (erofs_off_t)page->index << PAGE_SHIFT; + + err = z_erofs_do_read_page(&f, page, &pagepool); + (void)z_erofs_collector_end(&f.clt); + + /* if some compressed cluster ready, need submit them anyway */ + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, true); + + if (err) + erofs_err(inode->i_sb, "failed to read, err [%d]", err); + + if (f.map.mpage) + put_page(f.map.mpage); + + /* clean up the remaining free pages */ + put_pages_list(&pagepool); + return err; +} + +static bool should_decompress_synchronously(struct erofs_sb_info *sbi, + unsigned int nr) +{ + return nr <= sbi->max_sync_decompress_pages; +} + +static int z_erofs_vle_normalaccess_readpages(struct file *filp, + struct address_space *mapping, + struct list_head *pages, + unsigned int nr_pages) +{ + struct inode *const inode = mapping->host; + struct erofs_sb_info *const sbi = EROFS_I_SB(inode); + + bool sync = should_decompress_synchronously(sbi, nr_pages); + struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); + gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL); + struct page *head = NULL; + LIST_HEAD(pagepool); + + trace_erofs_readpages(mapping->host, lru_to_page(pages), + nr_pages, false); + + f.headoffset = (erofs_off_t)lru_to_page(pages)->index << PAGE_SHIFT; + + for (; nr_pages; --nr_pages) { + struct page *page = lru_to_page(pages); + + prefetchw(&page->flags); + list_del(&page->lru); + + /* + * A pure asynchronous readahead is indicated if + * a PG_readahead marked page is hitted at first. + * Let's also do asynchronous decompression for this case. + */ + sync &= !(PageReadahead(page) && !head); + + if (add_to_page_cache_lru(page, mapping, page->index, gfp)) { + list_add(&page->lru, &pagepool); + continue; + } + + set_page_private(page, (unsigned long)head); + head = page; + } + + while (head) { + struct page *page = head; + int err; + + /* traversal in reverse order */ + head = (void *)page_private(page); + + err = z_erofs_do_read_page(&f, page, &pagepool); + if (err) + erofs_err(inode->i_sb, + "readahead error at page %lu @ nid %llu", + page->index, EROFS_I(inode)->nid); + put_page(page); + } + + (void)z_erofs_collector_end(&f.clt); + + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, sync); + + if (f.map.mpage) + put_page(f.map.mpage); + + /* clean up the remaining free pages */ + put_pages_list(&pagepool); + return 0; +} + +const struct address_space_operations z_erofs_vle_normalaccess_aops = { + .readpage = z_erofs_vle_normalaccess_readpage, + .readpages = z_erofs_vle_normalaccess_readpages, +}; + diff --git a/drivers/staging/erofs/unzip_vle.h b/fs/erofs/zdata.h index ab509d75aefd..faf950189bd7 100644 --- a/drivers/staging/erofs/unzip_vle.h +++ b/fs/erofs/zdata.h @@ -1,20 +1,14 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * linux/drivers/staging/erofs/unzip_vle.h - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ -#ifndef __EROFS_FS_UNZIP_VLE_H -#define __EROFS_FS_UNZIP_VLE_H +#ifndef __EROFS_FS_ZDATA_H +#define __EROFS_FS_ZDATA_H #include "internal.h" -#include "unzip_pagevec.h" +#include "zpvec.h" #define Z_EROFS_NR_INLINE_PAGEVECS 3 @@ -22,80 +16,77 @@ * Structure fields follow one of the following exclusion rules. * * I: Modifiable by initialization/destruction paths and read-only - * for everyone else. + * for everyone else; + * + * L: Field should be protected by pageset lock; * + * A: Field should be accessed / updated in atomic for parallelized code. */ - -struct z_erofs_vle_work { +struct z_erofs_collection { struct mutex lock; - /* I: decompression offset in page */ + /* I: page offset of start position of decompression */ unsigned short pageofs; + + /* L: maximum relative page index in pagevec[] */ unsigned short nr_pages; - /* L: queued pages in pagevec[] */ - unsigned vcnt; + /* L: total number of pages in pagevec[] */ + unsigned int vcnt; union { - /* L: pagevec */ + /* L: inline a certain number of pagevecs for bootstrap */ erofs_vtptr_t pagevec[Z_EROFS_NR_INLINE_PAGEVECS]; + + /* I: can be used to free the pcluster by RCU. */ struct rcu_head rcu; }; }; -#define Z_EROFS_VLE_WORKGRP_FMT_PLAIN 0 -#define Z_EROFS_VLE_WORKGRP_FMT_LZ4 1 -#define Z_EROFS_VLE_WORKGRP_FMT_MASK 1 -#define Z_EROFS_VLE_WORKGRP_FULL_LENGTH 2 +#define Z_EROFS_PCLUSTER_FULL_LENGTH 0x00000001 +#define Z_EROFS_PCLUSTER_LENGTH_BIT 1 -typedef void *z_erofs_vle_owned_workgrp_t; +/* + * let's leave a type here in case of introducing + * another tagged pointer later. + */ +typedef void *z_erofs_next_pcluster_t; -struct z_erofs_vle_workgroup { +struct z_erofs_pcluster { struct erofs_workgroup obj; - struct z_erofs_vle_work work; + struct z_erofs_collection primary_collection; - /* point to next owned_workgrp_t */ - z_erofs_vle_owned_workgrp_t next; + /* A: point to next chained pcluster or TAILs */ + z_erofs_next_pcluster_t next; - /* compressed pages (including multi-usage pages) */ + /* A: compressed pages (including multi-usage pages) */ struct page *compressed_pages[Z_EROFS_CLUSTER_MAX_PAGES]; - unsigned int llen, flags; + + /* A: lower limit of decompressed length and if full length or not */ + unsigned int length; + + /* I: compression algorithm format */ + unsigned char algorithmformat; + /* I: bit shift of physical cluster size */ + unsigned char clusterbits; }; +#define z_erofs_primarycollection(pcluster) (&(pcluster)->primary_collection) + /* let's avoid the valid 32-bit kernel addresses */ /* the chained workgroup has't submitted io (still open) */ -#define Z_EROFS_VLE_WORKGRP_TAIL ((void *)0x5F0ECAFE) +#define Z_EROFS_PCLUSTER_TAIL ((void *)0x5F0ECAFE) /* the chained workgroup has already submitted io */ -#define Z_EROFS_VLE_WORKGRP_TAIL_CLOSED ((void *)0x5F0EDEAD) - -#define Z_EROFS_VLE_WORKGRP_NIL (NULL) - -#define z_erofs_vle_workgrp_fmt(grp) \ - ((grp)->flags & Z_EROFS_VLE_WORKGRP_FMT_MASK) - -static inline void z_erofs_vle_set_workgrp_fmt( - struct z_erofs_vle_workgroup *grp, - unsigned int fmt) -{ - grp->flags = fmt | (grp->flags & ~Z_EROFS_VLE_WORKGRP_FMT_MASK); -} +#define Z_EROFS_PCLUSTER_TAIL_CLOSED ((void *)0x5F0EDEAD) +#define Z_EROFS_PCLUSTER_NIL (NULL) -/* definitions if multiref is disabled */ -#define z_erofs_vle_grab_primary_work(grp) (&(grp)->work) -#define z_erofs_vle_grab_work(grp, pageofs) (&(grp)->work) -#define z_erofs_vle_work_workgroup(wrk, primary) \ - ((primary) ? container_of(wrk, \ - struct z_erofs_vle_workgroup, work) : \ - ({ BUG(); (void *)NULL; })) +#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_pcluster) - -#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_vle_workgroup) - -struct z_erofs_vle_unzip_io { +struct z_erofs_unzip_io { atomic_t pending_bios; - z_erofs_vle_owned_workgrp_t head; + z_erofs_next_pcluster_t head; union { wait_queue_head_t wait; @@ -103,13 +94,20 @@ struct z_erofs_vle_unzip_io { } u; }; -struct z_erofs_vle_unzip_io_sb { - struct z_erofs_vle_unzip_io io; +struct z_erofs_unzip_io_sb { + struct z_erofs_unzip_io io; struct super_block *sb; }; -#define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 -#define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) +#define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) +static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, + struct page *page) +{ + return page->mapping == MNGD_MAPPING(sbi); +} + +#define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 +#define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) #define Z_EROFS_ONLINEPAGE_INDEX_SHIFT (Z_EROFS_ONLINEPAGE_COUNT_BITS) /* @@ -124,7 +122,7 @@ union z_erofs_onlinepage_converter { unsigned long *v; }; -static inline unsigned z_erofs_onlinepage_index(struct page *page) +static inline unsigned int z_erofs_onlinepage_index(struct page *page) { union z_erofs_onlinepage_converter u; @@ -164,7 +162,7 @@ repeat: } v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) | - ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned)down); + ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down); if (cmpxchg(p, o, v) != o) goto repeat; } @@ -172,7 +170,7 @@ repeat: static inline void z_erofs_onlinepage_endio(struct page *page) { union z_erofs_onlinepage_converter u; - unsigned v; + unsigned int v; DBG_BUGON(!PagePrivate(page)); u.v = &page_private(page); @@ -184,13 +182,12 @@ static inline void z_erofs_onlinepage_endio(struct page *page) SetPageUptodate(page); unlock_page(page); } - - debugln("%s, page %p value %x", __func__, page, atomic_read(u.o)); + erofs_dbg("%s, page %p value %x", __func__, page, atomic_read(u.o)); } -#define Z_EROFS_VLE_VMAP_ONSTACK_PAGES \ +#define Z_EROFS_VMAP_ONSTACK_PAGES \ min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U) -#define Z_EROFS_VLE_VMAP_GLOBAL_PAGES 2048 +#define Z_EROFS_VMAP_GLOBAL_PAGES 2048 #endif diff --git a/drivers/staging/erofs/zmap.c b/fs/erofs/zmap.c index 9c0bd65c46bf..6a26c293ae2d 100644 --- a/drivers/staging/erofs/zmap.c +++ b/fs/erofs/zmap.c @@ -1,7 +1,5 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* - * linux/drivers/staging/erofs/zmap.c - * * Copyright (C) 2018-2019 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> @@ -12,17 +10,16 @@ int z_erofs_fill_inode(struct inode *inode) { - struct erofs_vnode *const vi = EROFS_V(inode); - struct super_block *const sb = inode->i_sb; + struct erofs_inode *const vi = EROFS_I(inode); - if (vi->datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { + if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { vi->z_advise = 0; vi->z_algorithmtype[0] = 0; vi->z_algorithmtype[1] = 0; - vi->z_logical_clusterbits = EROFS_SB(sb)->clusterbits; + vi->z_logical_clusterbits = LOG_BLOCK_SIZE; vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits; vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits; - set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); + set_bit(EROFS_I_Z_INITED_BIT, &vi->flags); } inode->i_mapping->a_ops = &z_erofs_vle_normalaccess_aops; @@ -31,7 +28,7 @@ int z_erofs_fill_inode(struct inode *inode) static int fill_inode_lazy(struct inode *inode) { - struct erofs_vnode *const vi = EROFS_V(inode); + struct erofs_inode *const vi = EROFS_I(inode); struct super_block *const sb = inode->i_sb; int err; erofs_off_t pos; @@ -39,21 +36,21 @@ static int fill_inode_lazy(struct inode *inode) void *kaddr; struct z_erofs_map_header *h; - if (test_bit(EROFS_V_Z_INITED_BIT, &vi->flags)) + if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) return 0; - if (wait_on_bit_lock(&vi->flags, EROFS_V_BL_Z_BIT, TASK_KILLABLE)) + if (wait_on_bit_lock(&vi->flags, EROFS_I_BL_Z_BIT, TASK_KILLABLE)) return -ERESTARTSYS; err = 0; - if (test_bit(EROFS_V_Z_INITED_BIT, &vi->flags)) + if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) goto out_unlock; - DBG_BUGON(vi->datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY); + DBG_BUGON(vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY); pos = ALIGN(iloc(EROFS_SB(sb), vi->nid) + vi->inode_isize + vi->xattr_isize, 8); - page = erofs_get_meta_page(sb, erofs_blknr(pos), false); + page = erofs_get_meta_page(sb, erofs_blknr(pos)); if (IS_ERR(page)) { err = PTR_ERR(page); goto out_unlock; @@ -67,9 +64,9 @@ static int fill_inode_lazy(struct inode *inode) vi->z_algorithmtype[1] = h->h_algorithmtype >> 4; if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX) { - errln("unknown compression format %u for nid %llu, please upgrade kernel", - vi->z_algorithmtype[0], vi->nid); - err = -ENOTSUPP; + erofs_err(sb, "unknown compression format %u for nid %llu, please upgrade kernel", + vi->z_algorithmtype[0], vi->nid); + err = -EOPNOTSUPP; goto unmap_done; } @@ -78,22 +75,21 @@ static int fill_inode_lazy(struct inode *inode) ((h->h_clusterbits >> 3) & 3); if (vi->z_physical_clusterbits[0] != LOG_BLOCK_SIZE) { - errln("unsupported physical clusterbits %u for nid %llu, please upgrade kernel", - vi->z_physical_clusterbits[0], vi->nid); - err = -ENOTSUPP; + erofs_err(sb, "unsupported physical clusterbits %u for nid %llu, please upgrade kernel", + vi->z_physical_clusterbits[0], vi->nid); + err = -EOPNOTSUPP; goto unmap_done; } vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits + ((h->h_clusterbits >> 5) & 7); + set_bit(EROFS_I_Z_INITED_BIT, &vi->flags); unmap_done: kunmap_atomic(kaddr); unlock_page(page); put_page(page); - - set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); out_unlock: - clear_and_wake_up_bit(EROFS_V_BL_Z_BIT, &vi->flags); + clear_and_wake_up_bit(EROFS_I_BL_Z_BIT, &vi->flags); return err; } @@ -131,7 +127,7 @@ static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m, put_page(mpage); } - mpage = erofs_get_meta_page(sb, eblk, false); + mpage = erofs_get_meta_page(sb, eblk); if (IS_ERR(mpage)) { map->mpage = NULL; return PTR_ERR(mpage); @@ -146,7 +142,7 @@ static int vle_legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, unsigned long lcn) { struct inode *const inode = m->inode; - struct erofs_vnode *const vi = EROFS_V(inode); + struct erofs_inode *const vi = EROFS_I(inode); const erofs_off_t ibase = iloc(EROFS_I_SB(inode), vi->nid); const erofs_off_t pos = Z_EROFS_VLE_LEGACY_INDEX_ALIGN(ibase + vi->inode_isize + @@ -179,7 +175,7 @@ static int vle_legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, break; default: DBG_BUGON(1); - return -EIO; + return -EOPNOTSUPP; } m->type = type; return 0; @@ -200,7 +196,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, unsigned int amortizedshift, unsigned int eofs) { - struct erofs_vnode *const vi = EROFS_V(m->inode); + struct erofs_inode *const vi = EROFS_I(m->inode); const unsigned int lclusterbits = vi->z_logical_clusterbits; const unsigned int lomask = (1 << lclusterbits) - 1; unsigned int vcnt, base, lo, encodebits, nblk; @@ -212,7 +208,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, else if (1 << amortizedshift == 2 && lclusterbits == 12) vcnt = 16; else - return -ENOTSUPP; + return -EOPNOTSUPP; encodebits = ((vcnt << amortizedshift) - sizeof(__le32)) * 8 / vcnt; base = round_down(eofs, vcnt << amortizedshift); @@ -264,7 +260,7 @@ static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m, unsigned long lcn) { struct inode *const inode = m->inode; - struct erofs_vnode *const vi = EROFS_V(inode); + struct erofs_inode *const vi = EROFS_I(inode); const unsigned int lclusterbits = vi->z_logical_clusterbits; const erofs_off_t ebase = ALIGN(iloc(EROFS_I_SB(inode), vi->nid) + vi->inode_isize + vi->xattr_isize, 8) + @@ -276,7 +272,7 @@ static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m, int err; if (lclusterbits != 12) - return -ENOTSUPP; + return -EOPNOTSUPP; if (lcn >= totalidx) return -EINVAL; @@ -318,7 +314,7 @@ out: static int vle_load_cluster_from_disk(struct z_erofs_maprecorder *m, unsigned int lcn) { - const unsigned int datamode = EROFS_V(m->inode)->datamode; + const unsigned int datamode = EROFS_I(m->inode)->datalayout; if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY) return vle_legacy_load_cluster_from_disk(m, lcn); @@ -332,15 +328,17 @@ static int vle_load_cluster_from_disk(struct z_erofs_maprecorder *m, static int vle_extent_lookback(struct z_erofs_maprecorder *m, unsigned int lookback_distance) { - struct erofs_vnode *const vi = EROFS_V(m->inode); + struct erofs_inode *const vi = EROFS_I(m->inode); struct erofs_map_blocks *const map = m->map; const unsigned int lclusterbits = vi->z_logical_clusterbits; unsigned long lcn = m->lcn; int err; if (lcn < lookback_distance) { + erofs_err(m->inode->i_sb, + "bogus lookback distance @ nid %llu", vi->nid); DBG_BUGON(1); - return -EIO; + return -EFSCORRUPTED; } /* load extent head logical cluster if needed */ @@ -351,6 +349,13 @@ static int vle_extent_lookback(struct z_erofs_maprecorder *m, switch (m->type) { case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: + if (!m->delta[0]) { + erofs_err(m->inode->i_sb, + "invalid lookback distance 0 @ nid %llu", + vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; + } return vle_extent_lookback(m, m->delta[0]); case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: map->m_flags &= ~EROFS_MAP_ZIPPED; @@ -359,10 +364,11 @@ static int vle_extent_lookback(struct z_erofs_maprecorder *m, map->m_la = (lcn << lclusterbits) | m->clusterofs; break; default: - errln("unknown type %u at lcn %lu of nid %llu", - m->type, lcn, vi->nid); + erofs_err(m->inode->i_sb, + "unknown type %u @ lcn %lu of nid %llu", + m->type, lcn, vi->nid); DBG_BUGON(1); - return -EIO; + return -EOPNOTSUPP; } return 0; } @@ -371,7 +377,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, int flags) { - struct erofs_vnode *const vi = EROFS_V(inode); + struct erofs_inode *const vi = EROFS_I(inode); struct z_erofs_maprecorder m = { .inode = inode, .map = map, @@ -383,7 +389,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, trace_z_erofs_map_blocks_iter_enter(inode, map, flags); /* when trying to read beyond EOF, leave it unmapped */ - if (unlikely(map->m_la >= inode->i_size)) { + if (map->m_la >= inode->i_size) { map->m_llen = map->m_la + 1 - inode->i_size; map->m_la = inode->i_size; map->m_flags = 0; @@ -417,10 +423,11 @@ int z_erofs_map_blocks_iter(struct inode *inode, break; } /* m.lcn should be >= 1 if endoff < m.clusterofs */ - if (unlikely(!m.lcn)) { - errln("invalid logical cluster 0 at nid %llu", - vi->nid); - err = -EIO; + if (!m.lcn) { + erofs_err(inode->i_sb, + "invalid logical cluster 0 at nid %llu", + vi->nid); + err = -EFSCORRUPTED; goto unmap_out; } end = (m.lcn << lclusterbits) | m.clusterofs; @@ -430,13 +437,14 @@ int z_erofs_map_blocks_iter(struct inode *inode, case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: /* get the correspoinding first chunk */ err = vle_extent_lookback(&m, m.delta[0]); - if (unlikely(err)) + if (err) goto unmap_out; break; default: - errln("unknown type %u at offset %llu of nid %llu", - m.type, ofs, vi->nid); - err = -EIO; + erofs_err(inode->i_sb, + "unknown type %u @ offset %llu of nid %llu", + m.type, ofs, vi->nid); + err = -EOPNOTSUPP; goto unmap_out; } @@ -450,9 +458,9 @@ unmap_out: kunmap_atomic(m.kaddr); out: - debugln("%s, m_la %llu m_pa %llu m_llen %llu m_plen %llu m_flags 0%o", - __func__, map->m_la, map->m_pa, - map->m_llen, map->m_plen, map->m_flags); + erofs_dbg("%s, m_la %llu m_pa %llu m_llen %llu m_plen %llu m_flags 0%o", + __func__, map->m_la, map->m_pa, + map->m_llen, map->m_plen, map->m_flags); trace_z_erofs_map_blocks_iter_exit(inode, map, flags, err); diff --git a/drivers/staging/erofs/unzip_pagevec.h b/fs/erofs/zpvec.h index 7af0ba8d8495..58556903aa94 100644 --- a/drivers/staging/erofs/unzip_pagevec.h +++ b/fs/erofs/zpvec.h @@ -1,21 +1,15 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * linux/drivers/staging/erofs/unzip_pagevec.h - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang <gaoxiang25@huawei.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ -#ifndef __EROFS_UNZIP_PAGEVEC_H -#define __EROFS_UNZIP_PAGEVEC_H +#ifndef __EROFS_FS_ZPVEC_H +#define __EROFS_FS_ZPVEC_H -#include <linux/tagptr.h> +#include "tagptr.h" -/* page type in pagevec for unzip subsystem */ +/* page type in pagevec for decompress subsystem */ enum z_erofs_page_type { /* including Z_EROFS_VLE_PAGE_TAIL_EXCLUSIVE */ Z_EROFS_PAGE_TYPE_EXCLUSIVE, @@ -54,9 +48,9 @@ static inline void z_erofs_pagevec_ctor_exit(struct z_erofs_pagevec_ctor *ctor, static inline struct page * z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor, - unsigned nr) + unsigned int nr) { - unsigned index; + unsigned int index; /* keep away from occupied pages */ if (ctor->next) @@ -64,7 +58,7 @@ z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor, for (index = 0; index < nr; ++index) { const erofs_vtptr_t t = ctor->pages[index]; - const unsigned tags = tagptr_unfold_tags(t); + const unsigned int tags = tagptr_unfold_tags(t); if (tags == Z_EROFS_PAGE_TYPE_EXCLUSIVE) return tagptr_unfold_ptr(t); @@ -91,8 +85,9 @@ z_erofs_pagevec_ctor_pagedown(struct z_erofs_pagevec_ctor *ctor, } static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, - unsigned nr, - erofs_vtptr_t *pages, unsigned i) + unsigned int nr, + erofs_vtptr_t *pages, + unsigned int i) { ctor->nr = nr; ctor->curr = ctor->next = NULL; @@ -106,23 +101,21 @@ static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, z_erofs_pagevec_ctor_pagedown(ctor, false); } } - ctor->next = z_erofs_pagevec_ctor_next_page(ctor, i); ctor->index = i; } -static inline bool -z_erofs_pagevec_ctor_enqueue(struct z_erofs_pagevec_ctor *ctor, - struct page *page, - enum z_erofs_page_type type, - bool *occupied) +static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor, + struct page *page, + enum z_erofs_page_type type, + bool *occupied) { *occupied = false; - if (unlikely(!ctor->next && type)) + if (!ctor->next && type) if (ctor->index + 1 == ctor->nr) return false; - if (unlikely(ctor->index >= ctor->nr)) + if (ctor->index >= ctor->nr) z_erofs_pagevec_ctor_pagedown(ctor, false); /* exclusive page type must be 0 */ @@ -134,19 +127,17 @@ z_erofs_pagevec_ctor_enqueue(struct z_erofs_pagevec_ctor *ctor, ctor->next = page; *occupied = true; } - - ctor->pages[ctor->index++] = - tagptr_fold(erofs_vtptr_t, page, type); + ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, page, type); return true; } static inline struct page * -z_erofs_pagevec_ctor_dequeue(struct z_erofs_pagevec_ctor *ctor, - enum z_erofs_page_type *type) +z_erofs_pagevec_dequeue(struct z_erofs_pagevec_ctor *ctor, + enum z_erofs_page_type *type) { erofs_vtptr_t t; - if (unlikely(ctor->index >= ctor->nr)) { + if (ctor->index >= ctor->nr) { DBG_BUGON(!ctor->next); z_erofs_pagevec_ctor_pagedown(ctor, true); } @@ -159,11 +150,8 @@ z_erofs_pagevec_ctor_dequeue(struct z_erofs_pagevec_ctor *ctor, if (*type == (uintptr_t)ctor->next) ctor->next = tagptr_unfold_ptr(t); - ctor->pages[ctor->index++] = - tagptr_fold(erofs_vtptr_t, NULL, 0); - + ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, NULL, 0); return tagptr_unfold_ptr(t); } - #endif diff --git a/drivers/staging/greybus/greybus.h b/include/linux/greybus.h index d03ddb7c9df0..18c0fb958b74 100644 --- a/drivers/staging/greybus/greybus.h +++ b/include/linux/greybus.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus driver and device API * @@ -20,18 +20,18 @@ #include <linux/pm_runtime.h> #include <linux/idr.h> -#include "greybus_id.h" -#include "greybus_manifest.h" -#include "greybus_protocols.h" -#include "manifest.h" -#include "hd.h" -#include "svc.h" -#include "control.h" -#include "module.h" -#include "interface.h" -#include "bundle.h" -#include "connection.h" -#include "operation.h" +#include <linux/greybus/greybus_id.h> +#include <linux/greybus/greybus_manifest.h> +#include <linux/greybus/greybus_protocols.h> +#include <linux/greybus/manifest.h> +#include <linux/greybus/hd.h> +#include <linux/greybus/svc.h> +#include <linux/greybus/control.h> +#include <linux/greybus/module.h> +#include <linux/greybus/interface.h> +#include <linux/greybus/bundle.h> +#include <linux/greybus/connection.h> +#include <linux/greybus/operation.h> /* Matches up with the Greybus Protocol specification document */ #define GREYBUS_VERSION_MAJOR 0x00 diff --git a/drivers/staging/greybus/bundle.h b/include/linux/greybus/bundle.h index 8734d2055657..df8d88424cb7 100644 --- a/drivers/staging/greybus/bundle.h +++ b/include/linux/greybus/bundle.h @@ -9,7 +9,10 @@ #ifndef __BUNDLE_H #define __BUNDLE_H +#include <linux/types.h> #include <linux/list.h> +#include <linux/pm_runtime.h> +#include <linux/device.h> #define BUNDLE_ID_NONE U8_MAX diff --git a/drivers/staging/greybus/connection.h b/include/linux/greybus/connection.h index 5ca3befc0636..d59b7fc1de3e 100644 --- a/drivers/staging/greybus/connection.h +++ b/include/linux/greybus/connection.h @@ -9,8 +9,11 @@ #ifndef __CONNECTION_H #define __CONNECTION_H +#include <linux/bits.h> #include <linux/list.h> #include <linux/kfifo.h> +#include <linux/kref.h> +#include <linux/workqueue.h> #define GB_CONNECTION_FLAG_CSD BIT(0) #define GB_CONNECTION_FLAG_NO_FLOWCTRL BIT(1) diff --git a/drivers/staging/greybus/control.h b/include/linux/greybus/control.h index 3a29ec05f631..da11fe871653 100644 --- a/drivers/staging/greybus/control.h +++ b/include/linux/greybus/control.h @@ -9,6 +9,9 @@ #ifndef __CONTROL_H #define __CONTROL_H +#include <linux/types.h> +#include <linux/device.h> + struct gb_control { struct device dev; struct gb_interface *intf; diff --git a/drivers/staging/greybus/greybus_id.h b/include/linux/greybus/greybus_id.h index f4c8440093e4..f4c8440093e4 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/include/linux/greybus/greybus_id.h diff --git a/drivers/staging/greybus/greybus_manifest.h b/include/linux/greybus/greybus_manifest.h index 2cec5cf7a846..6e62fe478712 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/include/linux/greybus/greybus_manifest.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus manifest definition * @@ -14,6 +14,9 @@ #ifndef __GREYBUS_MANIFEST_H #define __GREYBUS_MANIFEST_H +#include <linux/bits.h> +#include <linux/types.h> + enum greybus_descriptor_type { GREYBUS_TYPE_INVALID = 0x00, GREYBUS_TYPE_INTERFACE = 0x01, diff --git a/drivers/staging/greybus/greybus_protocols.h b/include/linux/greybus/greybus_protocols.h index ddc73f10eb22..dfbc6c39a74b 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/include/linux/greybus/greybus_protocols.h @@ -1,58 +1,14 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* 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) 2014 - 2015 Google Inc. All rights reserved. - * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. - * - * 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 version 2 for more details. - * - * BSD LICENSE - * * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. - * - * 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 Google Inc. or Linaro Ltd. 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 GOOGLE INC. OR - * LINARO LTD. 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 __GREYBUS_PROTOCOLS_H #define __GREYBUS_PROTOCOLS_H +#include <linux/types.h> + /* Fixed IDs for control/svc protocols */ /* SVC switch-port device ids */ diff --git a/drivers/staging/greybus/hd.h b/include/linux/greybus/hd.h index 6cf024a20a58..d3faf0c1a569 100644 --- a/drivers/staging/greybus/hd.h +++ b/include/linux/greybus/hd.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Host Device * @@ -9,6 +9,9 @@ #ifndef __HD_H #define __HD_H +#include <linux/types.h> +#include <linux/device.h> + struct gb_host_device; struct gb_message; diff --git a/drivers/staging/greybus/interface.h b/include/linux/greybus/interface.h index 1c00c5bb3ec9..ce4def881e6f 100644 --- a/drivers/staging/greybus/interface.h +++ b/include/linux/greybus/interface.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Interface Block code * @@ -9,6 +9,9 @@ #ifndef __INTERFACE_H #define __INTERFACE_H +#include <linux/types.h> +#include <linux/device.h> + enum gb_interface_type { GB_INTERFACE_TYPE_INVALID = 0, GB_INTERFACE_TYPE_UNKNOWN, diff --git a/drivers/staging/greybus/manifest.h b/include/linux/greybus/manifest.h index f3c95a255631..830301b7a8bc 100644 --- a/drivers/staging/greybus/manifest.h +++ b/include/linux/greybus/manifest.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus manifest parsing * @@ -9,6 +9,8 @@ #ifndef __MANIFEST_H #define __MANIFEST_H +#include <linux/types.h> + struct gb_interface; bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size); diff --git a/drivers/staging/greybus/module.h b/include/linux/greybus/module.h index b1ebcc6636db..47b839af145d 100644 --- a/drivers/staging/greybus/module.h +++ b/include/linux/greybus/module.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Module code * @@ -9,6 +9,9 @@ #ifndef __MODULE_H #define __MODULE_H +#include <linux/types.h> +#include <linux/device.h> + struct gb_module { struct device dev; struct gb_host_device *hd; diff --git a/drivers/staging/greybus/operation.h b/include/linux/greybus/operation.h index 40b7b02fff88..cb8e4ef45222 100644 --- a/drivers/staging/greybus/operation.h +++ b/include/linux/greybus/operation.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus operations * @@ -10,7 +10,12 @@ #define __OPERATION_H #include <linux/completion.h> +#include <linux/kref.h> +#include <linux/timer.h> +#include <linux/types.h> +#include <linux/workqueue.h> +struct gb_host_device; struct gb_operation; /* The default amount of time a request is given to complete */ diff --git a/drivers/staging/greybus/svc.h b/include/linux/greybus/svc.h index ad01783bac9c..5afaf5f06856 100644 --- a/drivers/staging/greybus/svc.h +++ b/include/linux/greybus/svc.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus SVC code * @@ -9,6 +9,11 @@ #ifndef __SVC_H #define __SVC_H +#include <linux/types.h> +#include <linux/device.h> + +struct gb_svc_l2_timer_cfg; + #define GB_SVC_CPORT_FLAG_E2EFC BIT(0) #define GB_SVC_CPORT_FLAG_CSD_N BIT(1) #define GB_SVC_CPORT_FLAG_CSV_N BIT(2) diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index 0c636b9fe8d7..ea1f50ce2e49 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -62,14 +62,20 @@ struct cros_ec_sensors_core_state { enum motionsensor_type type; enum motionsensor_location loc; - s16 calib[CROS_EC_SENSOR_MAX_AXIS]; - + struct calib_data { + s16 offset; + u16 scale; + } calib[CROS_EC_SENSOR_MAX_AXIS]; + s8 sign[CROS_EC_SENSOR_MAX_AXIS]; u8 samples[CROS_EC_SAMPLE_SIZE]; int (*read_ec_sensors_data)(struct iio_dev *indio_dev, unsigned long scan_mask, s16 *data); int curr_sampl_freq; + + /* Table of known available frequencies : 0, Min and Max in mHz */ + int frequencies[3]; }; /** @@ -151,6 +157,24 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, int *val, int *val2, long mask); /** + * cros_ec_sensors_core_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, IIO_AVAIL_RANGE or IIO_AVAIL_LIST + */ +int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, + int *type, + int *length, + long mask); + +/** * cros_ec_sensors_core_write() - function to write a value to the sensor * @st: pointer to state information for device * @chan: channel specification structure table diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 2948ac99e2da..686be532f4cb 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -16,11 +16,16 @@ #include <linux/iio/trigger.h> #include <linux/bitops.h> #include <linux/regulator/consumer.h> +#include <linux/regmap.h> #include <linux/platform_data/st_sensors_pdata.h> -#define ST_SENSORS_TX_MAX_LENGTH 2 -#define ST_SENSORS_RX_MAX_LENGTH 6 +/* + * Buffer size max case: 2bytes per channel, 3 channels in total + + * 8bytes timestamp channel (s64) + */ +#define ST_SENSORS_MAX_BUFFER_SIZE (ALIGN(2 * 3, sizeof(s64)) + \ + sizeof(s64)) #define ST_SENSORS_ODR_LIST_MAX 10 #define ST_SENSORS_FULLSCALE_AVL_MAX 10 @@ -170,36 +175,6 @@ struct st_sensor_data_ready_irq { }; /** - * struct st_sensor_transfer_buffer - ST sensor device I/O buffer - * @buf_lock: Mutex to protect rx and tx buffers. - * @tx_buf: Buffer used by SPI transfer function to send data to the sensors. - * This buffer is used to avoid DMA not-aligned issue. - * @rx_buf: Buffer used by SPI transfer to receive data from sensors. - * This buffer is used to avoid DMA not-aligned issue. - */ -struct st_sensor_transfer_buffer { - struct mutex buf_lock; - u8 rx_buf[ST_SENSORS_RX_MAX_LENGTH]; - u8 tx_buf[ST_SENSORS_TX_MAX_LENGTH] ____cacheline_aligned; -}; - -/** - * struct st_sensor_transfer_function - ST sensor device I/O function - * @read_byte: Function used to read one byte. - * @write_byte: Function used to write one byte. - * @read_multiple_byte: Function used to read multiple byte. - */ -struct st_sensor_transfer_function { - int (*read_byte) (struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 *res_byte); - int (*write_byte) (struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 data); - int (*read_multiple_byte) (struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, int len, u8 *data, - bool multiread_bit); -}; - -/** * struct st_sensor_settings - ST specific sensor settings * @wai: Contents of WhoAmI register. * @wai_addr: The address of WhoAmI register. @@ -242,19 +217,17 @@ struct st_sensor_settings { * @current_fullscale: Maximum range of measure by the sensor. * @vdd: Pointer to sensor's Vdd power supply * @vdd_io: Pointer to sensor's Vdd-IO power supply + * @regmap: Pointer to specific sensor regmap configuration. * @enabled: Status of the sensor (false->off, true->on). - * @multiread_bit: Use or not particular bit for [I2C/SPI] multiread. - * @buffer_data: Data used by buffer part. * @odr: Output data rate of the sensor [Hz]. * num_data_channels: Number of data channels used in buffer. * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). * @int_pin_open_drain: Set the interrupt/DRDY to open drain. - * @get_irq_data_ready: Function to get the IRQ used for data ready signal. - * @tf: Transfer function structure used by I/O operations. - * @tb: Transfer buffers and mutex used by I/O operations. + * @irq: the IRQ number. * @edge_irq: the IRQ triggers on edges and need special handling. * @hw_irq_trigger: if we're using the hardware interrupt on the sensor. * @hw_timestamp: Latest timestamp from the interrupt handler, when in use. + * @buffer_data: Data used by buffer part. */ struct st_sensor_data { struct device *dev; @@ -264,26 +237,22 @@ struct st_sensor_data { struct st_sensor_fullscale_avl *current_fullscale; struct regulator *vdd; struct regulator *vdd_io; + struct regmap *regmap; bool enabled; - bool multiread_bit; - - char *buffer_data; unsigned int odr; unsigned int num_data_channels; u8 drdy_int_pin; bool int_pin_open_drain; - - unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev); - - const struct st_sensor_transfer_function *tf; - struct st_sensor_transfer_buffer tb; + int irq; bool edge_irq; bool hw_irq_trigger; s64 hw_timestamp; + + char buffer_data[ST_SENSORS_MAX_BUFFER_SIZE] ____cacheline_aligned; }; #ifdef CONFIG_IIO_BUFFER @@ -334,8 +303,11 @@ int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale); int st_sensors_read_info_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val); -int st_sensors_check_device_support(struct iio_dev *indio_dev, - int num_sensors_list, const struct st_sensor_settings *sensor_settings); +int st_sensors_get_settings_index(const char *name, + const struct st_sensor_settings *list, + const int list_length); + +int st_sensors_verify_id(struct iio_dev *indio_dev); ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, struct device_attribute *attr, char *buf); diff --git a/include/linux/iio/common/st_sensors_i2c.h b/include/linux/iio/common/st_sensors_i2c.h index 5ada89944698..01e424e2af4f 100644 --- a/include/linux/iio/common/st_sensors_i2c.h +++ b/include/linux/iio/common/st_sensors_i2c.h @@ -14,8 +14,8 @@ #include <linux/iio/common/st_sensors.h> #include <linux/of.h> -void st_sensors_i2c_configure(struct iio_dev *indio_dev, - struct i2c_client *client, struct st_sensor_data *sdata); +int st_sensors_i2c_configure(struct iio_dev *indio_dev, + struct i2c_client *client); #ifdef CONFIG_ACPI int st_sensors_match_acpi_device(struct device *dev); diff --git a/include/linux/iio/common/st_sensors_spi.h b/include/linux/iio/common/st_sensors_spi.h index 6020f7167859..90b25f087f06 100644 --- a/include/linux/iio/common/st_sensors_spi.h +++ b/include/linux/iio/common/st_sensors_spi.h @@ -13,7 +13,7 @@ #include <linux/spi/spi.h> #include <linux/iio/common/st_sensors.h> -void st_sensors_spi_configure(struct iio_dev *indio_dev, - struct spi_device *spi, struct st_sensor_data *sdata); +int st_sensors_spi_configure(struct iio_dev *indio_dev, + struct spi_device *spi); #endif /* ST_SENSORS_SPI_H */ diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 3428d06b2f44..4c53815bb729 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -26,6 +26,7 @@ struct adis_burst; * struct adis_data - ADIS chip variant specific data * @read_delay: SPI delay for read operations in us * @write_delay: SPI delay for write operations in us + * @cs_change_delay: SPI delay between CS changes in us * @glob_cmd_reg: Register address of the GLOB_CMD register * @msc_ctrl_reg: Register address of the MSC_CTRL register * @diag_stat_reg: Register address of the DIAG_STAT register @@ -35,6 +36,7 @@ struct adis_burst; struct adis_data { unsigned int read_delay; unsigned int write_delay; + unsigned int cs_change_delay; unsigned int glob_cmd_reg; unsigned int msc_ctrl_reg; diff --git a/drivers/staging/erofs/include/trace/events/erofs.h b/include/trace/events/erofs.h index 660c92fc1803..27f5caa6299a 100644 --- a/drivers/staging/erofs/include/trace/events/erofs.h +++ b/include/trace/events/erofs.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ #undef TRACE_SYSTEM #define TRACE_SYSTEM erofs @@ -6,6 +6,9 @@ #define _TRACE_EROFS_H #include <linux/tracepoint.h> +#include <linux/fs.h> + +struct erofs_map_blocks; #define show_dev(dev) MAJOR(dev), MINOR(dev) #define show_dev_nid(entry) show_dev(entry->dev), entry->nid @@ -38,7 +41,7 @@ TRACE_EVENT(erofs_lookup, TP_fast_assign( __entry->dev = dir->i_sb->s_dev; - __entry->nid = EROFS_V(dir)->nid; + __entry->nid = EROFS_I(dir)->nid; __entry->name = dentry->d_name.name; __entry->flags = flags; ), @@ -63,7 +66,7 @@ TRACE_EVENT(erofs_fill_inode, TP_fast_assign( __entry->dev = inode->i_sb->s_dev; - __entry->nid = EROFS_V(inode)->nid; + __entry->nid = EROFS_I(inode)->nid; __entry->blkaddr = erofs_blknr(iloc(EROFS_I_SB(inode), __entry->nid)); __entry->ofs = erofs_blkoff(iloc(EROFS_I_SB(inode), __entry->nid)); __entry->isdir = isdir; @@ -92,7 +95,7 @@ TRACE_EVENT(erofs_readpage, TP_fast_assign( __entry->dev = page->mapping->host->i_sb->s_dev; - __entry->nid = EROFS_V(page->mapping->host)->nid; + __entry->nid = EROFS_I(page->mapping->host)->nid; __entry->dir = S_ISDIR(page->mapping->host->i_mode); __entry->index = page->index; __entry->uptodate = PageUptodate(page); @@ -125,7 +128,7 @@ TRACE_EVENT(erofs_readpages, TP_fast_assign( __entry->dev = inode->i_sb->s_dev; - __entry->nid = EROFS_V(inode)->nid; + __entry->nid = EROFS_I(inode)->nid; __entry->start = page->index; __entry->nrpage = nrpage; __entry->raw = raw; @@ -154,7 +157,7 @@ DECLARE_EVENT_CLASS(erofs__map_blocks_enter, TP_fast_assign( __entry->dev = inode->i_sb->s_dev; - __entry->nid = EROFS_V(inode)->nid; + __entry->nid = EROFS_I(inode)->nid; __entry->la = map->m_la; __entry->llen = map->m_llen; __entry->flags = flags; @@ -200,7 +203,7 @@ DECLARE_EVENT_CLASS(erofs__map_blocks_exit, TP_fast_assign( __entry->dev = inode->i_sb->s_dev; - __entry->nid = EROFS_V(inode)->nid; + __entry->nid = EROFS_I(inode)->nid; __entry->flags = flags; __entry->la = map->m_la; __entry->pa = map->m_pa; @@ -244,7 +247,7 @@ TRACE_EVENT(erofs_destroy_inode, TP_fast_assign( __entry->dev = inode->i_sb->s_dev; - __entry->nid = EROFS_V(inode)->nid; + __entry->nid = EROFS_I(inode)->nid; ), TP_printk("dev = (%d,%d), nid = %llu", show_dev_nid(__entry)) diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h index 1274c692e59c..903cc2d2750b 100644 --- a/include/uapi/linux/magic.h +++ b/include/uapi/linux/magic.h @@ -19,6 +19,7 @@ #define SQUASHFS_MAGIC 0x73717368 #define ECRYPTFS_SUPER_MAGIC 0xf15f #define EFS_SUPER_MAGIC 0x414A53 +#define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 #define EXT2_SUPER_MAGIC 0xEF53 #define EXT3_SUPER_MAGIC 0xEF53 #define XENFS_SUPER_MAGIC 0xabba1974 diff --git a/tools/iio/.gitignore b/tools/iio/.gitignore new file mode 100644 index 000000000000..3758202618bd --- /dev/null +++ b/tools/iio/.gitignore @@ -0,0 +1,4 @@ +iio_event_monitor +iio_generic_buffer +lsiio +include/ |